[pnetcdf] 01/08: upstream 1.7.0pre1

Alastair McKinstry mckinstry at moszumanska.debian.org
Sun Jan 24 09:06:30 UTC 2016


This is an automated email from the git hooks/post-receive script.

mckinstry pushed a commit to branch debian/master
in repository pnetcdf.

commit 4ada7d7360ae92b1600180a3246891f415ec882f
Author: Alastair McKinstry <mckinstry at debian.org>
Date:   Sun Jan 17 04:11:42 2016 +0000

    upstream 1.7.0pre1
---
 COPYRIGHT                                         |    34 +
 CREDITS                                           |    34 +
 INSTALL                                           |   319 +
 Makefile.in                                       |   242 +
 README                                            |    55 +
 README.CRAY                                       |   110 +
 README.IBM                                        |   269 +
 README.LINUX                                      |    62 +
 README.SGI                                        |    46 +
 README.SX                                         |    37 +
 README.large_files                                |    48 +
 RELEASE_NOTES                                     |   859 ++
 aclocal.m4                                        |  1727 +++
 benchmarks/C/Makefile.in                          |    59 +
 benchmarks/C/aggregation.c                        |   592 +
 benchmarks/C/depend                               |     2 +
 benchmarks/C/write_block_read_column.c            |   401 +
 benchmarks/FLASH-IO/Makefile.in                   |    93 +
 benchmarks/FLASH-IO/README                        |    81 +
 benchmarks/FLASH-IO/block_boundary_data.fh        |    83 +
 benchmarks/FLASH-IO/checkpoint_ncmpi_parallel.F90 |   639 +
 benchmarks/FLASH-IO/common.fh                     |    58 +
 benchmarks/FLASH-IO/configure.in                  |   225 +
 benchmarks/FLASH-IO/definitions.fh                |    98 +
 benchmarks/FLASH-IO/flash_benchmark_io.F90        |   273 +
 benchmarks/FLASH-IO/flash_release.F90             |    10 +
 benchmarks/FLASH-IO/get_mfluid_property.F90       |    34 +
 benchmarks/FLASH-IO/numfluids.fh                  |     3 +
 benchmarks/FLASH-IO/physicaldata.fh               |   196 +
 benchmarks/FLASH-IO/plotfile_ncmpi_parallel.F90   |   698 +
 benchmarks/FLASH-IO/tree.fh                       |   144 +
 benchmarks/Makefile.in                            |    54 +
 benchmarks/README                                 |    29 +
 cobalt.script                                     |    16 +
 configure                                         | 15165 ++++++++++++++++++++
 configure.in                                      |  1269 ++
 doc/Makefile.in                                   |    45 +
 doc/c_api.tex                                     |   203 +
 doc/data_mode_api.tex                             |   513 +
 doc/flexible_api.tex                              |    73 +
 doc/latex8.sty                                    |   175 +
 doc/multiple_io.tex                               |   152 +
 doc/nonblocking.tex                               |   362 +
 doc/pnetcdf-api.bbl                               |    10 +
 doc/pnetcdf-api.tex                               |   655 +
 doc/porting_notes.txt                             |    50 +
 doc/symbol_renaming.txt                           |    23 +
 examples/C/Makefile.in                            |   162 +
 examples/C/block_cyclic.c                         |   301 +
 examples/C/bput_varn_uint.c                       |   347 +
 examples/C/collective_write.c                     |   231 +
 examples/C/column_wise.c                          |   222 +
 examples/C/create_open.c                          |   105 +
 examples/C/depend                                 |    22 +
 examples/C/fill_mode.c                            |   206 +
 examples/C/flexible_api.c                         |   272 +
 examples/C/get_info.c                             |   145 +
 examples/C/get_vara.c                             |   188 +
 examples/C/ghost_cell.c                           |   206 +
 examples/C/global_attributes.c                    |   186 +
 examples/C/hints.c                                |   196 +
 examples/C/i_varn_int64.c                         |   371 +
 examples/C/mput.c                                 |   232 +
 examples/C/nonblocking_write.c                    |   276 +
 examples/C/nonblocking_write_in_def.c             |   268 +
 examples/C/put_vara.c                             |   194 +
 examples/C/put_varn_float.c                       |   218 +
 examples/C/put_varn_int.c                         |   219 +
 examples/C/req_all.c                              |   185 +
 examples/C/transpose.c                            |   235 +
 examples/C/vard_int.c                             |   192 +
 examples/CXX/Makefile.in                          |   130 +
 examples/CXX/block_cyclic.cpp                     |   301 +
 examples/CXX/collective_write.cpp                 |   217 +
 examples/CXX/column_wise.cpp                      |   200 +
 examples/CXX/depend                               |    14 +
 examples/CXX/fill_mode.cpp                        |   213 +
 examples/CXX/flexible_api.cpp                     |   228 +
 examples/CXX/get_info.cpp                         |   137 +
 examples/CXX/get_vara.cpp                         |   190 +
 examples/CXX/hints.cpp                            |   212 +
 examples/CXX/nonblocking_write.cpp                |   262 +
 examples/CXX/put_vara.cpp                         |   180 +
 examples/CXX/put_varn_float.cpp                   |   222 +
 examples/CXX/put_varn_int.cpp                     |   223 +
 examples/CXX/transpose.cpp                        |   226 +
 examples/CXX/vard_int.cpp                         |   209 +
 examples/F77/Makefile.in                          |   135 +
 examples/F77/block_cyclic.f                       |   284 +
 examples/F77/bput_varn_int8.f                     |   344 +
 examples/F77/column_wise.f                        |   196 +
 examples/F77/depend                               |    14 +
 examples/F77/fill_mode.f                          |   227 +
 examples/F77/flexible_api.f                       |   194 +
 examples/F77/get_info.f                           |   141 +
 examples/F77/hints.f                              |   251 +
 examples/F77/i_varn_real.f                        |   323 +
 examples/F77/nonblocking_write.f                  |   204 +
 examples/F77/put_vara.f                           |   159 +
 examples/F77/put_varn_int.f                       |   257 +
 examples/F77/put_varn_real.f                      |   261 +
 examples/F77/transpose.f                          |   290 +
 examples/F77/utils.F90                            |    53 +
 examples/F77/vard_int.F                           |   233 +
 examples/F90/Makefile.in                          |   123 +
 examples/F90/block_cyclic.f90                     |   278 +
 examples/F90/column_wise.f90                      |   186 +
 examples/F90/depend                               |    12 +
 examples/F90/fill_mode.f90                        |   218 +
 examples/F90/flexible_api.f90                     |   182 +
 examples/F90/get_info.f90                         |   139 +
 examples/F90/hints.f90                            |   248 +
 examples/F90/nonblocking_write.f90                |   197 +
 examples/F90/put_var.f90                          |   152 +
 examples/F90/put_varn_int.f90                     |   259 +
 examples/F90/put_varn_real.f90                    |   253 +
 examples/F90/transpose.f90                        |   235 +
 examples/F90/utils.F90                            |    53 +
 examples/F90/vard_int.f90                         |   225 +
 examples/Makefile.in                              |    72 +
 examples/README                                   |   322 +
 examples/tutorial/Makefile.in                     |   114 +
 examples/tutorial/depend                          |    14 +
 examples/tutorial/pnetcdf-permute.c               |   158 +
 examples/tutorial/pnetcdf-read-flexible.c         |   127 +
 examples/tutorial/pnetcdf-read-from-master.c      |   159 +
 examples/tutorial/pnetcdf-read-nb.c               |   150 +
 examples/tutorial/pnetcdf-read-nfiles.c           |   137 +
 examples/tutorial/pnetcdf-read-standard.c         |   126 +
 examples/tutorial/pnetcdf-write-buffered.c        |   129 +
 examples/tutorial/pnetcdf-write-bufferedf.f90     |   147 +
 examples/tutorial/pnetcdf-write-bufferedf77.f     |   149 +
 examples/tutorial/pnetcdf-write-flexible.c        |   111 +
 examples/tutorial/pnetcdf-write-from-master.c     |   117 +
 examples/tutorial/pnetcdf-write-nb.c              |   126 +
 examples/tutorial/pnetcdf-write-nfiles.c          |   218 +
 examples/tutorial/pnetcdf-write-standard.c        |   108 +
 macros.make.in                                    |   138 +
 man/Makefile.in                                   |    60 +
 man/pnetcdf.m4                                    |  1269 ++
 man/pnetcdf_f90.m4                                |   768 +
 pbs.script                                        |    18 +
 rules.make                                        |   260 +
 scripts/Makefile.in                               |    24 +
 scripts/config.guess                              |  1519 ++
 scripts/config.sub                                |  1767 +++
 scripts/install-sh                                |   527 +
 src/Makefile.in                                   |    49 +
 src/lib/Makefile.in                               |   117 +
 src/lib/attr.m4                                   |  1282 ++
 src/lib/bput.m4                                   |   551 +
 src/lib/convert_swap.m4                           |   311 +
 src/lib/depend                                    |    31 +
 src/lib/dim.c                                     |   525 +
 src/lib/error.c                                   |   761 +
 src/lib/fbits.h                                   |    26 +
 src/lib/filetype.c                                |   967 ++
 src/lib/fill.c                                    |   523 +
 src/lib/getput.m4                                 |  1246 ++
 src/lib/header.c                                  |  2530 ++++
 src/lib/i_getput.m4                               |   939 ++
 src/lib/i_varn.m4                                 |   336 +
 src/lib/m_getput_varx.m4                          |  1090 ++
 src/lib/macro.h                                   |   188 +
 src/lib/malloc.c                                  |   275 +
 src/lib/mpincio.c                                 |   592 +
 src/lib/mpinetcdf.c                               |  1183 ++
 src/lib/nc.c                                      |  1635 +++
 src/lib/nc.h                                      |   939 ++
 src/lib/ncconfig.h.in                             |   483 +
 src/lib/ncio.h                                    |    95 +
 src/lib/ncmpidtype.c                              |   575 +
 src/lib/ncmpidtype.h                              |    24 +
 src/lib/nctypes.h                                 |    46 +
 src/lib/ncx.h                                     |   979 ++
 src/lib/ncx.m4                                    |  3551 +++++
 src/lib/nonblocking.c                             |  2201 +++
 src/lib/pnetcdf.h.in                              |  3906 +++++
 src/lib/rnd.h                                     |    19 +
 src/lib/string.c                                  |   351 +
 src/lib/subfile.c                                 |  1109 ++
 src/lib/subfile.h                                 |    53 +
 src/lib/utf8proc.c                                |   600 +
 src/lib/utf8proc.h                                |   407 +
 src/lib/utf8proc_data.h                           | 13389 +++++++++++++++++
 src/lib/util.c                                    |    92 +
 src/lib/var.c                                     |   939 ++
 src/lib/vard.c                                    |   407 +
 src/lib/varn.m4                                   |   368 +
 src/libcxx/Makefile.in                            |    83 +
 src/libcxx/depend                                 |    67 +
 src/libcxx/ncmpiAtt.cpp                           |   224 +
 src/libcxx/ncmpiAtt.h                             |   121 +
 src/libcxx/ncmpiByte.cpp                          |    24 +
 src/libcxx/ncmpiByte.h                            |    30 +
 src/libcxx/ncmpiChar.cpp                          |    22 +
 src/libcxx/ncmpiChar.h                            |    27 +
 src/libcxx/ncmpiCheck.cpp                         |    94 +
 src/libcxx/ncmpiCheck.h                           |    35 +
 src/libcxx/ncmpiCompoundType.cpp                  |   156 +
 src/libcxx/ncmpiCompoundType.h                    |   107 +
 src/libcxx/ncmpiDim.cpp                           |   125 +
 src/libcxx/ncmpiDim.h                             |    84 +
 src/libcxx/ncmpiDouble.cpp                        |    22 +
 src/libcxx/ncmpiDouble.h                          |    28 +
 src/libcxx/ncmpiEnumType.cpp                      |   111 +
 src/libcxx/ncmpiEnumType.h                        |   109 +
 src/libcxx/ncmpiException.cpp                     |   308 +
 src/libcxx/ncmpiException.h                       |   437 +
 src/libcxx/ncmpiFile.cpp                          |   205 +
 src/libcxx/ncmpiFile.h                            |   125 +
 src/libcxx/ncmpiFloat.cpp                         |    22 +
 src/libcxx/ncmpiFloat.h                           |    28 +
 src/libcxx/ncmpiGroup.cpp                         |  1456 ++
 src/libcxx/ncmpiGroup.h                           |   596 +
 src/libcxx/ncmpiGroupAtt.cpp                      |    65 +
 src/libcxx/ncmpiGroupAtt.h                        |    44 +
 src/libcxx/ncmpiInt.cpp                           |    22 +
 src/libcxx/ncmpiInt.h                             |    28 +
 src/libcxx/ncmpiInt64.cpp                         |    22 +
 src/libcxx/ncmpiInt64.h                           |    28 +
 src/libcxx/ncmpiOpaqueType.cpp                    |    68 +
 src/libcxx/ncmpiOpaqueType.h                      |    58 +
 src/libcxx/ncmpiShort.cpp                         |    22 +
 src/libcxx/ncmpiShort.h                           |    28 +
 src/libcxx/ncmpiType.cpp                          |   179 +
 src/libcxx/ncmpiType.h                            |   157 +
 src/libcxx/ncmpiUbyte.cpp                         |    22 +
 src/libcxx/ncmpiUbyte.h                           |    28 +
 src/libcxx/ncmpiUint.cpp                          |    22 +
 src/libcxx/ncmpiUint.h                            |    28 +
 src/libcxx/ncmpiUint64.cpp                        |    22 +
 src/libcxx/ncmpiUint64.h                          |    28 +
 src/libcxx/ncmpiUshort.cpp                        |    22 +
 src/libcxx/ncmpiUshort.h                          |    28 +
 src/libcxx/ncmpiVar.cpp                           |  3289 +++++
 src/libcxx/ncmpiVar.h                             |  3322 +++++
 src/libcxx/ncmpiVarAtt.cpp                        |    63 +
 src/libcxx/ncmpiVarAtt.h                          |    46 +
 src/libcxx/ncmpiVlenType.cpp                      |    91 +
 src/libcxx/ncmpiVlenType.h                        |    57 +
 src/libcxx/ncmpi_notyet.cpp                       |   318 +
 src/libcxx/ncmpi_notyet.h                         |   214 +
 src/libcxx/pnetcdf.in                             |    14 +
 src/libf/Makefile.in                              |   403 +
 src/libf/buildiface                               |  4068 ++++++
 src/libf/createffiles                             |    24 +
 src/libf/defs                                     |  2547 ++++
 src/libf/inq_libversf.f                           |    10 +
 src/libf/mpinetcdf_impl.h                         |    77 +
 src/libf/nfconfig_inc.in                          |    91 +
 src/libf/pnetcdf.inc.in                           |  1512 ++
 src/libf/strerrorf.f                              |    10 +
 src/libf90/Makefile.in                            |    84 +
 src/libf90/api.f90.in                             |  4110 ++++++
 src/libf90/attributes.f90                         |   352 +
 src/libf90/dims.f90                               |    56 +
 src/libf90/file.f90                               |   331 +
 src/libf90/getput_text.m4                         |   251 +
 src/libf90/getput_var.m4                          |   678 +
 src/libf90/getput_vard.m4                         |   375 +
 src/libf90/getput_varn.m4                         |   666 +
 src/libf90/nf90_constants.f90                     |   302 +
 src/libf90/nfmpi_constants.f90.in                 |   423 +
 src/libf90/overloads.f90                          |   693 +
 src/libf90/pnetcdf.f90                            |    40 +
 src/libf90/variables.f90                          |   229 +
 src/libf90/visibility.f90                         |   617 +
 src/utils/Makefile.in                             |    34 +
 src/utils/ncmpidiff/Makefile.in                   |    63 +
 src/utils/ncmpidiff/depend                        |     1 +
 src/utils/ncmpidiff/ncmpidiff.1                   |    41 +
 src/utils/ncmpidiff/ncmpidiff.c                   |   782 +
 src/utils/ncmpidump/Makefile.in                   |    74 +
 src/utils/ncmpidump/depend                        |     3 +
 src/utils/ncmpidump/dumplib.c                     |   225 +
 src/utils/ncmpidump/dumplib.h                     |    73 +
 src/utils/ncmpidump/ncmpidump.1                   |   200 +
 src/utils/ncmpidump/ncmpidump.c                   |   823 ++
 src/utils/ncmpidump/ncmpidump.h                   |    83 +
 src/utils/ncmpidump/test0.cdl                     |    41 +
 src/utils/ncmpidump/vardata.c                     |   738 +
 src/utils/ncmpidump/vardata.h                     |    28 +
 src/utils/ncmpigen/Makefile.in                    |   179 +
 src/utils/ncmpigen/c0.cdl                         |   331 +
 src/utils/ncmpigen/depend                         |     9 +
 src/utils/ncmpigen/escapes.c                      |    96 +
 src/utils/ncmpigen/generic.h                      |    23 +
 src/utils/ncmpigen/genlib.c                       |  2043 +++
 src/utils/ncmpigen/genlib.h                       |    98 +
 src/utils/ncmpigen/getfill.c                      |   151 +
 src/utils/ncmpigen/init.c                         |    43 +
 src/utils/ncmpigen/load.c                         |   835 ++
 src/utils/ncmpigen/main.c                         |   223 +
 src/utils/ncmpigen/ncmpigen.1                     |   373 +
 src/utils/ncmpigen/ncmpigen.h                     |    57 +
 src/utils/ncmpigen/ncmpigen.l                     |   216 +
 src/utils/ncmpigen/ncmpigen.y                     |  1317 ++
 src/utils/ncmpigen/ncmpigentab.c                  |  1919 +++
 src/utils/ncmpigen/ncmpigentab.h                  |    30 +
 src/utils/ncmpigen/ncmpigenyy.c                   |  2294 +++
 src/utils/ncmpivalid/Makefile.in                  |    65 +
 src/utils/ncmpivalid/depend                       |     1 +
 src/utils/ncmpivalid/ncmpivalid.1                 |    28 +
 src/utils/ncmpivalid/ncmpivalid.c                 |   870 ++
 src/utils/ncoffsets/Makefile.in                   |    38 +
 src/utils/ncoffsets/ncoffsets.1                   |   109 +
 src/utils/ncoffsets/ncoffsets.c                   |  2099 +++
 src/utils/pnetcdf_version/Makefile.in             |    56 +
 src/utils/pnetcdf_version/depend                  |     1 +
 src/utils/pnetcdf_version/pnetcdf_version.1       |    61 +
 src/utils/pnetcdf_version/pnetcdf_version.c       |   107 +
 stamp-h.in                                        |     1 +
 test/C/Makefile.in                                |    76 +
 test/C/pres_temp_4D_rd.c                          |   205 +
 test/C/pres_temp_4D_wr.c                          |   262 +
 test/CXX/Makefile.in                              |    79 +
 test/CXX/nctst.cpp                                |   560 +
 test/CXX/test_classic.cpp                         |    96 +
 test/F90/Makefile.in                              |   142 +
 test/F90/depend                                   |    13 +
 test/F90/f90tst_parallel.f90                      |   169 +
 test/F90/f90tst_parallel2.f90                     |   176 +
 test/F90/f90tst_parallel3.f90                     |   196 +
 test/F90/f90tst_parallel4.f90                     |   105 +
 test/F90/f90tst_vars.f90                          |   139 +
 test/F90/f90tst_vars2.f90                         |   194 +
 test/F90/f90tst_vars3.f90                         |   193 +
 test/F90/f90tst_vars4.f90                         |   131 +
 test/F90/test_intent.f90                          |   150 +
 test/F90/tst_f90.f90                              |   207 +
 test/F90/tst_f90_cdf5.f90                         |    79 +
 test/F90/tst_flarge.f90                           |   102 +
 test/F90/tst_io.f90                               |   176 +
 test/F90/tst_types2.f90                           |   293 +
 test/Makefile.in                                  |   106 +
 test/cdf_format/Makefile.in                       |    77 +
 test/cdf_format/cdf_type.c                        |   126 +
 test/cdf_format/depend                            |     3 +
 test/cdf_format/dim_cdf12.c                       |   202 +
 test/cdf_format/test_cdf1.nc                      |   Bin 0 -> 32 bytes
 test/cdf_format/test_cdf2.nc                      |   Bin 0 -> 32 bytes
 test/cdf_format/test_cdf5.nc                      |   Bin 0 -> 48 bytes
 test/cdf_format/test_inq_format.c                 |   110 +
 test/common/Makefile.in                           |    55 +
 test/common/testutils.c                           |   207 +
 test/common/testutils.h                           |    35 +
 test/common/testutilsf.F90                        |    59 +
 test/fandc/Makefile.in                            |    88 +
 test/fandc/csnap.c                                |   475 +
 test/fandc/depend                                 |     2 +
 test/fandc/fixedform.f90                          |    27 +
 test/fandc/freeform.f                             |    27 +
 test/fandc/pnctest.c                              |    70 +
 test/fandc/pnctestf.f                             |    74 +
 test/fandc/pnf_test.f                             |   696 +
 test/header/Makefile.in                           |    64 +
 test/header/header_consistency.c                  |   621 +
 test/largefile/Makefile.in                        |    86 +
 test/largefile/large_files.c                      |   194 +
 test/largefile/large_var.c                        |   293 +
 test/nc_test/Makefile.in                          |   138 +
 test/nc_test/README                               |     9 +
 test/nc_test/depend                               |    41 +
 test/nc_test/error.c                              |    80 +
 test/nc_test/error.h                              |    37 +
 test/nc_test/nc_test.c                            |   549 +
 test/nc_test/t_nc.c                               |   664 +
 test/nc_test/test_get.m4                          |   958 ++
 test/nc_test/test_iget.m4                         |  1547 ++
 test/nc_test/test_iput.m4                         |  1732 +++
 test/nc_test/test_put.m4                          |  1265 ++
 test/nc_test/test_read.c                          |  1792 +++
 test/nc_test/test_write.c                         |  2185 +++
 test/nc_test/tests.h                              |   793 +
 test/nc_test/tst_atts.c                           |  2246 +++
 test/nc_test/tst_atts3.c                          |   804 ++
 test/nc_test/tst_misc.c                           |   100 +
 test/nc_test/tst_names.c                          |   327 +
 test/nc_test/tst_nofill.c                         |   484 +
 test/nc_test/tst_norm.c                           |   218 +
 test/nc_test/tst_small.c                          |   481 +
 test/nc_test/util.c                               |  1055 ++
 test/nf90_test/Makefile.in                        |    92 +
 test/nf90_test/README                             |     3 +
 test/nf90_test/depend                             |    28 +
 test/nf90_test/fortlib.c                          |   289 +
 test/nf90_test/nf90_error.F90                     |    80 +
 test/nf90_test/nf90_test.F90                      |   849 ++
 test/nf90_test/test_get.m4                        |  1163 ++
 test/nf90_test/test_iget.m4                       |  1018 ++
 test/nf90_test/test_iput.m4                       |  1087 ++
 test/nf90_test/test_put.m4                        |  1518 ++
 test/nf90_test/test_read.F90                      |  1454 ++
 test/nf90_test/test_write.F90                     |  1755 +++
 test/nf90_test/tests.inc                          |   230 +
 test/nf90_test/util.F90                           |  1514 ++
 test/nf_test/Makefile.in                          |    93 +
 test/nf_test/README                               |     9 +
 test/nf_test/depend                               |    31 +
 test/nf_test/fortlib.c                            |   289 +
 test/nf_test/nf_error.F                           |    81 +
 test/nf_test/nf_test.F                            |   861 ++
 test/nf_test/test_get.m4                          |  1149 ++
 test/nf_test/test_iget.m4                         |  1033 ++
 test/nf_test/test_iput.m4                         |  1108 ++
 test/nf_test/test_put.m4                          |  1518 ++
 test/nf_test/test_read.F                          |  1437 ++
 test/nf_test/test_write.F                         |  1740 +++
 test/nf_test/tests.inc.in                         |   234 +
 test/nf_test/util.F                               |  1531 ++
 test/nonblocking/Makefile.in                      |   140 +
 test/nonblocking/README                           |    12 +
 test/nonblocking/bput_varn_uint.c                 |   494 +
 test/nonblocking/column_wise.c                    |   227 +
 test/nonblocking/depend                           |    14 +
 test/nonblocking/flexible_bput.c                  |   270 +
 test/nonblocking/i_varn_indef.c                   |   574 +
 test/nonblocking/i_varn_int64.c                   |   501 +
 test/nonblocking/interleaved.c                    |   195 +
 test/nonblocking/mcoll_perf.c                     |   685 +
 test/nonblocking/mcoll_testf.f90                  |   461 +
 test/nonblocking/mcoll_testf77.f                  |   521 +
 test/nonblocking/req_all.c                        |   157 +
 test/nonblocking/test_bput.c                      |   145 +
 test/nonblocking/test_bputf.f90                   |   175 +
 test/nonblocking/test_bputf77.f                   |   190 +
 test/nonblocking/wait_after_indep.c               |    98 +
 test/subfile/Makefile.in                          |    79 +
 test/subfile/README                               |    15 +
 test/subfile/depend                               |     2 +
 test/subfile/test_subfile.c                       |   417 +
 test/testcases/Makefile.in                        |   251 +
 test/testcases/add_var.c                          |   116 +
 test/testcases/alignment_test.c                   |   295 +
 test/testcases/attrf.f                            |   156 +
 test/testcases/bigrecords.f                       |   338 +
 test/testcases/buftype_free.c                     |   126 +
 test/testcases/buftype_freef.f                    |   169 +
 test/testcases/check_striping.c                   |    99 +
 test/testcases/check_type.c                       |   249 +
 test/testcases/collective_error.c                 |   128 +
 test/testcases/depend                             |    37 +
 test/testcases/flexible.c                         |   205 +
 test/testcases/flexible2.c                        |   279 +
 test/testcases/flexible_varm.c                    |   247 +
 test/testcases/geopotential.ncdump                |    48 +
 test/testcases/inq_num_vars.c                     |   135 +
 test/testcases/inq_num_varsf.f90                  |   166 +
 test/testcases/inq_recsize.c                      |   115 +
 test/testcases/inq_recsizef.f90                   |   142 +
 test/testcases/interop1.sh                        |    37 +
 test/testcases/ivarn.c                            |   447 +
 test/testcases/last_large_var.c                   |   260 +
 test/testcases/modes.c                            |   156 +
 test/testcases/ncmpi_vars_null_stride.c           |    88 +
 test/testcases/noclobber.c                        |    76 +
 test/testcases/nonblocking.c                      |   163 +
 test/testcases/one_record.c                       |   118 +
 test/testcases/put_parameter.f                    |   166 +
 test/testcases/record.c                           |   299 +
 test/testcases/redef-good.ncdump                  |    63 +
 test/testcases/redef1.c                           |   197 +
 test/testcases/redef1.sh                          |    22 +
 test/testcases/test_erange.c                      |   100 +
 test/testcases/test_vard.c                        |   322 +
 test/testcases/test_vardf.F                       |   392 +
 test/testcases/test_vardf90.f90                   |   372 +
 test/testcases/test_varm.c                        |   201 +
 test/testcases/varn_contig.c                      |   240 +
 test/testcases/varn_int.c                         |   320 +
 test/testcases/varn_intf.f                        |   288 +
 test/testcases/varn_real.f90                      |   299 +
 test/testcases/vectors.c                          |   133 +
 474 files changed, 203901 insertions(+)

diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644
index 0000000..0482a47
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,34 @@
+Copyright (c) 2003 Northwestern University and Argonne National Laboratory
+All rights reserved.
+
+Portions of this software were developed by the Unidata Program at the
+University Corporation for Atmospheric Research.
+
+Access and use of this software shall impose the following obligations and
+understandings on the user. The user is granted the right, without any fee or
+cost, to use, copy, modify, alter, enhance and distribute this software, and
+any derivative works thereof, and its supporting documentation for any purpose
+whatsoever, provided that this entire notice appears in all copies of the
+software, derivative works and supporting documentation.  Further, Northwestern
+University and Argonne National Laboratory request that the user credit
+Northwestern University and Argonne National Laboratory in any publications
+that result from the use of this software or in any product that includes this
+software.  The names Northwestern University and Argonne National Laboratory,
+however, may not be used in any advertising or publicity to endorse or promote
+any products or commercial entity unless specific written permission is
+obtained from Northwestern University and Argonne National Laboratory. The user
+also understands that Northwestern University and Argonne National Laboratory
+are not obligated to provide the user with any support, consulting, training or
+assistance of any kind with regard to the use, operation and performance of
+this software nor to provide the user with any updates, revisions, new versions
+or "bug fixes."
+
+THIS SOFTWARE IS PROVIDED BY NORTHWESTERN UNIVERSITY AND ARGONNE NATIONAL
+LABORATORY "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 NORTHWESTERN UNIVERSITY
+AND ARGONNE NATIONAL LABORATORY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ACTION, ARISING OUT OF OR IN CONNECTION WITH THE ACCESS, USE OR PERFORMANCE OF
+THIS SOFTWARE.
diff --git a/CREDITS b/CREDITS
new file mode 100644
index 0000000..1687829
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,34 @@
+Parallel-netCDF is a joint effort between Northwestern University and Argonne
+National Laboratory.  We have also been fortunate to receive a great deal of
+help from the community.  A partial list follows.  Thanks everyone!
+
+- Parallel-NetCDF uses a great deal of NetCDF code, so the project would not
+  have gotten as far as it did as quickly as it did without the efforts of the
+  Unidata group.
+
+- Joachim Worringen <joachim at ccrl-nece.de> and Rene Redler
+  <redler at ccrl-nece.de> helped us build and run correctly on NEC SX-6
+
+- John Tannahill <tannahill1 at llnl.gov> contributed a great deal of effort
+  testing and improving our Fortran bindings
+
+- Richard Hedges <richard-hedges at llnl.gov> was another early adopter and
+  offered a lot of configuration tips, particularly for IFC
+
+- Renier Vogelsang <reiner at sgi.com> provided valuable assistance with the IRIX
+  port
+
+- Greg Sjaardema's <gdsjaar at sandia.gov> CDF-2 patch gave us and serial NetCDF
+  large file support
+
+- Jim Edwards <jedwards at ucar.edu> provided a great deal of assistance with our
+  AIX port, and testing the nonblocking APIs.
+
+- Tyce Mclarty <mclarty3 at llnl.gov> also did a lot of AIX work for us
+
+- Christopher Subich <csubich at math.uwaterloo.ca> contributed several configure
+  fixes, improving our handling of cross-compile environments.
+
+- Kurt Glaesemann <kurt.glaesemann at pnl.gov> contributed numerous cleanups for
+  PnetCDF on ia64 with HP-MPI
+
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..d0eadef
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,319 @@
+PnetCDF Installation Guide
+=====================
+
+1.  Getting Started
+2.  Alternate Configure Options
+3.  Testing the PnetCDF installation
+4.  Reporting Installation or Usage Problems
+
+
+-------------------------------------------------------------------------
+
+1. Getting Started
+==================
+
+The following instructions take you through a sequence of steps to get the
+default configuration of PnetCDF up and running.
+
+(a) You will need the following prerequisites.
+
+    - REQUIRED: This tar file
+
+    - REQUIRED: An MPI C compiler
+
+    - REQUIRED: GNU m4 (https://www.gnu.org/software/m4/m4.html)
+
+    - OPTIONAL: An MPI C++ compiler, if C++ applications are to be used.
+      If you do not require support for C++ applications, you can disable this
+      support using the configure option --disable-cxx (configuring PnetCDF is
+      described in step 1(d) below).
+
+    - OPTIONAL: An MPI Fortran 77 compiler, if Fortran 77 applications are to
+      be used. If you do not require support for Fortran 77 applications, you
+      can disable this support using --disable-fortran (configuring PnetCDF is
+      described in step 1(d) below).
+
+    - OPTIONAL: An MPI Fortran 90 compiler, if Fortran 90 applications are to
+      be used. If you do not require support for Fortran 90 applications, you
+      can disable this support using --disable-fortran. Note that Fortran 77
+      support is a prerequisite for Fortran 90 support (configuring PnetCDF is
+      described in step 1(d) below).
+
+    Also, you need to know what shell you are using since different shell has
+    different command syntax. Command "echo $SHELL" prints out the current
+    shell used by your terminal program.
+
+(b) Unpack the tar file and go to the top level directory:
+
+      gunzip parallel-netcdf-1.6.0.tar.gz
+      tar xf parallel-netcdf-1.6.0.tar
+      cd parallel-netcdf-1.6.0
+
+(c) Choose an installation directory, say $HOME/PnetCDF
+
+(d) Configure PnetCDF specifying the installation directory:
+
+      ./configure --prefix=$HOME/PnetCDF
+
+(e) Build PnetCDF:
+
+      make
+
+   Or if "make" runs slow, try parallel make, e.g. (using 8 simultaneous jobs)
+
+      make -j8
+
+(f) Install PnetCDF
+
+      make install
+
+    If a non-default install directory is desired, use command:
+
+      make install prefix=/OTHER/INSTALL/DIRECTORY
+
+(g) Add the bin subdirectory of the installation directory to your path in your
+    startup script (.bashrc for bash, .cshrc for csh, etc.):
+
+    for csh and tcsh:
+
+      setenv PATH $HOME/PnetCDF/bin:$PATH
+
+    for bash and sh:
+  
+      PATH=$HOME/PnetCDF/bin:$PATH ; export PATH
+
+    Check that everything is in order at this point by doing:
+
+      which ncmpidump
+      which ncmpidiff
+
+    These commands should display the path to your bin subdirectory of your
+    install directory.
+
+If you have completed all of the above steps, you have successfully installed
+PnetCDF.
+
+-------------------------------------------------------------------------
+
+2. Alternate Configure Options
+=================
+
+PnetCDF has a number of configure features.  A complete list of configuration
+options can be found using:
+
+   ./configure --help
+
+Here lists a few important options:
+
+  --prefix=PREFIX         install PnetCDF files in PREFIX [/usr/local]
+  --enable-echo           Turn on strong echoing. [default: disabled]
+  --disable-largefile     omit support for large files
+  --disable-mpi-io-test   Disable check for MPI-IO support in MPI
+                          implementation, if you know your MPI implementation
+                          has MPI-IO support but the configure test fails to
+                          find it. [default: enabled]
+  --disable-cxx           Turn off support for the C++ interface, if you only
+                          need the C interface. [default: enabled]
+  --enable-strict         Turn on strict debugging with gcc. [default:
+                          disabled]
+  --disable-fortran       Turn off support for the Fortran interface, if you
+                          only need the C interface. [default: enabled]
+  --enable-debug          Enable PnetCDF internal debug mode. This also
+                          enables safe mode. [default: disabled]
+  --disable-in-place-swap Disable memory in-place byte swap on Little Endian
+                          machines. [default: enabled]. See note below.
+  --enable-coverage       Compile with coverage support (gcc-based only).
+                          [default: disabled]
+  --disable-subfiling     Turns off subfiling support. [default: disabled]
+  --disable-file-sync     Disable MPI file sync if you know your file system
+                          can provide data consistency. [default: enabled]
+  --enable-large-file-test
+                          Enable testing for large (>4GB) file/variable I/O.
+                          This can run very slow. [default: disabled]
+
+Optional Packages:
+  --with-mpi=/path/to/implementation
+                          installation prefix for MPI implementation
+
+PnetCDF can automatically detect the available MPI compilers and compile flags.
+If alternate compilers or flags are desired, they can be specified by the
+following environment variables and/or configure options.
+
+Some influential environment variables:
+    CFLAGS, CPPFLAGS, CXXFLAGS, FFLAGS, FCFLAGS, LDFLAGS and LIBS
+    Setting these compile flags would result in the PnetCDF library being built
+    with these flags.
+
+    MPICC, MPICXX, MPIF77, MPIF90
+    Setting these variables would result in the PnetCDF library being built
+    with these compilers. CC, CXX, F77, and F90 will be ignored if these MPI
+    variables are present.
+
+    Note the compile flags, such as -O2 or -g, should be given in CFLAGS and
+    other flag environment variables. Please do not set them in compiler
+    variable. For instance, setting MPICC="mpcc -O2" may result in the error
+    of compiler not found.
+
+ - For platform-specific build instructions, see one of the README.<ARCH>
+   files.  
+
+
+----
+Note on configure option "--disable-in-place-swap"
+----
+   This option disables the byte-swap operations running in-place on the user's
+   write buffers.  The purpose of providing this option is to deal with the
+   problem when a Fortran program uses a immutable buffer for put APIs, e.g.
+   the buffer is declared as a PARAMETER, and in-place byte swap on this buffer
+   causes segmentation fault. See discussion threads of
+   http://lists.mcs.anl.gov/pipermail/parallel-netcdf/2013-July/001498.html
+
+   Impacts:
+      1. It takes effect only on Little Endian machines.
+      2. It only affects put/iput data APIs, but not attribute APIs.
+      3. The INTENT of buffer arguments in all Fortran 90 put/iput APIs will be
+         declared as "IN". Without this setting, the default is "INOUT".
+      4. It has an impact on performance, as an extra internal temporary buffer
+         will be allocated to copy data over from user's put buffer, so byte
+         swap can be run on the temporary buffer.
+
+   The default setting is to enable in-place byte swap. PnetCDF tries not to
+   allocate additional memory space, due to performance concern. Users are
+   discouraged to use Fortran PARAMETER buffers in put APIs.
+
+-------------------------------------------------------------------------
+
+3. Testing the PnetCDF installation
+==================================
+
+Two type of testings are implemented in PnetCDF: sequential and parallel.
+For testing sequential programs, the command is
+     make check
+For testing parallel programs, the command is
+     make ptest
+The parallel test uses up to 10 MPI processes.
+
+Command "make tests" will build executables of all the test programs. This can
+be handy if testing must run through a batch job system. Having the testing
+executables built before submitting a batch job could save a lot of time.
+
+There are three environment variables that can be used to run make check/ptest
+on a cross compile platform.
+ - TEST_MPIRUN : command to launch MPI jobs. default: mpiexec
+ - TEST_SEQRUN : command to run MPI executable sequentially. default: ./
+ - TEST_OUTDIR : output directory. default: ./
+
+Examples:
+    make check TEST_OUTDIR=/scratch
+    make ptest TEST_MPIRUN="aprun -n NP" TEST_OUTDIR=/scratch
+
+Note the keyword "NP" used in the environment variable string TEST_MPIRUN.  It
+will be replaced with the different numbers of MPI processes used in testing.
+Currently, the testing uses up to 8 processes. Hence, please make sure the
+process allocation at least contains 8 processes.
+
+One can also run "make ptest" on batch queue systems. One example PBS script is
+provide "pbs.script". It is recommended to build all the testing executables
+before submitting the batch job. This can be done by running the below command.
+    cd test ; make ; cd ../examples ; make ; cd ..
+
+Note on setting TEST_OUTDIR. In order to run parallel test correctly, the
+output directory must be on a file system accessible to all MPI processes.  We
+recommend to use parallel file systems or POSIX compliant file systems (Using
+NFS will most likely fail the parallel test.)
+
+Issue with older MPI-IO implementation.
+    During "make check", one may encounter the following error message:
+    "MPI error (MPI_File_delete) : MPI_ERR_IO: input/output error"
+    This is due to the underneath MPI-IO libraries fail to return the correct
+    error class MPI_ERR_NO_SUCH_FILE when trying to delete a non-existing file.
+    This message can be ignored.
+
+-------------------------------------------------------------------------
+
+4. Reporting Installation or Usage Problems
+===========================================
+
+Please send an email to parallel-netcdf at mcs.anl.gov
+
+
+
+-----------------------------------------------------------------------------
+Notes from previous releases
+-----------------------------------------------------------------------------
+
+To INSTALL parallel netCDF library:
+
+    1. 'autoreconf' (only necessary if you make changes to configure.in or
+        other configure-related files)
+
+    2. ./configure --prefix=<install dir> --with-mpi=/path/to/implementation
+	the --with-mpi argument should specify the prefix of where the mpi
+	implementation was installed.  If your mpicc is in
+	/usr/local/mpich-1.2.3/bin/mpicc then use the prefix
+	--with-mpi=/usr/local/mpich-1.2.3
+
+    NOTE: If configure cannot find your MPI implementation's C and/or
+	  Fortran compilers, define MPICC, MPICXX, MPIF77 and MPIF90
+	  environment variables to be the name of those compilers.  The
+	  configure script will then use those values instead of trying
+	  to guess.
+
+    3. make 
+
+       We have tried to make the Makefiles platform-independent.
+       However, each platform has its own make quirks:  if you run into
+       problems, please send a report to the developers at
+       parallel-netcdf at mcs.anl.gov.  If you have GNU Make, try using
+       that.
+
+    4. make install
+
+IF THIS DOESN'T WORK:
+
+Autoconf should do the right thing: using the system compiler to perform
+autoconf tests and then use the MPI compilers to build parallel-netcdf.
+If you need to set specific flags for a platform, and autoconf does not
+set them for you, then you will have to set some environment variables
+to help out the configure script.   Here are some suggested settings:
+
+       For Solaris
+            MPICC=mpicc
+
+       For SGI Origin2000
+            MPICC = mpicc
+            ------------ OR -------------
+            CC='/bin/cc -64 -mips4 -lmpi'
+            CPPFLAGS=-DNDEBUG
+            CFLAGS=-O
+            FC='/bin/f90 -64'
+            FFLAGS=-O
+            F90='/bin/f90 -64'
+            CXX='/bin/CC -64'
+            CXXFLAGS=-O
+
+       For Linux
+            MPICC=mpicc
+            CPPFLAGS='-DNDEBUG -Df2cFortran'
+            CFLAGS=-O
+            CXX=g++
+            FFLAGS='-O -W'
+
+       For IBM SP-2
+            MPICC mpcc_r
+            MPIF77 /bin/mpxlf_r
+            F90 /bin/mpxlf90_r
+            F90FLAGS -qsuffix=f=f90
+            CXX /bin/mpxlC_r
+            ------------- OR -------------
+            CC xlc
+            FC /bin/xlf
+            F90 /bin/xlf90
+            F90FLAGS -qsuffix=f=f90
+            CXX /bin/xlC
+                then manually edit macros.make:
+            CC = mpcc_r
+            FC = mpxlf_r
+            F90 = mpxlf90_r
+            F90FLAGS = -qsuffix=f=f90
+            CXX = mpxlC_r
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..5edbea0
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,242 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2298 2016-01-07 07:33:10Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include macros.make
+
+PACKAGE_NAME      = @PACKAGE_NAME@
+PACKAGE_VERSION   = @PACKAGE_VERSION@
+PACKAGE_STRING    = @PACKAGE_STRING@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+
+PACKAGE_FILENAME  = $(PACKAGE_NAME)-$(PACKAGE_VERSION)
+
+INSTALL_SUBDIRS	= src man
+
+SUBDIRS		= src \
+		  test \
+		  scripts \
+		  doc \
+		  man \
+		  benchmarks \
+		  examples
+
+GARBAGE		=
+
+DIST_GARBAGE	= config.cache \
+		  config.status \
+		  config.log \
+		  macros.make \
+		  stamp-h
+
+PACKING_LIST	= Makefile.in \
+		  aclocal.m4 \
+		  configure \
+		  configure.in \
+		  macros.make.in \
+		  rules.make \
+		  COPYRIGHT \
+		  CREDITS \
+		  INSTALL \
+		  README \
+		  README.CRAY \
+		  README.IBM \
+		  README.LINUX \
+		  README.SGI \
+		  README.SX \
+		  README.large_files \
+		  RELEASE_NOTES \
+		  pbs.script \
+		  cobalt.script \
+		  stamp-h.in
+
+PACKING_SUBDIRS	= $(SUBDIRS)
+
+all:
+	$(MAKE) $(MFLAGS) -C src
+
+TESTS_SUBDIRS = test examples benchmarks
+TESTS_DIRS = $(TESTS_SUBDIRS:%=tests-%)
+tests: $(TESTS_DIRS)
+$(TESTS_DIRS): 
+	$(MAKE) $(MFLAGS) -C $(@:tests-%=%)
+
+check testing:
+	$(MAKE) $(MFLAGS) -C test testing
+
+verbose_check verbose_testing:
+	$(MAKE) $(MFLAGS) -C test verbose_testing
+
+PTEST_SUBDIRS = test examples benchmarks
+PTEST_DIRS = $(PTEST_SUBDIRS:%=ptest-%)
+ptest: tests $(PTEST_DIRS)
+$(PTEST_DIRS): 
+ifeq (@enable_coverage@, yes)
+	echo "Parallel test is disabled because coverage analysis was enabled"
+else
+	$(MAKE) $(MFLAGS) -C $(@:ptest-%=%) ptest
+endif
+# make sure ptest runs one directory after another
+ptest-examples: ptest-test
+ptest-benchmarks: ptest-examples
+
+PTESTS_DIRS = $(PTEST_SUBDIRS:%=ptests-%)
+ptests: tests $(PTESTS_DIRS)
+$(PTESTS_DIRS): 
+ifeq (@enable_coverage@, yes)
+	echo "Parallel test is disabled because coverage analysis was enabled"
+else
+	$(MAKE) $(MFLAGS) -C $(@:ptests-%=%) ptests
+endif
+# make sure ptests runs one directory after another
+ptests-examples: ptests-test
+ptests-benchmarks: ptests-examples
+
+INSTALLDIRS = $(INSTALL_SUBDIRS:%=install-%)
+install: $(INSTALLDIRS)
+	@echo '+----------------------------------------------------------------------------+'
+	@echo '|'
+	@echo '|  PnetCDF has been successfully installed under $(prefix)'
+	@echo '|'
+	@echo '|  * PnetCDF header files are installed in $(prefix)/include'
+	@echo '|  * PnetCDF library file is installed in $(prefix)/lib'
+	@echo '|  * PnetCDF utility programs are installed in $(prefix)/bin'
+	@echo '|  * PnetCDF man pages are installed in $(prefix)/man/man1 and'
+	@echo '|    $(prefix)/man/man3'
+	@echo '|'
+	@echo '|  To compile your PnetCDF programs, please add the following to the command'
+	@echo '|  line, so the compiler can find the PnetCDF header files:'
+	@echo '|      -I$(prefix)/include'
+	@echo '|'
+	@echo '|  Add the following line to link your program to PnetCDF library:'
+	@echo '|      -L$(prefix)/lib -lpnetcdf'
+	@echo '|'
+	@echo '|  PnetCDF is jointly developed by a team at Northwestern University and'
+	@echo '|  Argonne National Laboratory.'
+	@echo '|'
+	@echo '|  Vist PnetCDF web sites for more information'
+	@echo '|      http://cucis.ece.northwestern.edu/projects/PnetCDF'
+	@echo '|      http://trac.mcs.anl.gov/projects/parallel-netcdf'
+	@echo '|'
+	@echo '+----------------------------------------------------------------------------+'
+
+$(INSTALLDIRS): 
+	$(MAKE) $(MFLAGS) -C $(@:install-%=%) install
+
+UNINSTALLDIRS = $(INSTALL_SUBDIRS:%=uninstall-%)
+uninstall: $(UNINSTALLDIRS)
+$(UNINSTALLDIRS): 
+	$(MAKE) $(MFLAGS) -C $(@:uninstall-%=%) uninstall
+
+################################################################################
+# Distribution:
+
+# The following rule checks to see that were on the right system.  If we're
+# not, then the distribution mightn't contain the intended ncgen(1) (not
+# to mention that dvips(1) is necessary for building the C++ User's Guide).
+#
+check_system:	FORCE
+	@case "$(OVERRIDE)" in \
+	'') case `uname -sr` in \
+	    'SunOS 5'*) \
+		exit 0;; \
+	    *)  echo 1>&2 "Error: Not on a SunOS 5 system."; \
+		echo 1>&2 "Set macro OVERRIDE to override."; \
+		exit 1;; \
+	    esac;; \
+	*) exit 0;; \
+	esac
+
+# Make a compressed, tar(1) file of the source distribution in the current 
+# directory.
+#
+tar.Z:		check_system FORCE
+	$(MAKE) $(MFLAGS) $(PACKAGE_FILENAME).tar.Z
+
+dist: ensure_manifest MANIFEST
+	id=$(PACKAGE_FILENAME) \
+	&& $(RM) -fr $$id \
+	&& $(LN_S) $(srcdir) $$id \
+	&& tar $(TARFLAGS) - `$(SED) "s|^|$$id/|" MANIFEST` | gzip  > $(PACKAGE_FILENAME).tar.gz \
+	&& tar $(TARFLAGS) - `$(SED) "s|^|$$id/|" MANIFEST` | bzip2 > $(PACKAGE_FILENAME).tar.bz2 \
+	&& $(RM) -f $$id MANIFEST
+
+MANIFEST:	FORCE
+	$(MAKE) $(MFLAGS) -s MANIFEST.echo >$@
+
+# Make a compressed, tar(1) file of the source distribution in the
+# appropriate FTP directory.
+#
+# NOTE: Making "ftp" will cause the "tar.Z" file to be made even if it
+# already exists.  This is because the MANIFEST file upon which it
+# depends must be remade every time.  This is not a waste of time,
+# however, if the "tar.Z" target is made in private directories and the
+# "ftp" target is made in the "/upc/$(PACKAGE_FILENAME)/build/" directory.
+#
+ftp:		check_system FORCE
+	$(MAKE) $(MFLAGS) $(FTPDIR)/$(PACKAGE_FILENAME).tar.Z \
+	test -r $(FTPDIR)/$(PACKAGE_FILENAME).tar.Z || exit 0; \
+	    cd $(FTPDIR) || exit 1;
+
+$(FTPDIR)/$(PACKAGE_FILENAME).tar.Z:	$(PACKAGE_FILENAME).tar.Z
+	$(RM) -f $@
+	cp $(PACKAGE_FILENAME).tar.Z $@ 
+	chmod u+rw,g+rw,o=r $@
+
+# Make a compressed, tar(1) file of the binary distribution in the 
+# appropriate FTP directory.
+#
+binftp:		FORCE
+	$(MAKE) $(MFLAGS) $(FTPBINDIR)/$(PACKAGE_FILENAME).tar.Z \
+
+ftpbin:		binftp
+
+$(FTPBINDIR)/$(PACKAGE_FILENAME).tar.Z:
+	$(RM) -f $@
+	id=$(PACKAGE_FILENAME) \
+	&& $(RM) -f $$id \
+	&& $(LN_S) $(prefix) $$id \
+	&& tar $(TARFLAGS) - README $$id/bin $$id/include \
+	    $$id/lib $$id/man | compress > $@ \
+	&& $(RM) -f $$id
+	chmod u+rw,g+rw,o=r $@
+	test -r $(FTPBINDIR)/$(PACKAGE_FILENAME).tar.Z || exit 0; \
+	    cd $(FTPBINDIR) || exit 1;
+
+
+# rule for generating cscope information
+cscope:
+	find $(srcdir) -iname "*.[ch]" > $(srcdir)/cscope.files
+	( cd $(srcdir); cscope -be -i $(srcdir)/cscope.files )
+
+# The following dependency is for configure.in and configure
+# See autoconf manual 2.69, Section 4.8.5 Automatic Remaking
+$(srcdir)/configure: configure.in aclocal.m4
+	cd '$(srcdir)' && autoconf
+     
+# autoheader might not change src/lib/ncconfig.h.in so touch a stamp file.
+$(srcdir)/src/lib/ncconfig.h.in: stamp-h.in
+$(srcdir)/stamp-h.in: configure.in aclocal.m4
+	cd '$(srcdir)' && autoheader
+	echo timestamp > '$(srcdir)/stamp-h.in'
+     
+src/lib/ncconfig.h: stamp-h
+stamp-h: src/lib/ncconfig.h.in config.status
+	./config.status
+     
+Makefile: Makefile.in config.status
+	./config.status
+     
+config.status: configure
+	./config.status --recheck
+
+include $(srcdir)/rules.make
+
+
diff --git a/README b/README
new file mode 100644
index 0000000..cfed149
--- /dev/null
+++ b/README
@@ -0,0 +1,55 @@
+
+Parallel netCDF (PnetCDF) is a library providing high-performance parallel I/O
+while still maintaining file-format compatibility with Unidata's NetCDF,
+specifically the CDF and CDF-2 formats. Although NetCDF supports parallel I/O
+starting from version 4, the files must be in HDF5 format. PnetCDF is currently
+the only choice for carrying out parallel I/O on files that are in classic
+formats (CDF-1 and 2).
+
+In addition, PnetCDF supports the CDF-5 file format, an extension of CDF-2,
+that supports more data types and allows users to define large dimensions,
+attributes, and variables (>2B elements).
+
+NetCDF gives scientific programmers a space-efficient and portable means for
+storing data. However, it does so in a serial manner, making it difficult to
+achieve high I/O performance. By making some small changes to the NetCDF APIs,
+PnetCDF can use MPI-IO to achieve high-performance parallel I/O.
+
+More extensive installation guides can be found in file INSTALL.  Additional
+information regarding the contents of the release can be found in
+the RELEASE_NOTES file in the top-level directory.  Finally, the PnetCDF web
+site,
+    http://trac.mcs.anl.gov/projects/parallel-netcdf
+contains information on bug fixes and new releases.
+
+
+Requirements:
+
+    - Parallel-NetCDF relies on MPI-IO.  ROMIO, the most common MPI-IO
+      implementation, can make use of a prefix in front of the file name to
+      specify the underlying file system and override ROMIO's auto detection. A
+      typical prefix would look like "nfs:" or "pvfs2:".  Bear this in mind if
+      you use a file name with ':' characters.  In some cases, ROMIO might
+      think you are passing in a prefix and will complain about an unsupported
+      file system type.  If that happens, add a file-system prefix to your file
+      name.   
+      
+    - To build parallel-netcdf you will need some additional programs:
+        - either yacc or bison
+	- either lex or flex
+      These are usually part of your operating system's development tools.
+
+
+Note on supporting large files and large variables.
+
+    - Fortran routines will pass in a 64 bit integer for some parameters (those
+      corresponding to MPI_Offset type in the C routines).  Declare those
+      parameters as 'integer(kind=MPI_OFFSET_KIND)'
+
+    - In places where you might use NF_UNLIMITED to define an unlimited 
+      dimension in one of the nfmpi_ routines, use NFMPI_UNLIMITED. 
+      NFMPI_UNLIMITED will be defined as the proper type for nfmpi_def_dim, 
+      whereas nf_unlimited might be too small. Similarly, for Fortran 90,
+      use NF90MPI_UNLIMITED instead of NF90_UNLIMITED.
+
+Please send an email to parallel-netcdf at mcs.anl.gov
diff --git a/README.CRAY b/README.CRAY
new file mode 100644
index 0000000..5c3094c
--- /dev/null
+++ b/README.CRAY
@@ -0,0 +1,110 @@
+# $Id: README.CRAY 1605 2014-05-01 20:22:23Z wkliao $
+
+===============================================================================
+    Cray XC30
+===============================================================================
+
+Building PnetCDF on the Cray XC30 (tested on Edison @ NERSC)
+http://www.nersc.gov/systems/edison-cray-xc30/
+
+The configure options are the same as Cray XE6, except when using the Intel
+compiler (the default on Edison) with optimization flag "-fast". According
+to the NERSC URL below, the flag "-no-ipo" must be used together with flag
+"-fast" to build a library.
+http://www.nersc.gov/users/software/compilers/intel-fortran-c-and-c/
+
+./configure --prefix=/path/to/install \
+            --with-mpi=/path/to/mpi/implementation \
+            CFLAGS="-fast -no-ipo" CXXFLAGS="-fast -no-ipo" \
+            FFLAGS="-fast -no-ipo" FCFLAGS="-fast -no-ipo"
+
+
+Note if running make is slow, try parallel make, e.g.
+
+    make -j8
+
+===============================================================================
+    Cray XE6
+===============================================================================
+
+Building PnetCDF on the Cray XE6 (tested on Hopper @ NERSC)
+http://www.nersc.gov/systems/hopper-cray-xe6/
+
+./configure --prefix=/path/to/install \
+            --with-mpi=/path/to/mpi/implementation \
+            CFLAGS=-fast CXXFLAGS=-fast FFLAGS=-fast FCFLAGS=-fast
+
+
+The configure command above works for PGI, GNU, and Intel
+compilers, i.e. when one of the module load commands below is used:
+
+    module load PrgEnv-pgi
+    module load PrgEnv-gnu
+    module load PrgEnv-intel
+
+
+For Pathscale compilers, i.e.
+    module load PrgEnv-pathscale
+    use command below:
+    ./configure --prefix=/path/to/install \
+                --with-mpi=/path/to/mpi/implementation \
+                CFLAGS=-Ofast CXXFLAGS=-Ofast FFLAGS=-Ofast FCFLAGS=-Ofast
+
+
+For Cray compilers, i.e.
+    module load PrgEnv-cray
+    use command below:
+    ./configure --prefix=/path/to/install \
+                --with-mpi=/path/to/mpi/implementation \
+                CFLAGS=-O2 CXXFLAGS=-O2 FFLAGS=-O2 FCFLAGS="-O2 -emf" \
+                LDFLAGS=-Wl,-z,muldefs
+
+    Check crayftn man page for using option "-emf" in FCFLAGS:
+    to creates .mod files to hold module and allows the creation
+    of lower-case module .mod file names.
+
+    Option "-Wl,-z,muldefs" in LDFLAGS is to get around the
+    error of multiple definitions of `tc_version', etc.
+
+
+===============================================================================
+    Cray X1
+===============================================================================
+
+2 May 2005
+
+I performed the following steps to get Parallel-NetCDF to build on the Cray X1
+at Oak Ridge (phoenix.ccs.ornl.gov).   Note that out-of-tree (or VPATH) builds
+do not work for the Fortran interface as of 1.0.0-pre2, but we will try to
+address this issue in a future release.  
+
+prompt:$ module load mpt
+prompt:$ export CC=cc
+prompt:$ export FC=ftn
+prompt:$ export MPIF77=$FC
+prompt:$ export MPICC=$CC
+prompt:$ export FFLAGS="-eh"
+prompt:$ ./configure --prefix=/path/to/install
+# note: configure takes a fairly long time. 
+prompt:$ make
+
+The "nc_test" test will exhaust the available MPI datatypes on the X1.  Your
+application might see this error:
+
+   MPI has run out of internal datatype entries.                  
+   Please set the environment variable MPI_TYPE_MAX for additional space.
+   The current value of MPI_TYPE_MAX is 2098                      
+
+I did as asked and nc_test completed with MPI_TYPE_MAX set to 4096
+
+If you run on the login node, expect to see a lot of these messages:
+
+  Process [nc_test] 89345 generated trap, but has signal 8 held or ignored
+        epc 0x1219bb4 ra 0x1219b94 badvaddr 0x40004f0004000020 
+
+The messages don't *appear* to impact the program results, and additionally do
+not show up if you submit the job to PBS.
+
+Fortran codes should use '-eh' so that the Cray ftn compiler will use 1 byte
+for int*1 and 2 bytes for int*2.  Otherwise, our Fortran bindings will pass
+incorrect values to the C routines.   
diff --git a/README.IBM b/README.IBM
new file mode 100644
index 0000000..3c4af3b
--- /dev/null
+++ b/README.IBM
@@ -0,0 +1,269 @@
+# $Id: README.IBM 1741 2014-08-23 16:13:13Z wkliao $
+
+1. Building PnetCDF on BGQ
+2. Building PnetCDF on BGP
+3. Building PnetCDF on BGL
+4. Building PnetCDF on UCAR BlueFire
+5. Building PnetCDF on IBM SP
+
+-------------------------------------------------------------------------------
+1. Building PnetCDF on BGQ
+-------------------------------------------------------------------------------
+
+Building for BGQ is not so different from BGP or BGL: front end node is still a
+cross compile host for the back end.    (as of this writing, the "log in io
+nodes", a.k.a lion nodes, are not on line for the Mira BGQ machine)
+
+Be sure to run configure with the --build and --host flags to put it in "cross
+compile mode".  This will make configure use compile-only tests, instead of the
+usual compile-and-run tests (running tests on the BGP login node won't work as
+the compute nodes are totally different.  This will change if/when lion
+nodes are available).
+
+./configure --host powerpc64-bgq-linux --build ppc64-redhat-linux \
+            MPICC=mpicc MPICXX=mpicxx MPIF77=mpif77 MPIF90=mpif90
+
+Note if running make is slow, try parallel make, e.g.
+
+    make -j8
+
+It's possible to build PnetCDF with the IBM xl compilers:
+
+./configure --host powerpc64-bgq-linux --build ppc64-redhat-linux \
+            --with-mpi=/bgsys/drivers/ppcfloor/comm/xl \
+            MPICC=mpixlc MPICXX=mpixlcxx MPIF77=mpixlf77 MPIF90=mpixlf90 \
+            FFLAGS="-qsuppress=cmpmsg" FCFLAGS="-qsuppress=cmpmsg"
+
+Fortran flag "-qsuppress=cmpmsg" can suppresses XLF compile informational
+messages that report compilation progress and a successful completion.
+
+
+Another possibility that uses thread-safe XL compilers is:
+
+./configure --host powerpc64-bgq-linux --build ppc64-redhat-linux \
+            --with-mpi=/bgsys/drivers/ppcfloor/comm/xl \
+            MPICC=mpixlc_r    MPICXX=mpixlcxx_r \
+            MPIF77=mpixlf77_r MPIF90=mpixlf90_r \
+            CFLAGS=-O2 CXXFLAGS=-O2 FFLAGS=-O2 FCFLAGS=-O2 \
+            --prefix=/path/to/install
+
+
+As far as we know, there are no issues with PnetCDF on BGQ, but should you
+find any, email parallel-netcdf at mcs.anl.gov
+
+----
+Note on compiling Fortran 90 programs on Intrepid @ ANL
+----
+https://www.alcf.anl.gov/user-guides/bgp-faqs-compiling-and-linking#how-do-i-use-xlf-and-"use-mpi"
+
+If you attempt to do a "use mpi" from XL Fortran, and build with the default
+compiler wrappers, you will encounter this error:
+
+  XL Fortran90 error: Module symbol file for module mpi is in a format not
+recognized by this compiler
+
+The cause of the error is that the mpi.mod referenced in the "default" software
+stack (/bgsys/drivers/ppcfloor/comm/default) is built with GNU Fortran.
+
+A work-around to the problem using mpif.h instead of "use mpi.mod", e.g.:
+
+program test
+include "mpif.h"
+
+... your MPI stuff ...
+
+end program test
+
+The proper solution is to use an alternate software stack with MPI built using
+the XL compilers instead of the GNU compilers, thus containing a Fortran mpi
+module (mpi.mod) generated by XLF. This software stack was introduced in
+V1R4M1. You may build with it using the wrappers in comm/xl:
+
+ /bgsys/drivers/ppcfloor/comm/xl/bin/mpixlf90
+
+
+----
+* Note on running PnetCDF testing programs on Mira/Cetus @ ALCF, ANL
+----
+Mira and Cetus are IBM BlueGene Q, a cross-compile system. Hence, one cannot
+run PnetCDF test programs on the login nodes. Test programs must run on the
+compute nodes through submitting a batch job. An example batch script file is
+provided in cobalt.script. The submission command for allocating 8 node with 90
+minutes is given below. Note the testing requires at least 8 MPI processes and
+in this example the command requests 8 nodes and the script runs 1 MPI process
+per node.
+
+qsub -A YOUR_ACCOUNT -n 8 -t 30 --mode script ./cobalt.script
+
+Running "make testing" can take a while (more than one hour on Mira/Cetus).
+This is because the testing performs many small read/write requests and under
+BlueGene's I/O forwarding architecture, local file-system caching is not
+available on the compute nodes.
+
+Running "make ptest" will take approximately 10 minutes.
+
+-------------------------------------------------------------------------------
+2. Building PnetCDF on BGP
+-------------------------------------------------------------------------------
+
+Building for BGP is not so different from BGL: front end node is still a cross
+compile host for the back end.  
+
+Be sure to run configure with the --build and --host flags to put it in "cross
+compile mode".  This will make configure use compile-only tests, instead of the
+usual compile-and-run tests (running tests on the bgp login node won't work as
+the compute nodes are totally different).
+
+There is one run-time check for MPI-IO support of resized types. Unfortunately
+we have to test for this with a runtime test, but you can set the environment
+variable "ac_cv_MPI_TYPE_RESIZED_WORKS" . 
+
+./configure --host powerpc-bgp-linux --build powerpc64-suse-linux \
+            --with-mpi=/bgsys/drivers/ppcfloor/comm
+
+It's possible to build PnetCDF with the IBM xl compilers:
+
+./configure --host powerpc-bgp-linux --build powerpc64-suse-linux \
+            --with-mpi=/bgsys/drivers/ppcfloor/comm/xl \
+            MPICC=mpixlc MPICXX=mpixlcxx MPIF77=mpixlf77 MPIF90=mpixlf90 \
+            FFLAGS="-qsuppress=cmpmsg" FCFLAGS="-qsuppress=cmpmsg"
+
+Fortran flag "-qsuppress=cmpmsg" can suppresses XLF compile informational
+messages that report compilation progress and a successful completion.
+
+As far as we know, there are no issues with PnetCDF on BGP, but should you
+find any, email parallel-netcdf at mcs.anl.gov
+
+----
+Note on compiling Fortran 90 programs on Intrepid @ ANL
+----
+https://www.alcf.anl.gov/user-guides/bgp-faqs-compiling-and-linking#how-do-i-use-xlf-and-"use-mpi"
+
+If you attempt to do a "use mpi" from XL Fortran, and build with the default
+compiler wrappers, you will encounter this error:
+
+  XL Fortran90 error: Module symbol file for module mpi is in a format not
+recognized by this compiler
+
+The cause of the error is that the mpi.mod referenced in the "default" software
+stack (/bgsys/drivers/ppcfloor/comm/default) is built with GNU Fortran.
+
+A work-around to the problem using mpif.h instead of "use mpi.mod", e.g.:
+
+program test
+include "mpif.h"
+
+... your MPI stuff ...
+
+end program test
+
+The proper solution is to use an alternate software stack with MPI built using
+the XL compilers instead of the GNU compilers, thus containing a Fortran mpi
+module (mpi.mod) generated by XLF. This software stack was introduced in
+V1R4M1. You may build with it using the wrappers in comm/xl:
+
+ /bgsys/drivers/ppcfloor/comm/xl/bin/mpixlf90
+
+
+-------------------------------------------------------------------------------
+3. Building PnetCDF on BGL
+-------------------------------------------------------------------------------
+
+Be sure to run configure with the --build and --host flags to put it in "cross
+compile mode".  This will make configure use compile-only tests, instead of the
+usual compile-and-run tests (running tests on the bgl login node won't work as
+the compute nodes are totally different).
+
+configure --build powerpc32-unknown-gnu --host powerpc-suse-linux  \
+          --with-mpi=/bgl/BlueLight/ppcfloor/bglsys/
+
+It's possible to build PnetCDF with the IBM xl compilers, but you have to set
+quite a few environment variables
+
+export CC=blrts_xlc
+export MPICC=blrts_xlc
+export CXX=blrts_xlC
+export MPICXX=blrts_xlC
+export FC=blrts_xlf
+export F77=blrts_xlf
+export MPIF77=blrts_xlf
+
+export CFLAGS="-I/bgl/BlueLight/ppcfloor/bglsys/include"
+export LIBS="-L/bgl/BlueLight/ppcfloor/bglsys/lib -lmpich.rts -lmsglayer.rts -ldevices.rts -lrts.rts -ldevices.rts -lrts.rts"
+
+configure --build powerpc32-unknown-gnu --host powerpc-suse-linux
+
+Several early versions of IBM's MPI-IO implementation would segfault under
+certain workloads.  If you are running driver version "V1R3M0_240_2006-060623"
+or newer, the segfault issue should be resolved.  If you are running an older
+driver, read on:
+
+When built against some older BlueGene drivers,  nc_test does not run
+completely without setting a special environment variable, hitting a seg fault
+deep inside ROMIO.  We first noticed this in IBM's "Driver 202" MPI and also in
+"V1R1M1_253_2005-051003" and "V1R2M1_020_2006-060110"  We have told IBM
+developers about the problem.  Code that makes use of the ncmpi_get_vara_*_all
+or ncmpi_put_vara_*_all routines will likely trigger a seg fault.  IBM has
+provided a workaround:  if your code seg-faults, try setting the
+"BGLMPIO_TUNEBLOCKING" environment variable to 0.  With this environment
+variable set, nc_tests runs to completion and passes.  For one real-world
+example, the FLASH-IO benchmark with 8 processors sees a 5% performance hit
+when writing out plotfiles.  That increases to 22% with 16 processors.   Again, upgrading to the latest BlueGene drivers should fix this issue.
+
+
+
+-------------------------------------------------------------------------------
+4. Building PnetCDF on UCAR BlueFire
+-------------------------------------------------------------------------------
+
+- the nc_test and nf_test tests use M4 to generate code.  AIX-m4 won't
+  generate correct code, so use gnu M4.
+
+- We had a report of a build failure when building the 'ncmpigen' utility.  The
+  system 'bison' tool (bison-1.875) did not produce output files, but when the
+  user installed a new version of gnu bison, everything worked fine.   
+
+- the PnetCDF code is slowly taking on more and more c99 features.  
+
+On BlueFire, the commands I used look like this:
+
+$ module add m4-1.4.14
+
+$ configure --prefix=/path/to/install \
+        CFLAGS=-qlanglvl=stdc99 \
+        CC=xlc FC=xlf F77=xlf F90=xlf90 \
+        MPICC=mpcc_r MPIF77=mpxlf_r MPIF90=mpxlf90_r CXX=xlC MPICXX=mpCC_r
+
+
+-------------------------------------------------------------------------------
+5. Building PnetCDF on IBM SP
+-------------------------------------------------------------------------------
+# John Tannahill <tannahill1 at llnl.gov> reported success building
+# parallel-netcdf on the 'seaborg' cluster (an IBM-SP at NERSC) and Tyce
+# Mclarty <mclarty3 at llnl.gov> reported success on LLNL's 'frost' cluster by
+# setting these environment variables:
+
+   setenv MPICC  mpcc_r
+   setenv MPIF77 mpxlf_r
+   setenv F77    xlf
+   setenv FC     xlf
+   setenv CC     xlc
+   setenv CXX    xlC
+
+# after setting these variables, configure/make/make install should "just work"
+
+
+# We also successfully tested 64-bit mode on 'DataStar' (an IBM-SP at SDSC)
+# with environment variables:
+
+   setenv OBJECT_MODE 64
+   setenv MPICC  mpcc_r
+   setenv MPIF77 mpxlf_r
+   setenv F77    xlf
+   setenv FC     xlf
+   setenv CC     xlc
+   setenv CXX    xlC
+   setenv CFLAGS -q64
+   setenv FFLAGS -q64
+   setenv F90FLAGS -q64
+   setenv CXXFLAGS -q64
diff --git a/README.LINUX b/README.LINUX
new file mode 100644
index 0000000..4ee9afe
--- /dev/null
+++ b/README.LINUX
@@ -0,0 +1,62 @@
+# $Id: README.LINUX 2082 2015-08-22 00:01:53Z wkliao $
+
+
+-----------------------------------------------------------------------------
+ Linux cluster using Intel compilers
+-----------------------------------------------------------------------------
+
+# here are the steps John Tannahill <tannahill1 at llnl.gov> used when
+# building PnetCDF on the "mcr" cluster at LLNL.  It is a Linux cluster
+# with the Intel compilers.
+
+   setenv MPICC  mpiicc
+   setenv MPIF77 mpiifc
+   setenv F77    ifc
+   setenv FC     ifc
+   setenv CC     icc
+
+# then run the usual "configure; make ; make install"
+
+On 5 October 2005, Richard Hedges reported that FFLAGS and CFLAGS needed the -O
+and -mp options or the test suite would report errors in the
+n[c,f]mpi_put_var*_float routines:
+
+FFLAGS = -O -mp
+CFLAGS = -O -mp
+
+
+-----------------------------------------------------------------------------
+ Jazz, a Linux cluster @ANL using Intel compilers
+-----------------------------------------------------------------------------
+# ;cat ~/.soft
+# # 
+# # This is the .soft file.
+# # It is used to customize your environment by setting up environment
+# # variables such as PATH and MANPATH.
+# # To learn what can be in this file, use 'man softenv'.
+# #
+# #
+# @default
+# +pbs
+# +intel-7.0
+# 
+# ---
+# 
+# ;which mpicc
+# /soft/apps/packages/mpich-gm-1.2.5..9-pre6-gm-1.6.3-intel-7.0/bin/mpicc
+# ;which mpif77
+# /soft/apps/packages/mpich-gm-1.2.5..9-pre6-gm-1.6.3-intel-7.0/bin/mpif77
+# ;which icc
+# /soft/com/packages/intel-7/compiler70/ia32/bin/icc
+# ;which ifc
+# /soft/com/packages/intel-7/compiler70/ia32/bin/ifc
+# 
+# ---
+
+setenv CC icc
+setenv FC ifc
+setenv F90 ifc
+setenv CXX icc
+setenv MPICC mpicc
+setenv MPIF77 mpif77
+
diff --git a/README.SGI b/README.SGI
new file mode 100644
index 0000000..88d6f96
--- /dev/null
+++ b/README.SGI
@@ -0,0 +1,46 @@
+# $Id: README.SGI 2082 2015-08-22 00:01:53Z wkliao $
+
+===============================================================================
+    SGI UV 2000
+===============================================================================
+Endeavour @ NASA
+http://www.nas.nasa.gov/hecc/resources/endeavour.html
+
+There are 2 compilers available on Endeavour: Intel and GNU.
+Intel compiler is recommended.
+
+To use Intel compiler, run command below to load the Intel compiler module.
+
+module load comp-intel
+module load mpi-intel
+
+run configure command:
+
+./configure --prefix=/path/to/install \
+            MPICC=icc MPICXX=icpc MPIF77=ifort MPIF90=ifort \
+            CFLAGS="-O2" FFLAGS="-O2" FCFLAGS="-O2" \
+            LIBS=-lmpi LDFLAGS=
+
+* Some users have their environment variable LDFLAGS set to "-shared",
+  which can prevent PnetCDF to build correctly. Please note PnetCDF
+  currently supports to build a static library only.
+
+It is also possible to build PnetCDF with GNU-based MPI compilers on Endeavour.
+Here is configure command.
+
+./configure --prefix=/path/to/install \
+            CFLAGS="-O2" FFLAGS="-O2" FCFLAGS="-O2" \
+            LDFLAGS=
+
+
+===============================================================================
+    SGI IRIX64
+===============================================================================
+The PnetCDF library should build fine under IRIX.  There are just a few
+issues not directly related to the library:
+
+. The IRIX compiler does not like the cnap.c test.  gcc compiles the
+  file without any warnings, even when the tests are configured with
+  "--enable-strict".  Renier Vogelsang <reiner at sgi.com> reports that the
+  latest MIPSpro compiler release fixes this issue, so upgrade if
+  possible.
diff --git a/README.SX b/README.SX
new file mode 100644
index 0000000..5bee293
--- /dev/null
+++ b/README.SX
@@ -0,0 +1,37 @@
+# Current notes for NEC SX; based on pnetcdf version 1.0.0; 28 July, 2005
+
+. SX Cross compiler environment is not supported yet (the check for a working
+  ftruncate is not possible). Configure steps have to be invoked on the SX directly.
+  Configuring on the target host and then cross-compiling works fine when setting
+  up necessary aliases on the configure host (cc -> sxcc, etc) or vice versa 
+  on the compile host (sxcc -> cc).
+
+. With the following environment variables a libpnetcdf.a has been
+  built successfully
+
+    MPICC=mpic++
+    MPIF77=mpif90
+    FC=f90
+    CC=c++
+    FFLAGS=-dW
+
+. Built on NEC SX6 with:
+   - Operating system SUPER-UX 14.1
+   - C++/SX compiler rev.061 2004/01/06
+   - f90/SX compiler rev.285 2003/09/25
+
+. Note on nf_test
+   -dW disables promotion of Integer*2. However no interfaces
+    for Integer*1 are built. This causes 2 compile time errors
+    in util.F . Lines 1158 and 1226 have to be turned into valid
+    Fortran syntax.
+
+. Note on test_dtype
+    The executables have to be compiled with -pvctl loopcnt=186048.
+    To avoid run time error in test_array the vectorisation of the
+    loop starting at line 256 needs to be disabled with
+    #pragma cdir novector
+
+Rob Latham <robl at mcs.anl.gov>
+Rene Redler <redler at ccrl-nece.de>
+Joachim Worringen <joachim at ccrl-nece.de>
diff --git a/README.large_files b/README.large_files
new file mode 100644
index 0000000..09096de
--- /dev/null
+++ b/README.large_files
@@ -0,0 +1,48 @@
+==== BACKGROUND
+
+The "traditional" netcdf file format (CDF-1) uses a 4-byte value to hold
+the offset into the file where one can find a variable's data
+
+Recently (October 2003), Greg Sjaardema <gdsjaar at sandia.gov> proposed a
+new file format (CDF-2) which uses an 8-byte value for the offset.
+We use his approach in parallel netcdf, though we have modified his
+patch against netcdf-3.5-beta1 to apply to our codebase.  
+
+I couldn't find a URL to Greg's original message, but here's Russ Rew's 
+followup: 
+http://www.unidata.ucar.edu/projects/coohl/mhonarc/MailArchives/netcdf/msg04811.html
+
+This means there are two different but compatible implementations of the
+CDF-2 file format.  We (the parallel netcdf developers) will make our
+best effort to keep our implementation compatible with the serial netcdf
+implementation.  Please report any incompatibilities to the developers
+at parallel-netcdf at mcs.anl.gov. 
+
+==== PRELIMINARIES
+
+First, it is important that your MPI-IO implementation uses an 8 byte
+type to represent the 'MPI_Offset'
+
+Second, your platform should use an 8 byte type to represent the 'off_t'
+type.  On Linux, solaris, IRIX64 (and quite possibly others), parallel-netcdf
+will automatically add the right options to the compiler to make this
+happen.   
+
+Run configure as you normally would.  Let the developers know if
+configure says your 'off_t' is 4 bytes.  Proceed to compile and install
+the library.
+
+==== USAGE
+
+By default, parallel-netcdf will create CDF-1 formatted files.  This
+will ensure that datasets created by our library will be compatible with
+the large body of applications which expect NetCDF files to be CDF-1
+formatted.
+
+To write a CDF-2 formatted file, add the flag 'NC_64BIT_OFFSET' to the
+ncmpi_create() function call ( or nfmpi_create() if using the Fortran
+interface)
+
+The parallel-netcdf library will detect the format of the dataset.
+There are no special options needed to read back files created with the
+NC_64BIT_OFFSET flag set.
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
new file mode 100644
index 0000000..8aff83d
--- /dev/null
+++ b/RELEASE_NOTES
@@ -0,0 +1,859 @@
+Parallel NetCDF Release Notes:
+=====================================
+
+-------------------------------------
+version  1.6.1 (June 1, 2015)
+-------------------------------------
+
+  o New features
+    * PnetCDF now supports fill mode. ncmpi_set_fill() can be used to set the
+      fill mode for the entire data set. Note the differences from netCDF:
+      1. The default mode in PnetCDF is NC_NOFILL. 
+      2. Setting fill mode for the entire file or individual variables must be
+         done in define mode.
+      3. For non-record variables, they are filled at the time ncmpi_enddef()
+         is called.
+      4. For record variables, users must explicitly call ncmpi_fill_var_rec()
+         to fill one record at a time before writing to the record of that
+         variable.
+
+  o New APIs
+    * ncmpi_def_var_fill() sets fill mode for an individual variable. This API
+      must be called in define mode.
+    * ncmpi_inq_var_fill() inquires fill mode of a variable.
+    * ncmpi_fill_var_rec() is a collective API that fills a record of a record
+      variable. This API must be called at data mode.
+    * ncmpi_inq_default_format() for inquiring the default file format for
+      new file creation. Note the default format can be changed by
+      ncmpi_set_default_format().
+    * The above new API are also available in Fortran and C++ versions.
+
+  o New error code
+    * NC_ENOTRECVAR when attempting operation only for record variables
+    * NC_ENOTFILL when attempting to fill a variable when its fill mode is off
+    * NC_EMULTIDEFINE_FILL_MODE	when inconsistent dataset fill mode is detected
+    * NC_EMULTIDEFINE_VAR_FILL_MODE when inconsistent variable fill mode is
+      detected
+    * NC_EMULTIDEFINE_VAR_FILL_VALUE when inconsistent variable fill value is
+      detected
+    * Fortran versions of the above error codes are also added.
+
+  o New example programs
+    * C/fill_mode.c shows the use of ncmpi_set_fill(), ncmpi_def_var_fill(),
+      ncmpi_inq_var_fill() and ncmpi_fill_var_rec()
+      F77/fill_mode.f is the Fortran version.
+      F90/fill_mode.f90 is the Fortran 90 version.
+      CXX/fill_mode.cpp is the C++ version.
+    * C/ghost_cell.c shows how to use varm API for writing from a user buffer
+      as a 2D array with ghost cells on both ends of every dimension.
+
+  o New test programs
+    * nc_test/tst_nofill.c borrowed from netCDF
+    * testcases/ivarn.c tests bug fix r2023 when the request IDs stored in
+      argument array_of_requests[] of ncmpi_wait_all() are not in an
+      increasing order.
+
+  o Other updates:
+    * Change the chunk size used for moving variable data when the file header
+      extent expands. The default is now 1MB. If the file's striping unit
+      size is known (from MPI-IO hint striping_unit) then the chunk size is
+      set to the striping unit size.
+
+  o Bug fixes
+    * Add missing F90 function overloading for f90mpi_put_var_all,
+      f90mpi_get_var_all, f90mpi_put_vard_all, and f90mpi_get_vard_all,
+      when the user buffer is a scalar.
+    * Fix when the request IDs passed in argument array_of_requests[] of
+      ncmpi_wait_all() are not in an increasing order. See r2023.
+    * Fix C++ compile error for converting NULL to string. See r2039.
+
+-------------------------------------
+version  1.6.0 (February 2, 2015)
+-------------------------------------
+
+  o Format conformation updates:
+    * Conform with netCDF4 on CDF-1 and CDF-2 formats. The only difference now
+      between the two formats are the OFFSET item in the format spec (32 vs.
+      64 bit integers.) All names (variable, dimension, attribute) now allow
+      extended characters (e.g. special2 and MUTF8).
+
+  o New APIs
+    * Nonblocking buffered varn API family.
+      For C,   ncmpi_bput_varn_<type>()
+      For F77, nfmpi_bput_varn_<type>()
+      For F90, nf90mpi_bput_varn()
+      For C++, NcmpiVar::bputVarn()
+    * Nonblocking varn API family.
+      For C,   ncmpi_iput_varn_<type>() and ncmpi_iget_varn_<type>()
+      For F77, nfmpi_iput_varn_<type>() and nfmpi_iget_varn_<type>()
+      For F90, nf90mpi_iput_varn()      and nf90mpi_iget_varn()
+      For C++, NcmpiVar::iputVarn()     and NcmpiVar::igetVarn()
+    * Blocking vard API family takes an argument of MPI derived data type that
+      describes the file access layout, as opposed to vara and vars APIs that
+      use start[] and count[].
+      For C,   ncmpi_put_vard()    and ncmpi_get_vard()
+      For F77, nfmpi_put_vard()    and nfmpi_get_vard()
+      For F90, nf90mpi_put_vard()  and nf90mpi_get_vard()
+      For C++, NcmpiVar::putVard() and NcmpiVar::getVard()
+    * Collective var1 API family
+      For C,   ncmpi_put_var1_all()        ncmpi_get_var1_all()
+               ncmpi_put_var1_<type>_all() ncmpi_get_var1_<type>_all()
+      For F77, nfmpi_put_var1_all()        nfmpi_get_var1_all()
+               nfmpi_put_var1_<type>_all() nfmpi_get_var1_<type>_all()
+      For F90, nf90mpi_put_var_all()       nf90mpi_get_var_all()
+      For C++, NcmpiVar::putVar_all()      NcmpiVar::getVar_all()
+    * ncmpi_inq_buffer_size() returns the size of buffer previously attached
+      for use of bput APIs. With ncmpi_inq_buffer_usage() one can calculate
+      the space remaining for additional bput requests.
+      For F77, nfmpi_inq_buffer_size()
+      For F90, nf90mpi_inq_buffer_size()
+      For C++, NcmpiFile::Inq_buffer_size()
+    * ncmpi_inq_recsize() returns the size of record block, i.e. the sum of
+      single records of all record variables.
+      For F77, nfmpi_inq_recsize()
+      For F90, nf90mpi_inq_recsize()
+      For C++, NcmpiGroup::getRecSize()
+    * ncmpi_inq_num_rec_vars() and ncmpi_inq_num_fix_vars() report the number
+      of record and fixed-size variables, respectively.
+      For F77, nfmpi_inq_num_rec_vars()     and nfmpi_inq_num_fix_vars()
+      For F90, nf90mpi_inq_num_rec_vars()   and nf90mpi_inq_num_fix_vars()
+      For C++, NcmpiGroup::getRecVarCount() and NcmpiGroup::getFixVarCount()
+
+  o New PnetCDF hint
+    * pnetcdf_subfiling -- it can be set in an MPI info object or in the
+      environment variable PNETCDF_HINTS to enable/disable subfiling.
+      The value is either "enable" or "disable".
+
+  o PnetCDF hint priority
+    * The alignment hints set in the environment variable "PNETCDF_HINTS" have
+      the highest priority, which overwrite the alignment hints set in
+      ncmpi__enddef(), which overwrite the alignment hints set in the MPI_Info
+      object used in the call of ncmpi_create() and ncmpi_open().
+
+  o New error code
+    * NC_ESTRICTCDF2 for attempting CDF-5 operation on CDF-2 file. For
+      example, define a variable of type NC_INT64 in a CDF-2 file.
+    * NC_ETYPESIZE when filetype size is bigger than the variable size
+    * NC_ETYPE_MISMATCH when the element type of filetype mismatches the
+      variable type
+    * NC_ETYPESIZE_MISMATCH when filetype size mismatches buffer type size
+    * NC_ENULLSTART when argument start is a NULL pointer
+    * NC_ENULLCOUNT when argument count is a NULL pointer
+    * NC_EINVAL_CMODE when invalid file create mode is set, (e.g. cannot have
+      both NC_64BIT_OFFSET & NC_64BIT_DATA. In PnetCDF 1.5.0 and earlier
+      versions, if both flags were set, then NC_64BIT_DATA triumphs
+      NC_64BIT_OFFSET.)
+
+  o New example programs
+    * C/bput_varn_uint.c and F77/bput_varn_int8.f show the use of
+      nonblocking bput_varn APIs
+    * C/i_varn_int64.c and F77/i_varn_real.f show the use of nonblocking
+      iput_varn and iget_varn APIs
+    * C/vard_int.c F77/vard_int.f F90/vard_int.f90 CXX/vard_int.cpp show the
+      use of vard API to write/read record and fixed-size variables.
+    * C/transpose.c shows the use of ncmpi_put_vara_int_all to write a 3D array
+      that is dimensional-transposed from the one stored in memory. Six
+      transposed 3D arrays are saved whose dimensions are organized as ZYX,
+      ZXY, YZX, YXZ, XZY, and XYZ. The C++, Fortran 77, and Fortran 90
+      versions are also provided.
+
+  o New test program
+    * nonblocking/wait_after_indep.c tests if ncmpi_end_indep_data() returns
+      properly when nonblocking APIs are called in independent data mode and
+      the wait call is made after exiting the independent mode.
+    * nonblocking/flexible_bput.c tests flexible bput APIs that use
+      noncontiguous buffer type, noncontiguous imap and require type conversion
+    * testcases/flexible2.c tests flexible APIs that perform type conversion
+    * testcases/flexible_varm.c tests flexible varm APIs
+    * testcases/varn_contig.c tests the case when the fileview is actually a
+      contiguous chunk. PnetCDF should be able to merge all.
+    * nonblocking/bput_varn_uint.c tests nonblocking bput_varn APIs
+    * nonblocking/i_varn_int64.c tests nonblocking iput_varn and iget_varn APIs
+    * test/testcases/test_vard.c test/testcases/test_vardf.f
+      test/testcases/test_vardf90.f90 test the new vard APIs.
+    * test/testcases/inq_recsize.c tests if one can correctly inquire the
+      size of record block from in a netCDF file. A similar program in F90,
+      named inq_recsizef.f90, is also added.
+    * In test/nc_test, the test programs below are borrowed from netCDF test
+      programs: t_nc.c tst_misc.c tst_norm.c tst_small.c tst_names.c
+      tst_atts3.c tst_atts.c
+    * test/testcases/one_record.c tests the special case defined in CDF-1 and
+      CDF-2 specification that "A special case: Where there is exactly one
+      record variable, we drop the requirement that each record be four-byte
+      aligned, so in this case there is no record padding."
+    * test/testcases/modes.c tests if correct error codes are returned when
+      various file create/open modes are used.
+    * Under test/testcases, varn_int.c varn_intf.f varn_real.f90 test varn APIs
+    * test/testcases/inq_num_vars.c test if one can correctly inquire the
+      numbers of record and fixed-size variables defined in a netCDF file.
+      A similar program in F90, named inq_num_varsf.f90, is also added.
+    * test/nonblocking/interleaved.c tests a combination of interleaved
+      file types. This is to test the bug fix in r1758.
+
+  o New optimization
+    * Prior to this release, PnetCDF wraps each MPI read/write call in put/get
+      APIs with two MPI_File_set_view(). One is before the MPI read/write call
+      to take advantage of MPI's fileview feature for accessing non-contiguous
+      file locations. The other is after the MPI read/write call to make the
+      whole file visible, as the root process may write to file header later
+      in the data mode and it alone cannot make a call to MPI_File_set_view()
+      because the function is collective.
+
+      In this release, the second MPI_File_set_view() has been removed. The
+      root process's fileview is changed to always keep the whole file header
+      visible. Saving a collective call to MPI_File_set_view() is expected to
+      improve some performance.
+
+  o Semantics updates
+    * Header consistency mechanism has been updated. See README.consistency for
+      details.
+    * The use of NC_SHARE is also revised. See README.consistency for details.
+
+  o Other updates:
+    * The subfiling feature is now disabled in ncmpidump and ncmpidiff until
+      a bug fix to allow reading the master file with the number of processes
+      that is smaller than the number of subfiles.
+    * The attribute names reserved for subfiling feature are now changed to
+      use a prefix of "_PnetCDF_SubFiling". The leading "_" underscore is a CDL
+      convention.
+    * The flexible APIs now allow argument buftype to be MPI_DATATYPE_NULL.
+      In this case, argument bufcount is ignored and argument buf's data type
+      must match the data type of variable defined in the file - no data
+      conversion will be done. This extension makes the flexible APIs be
+      able to correspond to the netCDF APIs whose names do not contain a data
+      type, e.g. nc_put_vara().
+    * Type conversion between NC_BYTE and unsigned char no longer checks for
+      out of range error (NC_ERANGE). CDF file format specification make a
+      special case for this kind of data type conversion. See: "Note on byte
+      data" in the format specification.
+    * Conform with the CDF-2 and CDF-5 formats that names are normalized
+      according to Unicode NFC normalization rules during encoding as UTF-8
+      for storing in the file header.
+    * A new configure option, --enable-large-file-test, to enable testing
+      I/O on large files and large variables. Note the testing programs will
+      run very slowly.
+
+  o Bug fixes
+    * fix the bug for flexible get_varn API. When buftype is noncontiguous, the
+      bug forgot to "unpacks" the temporary buffer that reads data from file to
+      the user buffer using buftype.
+    * fix the bug in blocking flexible get APIs when buftype is noncontiguous,
+      swap is needed, type conversion is not. The bug sets a NULL pointer to
+      the read buffer and passes it to MPI_File_read functions. See r1815.
+    * fix the bug for the NetCDF special case when there is only one record
+      variable and the record size is not four-byte aligned. In this case,
+      NetCDF spec says the alignment must dropped (no padding). See r1791.
+    * fix the bug in nonblocking APIs when requests are resorted into
+      nonoverlapping groups and the first group of file types are interleaved,
+      it was mistakenly identified as non-interleaved. See r1758.
+    * fix the setting for PNETCDF_RELEASE_DATE in configure.in. Using read
+      command together with IFS does not work as expected in bash 4.3.11. See
+      http://lists.mcs.anl.gov/pipermail/parallel-netcdf/2014-July/001586.html
+      for further detailed discussion.
+
+-------------------------------------
+version  1.5.0 (July 8, 2014)
+-------------------------------------
+
+  o New features
+    * A new configure option "--disable-in-place-swap" is added. It disables
+      the byte-swap operations running in-place on the user's write buffers.
+      The purpose of providing this option is to deal with the problem when a
+      Fortran program uses a immutable buffer for put APIs, e.g. the buffer is
+      declared as a PARAMETER, and in-place byte swap on this buffer causes
+      segmentation fault. See discussion threads of
+      http://lists.mcs.anl.gov/pipermail/parallel-netcdf/2013-July/001498.html
+
+      Impacts:
+      1. It takes effect only on Little Endian machines.
+      2. It only affects put/iput data APIs, but not attribute APIs.
+      3. The INTENT of buffer arguments in all Fortran 90 put/iput APIs will be
+         declared as "IN". Without this setting, the default is "INOUT".
+      4. It has an impact on performance, as an extra internal temporary buffer
+         will be allocated to copy data over from user's put buffer, so byte
+         swap can be run on the temporary buffer.
+
+      The default setting is to enable in-place byte swap. PnetCDF tries not to
+      allocate additional memory space, due to performance concern. Users are
+      discouraged to use Fortran PARAMETER buffers in put APIs.
+
+    * A new configure option "--enable-debug" is added. It enables a memory
+      allocation tracing mechanism internal in PnetCDF. In addition, it enables
+      the PnetCDF safe mode. (Note that setting the environment variable
+      PNETCDF_SAFE_MODE at the run time can still overwrite the safe mode.)
+      Default debug mode is disabled. When enabled, a user program can call
+      three new APIs below: ncmpi_inq_malloc_size, ncmpi_inq_malloc_max_size,
+      and ncmpi_inq_malloc_list to obtain the size in bytes of current memory
+      allocated internally. This feature uses a binary tree to manage all
+      malloc buffers, e.g. tsearch() and tdelete().
+
+    * Add three Fortran parameters for PnetCDF library version numbers:
+      PNETCDF_VERSION_MAJOR, PNETCDF_VERSION_MINOR, and PNETCDF_VERSION_SUB.
+      Similarly in C programs, these are defined in pnetcdf.h as constants.
+
+  o New APIs
+    * C++ APIs are now available. They are developed based on netCDF-4 C++
+      library. However, users are encouraged to use C APIs, instead C++.
+
+    * ncmpi_put_att, ncmpi_get_att, nfmpi_put_att, and nfmpi_get_att - these
+      APIs correspond to nc_put_att, nc_get_att, nf_put_att, and nf_get_att.
+      Note they are not the "flexible" APIs. Flexible APIs have an MPI derived
+      datatype argument.
+
+    * ncmpi__enddef, nfmpi__enddef, and nf90mpi_enddef - these APIs correspond
+      to netCDF nc__enddef, nf__enddef, and nf90_enddef (with additional
+      optional arguments).
+
+    * ncmpi_inq_file_info - the naming for ncmpi_get_file_info may cause
+      confusion, as "get" has a different meaning on PnetCDF. The correct
+      name should use "inq". However, ncmpi_get_file_info is kept for backward
+      compatibility.
+
+    * ncmpi_inq_striping, nfmpi_inq_striping, nf90mpi_inq_striping report the
+      file system striping settings of the opened file: striping size and
+      striping count, if the underneath MPI-IO can find their values from the
+      file system in use.
+
+    * ncmpi_inq_malloc_size, ncmpi_inq_malloc_max_size, ncmpi_inq_malloc_list
+      report the size in bytes of current memory allocated internally by
+      PnetCDF. Similar APIs for Fortran 77 and 90 are also available. These
+      APIs are enabled only when PnetCDF is configured with option
+      --enable-debug. When this option is not enabled, calling these APIs will
+      return the error code NC_ENOTENABLED. These APIs are usefully for
+      debugging.
+
+    * ncmpi_inq_files_opened reports the number of files that are currently
+      opened. Similar API for Fortran 77 and 90 are also available. The API
+      takes 2 arguments: number of files and array of file IDs. If the second
+      argument, array of IDs, is not NULL, then it will filled with the netCDF
+      dataset IDs. This API is useful for debugging.
+
+  o Syntax changes
+    * For all Fortran put/iput APIs, the INTENT of write buffer arguments is
+      changed to "INOUT" on Little Endian machines, if option
+      "--disable-in-place-swap" is not used at configuration. Otherwise, i.e.
+      on Big Endian machines or PnetCDF is configured with
+      "--disable-in-place-swap" on Little Endian machines, the INTENT is "IN".
+
+  o New PnetCDF hint
+    * nc_record_align_size - aligns the starting file offset of the record
+      variable section. Note this is for the entire section, not individual
+      records.
+
+  o New error code
+    * NC_ENOTENABLED indicates the API is available only when the corresponding
+      feature is enabled. For example, nfmpi_inq_malloc_size() returns this
+      error code when "--enable-debug" is not used at configure.
+
+    * NC_EBAD_FILE corresponds to MPI error code MPI_ERR_BAD_FILE, meaning
+      "Invalid file name (e.g., path name too long)."
+
+    * NC_ENO_SPACE corresponds to MPI error code MPI_ERR_NO_SPACE, meaning
+      "Not enough space."
+
+    * NC_EQUOTA corresponds to MPI error code MPI_ERR_QUOTA, meaning
+      "Quota exceeded."
+
+    * NC_EMULTIDEFINE_FNC_ARGS corresponds to MPI error code MPI_ERR_NOT_SAME,
+      meaning "inconsistent function arguments used in collective API."
+
+  o New run-time environment variables
+    * none
+
+  o New example programs
+    * Example programs now report if there is any PnetCDF internal malloc
+      residues yet to be freed, if --enable-debug option is used at
+      configure.
+
+    * Under examples/C, three examples are added: create_open.c, get_vara.c,
+      and global_attributes.c. File examples/README contains their
+      descriptions.
+
+    * Under examples/CXX, several example programs corresponding to those in
+      examples/C are added.
+
+  o New programs for I/O benchmarks
+    * none
+
+  o New test program
+    * Many test programs now report if there is any PnetCDF internal malloc
+      residues yet to be freed, if --enable-debug option is used at configure.
+
+    * add tests for flexible APIs. The tests borrow from nc_test/test_write.c
+      that tests nc_put_var1, nc_put_vara, nc_put_vars, and nc_put_varm.
+      Similarly for get APIs.
+
+    * testcases/record.c checks if the number of records is updated correctly.
+      It writes to a variable's 2nd record followed by the 1st record. A call
+      to ncmpi_inq_dim() or ncmpi_inq_dimlen() should report 2 records after
+      the writes complete.
+
+    * testcases/noclobber.c checks if error code NC_EEXIST can be returned
+      correctly when NC_NOCLOBBER modes is used in ncmpi_create and in the
+      meantime the file exists.
+
+    * Some test programs are developed to run in parallel. The test mechanism
+      for parallel runs is command "make ptest". Two environment variables
+      can be used to set the MPI run command and output file directory:
+      TEST_MPIRUN and TEST_OUTDIR. Their defaults are mpiexec and "." (current
+      directory), respectively. For example,
+          make ptest TEST_MPIRUN="aprun -n NP" TEST_OUTDIR=/scratch
+      Note the keyword "NP" will be replaced by the different numbers of
+      processes used to run the tests. The testing uses up to 8 MPI processes.
+
+    * A sample PBS script file is provided to test "make ptest" on machines
+      with a batch queue system: pbs.script. This example script can be
+      submitted from the build root directory (where you run "make" command to
+      build PnetCDF library).
+
+    * For cross compile environment (and batch queue system), the environment
+      variable TEST_SEQRUN can be used to set the MPI run command. For example,
+      the command for testing sequential programs:
+          make check TEST_SEQRUN="aprun -n 1" TEST_OUTDIR=/scratch
+
+      For non-cross compile environment, there is no need to set the environment
+      variables, as long as one can run the MPI executable without mpirun or
+      mpiexec.
+
+  o New optimization
+    * none
+
+  o New utility program
+    * pnetcdf_version prints the version information of the PnetCDF library and
+      command-line arguments used at configure
+
+  o Other updates:
+    * Revise FLASH-IO benchmark to use nonblocking APIs for both checkpoint and
+      plot writes. The control variable to switch between nonblocking and
+      blocking API is "use_nonblocking_io". Set it to .FALSE. in
+      flash_benchmark_io.F90 to switch to blocking APIs. Using nonblocking APIs
+      is now the default.
+
+    * To match ncdump, ncmpidump now only supports one input file.
+
+    * Makefiles are revised for better recursive make and fixed some build
+      target dependency for parallel make.
+
+    * File creation was revised for handling NC_CLOBBER and NC_NOCLOBBER modes.
+      On systems where Unix calls access() and unlink() are available, they
+      are used to check if a file exits and to delete an existing file.
+
+    * subfiling is now enabled by default. Users can use --disable-subfiling to
+      disable it
+
+    * man page of ncmpigen is updated to add the description for option "-v"
+      which lets users to specify the desired output file formats, e.g.
+      CDF-1, CDF-2, or CDF-5.
+
+    * flex, lex, bison, or yacc are no longer needed for building ncmpigen.
+
+  o Bug fixes
+    * fix ncmpigen.y on parsing CDL file to get the number of records. The bug
+      failed the command "make b-test", due to getting a wrong number of
+      records (current value for the unlimited dimension).
+
+    * fix the update for number of records when writing to a record that is
+      not the last record.
+
+-------------------------------------
+version  1.4.1 (December 23, 2013)
+-------------------------------------
+
+  o Bug fix:
+    * Improve pnetcdf.inc portability for fixed/free-form Fortran programs
+
+  o Fortran API syntax changes
+    * For nfmpi_put_att and nf90mpi_put_att family, the intent modifier for
+      the put buffer arguments are now declared as INTENT(IN).
+    * For nfmpi_put_var* and nf90mpi_put_var family
+      + On Big Endian machines, the the intent modifier for the put buffer
+        arguments are now declared as INTENT(IN).
+      + On Little Endian machines, the the intent modifier for the put buffer
+        arguments are still declared as INTENT(INOUT). This is because PnetCDF
+        does in-place byte-swap on user's put buffer. If user's buffer is
+        declared as parameter, then segment fault can happen when PnetCDF
+        tries to byte-swap a read-only memory.
+
+  o Subfiling
+    * Subfiling is a new PnetCDF feature that divides a file transparently
+      into several smaller subfiles, each of which stores subarrays
+      in CDF file formats. The file name supplied by the users serves as a
+      master file that contains all metadata about array partitioning
+      information among the subfiles. Because data partitioning is made
+      transparently from users, data accessing is kept the same through
+      the conventional PnetCDF APIs and the master file.
+    * To enable this feature at configure time, add configure option
+      "--enable-subfiling".
+
+
+-------------------------------------
+version  1.4.0 (November 17, 2013)
+-------------------------------------
+
+  o New APIs
+    * Fortran 90 APIs (adopted from netcdf-fortran-4.2). All F90 APIs have
+      prefix name "nf90mpi_". The APIs support function overloading.
+    * get/put_varn_<type> for reading/writing a list of subrequests (each is
+      specified by starts[i][ndims] and counts[i][ndims] for subrequest i.
+      ndims is the number of dimension of the variable) to a single variable.
+    * multiple put/get requests with explicit buffer type names:
+      ncmpi_mput_var_type(), ncmpi_mput_var1_type(), ncmpi_mput_vara_type(),
+      ncmpi_mput_vars_type(), ncmpi_mput_varm_type(). Similar for get APIs.
+      "type" is one of the followings: text, schar, uchar, short, ushort, int,
+      uint, long, float, double, longlong, or ulonglong.
+    * ncmpi_inq_nreqs() reports the number of pending nonblocking requests
+    * ncmpi_inq_header_size() reports the size of the file header
+    * ncmpi_inq_header_extent() reports the space currently allocated for the
+      file header, (also the file offset of the first variable)
+    * ncmpi_inq_put_size() reports the write amount committed by far
+    * ncmpi_inq_get_size() reports the read amount committed by far
+    * ncmpi_sync_numrecs() a collective API that can be called in independent
+      data mode to synchronize the number of records in memory across all
+      processes, and update to the file if NC_SHARE is set.
+
+  o Syntax change for Fortran put APIs
+    * intent of buffer argument in all Fortran APIs is changed to inout, as
+      byte-swap might be performed directly on the buffer. This change is
+      for performance consideration. For example, if the buffer is declared
+      as Fortran parameter, then compile will fail.
+
+  o New PnetCDF hint
+    * nc_header_read_chunk_size: PnetCDF reads the file headers in chunks. This
+      hint indicates the chunk size (in bytes). The default is 256 KB.
+
+  o New error code
+    * NC_EINTOVERFLOW reports the error of 4-byte integer overflow. This
+      usually happens due to MPI-IO data type constructor APIs' arguments using
+      4-byte integers.
+    * Error codes to report metadata defined inconsistently across processes.
+        NC_EMULTIDEFINE_OMODE      - create/open mode
+        NC_EMULTIDEFINE_DIM_NUM    - number of dimensions
+        NC_EMULTIDEFINE_DIM_SIZE   - size of dimension
+        NC_EMULTIDEFINE_DIM_NAME   - dimension names
+        NC_EMULTIDEFINE_VAR_NUM    - number of variables
+        NC_EMULTIDEFINE_VAR_NAME   - variable name
+        NC_EMULTIDEFINE_VAR_NDIMS  - variable's number of dimensions
+        NC_EMULTIDEFINE_VAR_DIMIDS - variable's dimid
+        NC_EMULTIDEFINE_VAR_TYPE   - variable's data type
+        NC_EMULTIDEFINE_VAR_LEN    - variable's size
+        NC_EMULTIDEFINE_NUMRECS    - number of records
+        NC_EMULTIDEFINE_VAR_BEGIN  - variable file begin offset
+        NC_EMULTIDEFINE_ATTR_NUM   - number of attributes
+        NC_EMULTIDEFINE_ATTR_SIZE  - memory space used by attribute
+        NC_EMULTIDEFINE_ATTR_NAME  - attribute name
+        NC_EMULTIDEFINE_ATTR_TYPE  - attribute type
+        NC_EMULTIDEFINE_ATTR_LEN   - attribute length
+        NC_EMULTIDEFINE_ATTR_VAL   - attribute value
+
+  o New run-time environment variables
+    * PNETCDF_SAFE_MODE environment variable can be used to enable/disable the
+      internal checking for data/argument consistency across all processes (by
+      calling collective MPI_Allreduce). Set it to 1 to enable the checking.
+      Default is 0, i.e. disabled.
+    * PNETCDF_HINTS environment variable can be used to pass the I/O hints to
+      PnetCDF library. Hints include both PnetCDF and MPI-IO hints.
+      PNETCDF_HINTS is a string of hints separated by ";" and each hint is in
+      the form of hint=value. E.g.
+          romio_ds_write=disable;nc_header_align_size=1048576
+      If this environment variable is set, it overrides any values that
+      were set by using calls to MPI_Info_set in the application code.
+
+  o New example programs
+    * example programs are now categorized into C, F77, and F90 directories
+    * nonblocking_write.f and nonblocking_write.f90 are the Fortran version of
+      nonblocking_write.c
+    * put_varn_float.c for using the new APIs ncmpi_put_varn_float_all()
+      put_varn_real.f and put_varn_real.f90 are the Fortran versions
+    * put_varn_int.c, put_varn_int.f, and put_varn_int.f90, for using the new
+      APIs ncmpi_put_varn_int_all() and nfmpi_put_varn_int_all()
+    * hints.c, hints.f, and hints.f90 for using PnetCDF hints
+    * flexible_api.c, flexible_api.f, and flexible_api.f90, for using blocking
+      and nonblocking flexible APIs
+    * mput.c for using ncmpi_mput_vara_all() to write a series of arbitrary
+      start[] and count[]
+    * block_cyclic.c, block_cyclic.f, and block_cyclic.f90 are for a
+      *-(block-cyclic) 2D partitioning pattern
+    * column_wise.c, for a *-cyclic 2D partitioning pattern
+    * put_vara.c, put_vara.f, and put_var.f90 for using for
+      nfmpi_put_vara_int_all()
+
+  o New programs for I/O benchmarks
+    * benchmarks/C/aggregation.c -- evaluate PnetCDF's performance on I/O
+      aggregation across multiple requests with different data access patterns.
+    * benchmarks/C/write_block_read_column.c -- writes variables and reads back
+      using different data partitioning patterns
+    * benchmarks/FLASH-IO -- I/O kernel of FLASH, a reacting hydrodynamics code
+      developed at University of Chicago. This benchmark can be built
+      independently from PnetCDF release.
+
+  o New test program
+    * test/F90 contains test programs adopted from netcdf-fortran-4.2
+    * test/nf90_test contains test programs adopted from test/nf_test
+    * testcases/alignment_test.c -- test for header and fixed variable file
+      offset alignments when entering redef mode
+    * testcases/nonblocking.c -- test nonblocking APIs ncmpi_iput_vara_int()
+      and ncmpi_iget_vara_int()
+    * testcases/flexible.c -- test flexible API ncmpi_get_vara_int_all() using
+      an MPI derived data type created by MPI_Type_create_hindex()
+    * test/header/header_consistency.c -- test header inconsistency and see if
+      inconsistent metadata is overwritten by root's
+
+  o New semantics for attribute APIs in data mode
+    The following APIs can modify file header while being called in data mode.
+    Note that these APIs can only modify existing attributes, rename variables
+    or dimensions, given that the new attributes and names do not take more
+    file space than the old ones. Otherwise, these APIs are prohibited in data
+    mode.
+      ncmpi_rename_dim(),
+      ncmpi_rename_var(),
+      ncmpi_copy_att(),
+      ncmpi_rename_att(), and
+      ncmpi_put_att_<type>()
+    Starting from this release of PnetCDF, these APIs must be called
+    collectively when in data mode. This new requirement is to ensure the
+    file header cached in memory is consistent across all processes.
+
+  o New synchronization for number of records
+    In collective data mode, the number of records cached in memory is
+    always synchronized across all processes. In independent mode, the value
+    can be inconsistent, unless ncmpi_sync_numrecs() (a collective API) is
+    called explicitly. Otherwise, the synchronization will have to wait until
+    the call to ncmpi_end_indep_data().
+
+    Flushing the number of records to file when it is changed used to be
+    delayed until ncmpi_close() or ncmpi_sync() is called. If a strong file
+    consistency is desired, users must enable NC_SHARE mode when opening the
+    file. However, note that in this mode any header change will cause file
+    I/O to flush  the dirty header data (not just number of records). For
+    programs that do not change header frequently, enabling NC_SHARE should
+    have no significant performance impact.
+
+    This flushing behavior has been changed in 1.4.0 to the following. At the
+    end of collective calls, if the number of records increases, the changed
+    value will be written to the file, no matter if NC_SHARE mode is used or
+    not. This change is to ensure the number of records is up-to-dated in
+    file, in case the application program does not close file (due to crash
+    or programming error). Note this change applies to collective APIs only.
+
+  o New optimization: I/O request aggregation
+    The original design of nonblocking I/O is to concatenate the fileviews of
+    individual nonblocking requests and serve them with a single MPI-IO call,
+    if possible. However, because MPI-IO requires the file displacements of
+    the flattened fileview be in an monotonically nondecreasing order, the
+    original approach (in v1.3.1 and prior) divides the nonblocking requests
+    into groups such that each group abides by this MPI-IO fileview
+    requirement. Each group is then carried out by a separate MPI-IO call.
+    Performance can be poor if there are multiple groups and each group's
+    aggregate access region is non-contiguous in the file.
+
+    This revision fixes this problem by 1) sorting the starting offset of all
+    nonblocking requests into a non-decreasing order; 2) dividing the requests
+    into groups (two types of groups are identified: interleaving and
+    non-interleaving); 3) for each non-interleaving group, concatenating
+    fileviews of all requests in the group; 4) for each interleaving group,
+    flattening fileviews of all requests in the group, merging the
+    offset-length pairs, and concatenating them into a new integrated fileview;
+    5) concatenating the fileviews of all groups into a single one; 6) the
+    final combined fileview is used by a single MPI-IO call to carry out the
+    requests.  Performance is expected to be improved as the number of MPI-IO
+    calls is reduced to one.
+
+    However, be warned about the additional memory requirement. The additional
+    memory needed for flattening the fileviews might be more than the I/O data
+    itself. For example, a request to accessing a single column of a 2D integer
+    array will result in offset-length pairs, each representing only a 4-byte
+    integer where the C struct in PnetCDF for storing an offset-length pair
+    takes 3*sizeof(MPI_Offset)=24 bytes (offset, length, and I/O buffer
+    pointer).
+
+  o Other updates:
+    * configure.in and Makefile.in have been revised to detect MPI compilers
+      and other compile options automatically.
+    * A new configure option "--disable-file-sync" to disable calling file
+      sync. This is to be used when the underlying file system provides data
+      consistency control.
+    * add build recipe for IBM BGQ (e.g. Vesta/Mira/Cetus @ANL) in README.IBM
+    * add build recipe for CRAY-XE6, Hopper @NERSC in README.CRAY
+    * add build recipe for CRAY-XC30, Edison @NERSC in README.CRAY
+    * add build recipe for Endeavour @ NASA in README.SGI
+    * add declaration of flexible APIs for Fortran90
+    * "make testing" now hides most of the stdout. Use "make verbose_testing"
+      for verbose output.
+    * ncmpidump: add the command-line option "-k" to report the format of
+      netCDF file.
+    * ncvalid is renamed to ncmpivalid, a tool to validate the structure of
+      netCDF files for conforming with CDF formats.
+    * Fortran type NFMPI_OFFSET is removed. It was merely a shortcut to
+      integer(KIND=MPI_OFFSET_KIND). Some Fortran 77 compiler does not
+      recognize keyword KIND. In that case, please set MPIF77 to the MPI
+      Fortran 90 compiler, e.g. ./configure MPIF77=mpif90
+    * configure now automatically checks Fortran module compile flags
+    * Support additional Fortran netCDF data types: nf_ubyte, nf_ushort,
+      nf_uint, nf_uint64, nf90_ubyte, nf90_ushort, nf90_uint, nf90_uint64.
+    * Error codes and messages conform with netCDF's
+
+  o Bug fixes
+    * Argument unlimdimid of nfmpi_inq() returns -1 when no unlimited length
+      dimension has been defined (to conform nf_inq()).
+    * Argument varid of nfmpi_inq_varoffset() is fixed to be the C's varid
+      plus one.
+    * For collective APIs, many places have been changed to prevent program
+      from hanging if a subset of the processes got errors. The fix will allow
+      all processes participating the MPI collective calls in the PnetCDF, even
+      if errors are detected on a subset of processes.
+    * set the nonblocking request ID to NULL when the request length is zero
+    * report error when bogus request IDs are passed in ncmpi_wait
+    * when entering redef with different alignment hints, fixed-size
+      variables' file starting offsets will only be changed when it is bigger
+      than the old ones
+    * Fix some Fortran API intent in/out argument declarations
+    * ncmpi_def_var is fixed to detect if CDF-5 data types is used on CDF-1 or
+      CDF-2 files. Error code NC_ESTRICTNC3 will return.
+
+
+
+-------------------------------------
+version  1.3.1 (September 24, 2012)
+-------------------------------------
+
+    This release is primarily a bug-fix release, tidying up a few issues and
+    incorporating some early feedback on our "buffered put" interface (see
+    http://trac.mcs.anl.gov/projects/parallel-netcdf/wiki/BufferedInterface for
+    more information)
+
+    - add a new API ncmpi_inq_buffer_usage/nfmpi_inq_buffer_usage for inquiring
+      the current usage of the internal buffer allocated by the "buffered"-put
+      APIs.
+    - bug fix to make bput APIs properly return error code NC_EINSUFFBUF.
+    - bug fixes for ncmpidump to avoid residue contents from a previous read
+      when it read beyond EOF.
+    - bug fixes in the tutorial example codes.
+    - add more in-line comments for the tutorial example codes.
+    - add the error string for error code NC_ENOENT.
+
+-------------------------------------
+version  1.3.0 (June 26, 2012)
+-------------------------------------
+
+    - Bug fixes in new ncmpidiff tool.
+    - Small optimizations to reduce communication in library.
+    - Improved documentation, including more test programs and a QuickTutorial.
+    - Bug fixes in our Fortran90 support.
+    - Better compatibility with NetCDF-4: no need for a modified pnetcdf.h from
+      Unidata when building NetCDF-4 with PnetCDF support.
+    - PnetCDF now duplicates the MPI communicator internally, which fixed at
+      least one odd behavior seen in a PnetCDF-using application.
+    - Improvements to PnetCDF header and variable alignment (see wiki page
+      VariableAlignment).
+    - Add a checking for file create mode consistency across all processes and
+      an error code for it, NC_ECMODE.
+    - Bug fix for updating the number of record variables in nonblocking APIs.
+    - Bug fix for variable starting file offsets when defining multiple large
+      variables (> 232 elements) in one CDF-5 file.
+    - Add a new configure option that takes environment variable $RM to replace
+      the default "rm" command in all Makefiles.
+    - Bug fix for nonblocking varm APIs.
+    - Support for CDF-2's special2 characters in names (variables, attributes,
+      dimensions, etc.)
+    - Release of the official CDF-5 file format specification (see wiki page
+      CD-5).
+    - Support for CDF-5 data types: NC_UBYTE, NC_USHORT, NC_UINT, NC_INT64,
+      NC_UINT64, and NF_INT64.
+    - New C APIs: ncmpi_put_vara_ushort, ncmpi_put_vara_uint,
+      ncmpi_put_vara_longlong, and ncmpi_put_vara_ulonglong. Similarly for
+      var1, var, vars and varm APIs. Also for get and nonblocking APIs.
+    - New Fortran APIs: nfmpi_put_vars_int8 and similarly for var1, var, vars,
+      varm, get, and nonblocking APIs.
+    - Add a new error code, NC_ENOTSUPPORT, for not-yet-supported features.
+    - A new set of buffered put APIs (eg. ncmpi_bput_vara_float) is added (see
+      BufferedInterface). They make a copy of the user's buffer internally, so
+      the user's buffer can be reused when the call returns. Their usage are
+      similar to the iput APIs.
+    - Add new error codes for buffered put APIs: NC_ENULLBUF,
+      NC_EPREVATTACHBUF, NC_ENULLABUF, NC_EPENDINGBPUT, and NC_EINSUFFBUF.
+    - Add new test and example programs for the buffered put APIs.
+    - The error string returned by ncmpi_strerror() for an undefined error code
+      is updated from "Unknown Error" to "Unknown Error: Unrecognized PnetCDF
+      error code ID" to be more descriptive.
+    - Remove the use of POSIX error codes: EINVAL, ENOERR, ERANGE, and ENOMEM.
+      They are replaced by NC error codes now: NC_EINVAL, NC_NOERR, NC_ERANGE,
+      and NC_ENOMEM.
+    - A better translation of MPI-IO error classes to netCDF/PnetCDF error
+      codes. For example, MPI-IO error class MPI_ERR_NO_SUCH_FILE is translated
+      to NC_ENOENT.
+
+    - Compatibility note
+
+    - In testing with version 11.7 of the Portland Group compiler, some of the
+      Fortran test programs fail to compile if built with pgf77. The tests work
+      if built with the Fortran90 compiler.
+
+-------------------------------------
+version  1.2.0 (August 19, 2010)
+-------------------------------------
+
+    - Several bugs fixed, memory leaks reduced,
+
+    - Internal housekeeping
+
+    - Reduce the places where PnetCDF will call MPI_FILE_SYNC
+
+    - A new 'ncmpidiff' utility to compare two datasets in parallel
+
+    - Addressed a build failure when compiling with some versions of MVAPICH2.
+      See
+      http://lists.mcs.anl.gov/pipermail/parallel-netcdf/2010-July/001045.html
+      for an example of the build failure.
+
+    - If you build this release and still get "undefined reference to 'yyin'",
+      then you have some stale object files. "make clean" and re-build.
+
+    - Additional error checking for collective routines
+
+    - We have also made API changes to our non-blocking interface. Our
+      non-blocking semantics have been relaxed somewhat, and should be more
+      usable in more situations.
+
+
+-------------------------------------
+version  1.1.0 (November 2, 2009)
+-------------------------------------
+
+    - A new file format, CDF-5, is introduced. This format allows defining
+      large array variables with more than 2^32 elements.
+
+    - A new optimization in parallel-netcdf with this release. If the hint
+      "striping_unit" is set, then PnetCDF will align the start of non-record
+      variables to a multiple of that value.
+
+    - A new set of APIs for reading/writing multiple variables. The existing
+      asynchronous APIs have also been improved to enable combination of
+      multiple variable access into fewer I/O requests.
+
+    - There is now a simple pnetcdf.F90 module for F90 codes. Please consider
+      this as an "early feedback" version and not a hard guarantee of a fixed
+      F90 API (though we don't expect it to change drastically if at all).
+      This module is generated from the F77 'pnetcdf.inc': thanks to
+      Annette Koontz for the idea.
+
+    - The 'ncmpigen' utility can now create "big variable" (CDF-5) files, in
+      addition to the older "big file" (CDF-2) files.
+
+-------------------------------------
+version  1.0.0 (July 27, 2005)
+-------------------------------------
+
+    - The Parallel-NetCDF developers are quite happy to announce our 1.0.0
+      release.  This release reflects the culmination of several years of
+      work and lots of community feedback.  
+
+      A brief list of the major changes since 0.9.4:
+
+    - Has both the high level and flexible data mode interfaces 
+    - Improved support for many more platforms
+    - Support for all serial NetCDF access patterns (var, vara, vars,
+      varm) and types (text, char, uchar, schar, short, int, float, long,
+      double)
+    - Synced up with netcdf-3.6.0
+    - The usual array of bug fixes and improvements.
+
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..da9d2a1
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,1727 @@
+dnl $Id: aclocal.m4 2280 2015-12-26 17:41:38Z wkliao $
+dnl UD macros for netcdf configure
+
+
+dnl Convert a string to all uppercase.
+dnl
+define([uppercase],
+[translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)])
+
+dnl
+dnl Check for an m4(1) preprocessor utility.
+dnl
+AC_DEFUN(UD_PROG_M4,
+[
+    dnl AS_MESSAGE([checking for m4 preprocessor...])
+    case "${M4-unset}" in
+	unset) AC_CHECK_PROGS(M4, m4 gm4, m4) ;;
+	*) AC_CHECK_PROGS(M4, $M4 m4 gm4, m4) ;;
+    esac
+    AC_MSG_CHECKING(m4 flags)
+    case "${M4FLAGS-unset}" in
+	unset) dnl test if M4 runs fine without option -B10000
+               `${M4} /dev/null > conftest.err 2>&1`
+               ac_cv_m4_stdout=`cat conftest.err`
+               if test "x$ac_cv_m4_stdout" != x; then
+                  M4FLAGS=-B10000
+               fi
+               ${RM} -f conftest.err
+               ;;
+    esac
+    AC_MSG_RESULT($M4FLAGS)
+    AC_SUBST(M4FLAGS)
+])
+
+dnl
+dnl Check for an ar(1) utility.
+dnl
+AC_DEFUN(UD_PROG_AR,
+[
+    dnl AS_MESSAGE([checking for ar utility...])
+    case "${AR-unset}" in
+	unset) AC_CHECK_PROGS(AR, ar, ar) ;;
+	*) AC_CHECK_PROGS(AR, $AR ar, ar) ;;
+    esac
+    AC_MSG_CHECKING(ar flags)
+    case "${ARFLAGS-unset}" in
+	unset) ARFLAGS=cru ;;
+    esac
+    AC_MSG_RESULT($ARFLAGS)
+    AC_SUBST(ARFLAGS)
+])
+
+dnl
+dnl Check for an nm(1) utility.
+dnl
+AC_DEFUN(UD_PROG_NM,
+[
+    dnl AS_MESSAGE([checking for nm utility...])
+    case "${NM-unset}" in
+	unset) AC_CHECK_PROGS(NM, nm, nm) ;;
+	*) AC_CHECK_PROGS(NM, $NM nm, nm) ;;
+    esac
+    AC_MSG_CHECKING(nm flags)
+    case "${NMFLAGS-unset}" in
+	unset) NMFLAGS= ;;
+    esac
+    AC_MSG_RESULT($NMFLAGS)
+    AC_SUBST(NMFLAGS)
+])
+
+dnl
+dnl Set the top-level source-directory.
+dnl
+AC_DEFUN(UD_SRCDIR,
+[
+    AC_MSG_CHECKING(for top-level source-directory)
+    SRCDIR=`(cd $srcdir && pwd)`
+    AC_MSG_RESULT($SRCDIR)
+    AC_SUBST(SRCDIR)
+])
+
+dnl
+dnl Check for a Standard C compiler.  Prefer a native one over the
+dnl GNU one to reduce the chance that the environment variable LIBS
+dnl will have to be set to reference the GNU C runtime library.
+dnl
+AC_DEFUN(UD_PROG_CC,
+[
+    # Because we must have a C compiler, we treat an unset CC
+    # the same as an empty CC.
+    case "${CC}" in
+	'')
+	    case `uname` in
+		ULTRIX)
+		    # The native ULTRIX C compiler isn't standard.
+		    ccs='gcc cc'
+		    ;;
+		*)
+		    # xlc is before c89 because AIX's sizeof(long long)
+		    # differs between the two.
+		    #
+		    ccs='xlc c89 acc cc gcc'
+		    ;;
+	    esac
+	    for cc in $ccs; do
+		AC_CHECK_PROG(CC, $cc, $cc)
+		case "$CC" in
+		    '') ;;
+		    *)  break
+			;;
+		esac
+	    done
+	    case "${CC}" in
+		'')
+		    AC_MSG_ERROR("Could not find C compiler")
+		    ;;
+	    esac
+	    ;;
+    esac
+    #
+    # On some systems, a discovered compiler nevertheless won't
+    # work (due to licensing, for example); thus, we check the
+    # compiler with a test program.
+    # 
+    AC_MSG_CHECKING([C compiler "$CC"])
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+                      [AC_MSG_RESULT(works)],
+                      [AC_MSG_RESULT(failed to compile test program)])
+    AC_SUBST(CC)
+    case "$CC" in
+	*gcc*)
+	    GCC=yes		# Expected by autoconf(1) macros
+	    ;;
+    esac
+    case `uname -sr` in
+	'HP-UX A.09'*)
+	    AC_DEFINE(_HPUX_SOURCE)
+	    ;;
+    esac
+])
+
+dnl
+dnl Check for a C++ compiler.  Prefer a native one over the
+dnl GNU one to reduce the chance that the environment variable LIBS
+dnl will have to be set to reference the GNU C runtime library.
+dnl
+AC_DEFUN(UD_PROG_CXX,
+[
+    case "${CXX-unset}" in
+	unset)
+	    case `uname` in
+		AIX)
+		    preferred_cxx='xlC'
+		    ;;
+	    esac
+	    possible_cxxs="${preferred_cxx} CC cxx c++ g++ gcc"
+	    ;;
+	'') AC_MSG_WARN("Empty CXX variable")
+	    possible_cxxs=
+	    ;;
+	*)  possible_cxxs=$CXX
+	    ;;
+    esac
+    case "${possible_cxxs}" in
+	'') CXX=
+	    ;;
+	*)  AC_LANG_PUSH([C++])
+	    for cxx in $possible_cxxs; do
+		AC_CHECK_PROG(CXX, $cxx, $cxx)
+		case "$CXX" in
+		    '') ;;
+		    *)  # On some systems, a discovered compiler nevertheless
+			# won't work (because it's a script to a non-existent
+			# executable, for example); thus, we check the
+			# compiler with a test program.  We also test
+			# for <iostream.h> and the standard C++ library
+			# because we need these to work.
+			# 
+			AC_MSG_CHECKING(C++ compiler \"$CXX\")
+			AC_RUN_IFELSE([AC_LANG_SOURCE([[
+				#include <iostream.h>
+				int main() {
+				    cout << "";
+				    return 0;
+				}
+			    ]])],[
+				AC_MSG_RESULT(works)
+				break
+			    ],[
+				AC_MSG_WARN($CXX failed on test program)
+				CXX=
+				unset ac_cv_prog_CXX
+			    ],[])
+			;;
+		esac
+	    done
+	    AC_LANG_POP([C++])
+	    case "${CXX}" in
+		'') AC_MSG_WARN("Could not find working C++ compiler")
+		    AC_MSG_WARN(Setting CXX to the empty string)
+		    ;;
+	    esac
+	    ;;
+    esac
+    case "${CXX}" in
+	'') AC_MSG_WARN(The C++ interface will not be built)
+	    ;;
+    esac
+    AC_SUBST(CXX)
+    case `uname` in
+	'HP-UX A.09'*)
+	    AC_DEFINE(_HPUX_SOURCE)
+	    ;;
+    esac
+])
+
+
+dnl
+dnl like AC_TYPE_LONG_DOUBLE, except checks for 'long long'
+dnl
+AC_DEFUN(UD_C_LONG_LONG,
+[AC_MSG_CHECKING(for long long)
+AC_CACHE_VAL(ac_cv_c_long_long,
+[if test "$GCC" = yes; then
+  ac_cv_c_long_long=yes
+else
+AC_RUN_IFELSE([AC_LANG_SOURCE([[int main() {
+long long foo = 0;
+return(sizeof(long long) < sizeof(long)); }]])],
+[ac_cv_c_long_long=yes],
+[ac_cv_c_long_long=no],[:])
+fi])dnl
+AC_MSG_RESULT($ac_cv_c_long_long)
+if test $ac_cv_c_long_long = yes; then
+  AC_DEFINE(HAVE_LONG_LONG)
+fi
+])
+
+dnl 
+dnl UD_CHECK_IEEE
+dnl If the 'double' is not an IEEE double
+dnl or the 'float' is not and IEEE single,
+dnl define NO_IEEE_FLOAT
+dnl
+AC_DEFUN(UD_CHECK_IEEE,
+[
+AC_MSG_CHECKING(for IEEE floating point format)
+AC_RUN_IFELSE([AC_LANG_SOURCE([[#ifndef NO_FLOAT_H
+#include <float.h>
+#endif
+
+#define EXIT_NOTIEEE	1
+#define EXIT_MAYBEIEEE	0
+
+int
+main()
+{
+#if	defined(FLT_RADIX)	&& FLT_RADIX != 2
+		return EXIT_NOTIEEE;
+#elif	defined(DBL_MAX_EXP)	&& DBL_MAX_EXP != 1024
+		return EXIT_NOTIEEE;
+#elif	defined(DBL_MANT_DIG)	&& DBL_MANT_DIG != 53
+		return EXIT_NOTIEEE;
+#elif 	defined(FLT_MAX_EXP)	&& !(FLT_MAX_EXP == 1024 || FLT_MAX_EXP == 128)
+		return EXIT_NOTIEEE;
+#elif	defined(FLT_MANT_DIG)	&& !(FLT_MANT_DIG == 53 || FLT_MANT_DIG == 24)
+		return EXIT_NOTIEEE;
+#else
+	/* (assuming eight bit char) */
+	if(sizeof(double) != 8)
+		return EXIT_NOTIEEE;
+	if(!(sizeof(float) == 4 || sizeof(float) == 8))
+		return EXIT_NOTIEEE;
+
+	return EXIT_MAYBEIEEE;
+#endif
+}]])],[ac_cv_c_ieeefloat=yes],[ac_cv_c_ieeefloat=no],[:])
+AC_MSG_RESULT($ac_cv_c_ieeefloat)
+if test x$ac_cv_c_ieeefloat = xno; then
+  AC_DEFINE(NO_IEEE_FLOAT)
+fi
+])
+
+dnl Check for utility for generating makefile dependencies.
+dnl Should only be used at the UPC.
+dnl
+AC_DEFUN(UD_PROG_CC_MAKEDEPEND,
+[
+    AC_MSG_CHECKING(how to make dependencies)
+    case `uname -s` in
+	IRIX*|OSF1)
+	    CC_MAKEDEPEND='cc -M'
+	    ;;
+	SunOS)
+	    case `uname -r` in
+		4*)
+		    CC_MAKEDEPEND='cc -M'
+		    ;;
+		5*|*)
+		    CC_MAKEDEPEND='cc -xM'
+		    ;;
+	    esac
+	    ;;
+	ULTRIX)
+	    case `uname -m` in
+		RISC)
+		    CC_MAKEDEPEND='cc -M'
+		    ;;
+		VAX)	# Can't handle prototypes in netcdf.h
+		    ;;
+	    esac
+	    ;;
+	AIX)	# Writes to .u files rather than standard out
+	    ;;
+	HP-UX)	# Writes escaped newlines to standard error
+	    ;;
+    esac
+    case "${CC_MAKEDEPEND}" in
+	'')
+	    CC_MAKEDEPEND=false
+	    ;;
+    esac
+    AC_MSG_RESULT($CC_MAKEDEPEND)
+    AC_SUBST(CC_MAKEDEPEND)
+])
+
+
+dnl Check for Fortran-90 compiler.
+dnl
+AC_DEFUN(UD_PROG_F90,
+[
+    case "${F90+set}" in
+	set)
+	    AC_MSG_CHECKING(user-defined Fortran-90 compiler \"$F90\")
+            AC_LANG_PUSH([Fortran])
+            AC_COMPILE_IFELSE(
+               [AC_LANG_SOURCE([
+		   subroutine foo(bar)
+		   integer, intent(in) :: bar
+		   end subroutine foo
+               ])],
+               [AC_MSG_RESULT(works)],
+               [AC_MSG_RESULT(failed to compile test program)
+		unset F90
+               ]
+            )
+            AC_LANG_POP([Fortran])
+	    ;;
+	*)
+	    case "${FC+set}" in
+		set)
+		    F90=$FC
+		    F90FLAGS="${F90FLAGS-${FFLAGS--O}}"
+		    F90LIBS="${F90LIBS-${FLIBS}}"
+		    cat <<EOF >conftest.f90
+			program foo
+			call bar(1)
+			end
+			subroutine bar(bof)
+			integer, intent(in) :: bof
+			end
+EOF
+		    AC_MSG_CHECKING(\"$F90\" as Fortran-90 compiler)
+		    doit='$F90 -o conftest ${F90FLAGS} conftest.f90 ${F90LIBS}'
+		    if AC_TRY_EVAL(doit); then
+			doit=./conftest
+			if AC_TRY_EVAL(doit); then
+			    AC_MSG_RESULT(works)
+			else
+			    AC_MSG_RESULT(failed to build executable program)
+			    unset F90
+			fi
+		    else
+			AC_MSG_RESULT(failed to build test program)
+			unset F90
+		    fi
+		    ${RM} -f conftest*
+		    ;;
+	    esac
+	    case "${F90-unset}" in
+		unset)
+		    cat <<EOF >conftest.f90
+			program foo
+			call bar(1)
+			end
+			subroutine bar(bof)
+			integer, intent(in) :: bof
+			end
+EOF
+		    for f90 in xlf90 pgf90 f90; do
+			AC_CHECK_PROG(F90, $f90, $f90)
+			case "${F90}" in
+			    '')
+				;;
+			    *)
+				AC_MSG_CHECKING(Fortran-90 compiler \"$F90\")
+				doit='$F90 -o conftest ${F90FLAGS} conftest.f90 ${F90LIBS}'
+				if AC_TRY_EVAL(doit); then
+				    doit=./conftest
+				    if AC_TRY_EVAL(doit); then
+					AC_MSG_RESULT(works)
+					break
+				    else
+					AC_MSG_RESULT(
+					    failed to build executable program)
+					unset F90
+					unset ac_cv_prog_F90
+				    fi
+				else
+				    AC_MSG_RESULT(failed to build test program)
+				    unset F90
+				    unset ac_cv_prog_F90
+				fi
+				;;
+			esac
+		    done
+		    ${RM} -f conftest*
+		    case "${F90}" in
+			'') AC_MSG_WARN(
+			    "Could not find working Fortran-90 compiler")
+			    ;;
+		    esac
+		    ;;
+	    esac
+	    ;;
+    esac
+    case "${F90}" in
+	'')
+	    AC_MSG_WARN("The Fortran-90 interface will not be built")
+	    ;;
+	*f90*)
+	    case `uname -s` in
+		IRIX*)
+		    NETCDF_MOD=NETCDF.mod
+		    ;;
+		*)
+		    NETCDF_MOD=netcdf.mod
+		    ;;
+	    esac
+	    AC_SUBST(NETCDF_MOD)
+	    ;;
+    esac
+    AC_SUBST(F90)
+    AC_SUBST(F90FLAGS)
+    AC_SUBST(F90LIBS)
+])
+
+dnl Check for Fortran-77 compiler.
+dnl
+AC_DEFUN(UD_PROG_FC,
+[
+    AC_BEFORE([UD_FORTRAN_TYPES])
+    case "${FC+set}" in
+	set)
+	    case "$FC" in
+		'')
+		    AC_MSG_WARN(Fortran-77 compiler is explicitly set to null)
+		    ;;
+		*)
+		    AC_MSG_CHECKING(user-defined Fortran-77 compiler \"$FC\")
+                    AC_LANG_PUSH([Fortran 77])
+                    AC_COMPILE_IFELSE([AC_LANG_CALL([],[FOO])],
+                       [AC_MSG_RESULT(works)],
+                       [AC_MSG_RESULT(failed to compile test program)
+                        FC=
+                       ]
+                    )
+                    AC_LANG_POP([Fortran 77])
+		    ;;
+	    esac
+	    ;;
+	*)
+            dnl FC is not set, let's try F90 as FC if F90 is set
+	    case "${F90+set}" in
+		set)
+		    FC=$F90
+		    FFLAGS="${FFLAGS-${F90FLAGS--O}}"
+		    FLIBS="${FLIBS-${F90LIBS-}}"
+		    AC_MSG_CHECKING(\"$FC\" as Fortran-77 compiler)
+                    AC_LANG_PUSH([Fortran])
+                    AC_COMPILE_IFELSE([AC_LANG_CALL([],[FOO])],
+                       [AC_MSG_RESULT(works)],
+                       [AC_MSG_RESULT(failed to compile test program)
+			unset FC
+                       ]
+                    )
+                    AC_LANG_POP([Fortran])
+		    ;;
+		*)
+		    ;;
+	    esac
+	    case "${FC-unset}" in
+		unset)
+		    case `uname -sr` in
+			AIX*)
+			    # xlf90(1) thinks fortran/ftest.F has bad syntax.
+			    forts="xlf f77 gfortran"
+			    ;;
+			BSD/OS*|FreeBSD*)
+			    forts="f77 fort77 g77 gfortran"
+			    ;;
+			HP-UX*)
+			    # f77(1) doesn't have the -L option.
+			    forts=fort77
+			    FLIBS=-lU77
+			    ;;
+			IRIX*)
+			    # f90(1) can't link with c89(1)-compiled objects
+			    forts=f77
+			    ;;
+			IRIX64*)
+			    forts='f77 g77 gfortran fort77 '
+			    ;;
+			Linux*)
+			    forts="pgf90 f77 fort77 g77 gfortran"
+			    ;;
+			OSF1*)
+			    # The use of f90(1) results in the following for
+			    # an unknown reason (`make' works in the fortran/
+			    # directory):
+			    # f90 -c -I../libsrc ftest.F 
+			    # Last chance handler: pc = 0xa971b8, 
+			    # sp = 0x3fece0, ra = 0xa971b8
+			    # Last chance handler: internal exception: unwinding
+			    forts="f77 gfortran"
+			    ;;
+			'SunOS 4'*)
+			    forts='f77 g77 gfortran fort77'
+			    ;;
+			'SunOS 5'*)
+			    # SunOS's f90(1) has problems passing a C `char'
+			    # as a Fortran `integer*1' => use f77(1)
+			    forts="pgf90 f77"
+			    ;;
+			sn*|UNICOS*|unicos*)
+			    forts="fort77 cf77 f77 g77 gfortran f90"
+			    ;;
+			*)
+			    forts="xlf fort77 ghf77 f77 cf77 g77 gfortran xlf90 f90"
+			    ;;
+		    esac
+		    for fc in $forts; do
+			AC_CHECK_PROG(FC, $fc, $fc)
+			case "${FC}" in
+			    '')
+				;;
+			    *)
+				#
+				# On some systems, a discovered compiler
+				# nevertheless won't work (due to licensing,
+				# for example); thus, we check the compiler
+				# with a test program.
+				# 
+                                AC_LANG_PUSH([Fortran])
+                                AC_COMPILE_IFELSE([AC_LANG_CALL([],[FOO])],
+                                   [AC_MSG_RESULT(works)],
+                                   [AC_MSG_RESULT(failed to compile test program)
+			            unset FC
+				    unset ac_cv_prog_FC
+                                   ]
+                                )
+                                AC_LANG_POP([Fortran])
+				;;
+			esac
+		    done
+		    ${RM} -f conftest.*
+		    case "${FC}" in
+			'') AC_MSG_WARN(
+				"Could not find working Fortran-77 compiler")
+			    ;;
+		    esac
+		    ;;
+	    esac
+	    ;;
+    esac
+    case "${FC}" in
+	'') AC_MSG_WARN("The Fortran-77 interface will not be built")
+	    ;;
+    esac
+    AC_SUBST(FC)
+    AC_SUBST(FFLAGS)
+    AC_SUBST(FLIBS)
+    #
+    # Set the make(1) macro for compiling a .F file.
+    #
+    case "${FPP-}" in
+    '')
+	AC_MSG_CHECKING(for Fortran .F compiler)
+	AC_MSG_RESULT($COMPILE_F)
+	case "${COMPILE_F-unset}" in
+	unset)
+	    case "${FC}" in
+	    '')
+		COMPILE_F=
+		;;
+	    *)
+		cat >conftest.h <<\EOF
+#define J 1
+EOF
+                AC_LANG_PUSH([Fortran])
+                AC_FC_SRCEXT([F])
+		AC_MSG_CHECKING(if Fortran-77 compiler handles *.F files)
+                AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[
+#include "conftest.h"
+#define N 5
+		  real r(J,N)
+                   ])],
+                   [AC_MSG_RESULT(yes)
+                    COMPILE_F='$(COMPILE.f)'],
+                   [AC_MSG_RESULT(no)
+		    COMPILE_F=
+                   ]
+                )
+                AC_FC_SRCEXT([f])
+                AC_LANG_POP([Fortran])
+		${RM} -f conftest.h
+		;;
+	    esac
+	    ;;
+	esac
+	;;
+    *)
+	unset COMPILE_F
+	;;
+    esac
+    case "${COMPILE_F-}" in
+	'') UD_PROG_FPP;;
+    esac
+    AC_SUBST(COMPILE_F)
+    FPPFLAGS=${FPPFLAGS-}
+    AC_SUBST(FPPFLAGS)
+])
+
+
+dnl Check for Fortran preprocessor.
+dnl
+AC_DEFUN(UD_PROG_FPP,
+[
+    AC_MSG_CHECKING(for Fortran preprocessor)
+    case "$FPP" in
+    '')
+	AC_REQUIRE([AC_PROG_CPP])
+	FPP="$CPP"
+	;;
+    esac
+    AC_MSG_RESULT($FPP)
+    AC_SUBST(FPP)
+])
+
+
+dnl Check for a Fortran type equivalent to a netCDF type.
+dnl
+dnl UD_CHECK_FORTRAN_NCTYPE(forttype, possibs, nctype)
+dnl
+AC_DEFUN(UD_CHECK_FORTRAN_NCTYPE,
+[
+    AC_MSG_CHECKING([for Fortran-equivalent to netCDF "$3"])
+dnl     for type in $2; do
+dnl         cat >conftest.f <<EOF
+dnl                $type foo
+dnl                end
+dnl EOF
+dnl         doit='$FC -c ${FFLAGS} conftest.f'
+dnl         if AC_TRY_EVAL(doit); then
+dnl             break
+dnl         fi
+dnl     done
+dnl     ${RM} -f conftest.f conftest.o
+
+    AC_LANG_PUSH([Fortran])
+    for type in $2; do
+        AC_COMPILE_IFELSE(
+           [AC_LANG_SOURCE([
+               $type foo
+               end
+           ])],
+           [break]
+        )
+    done
+    AC_LANG_POP([Fortran])
+    AC_DEFINE_UNQUOTED($1, $type)
+    AC_MSG_RESULT($type)
+    $1=$type
+])
+
+
+dnl Check for a Fortran type equivalent to a C type.
+dnl
+dnl UD_CHECK_FORTRAN_CTYPE(v3forttype, v2forttype, ctype, min, max)
+dnl
+AC_DEFUN(UD_CHECK_FORTRAN_CTYPE,
+[
+    AC_MSG_CHECKING([for Fortran-equivalent to C "$3"])
+    AC_LANG_PUSH([Fortran])
+    AC_COMPILE_IFELSE(
+       [AC_LANG_SOURCE([
+        subroutine sub(values, minval, maxval)
+        implicit        none
+        $2              values(5), minval, maxval
+        minval = values(2)
+        maxval = values(4)
+        if (values(2) .ge. values(4)) then
+            minval = values(4)
+            maxval = values(2)
+        endif
+        end
+       ])],
+       [found_f2c=yes], [found_f2c=no]
+    )
+    AC_LANG_POP([Fortran])
+    if test "x${found_f2c}" = xyes ; then
+dnl     cat >conftest.f <<EOF
+dnl         subroutine sub(values, minval, maxval)
+dnl         implicit        none
+dnl         $2              values(5), minval, maxval
+dnl         minval = values(2)
+dnl         maxval = values(4)
+dnl         if (values(2) .ge. values(4)) then
+dnl             minval = values(4)
+dnl             maxval = values(2)
+dnl         endif
+dnl         end
+dnl EOF
+dnl     doit='$FC -c ${FFLAGS} conftest.f'
+dnl     if AC_TRY_EVAL(doit); then
+dnl         mv conftest.o conftestf.o
+	cat >conftest.c <<EOF
+#include <limits.h>
+#include <float.h>
+void main()
+{
+$3		values[[]] = {0, $4, 0, $5, 0};
+$3		minval, maxval;
+int	$FCALLSCSUB($3*, $3*, $3*);
+$FCALLSCSUB(values, &minval, &maxval);
+return(!(minval == $4 && maxval == $5));
+}
+EOF
+	doit='$CC -o conftest ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} conftest.c conftestf.o ${LIBS}'
+	if AC_TRY_EVAL(doit); then
+	    doit=./conftest
+	    if AC_TRY_EVAL(doit); then
+		AC_MSG_RESULT($2)
+		$1=$2
+		AC_DEFINE_UNQUOTED($1,$2)
+	    else
+		AC_MSG_RESULT(no equivalent type)
+		unset $1
+	    fi
+	else
+	    AC_MSG_ERROR(Could not compile-and-link conftest.c and conftestf.o)
+	fi
+    else
+	AC_MSG_ERROR(Could not compile conftest.f)
+    fi
+    ${RM} -f conftest*
+    unset found_f2c
+])
+
+
+dnl Check for a Fortran data type.
+dnl
+dnl UD_CHECK_FORTRAN_TYPE(varname, ftypes)
+dnl
+AC_DEFUN(UD_CHECK_FORTRAN_TYPE,
+[
+    AC_LANG_PUSH([Fortran])
+    for ftype in $2; do
+	AC_MSG_CHECKING([for Fortran "$ftype"])
+        AC_COMPILE_IFELSE(
+           [AC_LANG_SOURCE([
+               subroutine sub(value)
+               $ftype value
+               end
+           ])],
+           [AC_MSG_RESULT(yes)
+	    $1=$ftype
+	    AC_DEFINE_UNQUOTED([$1], [$ftype])
+            break],
+           [AC_MSG_RESULT(no)]
+        )
+    done
+    AC_LANG_POP([Fortran])
+])
+
+
+dnl Check for the name format of a Fortran-callable C routine.
+dnl
+dnl UD_CHECK_FCALLSCSUB
+AC_DEFUN([UD_CHECK_FCALLSCSUB],
+[
+    dnl AC_REQUIRE([UD_PROG_FC])
+    case "$FC" in
+	'') ;;
+	*)
+	    AC_REQUIRE([UD_PROG_NM])
+	    AC_BEFORE([UD_CHECK_FORTRAN_CTYPE])
+	    AC_BEFORE([UD_CHECK_CTYPE_FORTRAN])
+	    AC_MSG_CHECKING([for C-equivalent to Fortran routine "SUB"])
+            AC_FC_FUNC([sub], [FCALLSCSUB])
+            AC_MSG_RESULT([$FCALLSCSUB])
+	    ;;
+    esac
+])
+
+
+dnl Check for a C type equivalent to a Fortran type.
+dnl
+dnl UD_CHECK_CTYPE_FORTRAN(ftype, ctypes, fmacro_root)
+dnl
+AC_DEFUN(UD_CHECK_CTYPE_FORTRAN,
+[
+    cat >conftestf.f <<EOF
+           $1 values(4)
+           integer status, sub
+           data values /-1, -2, -3, -4/
+           status = sub(values)
+           end
+EOF
+    ac_cv_ctype_fortran=no
+    AC_MSG_CHECKING([if Fortran "$1" is ])
+    for ctype in $2; do
+	dnl AC_MSG_CHECKING(if Fortran \"$1\" is C \"$ctype\")
+	cat >conftest.c <<EOF
+	    int $FCALLSCSUB($ctype values[[4]])
+	    {
+		return(values[[1]] != -2 || values[[2]] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if AC_TRY_EVAL(doit); then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if AC_TRY_EVAL(doit); then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LDFLAGS} ${LIBS}'
+	        if AC_TRY_EVAL(doit); then
+		    doit=./conftest
+		    if AC_TRY_EVAL(doit); then
+		        dnl AC_MSG_RESULT(yes)
+		        AC_MSG_RESULT(["$ctype" in C])
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        AC_DEFINE_UNQUOTED(NF_$3[]_IS_C_$cname)
+                        ac_cv_ctype_fortran=yes
+		        break
+		    fi
+	        else
+		    AC_MSG_ERROR([Could not link conftestf.o and conftest.o])
+	        fi
+	    else
+		AC_MSG_ERROR([Could not compile conftestf.f])
+	    fi
+	else
+	    AC_MSG_ERROR([Could not compile conftest.c])
+	fi
+    done
+    ${RM} -f conftest*
+
+    if test "$ac_cv_ctype_fortran" = no ; then
+        AC_MSG_RESULT(no correspond data type in C)
+    fi
+    unset ac_cv_ctype_fortran
+])
+
+
+dnl Get information about Fortran data types.
+dnl
+AC_DEFUN([UD_FORTRAN_TYPES],
+[
+    dnl AC_REQUIRE([UD_PROG_FC])
+    case "$FC" in
+    '')
+	;;
+    *)
+	AC_REQUIRE([UD_CHECK_FCALLSCSUB])
+	UD_CHECK_FORTRAN_TYPE([NF_INT1_T], [integer*1 byte "integer(kind=1)"])
+	UD_CHECK_FORTRAN_TYPE([NF_INT2_T], [integer*2 "integer(kind=2)"])
+	UD_CHECK_FORTRAN_TYPE([NF_INT8_T], [integer*8 "integer(kind=8)"])
+
+	case "${NF_INT1_T}" in
+	    '') ;;
+	    *)  UD_CHECK_CTYPE_FORTRAN($NF_INT1_T, "signed char" short int long, INT1)
+		;;
+	esac
+	case "${NF_INT2_T}" in
+	    '') ;;
+	    *)  UD_CHECK_CTYPE_FORTRAN($NF_INT2_T, short int long, INT2)
+		;;
+	esac
+	case "${NF_INT8_T}" in
+	    '') ;;
+	    *)  UD_CHECK_CTYPE_FORTRAN($NF_INT8_T, int long "long long", INT8)
+		;;
+	esac
+	UD_CHECK_CTYPE_FORTRAN(integer, int long, INT)
+	UD_CHECK_CTYPE_FORTRAN(real, float double, REAL)
+	UD_CHECK_CTYPE_FORTRAN(doubleprecision, double float, DOUBLEPRECISION)
+
+	UD_CHECK_FORTRAN_NCTYPE(NCBYTE_T, byte integer*1 integer, byte)
+
+	UD_CHECK_FORTRAN_NCTYPE(NCSHORT_T, integer*2 integer, short)
+dnl	UD_CHECK_FORTRAN_CTYPE(NF_SHORT_T, $NCSHORT_T, short, SHRT_MIN, SHRT_MAX)
+
+dnl	UD_CHECK_FORTRAN_NCTYPE(NCLONG_T, integer*4 integer, long)
+dnl	UD_CHECK_FORTRAN_CTYPE(NF_INT_T, integer, int, INT_MIN, INT_MAX)
+
+dnl	UD_CHECK_FORTRAN_NCTYPE(NCFLOAT_T, real*4 real, float)
+dnl	UD_CHECK_FORTRAN_CTYPE(NF_FLOAT_T, $NCFLOAT_T, float, FLT_MIN, FLT_MAX)
+
+dnl	UD_CHECK_FORTRAN_NCTYPE(NCDOUBLE_T, real*8 doubleprecision real, double)
+dnl	UD_CHECK_FORTRAN_CTYPE(NF_DOUBLE_T, $NCDOUBLE_T, double, DBL_MIN, DBL_MAX)
+	;;
+    esac
+])
+
+
+dnl Setup for making a manual-page database.
+dnl
+AC_DEFUN(UD_MAKEWHATIS,
+[
+    #
+    # NB: We always want to define WHATIS to prevent the
+    # $(MANDIR)/$(WHATIS) make(1) target from being just $(MANDIR)/ and
+    # conflicting with the (directory creation) target with the same name.
+    #
+    WHATIS=whatis
+    case `uname -sr` in
+	BSD/OS*|FreeBSD*)
+	    # Can't generate a user-database -- only /usr/share/man/whatis.db.
+	    MAKEWHATIS_CMD=
+	    ;;
+	'IRIX64 6.5'|'IRIX 6.5')
+	    MAKEWHATIS_CMD='/usr/lib/makewhatis -M $(MANDIR) $(MANDIR)/whatis'
+	    ;;
+	'IRIX 6'*)
+	    # Can't generate a user-database.
+	    MAKEWHATIS_CMD=
+	    ;;
+	HP-UX*)
+	    # Can't generate a user-database -- only /usr/lib/whatis.
+	    MAKEWHATIS_CMD=
+	    ;;
+	'Linux '*)
+	    # /usr/sbin/makewhatis doesn't work
+	    MAKEWHATIS_CMD=
+	    ;;
+	ULTRIX*)
+	    # Can't generate a user-database -- only /usr/lib/whatis.
+	    MAKEWHATIS_CMD=
+	    ;;
+	*)
+	    if test -r /usr/man/windex; then
+		WHATIS=windex
+	    fi
+	    AC_CHECK_PROGS(prog, catman makewhatis /usr/lib/makewhatis)
+	    case "$prog" in
+		*catman*)
+		    MAKEWHATIS_CMD=$prog' -w -M $(MANDIR)'
+		    ;;
+		*makewhatis*)
+		    MAKEWHATIS_CMD=$prog' $(MANDIR)'
+		    ;;
+	    esac
+	    ;;
+    esac
+    AC_SUBST(WHATIS)
+    AC_SUBST(MAKEWHATIS_CMD)
+    AC_MSG_CHECKING(for manual-page index command)
+    AC_MSG_RESULT($MAKEWHATIS_CMD)
+])
+
+
+dnl Check for the math library.
+dnl
+AC_DEFUN(UD_CHECK_LIB_MATH,
+[
+    dnl AS_MESSAGE([checking for math library...])
+    case "${MATHLIB}" in
+	'')
+	    AC_CHECK_LIB(c, floor, MATHLIB=,
+		    AC_CHECK_LIB(m, floor, MATHLIB=-lm, MATHLIB=))
+	    ;;
+	*)
+	    AC_MSG_RESULT($MATHLIB (user defined))
+	    ;;
+    esac
+    AC_SUBST(MATHLIB)
+])
+
+dnl steal from autoconf 2.69
+AC_DEFUN([UD_FC_PP_SRCEXT],
+[AC_LANG_PUSH(Fortran)dnl
+AC_CACHE_CHECK([for Fortran flag to compile preprocessed .$1 files],
+                ac_cv_fc_pp_srcext_$1,
+[ac_ext=$1
+FCFLAGS_SRCEXT_save=$FCFLAGS_SRCEXT
+FCFLAGS_SRCEXT=
+ac_fcflags_pp_srcext_save=$ac_fcflags_srcext
+ac_fcflags_srcext=
+ac_cv_fc_pp_srcext_$1=unknown
+case $ac_ext in #(
+  [[fF]]77) ac_try=f77-cpp-input;; #(
+  [[fF]]) ac_try=f77-cpp-input;; #(
+  *) ac_try=f95-cpp-input;;
+esac
+for ac_flag in none -ftpp -fpp -Tf "-fpp -Tf" -xpp=fpp -Mpreprocess "-e Z" \
+               -cpp -xpp=cpp -qsuffix=cpp=$1 "-x $ac_try" +cpp -Cpp; do
+  test "x$ac_flag" != xnone && FCFLAGS_SRCEXT="$ac_flag" && ac_fcflags_srcext="$ac_flag"
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[
+#if 0
+#include <ac_nonexistent.h>
+      choke me
+#endif]])],
+    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[
+#if 1
+#include <ac_nonexistent.h>
+      choke me
+#endif]])],
+       [],
+       [ac_cv_fc_pp_srcext_$1=$ac_flag; break])])
+done
+${RM} -f conftest.$ac_objext conftest.$1
+FCFLAGS_SRCEXT=$FCFLAGS_SRCEXT_save
+ac_fcflags_srcext=$ac_fcflags_pp_srcext_save
+])
+if test "x$ac_cv_fc_pp_srcext_$1" = xunknown; then
+  m4_default([$3],
+             [AC_MSG_ERROR([Fortran could not compile preprocessed .$1 files])])
+else
+  ac_fc_srcext=$1
+  if test "x$ac_cv_fc_pp_srcext_$1" = xnone; then
+    FCFLAGS_SRCEXT=""
+    ac_cv_fc_pp_srcext_$1=""
+    dnl FCPPFLAGS_[]$1[]=""
+  else
+    FCFLAGS_SRCEXT=$ac_cv_fc_pp_srcext_$1
+    dnl FCPPFLAGS_[]$1[]=$ac_cv_fc_pp_srcext_$1
+  fi
+  dnl AC_SUBST(FCPPFLAGS_[]$1)
+  $2
+fi
+AC_LANG_POP(Fortran)dnl
+])# UD_FC_PP_SRCEXT
+
+dnl steal from autoconf 2.69
+AC_DEFUN([UD_FC_PP_DEFINE],
+[AC_LANG_PUSH([Fortran])dnl
+ac_fc_pp_define_srcext_save=$ac_fc_srcext
+ac_ext_saved=$ac_ext
+UD_FC_PP_SRCEXT([F])
+ac_ext=F
+AC_CACHE_CHECK([how to define symbols for preprocessed Fortran],
+  [ac_cv_fc_pp_define],
+[ac_fc_pp_define_srcext_save=$ac_fc_srcext
+ac_cv_fc_pp_define=unknown
+ac_fc_pp_define_FCFLAGS_save=$FCFLAGS
+for ac_flag in -D -WF,-D -Wp,-D -Wc,-D
+do
+  FCFLAGS="$ac_fc_pp_define_FCFLAGS_save ${ac_flag}FOOBAR ${ac_flag}ZORK=42"
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[
+#ifndef FOOBAR
+      choke me
+#endif
+#if ZORK != 42
+      choke me
+#endif]])],
+    [ac_cv_fc_pp_define=$ac_flag])
+  test x"$ac_cv_fc_pp_define" != xunknown && break
+done
+FCFLAGS=$ac_fc_pp_define_FCFLAGS_save
+])
+ac_fc_srcext=$ac_fc_pp_define_srcext_save
+if test "x$ac_cv_fc_pp_define" = xunknown; then
+  FC_DEFINE=
+  m4_default([$2],
+             [AC_MSG_ERROR([Fortran does not allow to define preprocessor symbols], 77)])
+else
+  FC_DEFINE=$ac_cv_fc_pp_define
+  $1
+fi
+ac_ext=$ac_ext_saved
+AC_SUBST([FC_DEFINE])dnl
+AC_LANG_POP([Fortran])dnl
+])
+
+# AC_PROG_FC_MOD
+# ---------------
+dnl Note that Mac OSX file system is case-insensitive, so this function does
+dnl not work precisely on Mac. Hence, we check whether the file system can
+dnl find the file with name in lowercase. If not, we say the mod file is in
+dnl uppercase.
+AC_DEFUN([UD_PROG_FC_UPPERCASE_MOD],
+[
+AC_REQUIRE([UD_FC_MODULE_EXTENSION])
+AC_LANG_PUSH(Fortran)
+AC_MSG_CHECKING([if Fortran 90 compiler capitalizes .mod filenames])
+AC_COMPILE_IFELSE(
+    [AC_LANG_SOURCE([
+        module conftest
+        end module conftest
+    ])]
+)
+dnl ac_try='$F90 ${F90FLAGS} conftest.f90 ${F90LIBS}>&AS_MESSAGE_LOG_FD'
+dnl AC_TRY_EVAL(ac_try)
+if test -f conftest.${FC_MODEXT} ; then
+   ac_cv_prog_f90_uppercase_mod=no
+else
+   ac_cv_prog_f90_uppercase_mod=yes
+   ${RM} -f CONFTEST.${FC_MODEXT}
+fi
+AC_MSG_RESULT($ac_cv_prog_f90_uppercase_mod)
+${RM} -f conftest*
+AC_LANG_POP(Fortran)
+])
+
+dnl steal from autoconf 2.69
+# UD_FC_MODULE_EXTENSION
+# ----------------------
+# Find the Fortran 90 module file extension.  The module extension is stored
+# in the variable FC_MODEXT and empty if it cannot be determined.  The result
+# or "unknown" is cached in the cache variable ac_cv_fc_module_ext.
+AC_DEFUN([UD_FC_MODULE_EXTENSION],
+[AC_CACHE_CHECK([Fortran 90 module extension], [ac_cv_fc_module_ext],
+[AC_LANG_PUSH(Fortran)
+mkdir conftest.dir
+cd conftest.dir
+ac_cv_fc_module_ext=unknown
+AC_COMPILE_IFELSE([[
+      module conftest_module
+      contains
+      subroutine conftest_routine
+      write(*,'(a)') 'gotcha!'
+      end subroutine
+      end module]],
+  [ac_cv_fc_module_ext=`ls | sed -n 's,conftest_module\.,,p'`
+   if test x$ac_cv_fc_module_ext = x; then
+dnl Some F90 compilers use upper case characters for the module file name.
+     ac_cv_fc_module_ext=`ls | sed -n 's,CONFTEST_MODULE\.,,p'`
+   fi])
+cd ..
+${RM} -rf conftest.dir
+AC_LANG_POP(Fortran)
+])
+FC_MODEXT=$ac_cv_fc_module_ext
+if test "$FC_MODEXT" = unknown; then
+  FC_MODEXT=
+fi
+AC_SUBST([FC_MODEXT])dnl
+])
+
+dnl steal from autoconf 2.69
+# UD_FC_MODULE_FLAG([ACTION-IF-SUCCESS], [ACTION-IF-FAILURE = FAILURE])
+# ---------------------------------------------------------------------
+# Find a flag to include Fortran 90 modules from another directory.
+# If successful, run ACTION-IF-SUCCESS (defaults to nothing), otherwise
+# run ACTION-IF-FAILURE (defaults to failing with an error message).
+# The module flag is cached in the ac_cv_fc_module_flag variable.
+# It may contain significant trailing whitespace.
+#
+# Known flags:
+# gfortran: -Idir, -I dir (-M dir, -Mdir (deprecated), -Jdir for writing)
+# g95: -I dir (-fmod=dir for writing)
+# SUN: -Mdir, -M dir (-moddir=dir for writing;
+#                     -Idir for includes is also searched)
+# HP: -Idir, -I dir (+moddir=dir for writing)
+# IBM: -Idir (-qmoddir=dir for writing)
+# Intel: -Idir -I dir (-mod dir for writing)
+# Absoft: -pdir
+# Lahey: -mod dir
+# Cray: -module dir, -p dir (-J dir for writing)
+#       -e m is needed to enable writing .mod files at all
+# Compaq: -Idir
+# NAGWare: -I dir (-mdir dir for writing)
+# PathScale: -I dir  (but -module dir is looked at first)
+# Portland: -module dir (first -module also names dir for writing)
+# Fujitsu: -Am -Idir (-Mdir for writing is searched first, then '.', then -I)
+#                    (-Am indicates how module information is saved)
+AC_DEFUN([UD_FC_MODULE_FLAG],[
+AC_CACHE_CHECK([Fortran 90 module inclusion flag], [ac_cv_fc_module_flag],
+[AC_LANG_PUSH([Fortran])
+ac_cv_fc_module_flag=unknown
+mkdir conftest.dir
+cd conftest.dir
+AC_COMPILE_IFELSE([[
+      module conftest_module
+      contains
+      subroutine conftest_routine
+      write(*,'(a)') 'gotcha!'
+      end subroutine
+      end module]],
+  [cd ..
+   ac_fc_module_flag_FCFLAGS_save=$FCFLAGS
+   # Flag ordering is significant for gfortran and Sun.
+   for ac_flag in -I '-I ' -M '-M ' -p '-mod ' '-mdir ' '-module ' '-Am -I'; do
+     # Add the flag twice to prevent matching an output flag.
+     FCFLAGS="$ac_fc_module_flag_FCFLAGS_save ${ac_flag}conftest.dir ${ac_flag}conftest.dir"
+     AC_COMPILE_IFELSE([[
+      program main
+      use conftest_module
+      call conftest_routine
+      end]],
+       [ac_cv_fc_module_flag="$ac_flag"])
+     if test "$ac_cv_fc_module_flag" != unknown; then
+       break
+     fi
+   done
+   FCFLAGS=$ac_fc_module_flag_FCFLAGS_save
+])
+${RM} -rf conftest.dir
+AC_LANG_POP([Fortran])
+])
+if test "$ac_cv_fc_module_flag" != unknown; then
+  FC_MODINC=$ac_cv_fc_module_flag
+  $1
+else
+  FC_MODINC=
+  m4_default([$2],
+    [AC_MSG_ERROR([unable to find compiler flag for module search path])])
+fi
+AC_SUBST([FC_MODINC])
+# Ensure trailing whitespace is preserved in a Makefile.
+AC_SUBST([ac_empty], [""])
+AC_CONFIG_COMMANDS_PRE([case $FC_MODINC in #(
+  *\ ) FC_MODINC=$FC_MODINC'${ac_empty}' ;;
+esac])dnl
+])
+
+
+dnl steal from autoconf 2.69
+# UD_FC_MODULE_OUTPUT_FLAG([ACTION-IF-SUCCESS], [ACTION-IF-FAILURE = FAILURE])
+# ----------------------------------------------------------------------------
+# Find a flag to write Fortran 90 module information to another directory.
+# If successful, run ACTION-IF-SUCCESS (defaults to nothing), otherwise
+# run ACTION-IF-FAILURE (defaults to failing with an error message).
+# The module flag is cached in the ac_cv_fc_module_output_flag variable.
+# It may contain significant trailing whitespace.
+#
+# For known flags, see the documentation of AC_FC_MODULE_FLAG above.
+AC_DEFUN([UD_FC_MODULE_OUTPUT_FLAG],[
+AC_CACHE_CHECK([Fortran 90 module output flag], [ac_cv_fc_module_output_flag],
+[AC_LANG_PUSH([Fortran])
+mkdir conftest.dir conftest.dir/sub
+cd conftest.dir
+ac_cv_fc_module_output_flag=unknown
+ac_fc_module_output_flag_FCFLAGS_save=$FCFLAGS
+# Flag ordering is significant: put flags late which some compilers use
+# for the search path.
+for ac_flag in -J '-J ' -fmod= -moddir= +moddir= -qmoddir= '-mod ' \
+	      '-mdir ' '-module ' -M '-Am -M' '-e m -J '; do
+  FCFLAGS="$ac_fc_module_output_flag_FCFLAGS_save ${ac_flag}sub"
+  AC_COMPILE_IFELSE([[
+      module conftest_module
+      contains
+      subroutine conftest_routine
+      write(*,'(a)') 'gotcha!'
+      end subroutine
+      end module]],
+    [cd sub
+     AC_COMPILE_IFELSE([[
+      program main
+      use conftest_module
+      call conftest_routine
+      end]],
+       [ac_cv_fc_module_output_flag="$ac_flag"])
+     cd ..
+     if test "$ac_cv_fc_module_output_flag" != unknown; then
+       break
+     fi])
+done
+FCFLAGS=$ac_fc_module_output_flag_FCFLAGS_save
+cd ..
+${RM} -rf conftest.dir
+AC_LANG_POP([Fortran])
+])
+if test "$ac_cv_fc_module_output_flag" != unknown; then
+  FC_MODOUT=$ac_cv_fc_module_output_flag
+  $1
+else
+  FC_MODOUT=
+  m4_default([$2],
+    [AC_MSG_ERROR([unable to find compiler flag to write module information to])])
+fi
+AC_SUBST([FC_MODOUT])
+# Ensure trailing whitespace is preserved in a Makefile.
+AC_SUBST([ac_empty], [""])
+AC_CONFIG_COMMANDS_PRE([case $FC_MODOUT in #(
+  *\ ) FC_MODOUT=$FC_MODOUT'${ac_empty}' ;;
+esac])dnl
+])
+
+dnl steal from autoconf 2.69
+# AC_FC_FREEFORM([ACTION-IF-SUCCESS], [ACTION-IF-FAILURE = FAILURE])
+# ------------------------------------------------------------------
+# Look for a compiler flag to make the Fortran (FC) compiler accept
+# free-format source code, and adds it to FCFLAGS.  Call
+# ACTION-IF-SUCCESS (defaults to nothing) if successful (i.e. can
+# compile code using new extension) and ACTION-IF-FAILURE (defaults to
+# failing with an error message) if not.  (Defined via DEFUN_ONCE to
+# prevent flag from being added to FCFLAGS multiple times.)
+#
+# The known flags are:
+#        -ffree-form: GNU g77, gfortran, g95
+#         -FR, -free: Intel compiler (icc, ecc, ifort)
+#              -free: Compaq compiler (fort), Sun compiler (f95)
+# -qfree=f90, -qfree: IBM compiler (xlf)
+# -Mfree, -Mfreeform: Portland Group compiler
+#          -freeform: SGI compiler
+#        -8, -f free: Absoft Fortran
+#       +source=free: HP Fortran
+#    (-)-nfix, -Free: Lahey/Fujitsu Fortran
+#              -free: NAGWare
+#         -f, -Wf,-f: f2c (but only a weak form of "free-form" and long lines)
+# We try to test the "more popular" flags first, by some prejudiced
+# notion of popularity.
+AC_DEFUN_ONCE([UD_FC_FREEFORM],
+[AC_LANG_PUSH([Fortran])dnl
+AC_CACHE_CHECK([for Fortran flag needed to accept free-form source],
+	       [ac_cv_fc_freeform],
+[ac_cv_fc_freeform=unknown
+ac_fc_freeform_FCFLAGS_save=$FCFLAGS
+for ac_flag in none -ffree-form -FR -free -qfree=f90 -qfree -Mfree -Mfreeform \
+	       -freeform "-f free" -8 +source=free -nfix --nfix -Free
+do
+  test "x$ac_flag" != xnone && FCFLAGS="$ac_fc_freeform_FCFLAGS_save $ac_flag"
+dnl Use @&t@ below to ensure that editors don't turn 8+ spaces into tab.
+  AC_COMPILE_IFELSE([[
+  program freeform
+       ! FIXME: how to best confuse non-freeform compilers?
+       print *, 'Hello ', &
+     @&t@     'world.'
+       end]],
+		    [ac_cv_fc_freeform=$ac_flag; break])
+done
+${RM} -f conftest.err conftest.$ac_objext conftest.$ac_ext
+FCFLAGS=$ac_fc_freeform_FCFLAGS_save
+])
+if test "x$ac_cv_fc_freeform" = xunknown; then
+  m4_default([$2],
+	     [AC_MSG_WARN([Fortran $FC does not accept free-form source], 77)])
+else
+  dnl Do not append to FCFLAGS
+  dnl if test "x$ac_cv_fc_freeform" != xnone; then
+  dnl   FCFLAGS="$FCFLAGS $ac_cv_fc_freeform"
+  dnl fi
+  if test "x$ac_cv_fc_freeform" = xnone; then
+     ac_cv_fc_freeform=
+  fi
+  $1
+fi
+AC_LANG_POP([Fortran])dnl
+])# AC_FC_FREEFORM
+
+dnl steal from autoconf 2.69
+# AC_FC_FIXEDFORM([ACTION-IF-SUCCESS], [ACTION-IF-FAILURE = FAILURE])
+# ------------------------------------------------------------------
+# Look for a compiler flag to make the Fortran (FC) compiler accept
+# fixed-format source code, and adds it to FCFLAGS.  Call
+# ACTION-IF-SUCCESS (defaults to nothing) if successful (i.e. can
+# compile code using new extension) and ACTION-IF-FAILURE (defaults to
+# failing with an error message) if not.  (Defined via DEFUN_ONCE to
+# prevent flag from being added to FCFLAGS multiple times.)
+#
+# The known flags are:
+#       -ffixed-form: GNU g77, gfortran, g95
+#             -fixed: Intel compiler (ifort), Sun compiler (f95)
+#            -qfixed: IBM compiler (xlf*)
+#            -Mfixed: Portland Group compiler
+#         -fixedform: SGI compiler
+#           -f fixed: Absoft Fortran
+#      +source=fixed: HP Fortran
+#    (-)-fix, -Fixed: Lahey/Fujitsu Fortran
+#             -fixed: NAGWare
+# Since compilers may accept fixed form based on file name extension,
+# but users may want to use it with others as well, call AC_FC_SRCEXT
+# with the respective source extension before calling this macro.
+AC_DEFUN_ONCE([UD_FC_FIXEDFORM],
+[AC_LANG_PUSH([Fortran])dnl
+AC_CACHE_CHECK([for Fortran flag needed to accept fixed-form source],
+               [ac_cv_fc_fixedform],
+[ac_cv_fc_fixedform=unknown
+ac_fc_fixedform_FCFLAGS_save=$FCFLAGS
+for ac_flag in none -ffixed-form -fixed -qfixed -Mfixed -fixedform "-f fixed" \
+               +source=fixed -fix --fix -Fixed
+do
+  test "x$ac_flag" != xnone && FCFLAGS="$ac_fc_fixedform_FCFLAGS_save $ac_flag"
+  AC_COMPILE_IFELSE([[
+C     This comment should confuse free-form compilers.
+      program main
+      end]],
+                    [ac_cv_fc_fixedform=$ac_flag; break])
+done
+${RM} -f conftest.err conftest.$ac_objext conftest.$ac_ext
+FCFLAGS=$ac_fc_fixedform_FCFLAGS_save
+])
+if test "x$ac_cv_fc_fixedform" = xunknown; then
+  m4_default([$2],
+             [AC_MSG_WARN([Fortran does not accept fixed-form source], 77)])
+  ac_cv_fc_fixedform=
+else
+  dnl Do not append to FCFLAGS
+  dnl if test "x$ac_cv_fc_fixedform" != xnone; then
+  dnl   FCFLAGS="$FCFLAGS $ac_cv_fc_fixedform"
+  dnl fi
+  if test "x$ac_cv_fc_fixedform" = xnone; then
+     ac_cv_fc_fixedform=
+  fi
+  $1
+fi
+AC_LANG_POP([Fortran])dnl
+])# AC_FC_FIXEDFORM
+
+# AX_C_FLOAT_WORDS_BIGENDIAN# added by:
+#   Warren Turkal <wt at penguintechs.org>
+#
+# Copyright © 2006 Daniel Amelang <dan at amelang.net>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice and
+# this notice are preserved.
+#
+# This macro will detect if double variables are words packed in big endian
+# order while the bits in the words are arranged in little endian order. This
+# macro was added to support the ARM architecture. The FLOAT_WORDS_BIGENDIAN
+# macro will be set to 1 if the word order is big endian. If the word order is
+# not big endian, FLOAT_WORDS_BIGENDIAN will be not be set.
+AC_DEFUN([AX_C_FLOAT_WORDS_BIGENDIAN],
+  [AC_CACHE_CHECK(whether float word ordering is bigendian,
+                  ax_cv_c_float_words_bigendian, [
+
+ax_cv_c_float_words_bigendian=unknown
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+
+double d = 9090423496703681033747047890550501147621169273561563201479712084405348
+886581669527372346909785805625751702019124748742951693213050356065000232756451757
+0778480236724525140520121371739201496540132640109977779420565776568942592.0;
+
+]])], [
+
+if grep noonsees conftest.$ac_objext >/dev/null ; then
+  ax_cv_c_float_words_bigendian=yes
+fi
+if grep seesnoon conftest.$ac_objext >/dev/null ; then
+  if test "$ax_cv_c_float_words_bigendian" = unknown; then
+    ax_cv_c_float_words_bigendian=no
+  else
+    ax_cv_c_float_words_bigendian=unknown
+  fi
+fi
+
+])])
+
+case $ax_cv_c_float_words_bigendian in
+  yes)
+    m4_default([$1],
+      [AC_DEFINE([FLOAT_WORDS_BIGENDIAN], 1,
+                 [Define to 1 if your system stores words within floats
+                  with the most significant word first])]) ;;
+  no)
+    $2 ;;
+  *)
+    m4_default([$3],
+      [AC_MSG_ERROR([
+
+Unknown float word ordering. You need to manually preset
+ax_cv_c_float_words_bigendian=no (or yes) according to your system.
+
+    ])]) ;;
+esac
+
+])# AX_C_FLOAT_WORDS_BIGENDIAN
+
+dnl Find the full path of a header file
+dnl
+dnl UD_CHECK_HEADER_PATH(file, [action-if-found], [action-if-not-found])
+dnl Example:
+dnl UD_CHECK_HEADER_PATH([math.h])
+dnl AC_MSG_NOTICE([ac_cv_header_path_math_h=$ac_cv_header_path_math_h])
+dnl
+dnl
+AC_DEFUN([UD_CHECK_HEADER_PATH],
+[
+    AS_VAR_PUSHDEF([ac_Path], [ac_cv_header_path_$1])dnl
+    AC_CACHE_CHECK(
+       [for full path of header file \"$1\"], [ac_Path],
+       [AC_PREPROC_IFELSE(
+           [AC_LANG_PROGRAM([[#include <$1>]])],
+           [AS_VAR_SET([ac_Path], [`sed -n '/\.h"/s/.*"\(.*\)".*/\1/p' conftest.i | grep -m 1 $1`])],
+           [AC_MSG_RESULT([not found])]
+       )])
+    AS_VAR_SET_IF([ac_Path], [$2], [$3])
+    dnl eval AS_TR_SH([ac_cv_header_path_$1])=$ac_Path
+    AS_VAR_POPDEF([ac_Path])dnl
+])
+
+dnl Check if Fortran 77 compiler allows _8 modifier (a Fortran 90 feature)
+dnl for integer*8 parameter
+dnl NAG nagfor requires a modifier but does not like _8
+dnl xlf is OK with _8 but when none is used it strangely passes the
+dnl compilation with a warning message
+dnl
+AC_DEFUN([UD_FC_CONSTANT_MODIFIER],[
+    AC_CACHE_CHECK([Fortran compiler treating constant modifier], [ac_cv_fc_constant_modifier],
+    [AC_LANG_PUSH([Fortran 77])
+        AC_COMPILE_IFELSE([[
+         program main
+         integer*8  nf_fill_uint
+         integer*8  nf_fill_int64
+         parameter (nf_fill_uint  = 4294967295_8)
+         parameter (nf_fill_int64 = -9223372036854775806_8) 
+         end]],
+        [ac_cv_fc_constant_modifier=8],
+        [AC_COMPILE_IFELSE([[
+         program main
+         integer*8  nf_fill_uint
+         integer*8  nf_fill_int64
+         parameter (nf_fill_uint  = 4294967295)
+         parameter (nf_fill_int64 = -9223372036854775806) 
+         end]],
+        [ac_cv_fc_constant_modifier=none],
+        [AC_COMPILE_IFELSE([[
+         program main
+         integer, parameter :: EightByteInt = selected_int_kind(18)
+         integer*8  nf_fill_uint
+         integer*8  nf_fill_int64
+         parameter (nf_fill_uint  = 4294967295_EightByteInt)
+         parameter (nf_fill_int64 = -9223372036854775806_EightByteInt) 
+         end]],
+        [ac_cv_fc_constant_modifier=EightByteInt],
+        [AC_MSG_ERROR([no appropriate modifier found])])
+        ])
+        ])
+    ])
+    AC_LANG_POP([Fortran 77])
+])
+
+dnl Check if Fortran 77 compiler is pgf77
+dnl According to pgf77 manual the command-line option to should version is -V
+dnl
+AC_DEFUN([UD_CHECK_PGF77],[
+    AC_CACHE_CHECK([if Fortran 77 compiler is pgf77], [ac_cv_fc_compiler_pgf77],
+    [ac_cv_fc_compiler_pgf77=no
+     eval $MPIF77 -V </dev/null >& conftest.ver
+     _F77_VENDOR=`head -c 5 conftest.ver`
+     if test "x${_F77_VENDOR}" = xpgf77 ; then
+        ac_cv_fc_compiler_pgf77=yes
+     fi
+     ${RM} -f conftest.ver
+     unset _F77_VENDOR
+    ])
+])
+
+dnl Check if Fortran compiler is NAG
+dnl According to nagfor manual the command-line option to should version is -V
+dnl
+AC_DEFUN([UD_CHECK_FC_NAG],[
+    AC_CACHE_CHECK([if Fortran compiler is NAG], [ac_cv_fc_compiler_nag],
+    [ac_cv_fc_compiler_nag=no
+     eval $MPIF90 -V </dev/null >& conftest.ver
+     _FC_VENDOR=`head -c 3 conftest.ver`
+     if test "x${_FC_VENDOR}" = xNAG ; then
+        ac_cv_fc_compiler_nag=yes
+     fi
+     ${RM} -f conftest.ver
+     unset _FC_VENDOR
+    ])
+])
+
+AC_DEFUN([UD_CXX_MACRO_FUNC],[
+   AC_CACHE_CHECK([if C++ macro __func__ or __FUNCTION__ is defined], [ac_cv_cxx_macro_func],
+   [ac_cv_cxx_macro_func=no
+    ac_cv_cxx_macro_function=no
+    AC_LANG_PUSH([C++])
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <iostream>]],
+                                       [[std::cout << __func__;]])],
+                                       [ac_cv_cxx_macro_func=yes],[])
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <iostream>]],
+                                       [[std::cout << __FUNCTION__;]])],
+                                       [ac_cv_cxx_macro_function=yes],[])
+    AC_LANG_POP([C++])
+   ])
+])
+
+dnl
+dnl Borrowed macros from MPICH: aclocal_f77.m4
+dnl
+
+dnl
+dnl Check to see if a C program can be linked when using the libraries
+dnl needed by C programs
+dnl
+AC_DEFUN([PAC_PROG_FC_CHECK_FCLIBS],[
+AC_REQUIRE([AC_FC_LIBRARY_LDFLAGS])
+AC_MSG_CHECKING([whether $CC links with FCLIBS found by autoconf])
+AC_LANG_PUSH([C])
+# Create a simple C program for the tests.
+AC_LANG_CONFTEST([
+    AC_LANG_PROGRAM([],[int a;])
+])
+# Try to link a C program with all of these libraries
+saved_LIBS="$LIBS"
+LIBS="$FCLIBS $saved_LIBS"
+AC_LINK_IFELSE([],[
+    AC_MSG_RESULT([yes])
+],[
+    AC_MSG_RESULT([no])
+    AC_MSG_CHECKING([for which libraries can be used])
+    pac_ldirs=""
+    pac_libs=""
+    pac_other=""
+    for name in $FCLIBS ; do
+        case $name in 
+        -l*) pac_libs="$pac_libs $name"   ;;
+        -L*) pac_ldirs="$pac_ldirs $name" ;;
+          *) pac_other="$pac_other $name" ;;
+        esac
+    done
+    keep_libs=""
+    for name in $pac_libs ; do
+        LIBS="$saved_LIBS $pac_ldirs $pac_other $name"
+        AC_LINK_IFELSE([],[
+            keep_libs="$keep_libs $name"
+        ])
+    done
+    AC_MSG_RESULT($keep_libs)
+    FCLIBS="$pac_ldirs $pac_other $keep_libs"
+])
+LIBS="$saved_LIBS"
+rm -f conftest.$ac_ext
+AC_LANG_PUSH([C])
+])
+
+
+AC_DEFUN([UD_CHECK_MPI_COMPILER], [
+   if test "x$MPI_INSTALL" != x ; then
+      UD_MSG_DEBUG(--with-mpi=$MPI_INSTALL is used)
+      if test "x$$1" = x ; then
+         if test "x$$1" = x && (test -d "${MPI_INSTALL}/bin") ; then
+            UD_MSG_DEBUG(search possible $1 under $MPI_INSTALL/bin)
+            AC_PATH_PROGS([$1], [$2], [], [$MPI_INSTALL/bin])
+         fi
+         if test "x$$1" = x ; then
+             UD_MSG_DEBUG(search possible $1 under $MPI_INSTALL)
+             AC_PATH_PROGS([$1], [$2], [], [$MPI_INSTALL])
+         fi
+      else
+         UD_MSG_DEBUG(check if file $$1 exists)
+         if ! test -f "$$1" ; then
+            dnl file does not exist, check under MPI_INSTALL
+            UD_MSG_DEBUG(File $1= $$1 cannot be found ... check under $MPI_INSTALL)
+            if test -f "$MPI_INSTALL/$$1" ; then
+               UD_MSG_DEBUG(File $1= $$1 is found under $MPI_INSTALL)
+               $1="$MPI_INSTALL/$$1"
+            elif test -f "$MPI_INSTALL/bin/$$1" ; then
+               UD_MSG_DEBUG(File $1= $$1 is found under $MPI_INSTALL/bin)
+               $1="$MPI_INSTALL/bin/$$1"
+            else
+               UD_MSG_DEBUG(File $1= $$1 cannot be found under $MPI_INSTALL)
+               $1=
+            fi
+         fi
+      fi
+   else
+       UD_MSG_DEBUG(--with-mpi=$MPI_INSTALL is NOT used)
+       UD_MSG_DEBUG([check if $1 is defined. If yes, check if file exists])
+       if test "x$$1" != x && (! test -f "$$1") ; then
+          UD_MSG_DEBUG(check if file $$1 exists under user's PATH)
+          AC_PATH_PROGS([$1], [$$1])
+       fi
+   fi
+   dnl if $$1 is not empty, then compiler file does exist
+   dnl if $$1 is empty, search under user's PATH
+   if test "x$$1" = x ; then
+      UD_MSG_DEBUG(find possible $1 under user's PATH)
+      AC_PATH_PROGS([$1], [$2])
+   fi
+])
+
+dnl Check for presence of an MPI constant.
+dnl These could be enums, so we have to do compile checks.
+AC_DEFUN([UD_HAS_MPI_CONST], [
+   AC_MSG_CHECKING(if MPI constant $1 is defined )
+   AC_COMPILE_IFELSE(
+      [AC_LANG_SOURCE([
+          #include <mpi.h>
+          int dummy = $1;
+      ])],
+      [AC_MSG_RESULT(yes)
+       AC_DEFINE(HAVE_$1, 1, available)
+      ],
+      [AC_MSG_RESULT(no)]
+   )]
+)
+
+dnl Check for presence of an MPI datatype.
+dnl These could be enums, so we have to do compile checks.
+AC_DEFUN([UD_HAS_MPI_DATATYPE], [
+   AC_MSG_CHECKING(if MPI datatype $1 is defined )
+   AC_COMPILE_IFELSE(
+      [AC_LANG_SOURCE([
+          #include <mpi.h>
+          MPI_Datatype dummy = $1;
+      ])],
+      [AC_MSG_RESULT(yes)
+       AC_DEFINE(HAVE_$1$2, 1, available)
+      ],
+      [AC_MSG_RESULT(no)]
+   )]
+)
+
+dnl Check if older Intel MPI C compiler (4.x) for issue of redefined SEEK_SET
+dnl See https://software.intel.com/en-us/articles/intel-cluster-toolkit-for-linux-error-when-compiling-c-aps-using-intel-mpi-library-compilation-driver-mpiicpc
+AC_DEFUN([UD_CHECK_MPI_CPP_SEEK_SET], [
+   AC_MSG_CHECKING(if MPI C++ compiler redefines SEEK_SET )
+   CXX=${MPICXX}
+   AC_LANG_PUSH(C++)
+   AC_COMPILE_IFELSE(
+      [AC_LANG_SOURCE([
+          #include <stdio.h>
+          #include <mpi.h>
+          int main() { return 0; }
+      ])],
+      [ac_cv_CHECK_MPI_CPP_SEEK_SET=no],
+      [ac_cv_CHECK_MPI_CPP_SEEK_SET=yes]
+   )
+   AC_MSG_RESULT([$ac_cv_CHECK_MPI_CPP_SEEK_SET])
+   AC_LANG_POP(C++)]
+)
+
diff --git a/benchmarks/C/Makefile.in b/benchmarks/C/Makefile.in
new file mode 100644
index 0000000..a1c697d
--- /dev/null
+++ b/benchmarks/C/Makefile.in
@@ -0,0 +1,59 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2215 2015-12-08 04:58:04Z wkliao $
+#
+# @configure_input@
+
+srcdir  = @srcdir@
+VPATH   = @srcdir@
+
+include ../../macros.make
+
+# note the order of -L list matters
+INCLUDES  = -I../../src/lib
+LDFLAGS  := -L../../src/lib $(LDFLAGS)
+LIBS     := -lpnetcdf $(LIBS)
+
+C_SRCS    = aggregation.c \
+            write_block_read_column.c
+
+PROGS     = $(C_SRCS:.c=)
+OBJS      = $(C_SRCS:.c=.o)
+
+GARBAGE      = $(PROGS) *.nc
+
+PACKING_LIST = $(C_SRCS) Makefile.in depend
+
+all: $(PROGS)
+
+install:
+
+uninstall:
+
+aggregation: aggregation.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+write_block_read_column: write_block_read_column.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+
+ptest: $(PROGS)
+	@for i in $(PROGS); do ( \
+	echo "-----------------------------------------------------" ; \
+	echo "$(TEST_MPIRUN_4) ./$$i 10 $(TEST_OUTDIR)/testfile.nc" ; \
+	echo "-----------------------------------------------------" ; \
+	$(TEST_MPIRUN_4) ./$$i 10 $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+	@echo "-----------------------------------------------------"
+
+ptests:
+
+include $(srcdir)/depend
+
+include $(srcdir)/../../rules.make
+
+$(LIBRARY): ;
+
diff --git a/benchmarks/C/aggregation.c b/benchmarks/C/aggregation.c
new file mode 100644
index 0000000..f5c8e20
--- /dev/null
+++ b/benchmarks/C/aggregation.c
@@ -0,0 +1,592 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2013, Northwestern University
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: aggregation.c 2215 2015-12-08 04:58:04Z wkliao $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This program writes a series of 2D variables with data partitioning patterns
+ * of block-block, *-cyclic, block-*, and *-block, round-robinly. The block-*
+ * partitioning case writes 1st half followed by 2nd half. The same partitioning
+ * patterns are used for read. In both cases, nonblocking APIs are used to
+ * evaluate the performance.
+ * 
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file. In this example, NVARS = 5.
+ *
+ *    % mpicc -O2 -o aggregation aggregation.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 4 ./aggregation 5 /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *      netcdf testfile {
+ *      // file format: CDF-5 (big variables)
+ *      dimensions:
+ *              Block_BLOCK_Y = 10 ;
+ *              Block_BLOCK_X = 10 ;
+ *              Star_Y = 5 ;
+ *              Cyclic_X = 20 ;
+ *              Block_Y = 20 ;
+ *              Star_X = 5 ;
+ *      variables:
+ *              int block_block_var_0(Block_BLOCK_Y, Block_BLOCK_X) ;
+ *              float star_cyclic_var_1(Star_Y, Cyclic_X) ;
+ *              short block_star_var_2(Block_Y, Star_X) ;
+ *              double star_block_var_3(Star_Y, Cyclic_X) ;
+ *              int block_block_var_4(Block_BLOCK_Y, Block_BLOCK_X) ;
+ *      data:
+ *
+ *       block_block_var_0 =
+ *        0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ *        0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ *        0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ *        0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ *        0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ *        1, 1, 1, 1, 1, 3, 3, 3, 3, 3,
+ *        1, 1, 1, 1, 1, 3, 3, 3, 3, 3,
+ *        1, 1, 1, 1, 1, 3, 3, 3, 3, 3,
+ *        1, 1, 1, 1, 1, 3, 3, 3, 3, 3,
+ *        1, 1, 1, 1, 1, 3, 3, 3, 3, 3 ;
+ *
+ *       star_cyclic_var_1 =
+ *        0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *        0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *        0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *        0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *        0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 ;
+ *
+ *       block_star_var_2 =
+ *        0, 0, 0, 0, 0,
+ *        0, 0, 0, 0, 0,
+ *        0, 0, 0, 0, 0,
+ *        0, 0, 0, 0, 0,
+ *        0, 0, 0, 0, 0,
+ *        1, 1, 1, 1, 1,
+ *        1, 1, 1, 1, 1,
+ *        1, 1, 1, 1, 1,
+ *        1, 1, 1, 1, 1,
+ *        1, 1, 1, 1, 1,
+ *        2, 2, 2, 2, 2,
+ *        2, 2, 2, 2, 2,
+ *        2, 2, 2, 2, 2,
+ *        2, 2, 2, 2, 2,
+ *        2, 2, 2, 2, 2,
+ *        3, 3, 3, 3, 3,
+ *        3, 3, 3, 3, 3,
+ *        3, 3, 3, 3, 3,
+ *        3, 3, 3, 3, 3,
+ *        3, 3, 3, 3, 3 ;
+ *
+ *       star_block_var_3 =
+ *        0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *        0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *        0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *        0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *        0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 ;
+ *
+ *       block_block_var_4 =
+ *        0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ *        0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ *        0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ *        0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ *        0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ *        1, 1, 1, 1, 1, 3, 3, 3, 3, 3,
+ *        1, 1, 1, 1, 1, 3, 3, 3, 3, 3,
+ *        1, 1, 1, 1, 1, 3, 3, 3, 3, 3,
+ *        1, 1, 1, 1, 1, 3, 3, 3, 3, 3,
+ *        1, 1, 1, 1, 1, 3, 3, 3, 3, 3 ;
+ *      }
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define NVARS 5
+
+#define ERR(e) {if((e)!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(e));}
+
+/*----< print_info() >------------------------------------------------------*/
+static
+void print_info(MPI_Info *info_used)
+{
+    int  i, nkeys;
+
+    MPI_Info_get_nkeys(*info_used, &nkeys);
+    printf("MPI File Info: nkeys = %d\n",nkeys);
+    for (i=0; i<nkeys; i++) {
+        char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
+        int  valuelen, flag;
+
+        MPI_Info_get_nthkey(*info_used, i, key);
+        MPI_Info_get_valuelen(*info_used, key, &valuelen, &flag);
+        MPI_Info_get(*info_used, key, valuelen+1, value, &flag);
+        printf("MPI File Info: [%2d] key = %24s, value = %s\n",i,key,value);
+    }
+}
+
+/*----< benchmark_write() >---------------------------------------------------*/
+static
+int benchmark_write(char       *filename,
+                    MPI_Offset  len,
+                    MPI_Offset *w_size,
+                    MPI_Info   *w_info_used,
+                    double     *timing)  /* [6] */
+{
+    int i, j, k, verbose, rank, nprocs, err, num_reqs;
+    int ncid, cmode, varid[NVARS], dimid[6], *reqs, *sts, psizes[2];
+    void *buf[NVARS];
+    double start_t, end_t;
+    MPI_Comm comm=MPI_COMM_WORLD;
+    MPI_Offset gsizes[2], start[2], count[2];
+    MPI_Info info=MPI_INFO_NULL;
+
+    verbose = 0;
+    MPI_Comm_rank(comm, &rank);
+    MPI_Comm_size(comm, &nprocs);
+
+    /* set PnetCDF I/O hints */
+    MPI_Info_create(&info);
+    /* To disable the header and fixed-size variable alignments, set the
+       following hints.
+    MPI_Info_set(info, "nc_header_align_size", "1");    size in bytes
+    MPI_Info_set(info, "nc_var_align_size",    "1");    size in bytes
+    */
+
+    /* initialize I/O buffer with random numbers */
+    srand(rank);
+    for (i=0; i<NVARS; i++) {
+        if (i % 4 == 0) {
+            int *int_b = (int*) malloc(len * len * sizeof(int));
+            for (j=0; j<len*len; j++) int_b[j] = rank; /* rand(); */
+            buf[i] = (void*)int_b;
+        }
+        else if (i % 4 == 1) {
+            float *flt_b = (float*) malloc(len * len * sizeof(float));
+            for (j=0; j<len*len; j++) flt_b[j] = rank; /* rand(); */
+            buf[i] = (void*)flt_b;
+        }
+        else if (i % 4 == 2) {
+            short *shr_b = (short*) malloc(len * len * sizeof(short));
+            for (j=0; j<len*len; j++) shr_b[j] = rank; /* rand(); */
+            buf[i] = (void*)shr_b;
+        }
+        else {
+            double *dbl_b = (double*) malloc(len * len * sizeof(double));
+            for (j=0; j<len*len; j++) dbl_b[j] = rank; /* rand(); */
+            buf[i] = (void*)dbl_b;
+        }
+    }
+    MPI_Barrier(comm);
+    timing[0] = MPI_Wtime();
+
+    /* create a new file for writing -----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR(err)
+    start_t = MPI_Wtime();
+    timing[1] = start_t - timing[0];
+    MPI_Info_free(&info);
+
+    psizes[0] = psizes[1] = 0;
+    MPI_Dims_create(nprocs, 2, psizes);
+
+    gsizes[0] = len * psizes[0];
+    gsizes[1] = len * psizes[1];
+
+    err = ncmpi_def_dim(ncid, "Block_BLOCK_Y",  gsizes[0],  &dimid[0]); ERR(err)
+    err = ncmpi_def_dim(ncid, "Block_BLOCK_X",  gsizes[1],  &dimid[1]); ERR(err)
+    err = ncmpi_def_dim(ncid, "Star_Y",         len,        &dimid[2]); ERR(err)
+    err = ncmpi_def_dim(ncid, "Cyclic_X",       len*nprocs, &dimid[3]); ERR(err)
+    err = ncmpi_def_dim(ncid, "Block_Y",        len*nprocs, &dimid[4]); ERR(err)
+    err = ncmpi_def_dim(ncid, "Star_X",         len,        &dimid[5]); ERR(err)
+
+    /* define variables */
+    num_reqs = 0;
+    for (i=0; i<NVARS; i++) {
+        char var_name[32];
+        if (i % 4 == 0) {
+            /* variables are block-block partitioned */
+            sprintf(var_name,"block_block_var_%d",i);
+            err = ncmpi_def_var(ncid, var_name, NC_INT, 2, dimid, &varid[i]);
+            ERR(err)
+            num_reqs++; /* complete in 1 nonblocking call */
+        }
+        else if (i % 4 == 1) {
+            /* variables are *-cyclic partitioned */
+            sprintf(var_name,"star_cyclic_var_%d",i);
+            err = ncmpi_def_var(ncid, var_name, NC_FLOAT, 2, dimid+2, &varid[i]);
+            ERR(err)
+            num_reqs += len; /* complete in len nonblocking calls */
+        }
+        else if (i % 4 == 2) {
+            /* variables are block-* partitioned */
+            sprintf(var_name,"block_star_var_%d",i);
+            err = ncmpi_def_var(ncid, var_name, NC_SHORT, 2, dimid+4, &varid[i]);
+            ERR(err)
+            num_reqs += 2; /* write 1st half followed by 2nd half */
+        }
+        else {
+            /* variables are *-block partitioned */
+            sprintf(var_name,"star_block_var_%d",i);
+            err = ncmpi_def_var(ncid, var_name, NC_DOUBLE, 2, dimid+2, &varid[i]);
+            ERR(err)
+            num_reqs++; /* complete in 1 nonblocking call */
+        }
+    }
+    reqs = (int*) malloc(num_reqs * sizeof(int));
+
+    err = ncmpi_enddef(ncid); ERR(err)
+    end_t = MPI_Wtime();
+    timing[2] = end_t - start_t;
+    start_t = end_t;
+
+    k = 0;
+    for (i=0; i<NVARS; i++) {
+        if (i % 4 == 0) {
+            int *int_b = (int*) buf[i];
+            start[0] = len * (rank % psizes[0]);
+            start[1] = len * ((rank / psizes[1]) % psizes[1]);
+            count[0] = len;
+            count[1] = len;
+            err = ncmpi_iput_vara_int(ncid, varid[i], start, count, int_b,
+                                      &reqs[k++]);
+            ERR(err)
+            if (verbose) printf("block-block %d: start=%lld %lld count=%lld %lld\n",i,start[0],start[1],count[0],count[1]);
+        }
+        else if (i % 4 == 1) {
+            float *flt_b = (float*) buf[i];
+            start[0] = 0;
+            count[0] = len;
+            count[1] = 1;
+            for (j=0; j<len; j++) {
+                start[1] = rank + j * nprocs;
+                err = ncmpi_iput_vara_float(ncid, varid[i], start, count,
+                                            flt_b, &reqs[k++]);
+                ERR(err)
+                flt_b += len;
+                if (verbose) printf("*-cyclic i=%d j=%d: start=%lld %lld count=%lld %lld\n",i,j,start[0],start[1],count[0],count[1]);
+            }
+        }
+        else if (i % 4 == 2) {
+            short *shr_b = (short*) buf[i];
+            start[0] = len * rank;
+            start[1] = 0;
+            count[0] = len;
+            count[1] = len/2;
+            err = ncmpi_iput_vara_short(ncid, varid[i], start, count,
+                                        shr_b, &reqs[k++]);
+            ERR(err)
+            if (verbose) printf("block-* i=0 start=%lld %lld count=%lld %lld\n",start[0],start[1],count[0],count[1]);
+
+            shr_b += len * (len/2);
+            start[1] = len/2;
+            count[1] = len - len/2;
+            err = ncmpi_iput_vara_short(ncid, varid[i], start, count,
+                                        shr_b, &reqs[k++]);
+            ERR(err)
+            if (verbose) printf("block-* i=1 start=%lld %lld count=%lld %lld\n",start[0],start[1],count[0],count[1]);
+        }
+        else {
+            double *dbl_b = (double*) buf[i];
+            start[0] = 0;
+            start[1] = len * rank;
+            count[0] = len;
+            count[1] = len;
+            err = ncmpi_iput_vara_double(ncid, varid[i], start, count, dbl_b,
+                                         &reqs[k++]);
+            ERR(err)
+            if (verbose) printf("*-block %d: start=%lld %lld count=%lld %lld\n",i,start[0],start[1],count[0],count[1]);
+        }
+    }
+    num_reqs = k;
+
+    end_t = MPI_Wtime();
+    timing[3] = end_t - start_t;
+    start_t = end_t;
+
+    sts = (int*) malloc(num_reqs * sizeof(int));
+
+#ifdef USE_INDEP_MODE
+    err = ncmpi_begin_indep_data(ncid);          ERR(err)
+    err = ncmpi_wait(ncid, num_reqs, reqs, sts); ERR(err)
+    err = ncmpi_end_indep_data(ncid);            ERR(err)
+#else
+    err = ncmpi_wait_all(ncid, num_reqs, reqs, sts); ERR(err)
+#endif
+    /* check status of all requests */
+    for (i=0; i<num_reqs; i++) ERR(sts[i])
+
+    end_t = MPI_Wtime();
+    timing[4] = end_t - start_t;
+    start_t = end_t;
+
+    /* get the true I/O amount committed */
+    err = ncmpi_inq_put_size(ncid, w_size); ERR(err)
+
+    /* get all the hints used */
+    err = ncmpi_get_file_info(ncid, w_info_used); ERR(err)
+
+    err = ncmpi_close(ncid); ERR(err)
+
+    end_t = MPI_Wtime();
+    timing[5] = end_t - start_t;
+    timing[0] = end_t - timing[0];
+
+    free(sts);
+    free(reqs);
+    for (i=0; i<NVARS; i++) free(buf[i]);
+
+    return 1;
+}
+
+/*----< benchmark_read() >---------------------------------------------------*/
+static
+int benchmark_read(char       *filename,
+                   MPI_Offset  len,
+                   MPI_Offset *r_size,
+                   MPI_Info   *r_info_used,
+                   double     *timing)  /* [5] */
+{
+    int i, j, k, verbose, rank, nprocs, s_rank, err, num_reqs;
+    int ncid, omode, varid[NVARS], *reqs, *sts, psizes[2];
+    void *buf[NVARS];
+    double start_t, end_t;
+    MPI_Comm comm=MPI_COMM_WORLD;
+    MPI_Offset start[2], count[2];
+    MPI_Info info=MPI_INFO_NULL;
+
+    verbose = 0;
+    MPI_Comm_rank(comm, &rank);
+    MPI_Comm_size(comm, &nprocs);
+    s_rank = (rank + nprocs / 2 ) % nprocs;
+
+    psizes[0] = psizes[1] = 0;
+    MPI_Dims_create(nprocs, 2, psizes);
+
+    /* allocate I/O buffer */
+    for (i=0; i<NVARS; i++) {
+        if (i % 4 == 0)
+            buf[i] = malloc(len * len * sizeof(int));
+        else if (i % 4 == 1)
+            buf[i] = (float*) malloc(len * len * sizeof(float));
+        else if (i % 4 == 2)
+            buf[i] = (short*) malloc(len * len * sizeof(short));
+        else
+            buf[i] = (double*) malloc(len * len * sizeof(double));
+    }
+    MPI_Barrier(comm);
+    timing[0] = MPI_Wtime();
+
+    /* open file for reading -----------------------------------------*/
+    omode = NC_NOWRITE;
+    err = ncmpi_open(comm, filename, omode, info, &ncid); ERR(err)
+    start_t = MPI_Wtime();
+    timing[1] = start_t - timing[0];
+
+    /* Note that PnetCDF read the file in chunks of size 256KB, thus the read
+     * amount may be more than the file header size
+     */
+    if (verbose) {
+        MPI_Offset h_size, h_extent;
+        ncmpi_inq_header_size(ncid, &h_size);
+        ncmpi_inq_header_extent(ncid, &h_extent);
+        printf("File header size=%lld extent=%lld\n",h_size,h_extent);
+    }
+
+    num_reqs = 0;
+    for (i=0; i<NVARS; i++) {
+        varid[i] = i;
+        if (i % 4 == 0)
+            num_reqs++; /* complete in 1 nonblocking call */
+        else if (i % 4 == 1)
+            num_reqs += len; /* complete in len nonblocking calls */
+        else if (i % 4 == 2)
+            num_reqs += 2; /* write 1st half followed by 2nd half */
+        else
+            num_reqs++; /* complete in 1 nonblocking call */
+    }
+    reqs = (int*) malloc(num_reqs * sizeof(int));
+
+    k = 0;
+    for (i=0; i<NVARS; i++) {
+        if (i % 4 == 0) {
+            int *int_b = (int*) buf[i];
+            start[0] = len * (s_rank % psizes[0]);
+            start[1] = len * ((s_rank / psizes[1]) % psizes[1]);
+            count[0] = len;
+            count[1] = len;
+            err = ncmpi_iget_vara_int(ncid, varid[i], start, count, int_b,
+                                      &reqs[k++]);
+            ERR(err)
+        }
+        else if (i % 4 == 1) {
+            float *flt_b = (float*) buf[i];
+            start[0] = 0;
+            count[0] = len;
+            count[1] = 1;
+            for (j=0; j<len; j++) {
+                start[1] = s_rank + j * nprocs;
+                err = ncmpi_iget_vara_float(ncid, varid[i], start, count,
+                                            flt_b, &reqs[k++]);
+                ERR(err)
+                flt_b += len;
+            }
+        }
+        else if (i % 4 == 2) {
+            short *shr_b = (short*) buf[i];
+            start[0] = len * s_rank;
+            start[1] = 0;
+            count[0] = len;
+            count[1] = len/2;
+            err = ncmpi_iget_vara_short(ncid, varid[i], start, count,
+                                        shr_b, &reqs[k++]);
+            ERR(err)
+
+            shr_b += len * (len/2);
+            start[1] = len/2;
+            count[1] = len - len/2;
+            err = ncmpi_iget_vara_short(ncid, varid[i], start, count,
+                                        shr_b, &reqs[k++]);
+            ERR(err)
+        }
+        else {
+            double *dbl_b = (double*) buf[i];
+            start[0] = 0;
+            start[1] = len * s_rank;
+            count[0] = len;
+            count[1] = len;
+            err = ncmpi_iget_vara_double(ncid, varid[i], start, count, dbl_b,
+                                         &reqs[k++]);
+            ERR(err)
+        }
+    }
+    num_reqs = k;
+
+    end_t = MPI_Wtime();
+    timing[2] = end_t - start_t;
+    start_t = end_t;
+
+    sts = (int*) malloc(num_reqs * sizeof(int));
+
+#ifdef USE_INDEP_MODE
+    err = ncmpi_begin_indep_data(ncid);          ERR(err)
+    err = ncmpi_wait(ncid, num_reqs, reqs, sts); ERR(err)
+    err = ncmpi_end_indep_data(ncid);            ERR(err)
+#else
+    err = ncmpi_wait_all(ncid, num_reqs, reqs, sts); ERR(err)
+#endif
+    /* check status of all requests */
+    for (i=0; i<num_reqs; i++) ERR(sts[i])
+
+    end_t = MPI_Wtime();
+    timing[3] = end_t - start_t;
+    start_t = end_t;
+
+    /* get the true I/O amount committed */
+    err = ncmpi_inq_get_size(ncid, r_size); ERR(err)
+
+    /* get all the hints used */
+    err = ncmpi_get_file_info(ncid, r_info_used); ERR(err)
+
+    err = ncmpi_close(ncid); ERR(err)
+
+    end_t = MPI_Wtime();
+    timing[4] = end_t - start_t;
+    timing[0] = end_t - timing[0];
+
+    free(sts);
+    free(reqs);
+    for (i=0; i<NVARS; i++) free(buf[i]);
+
+    return 1;
+}
+
+/*----< main() >--------------------------------------------------------------*/
+int main(int argc, char** argv) {
+    int rank, nprocs;
+    double timing[11], max_t[11];
+    MPI_Offset len, w_size=0, r_size=0, sum_w_size, sum_r_size;
+    MPI_Comm comm=MPI_COMM_WORLD;
+    MPI_Info w_info_used, r_info_used;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(comm, &rank);
+    MPI_Comm_size(comm, &nprocs);
+
+    if (argc != 3) {
+        if (!rank) printf("Usage: %s len filename\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    len = atoll(argv[1]);
+
+    benchmark_write(argv[2], len, &w_size, &w_info_used, timing);
+    benchmark_read (argv[2], len, &r_size, &r_info_used, timing+6);
+
+    MPI_Reduce(&timing, &max_t,     11, MPI_DOUBLE, MPI_MAX, 0, comm);
+#ifdef MPI_OFFSET
+    MPI_Reduce(&w_size, &sum_w_size, 1, MPI_OFFSET, MPI_SUM, 0, comm);
+    MPI_Reduce(&r_size, &sum_r_size, 1, MPI_OFFSET, MPI_SUM, 0, comm);
+#else
+    MPI_Reduce(&w_size, &sum_w_size, 1, MPI_LONG_LONG, MPI_SUM, 0, comm);
+    MPI_Reduce(&r_size, &sum_r_size, 1, MPI_LONG_LONG, MPI_SUM, 0, comm);
+#endif
+    if (rank == 0) {
+        double bw = sum_w_size;
+        bw /= 1048576.0;
+        print_info(&w_info_used);
+        printf("-----------------------------------------------------------\n");
+        printf("Write %d variables using nonblocking APIs\n", NVARS);
+        printf("In each process, the local variable size is %lld x %lld\n", len,len);
+        printf("Total write amount        = %13lld    B\n", sum_w_size);
+        printf("            amount        = %16.4f MiB\n", bw);
+        printf("            amount        = %16.4f GiB\n", bw/1024);
+        printf("Max file open/create time = %16.4f sec\n", max_t[1]);
+        printf("Max PnetCDF define   time = %16.4f sec\n", max_t[2]);
+        printf("Max nonblocking post time = %16.4f sec\n", max_t[3]);
+        printf("Max nonblocking wait time = %16.4f sec\n", max_t[4]);
+        printf("Max file close       time = %16.4f sec\n", max_t[5]);
+        printf("Max open-to-close    time = %16.4f sec\n", max_t[0]);
+        printf("Write bandwidth           = %16.4f MiB/s\n", bw/max_t[0]);
+        bw /= 1024.0;
+        printf("Write bandwidth           = %16.4f GiB/s\n", bw/max_t[0]);
+
+        bw = sum_r_size;
+        bw /= 1048576.0;
+        printf("-----------------------------------------------------------\n");
+        printf("Read  %d variables using nonblocking APIs\n", NVARS);
+        printf("In each process, the local variable size is %lld x %lld\n", len,len);
+        printf("Total read  amount        = %13lld    B\n", sum_r_size);
+        printf("            amount        = %16.4f MiB\n", bw);
+        printf("            amount        = %16.4f GiB\n", bw/1024);
+        printf("Max file open/create time = %16.4f sec\n", max_t[7]);
+        printf("Max nonblocking post time = %16.4f sec\n", max_t[8]);
+        printf("Max nonblocking wait time = %16.4f sec\n", max_t[9]);
+        printf("Max file close       time = %16.4f sec\n", max_t[10]);
+        printf("Max open-to-close    time = %16.4f sec\n", max_t[6]);
+        printf("Read  bandwidth           = %16.4f MiB/s\n", bw/max_t[6]);
+        bw /= 1024.0;
+        printf("Read  bandwidth           = %16.4f GiB/s\n", bw/max_t[6]);
+    }
+    MPI_Info_free(&w_info_used);
+    MPI_Info_free(&r_info_used);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/benchmarks/C/depend b/benchmarks/C/depend
new file mode 100644
index 0000000..04d0b02
--- /dev/null
+++ b/benchmarks/C/depend
@@ -0,0 +1,2 @@
+aggregation.o: aggregation.c
+write_block_read_column.o: write_block_read_column.c
diff --git a/benchmarks/C/write_block_read_column.c b/benchmarks/C/write_block_read_column.c
new file mode 100644
index 0000000..d756391
--- /dev/null
+++ b/benchmarks/C/write_block_read_column.c
@@ -0,0 +1,401 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2013, Northwestern University
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: write_block_read_column.c 2215 2015-12-08 04:58:04Z wkliao $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This program writes a series of 2D variables with a block-block data
+ * partitioning pattern. The 2D variables are read back in a *-block pattern.
+ * 
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file. In this example, NVARS = 4.
+ *
+ *    % mpicc -O2 -o write_block_read_column write_block_read_column.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 4 ./write_block_read_column 128 /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump -h /pvfs2/wkliao/testfile.nc
+ *      netcdf testfile {
+ *      // file format: CDF-5 (big variables)
+ *      dimensions:
+ *              Y = 256 ;
+ *              X = 256 ;
+ *      variables:
+ *              int block_block_var_0(Y, X) ;
+ *              float block_block_var_1(Y, X) ;
+ *              short block_block_var_2(Y, X) ;
+ *              double block_block_var_3(Y, X) ;
+ *      }
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define NVARS 4
+
+#define ERR(e) {if((e)!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(e));}
+
+/*----< print_info() >------------------------------------------------------*/
+static
+void print_info(MPI_Info *info_used)
+{
+    int  i, nkeys;
+
+    MPI_Info_get_nkeys(*info_used, &nkeys);
+    printf("MPI File Info: nkeys = %d\n",nkeys);
+    for (i=0; i<nkeys; i++) {
+        char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
+        int  valuelen, flag;
+
+        MPI_Info_get_nthkey(*info_used, i, key);
+        MPI_Info_get_valuelen(*info_used, key, &valuelen, &flag);
+        MPI_Info_get(*info_used, key, valuelen+1, value, &flag);
+        printf("MPI File Info: [%2d] key = %25s, value = %s\n",i,key,value);
+    }
+}
+
+/*----< benchmark_write() >---------------------------------------------------*/
+static
+int benchmark_write(char       *filename,
+                    MPI_Offset  len,
+                    MPI_Offset *w_size,
+                    MPI_Info   *w_info_used,
+                    double     *timing)  /* [6] */
+{
+    int i, j, rank, nprocs, err;
+    int ncid, cmode, varid[NVARS], dimid[2], psizes[2];
+    void *buf[NVARS];
+    double start_t, end_t;
+    MPI_Comm comm=MPI_COMM_WORLD;
+    MPI_Offset gsizes[2], start[2], count[2];
+    MPI_Info info=MPI_INFO_NULL;
+
+    MPI_Comm_rank(comm, &rank);
+    MPI_Comm_size(comm, &nprocs);
+
+    /* set PnetCDF I/O hints */
+    MPI_Info_create(&info);
+    MPI_Info_set(info, "nc_header_align_size",      "1");   /* size in bytes */
+    MPI_Info_set(info, "nc_var_align_size",         "1");   /* size in bytes */
+    MPI_Info_set(info, "nc_header_read_chunk_size", "512"); /* size in bytes */
+    /* note that set the above values to 1 to disable the alignment */
+
+    /* initialize I/O buffer with random numbers */
+    srand(rank);
+    for (i=0; i<NVARS; i++) {
+        if (i % 4 == 0) {
+            int *int_b = (int*) malloc(len * len * sizeof(int));
+            for (j=0; j<len*len; j++) int_b[j] = rank; /* rand(); */
+            buf[i] = (void*)int_b;
+        }
+        else if (i % 4 == 1) {
+            float *flt_b = (float*) malloc(len * len * sizeof(float));
+            for (j=0; j<len*len; j++) flt_b[j] = rank; /* rand(); */
+            buf[i] = (void*)flt_b;
+        }
+        else if (i % 4 == 2) {
+            short *shr_b = (short*) malloc(len * len * sizeof(short));
+            for (j=0; j<len*len; j++) shr_b[j] = rank; /* rand(); */
+            buf[i] = (void*)shr_b;
+        }
+        else {
+            double *dbl_b = (double*) malloc(len * len * sizeof(double));
+            for (j=0; j<len*len; j++) dbl_b[j] = rank; /* rand(); */
+            buf[i] = (void*)dbl_b;
+        }
+    }
+    MPI_Barrier(comm);
+    timing[0] = MPI_Wtime();
+
+    /* create a new file for writing -----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR(err)
+    start_t = MPI_Wtime();
+    timing[1] = start_t - timing[0];
+    MPI_Info_free(&info);
+
+    psizes[0] = psizes[1] = 0;
+    MPI_Dims_create(nprocs, 2, psizes);
+
+    gsizes[0] = len * psizes[0];
+    gsizes[1] = len * psizes[1];
+
+    err = ncmpi_def_dim(ncid, "Y", gsizes[0], &dimid[0]); ERR(err)
+    err = ncmpi_def_dim(ncid, "X", gsizes[1], &dimid[1]); ERR(err)
+
+    /* define variables */
+    for (i=0; i<NVARS; i++) {
+        char var_name[32];
+        sprintf(var_name,"block_block_var_%d",i);
+        if (i % 4 == 0) {
+            err = ncmpi_def_var(ncid, var_name, NC_INT, 2, dimid, &varid[i]);
+            ERR(err)
+        }
+        else if (i % 4 == 1) {
+            err = ncmpi_def_var(ncid, var_name, NC_FLOAT, 2, dimid, &varid[i]);
+            ERR(err)
+        }
+        else if (i % 4 == 2) {
+            err = ncmpi_def_var(ncid, var_name, NC_SHORT, 2, dimid, &varid[i]);
+            ERR(err)
+        }
+        else {
+            err = ncmpi_def_var(ncid, var_name, NC_DOUBLE, 2, dimid, &varid[i]);
+            ERR(err)
+        }
+    }
+
+    err = ncmpi_enddef(ncid); ERR(err)
+    end_t = MPI_Wtime();
+    timing[2] = end_t - start_t;
+    start_t = end_t;
+
+    start[0] = len * (rank % psizes[0]);
+    start[1] = len * ((rank / psizes[1]) % psizes[1]);
+    count[0] = len;
+    count[1] = len;
+
+    for (i=0; i<NVARS; i++) {
+        if (i % 4 == 0) {
+            err = ncmpi_put_vara_int_all(ncid, varid[i], start, count, (int*)buf[i]);
+            ERR(err)
+        }
+        else if (i % 4 == 1) {
+            err = ncmpi_put_vara_float_all(ncid, varid[i], start, count, (float*)buf[i]);
+            ERR(err)
+        }
+        else if (i % 4 == 2) {
+            err = ncmpi_put_vara_short_all(ncid, varid[i], start, count, (short*)buf[i]);
+            ERR(err)
+        }
+        else {
+            err = ncmpi_put_vara_double_all(ncid, varid[i], start, count, (double*)buf[i]);
+            ERR(err)
+        }
+    }
+
+    end_t = MPI_Wtime();
+    timing[3] = end_t - start_t;
+    start_t = end_t;
+
+    /* get the true I/O amount committed */
+    err = ncmpi_inq_put_size(ncid, w_size); ERR(err)
+
+    /* get all the hints used */
+    err = ncmpi_get_file_info(ncid, w_info_used); ERR(err)
+
+    err = ncmpi_close(ncid); ERR(err)
+
+    end_t = MPI_Wtime();
+    timing[4] = end_t - start_t;
+    timing[0] = end_t - timing[0];
+
+    for (i=0; i<NVARS; i++) free(buf[i]);
+
+    return 1;
+}
+
+/*----< benchmark_read() >---------------------------------------------------*/
+static
+int benchmark_read(char       *filename,
+                   MPI_Offset  len,
+                   MPI_Offset *r_size,
+                   MPI_Info   *r_info_used,
+                   double     *timing)  /* [5] */
+{
+    int i, rank, nprocs, err;
+    int ncid, omode, nvars, dimid[2], *varid;
+    void **buf;
+    double start_t, end_t;
+    MPI_Offset gsizes[2], start[2], count[2];
+    MPI_Comm comm=MPI_COMM_WORLD;
+    MPI_Info info=MPI_INFO_NULL;
+
+    MPI_Comm_rank(comm, &rank);
+    MPI_Comm_size(comm, &nprocs);
+
+    /* set PnetCDF I/O hints */
+    MPI_Info_create(&info);
+    MPI_Info_set(info, "nc_header_read_chunk_size", "512"); /* size in bytes */
+
+    MPI_Barrier(comm);
+    timing[0] = MPI_Wtime();
+
+    /* open file for reading -----------------------------------------*/
+    omode = NC_NOWRITE;
+    err = ncmpi_open(comm, filename, omode, info, &ncid); ERR(err)
+    start_t = MPI_Wtime();
+    timing[1] = start_t - timing[0];
+    MPI_Info_free(&info);
+
+    err = ncmpi_inq_nvars(ncid, &nvars); ERR(err)
+    err = ncmpi_inq_dimid(ncid, "Y", &dimid[0]); ERR(err)
+    err = ncmpi_inq_dimid(ncid, "X", &dimid[1]); ERR(err)
+    err = ncmpi_inq_dimlen(ncid, dimid[0], &gsizes[0]); ERR(err)
+    err = ncmpi_inq_dimlen(ncid, dimid[1], &gsizes[1]); ERR(err)
+
+    varid = (int*)   malloc(nvars * sizeof(int));
+    buf   = (void**) malloc(nvars * sizeof(void*));
+
+    /* construct *-block partitioning pattern */
+    start[0] = 0;
+    start[1] = (gsizes[1] / nprocs) * rank;
+    count[0] = gsizes[0];
+    count[1] = gsizes[1] / nprocs;
+    if (rank < gsizes[1] % nprocs) {
+        start[1] += rank;
+        count[1]++;
+    }
+    else
+        start[1] += gsizes[1] % nprocs;
+
+    /* allocate I/O buffer */
+    len = count[0] * count[1];
+    for (i=0; i<nvars; i++) {
+        varid[i] = i;
+        if (i % 4 == 0)
+            buf[i] = malloc(len * sizeof(int));
+        else if (i % 4 == 1)
+            buf[i] = (float*) malloc(len * sizeof(float));
+        else if (i % 4 == 2)
+            buf[i] = (short*) malloc(len * sizeof(short));
+        else
+            buf[i] = (double*) malloc(len * sizeof(double));
+    }
+    end_t = MPI_Wtime();
+    timing[2] = end_t - start_t;
+    start_t = end_t;
+
+    for (i=0; i<nvars; i++) {
+        if (i % 4 == 0) {
+            err = ncmpi_get_vara_int_all(ncid, varid[i], start, count, (int*)buf[i]);
+            ERR(err)
+        }
+        else if (i % 4 == 1) {
+            err = ncmpi_get_vara_float_all(ncid, varid[i], start, count, (float*)buf[i]);
+            ERR(err)
+        }
+        else if (i % 4 == 2) {
+            err = ncmpi_get_vara_short_all(ncid, varid[i], start, count, (short*)buf[i]);
+            ERR(err)
+        }
+        else {
+            err = ncmpi_get_vara_double_all(ncid, varid[i], start, count, (double*)buf[i]);
+            ERR(err)
+        }
+    }
+
+    end_t = MPI_Wtime();
+    timing[3] = end_t - start_t;
+    start_t = end_t;
+
+    /* get the true I/O amount committed */
+    err = ncmpi_inq_get_size(ncid, r_size); ERR(err)
+
+    /* get all the hints used */
+    err = ncmpi_get_file_info(ncid, r_info_used); ERR(err)
+
+    err = ncmpi_close(ncid); ERR(err)
+
+    end_t = MPI_Wtime();
+    timing[4] = end_t - start_t;
+    timing[0] = end_t - timing[0];
+
+    for (i=0; i<nvars; i++) free(buf[i]);
+    free(buf);
+    free(varid);
+
+    return 1;
+}
+
+/*----< main() >--------------------------------------------------------------*/
+int main(int argc, char** argv) {
+    int rank, nprocs;
+    double timing[10], max_t[10];
+    MPI_Offset len, w_size, r_size, sum_w_size, sum_r_size;
+    MPI_Comm comm=MPI_COMM_WORLD;
+    MPI_Info w_info_used, r_info_used;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(comm, &rank);
+    MPI_Comm_size(comm, &nprocs);
+
+    if (argc != 3) {
+        if (!rank) printf("Usage: %s len filename\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    len = atoll(argv[1]);
+
+    benchmark_write(argv[2], len, &w_size, &w_info_used, timing);
+    benchmark_read (argv[2], len, &r_size, &r_info_used, timing+5);
+
+    MPI_Reduce(&timing, &max_t,     10, MPI_DOUBLE, MPI_MAX, 0, comm);
+#ifdef MPI_OFFSET
+    MPI_Reduce(&w_size, &sum_w_size, 1, MPI_OFFSET, MPI_SUM, 0, comm);
+    MPI_Reduce(&r_size, &sum_r_size, 1, MPI_OFFSET, MPI_SUM, 0, comm);
+#else
+    MPI_Reduce(&w_size, &sum_w_size, 1, MPI_LONG_LONG, MPI_SUM, 0, comm);
+    MPI_Reduce(&r_size, &sum_r_size, 1, MPI_LONG_LONG, MPI_SUM, 0, comm);
+#endif
+    if (rank == 0) {
+        double bw = sum_w_size;
+        bw /= 1048576.0;
+        print_info(&w_info_used);
+
+        printf("-----------------------------------------------------------\n");
+        printf("Write %d variables using blocking APIs\n", NVARS);
+        printf("In each process, the local variable size is %lld x %lld\n", len,len);
+        printf("Total write amount        = %13lld    B\n", sum_w_size);
+        printf("            amount        = %16.4f MiB\n", bw);
+        printf("            amount        = %16.4f GiB\n", bw/1024);
+        printf("Max file open/create time = %16.4f sec\n", max_t[1]);
+        printf("Max PnetCDF define   time = %16.4f sec\n", max_t[2]);
+        printf("Max PnetCDF put      time = %16.4f sec\n", max_t[3]);
+        printf("Max file close       time = %16.4f sec\n", max_t[4]);
+        printf("Max open-to-close    time = %16.4f sec\n", max_t[0]);
+        printf("Write bandwidth           = %16.4f MiB/s\n", bw/max_t[0]);
+        bw /= 1024.0;
+        printf("Write bandwidth           = %16.4f GiB/s\n", bw/max_t[0]);
+
+        bw = sum_r_size;
+        bw /= 1048576.0;
+        printf("-----------------------------------------------------------\n");
+        printf("Read  %d variables using blocking APIs\n", NVARS);
+        printf("In each process, the local variable size is %lld x %lld\n", len,len);
+        printf("Total read  amount        = %13lld    B\n", sum_r_size);
+        printf("            amount        = %16.4f MiB\n", bw);
+        printf("            amount        = %16.4f GiB\n", bw/1024);
+        printf("Max file open/create time = %16.4f sec\n", max_t[6]);
+        printf("Max PnetCDF inquire  time = %16.4f sec\n", max_t[7]);
+        printf("Max PnetCDF get      time = %16.4f sec\n", max_t[8]);
+        printf("Max file close       time = %16.4f sec\n", max_t[9]);
+        printf("Max open-to-close    time = %16.4f sec\n", max_t[5]);
+        printf("Read  bandwidth           = %16.4f MiB/s\n", bw/max_t[5]);
+        bw /= 1024.0;
+        printf("Read  bandwidth           = %16.4f GiB/s\n", bw/max_t[5]);
+    }
+    MPI_Info_free(&w_info_used);
+    MPI_Info_free(&r_info_used);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/benchmarks/FLASH-IO/Makefile.in b/benchmarks/FLASH-IO/Makefile.in
new file mode 100644
index 0000000..032e791
--- /dev/null
+++ b/benchmarks/FLASH-IO/Makefile.in
@@ -0,0 +1,93 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2219 2015-12-11 22:30:03Z wkliao $
+#
+# @configure_input@
+
+.SUFFIXES:      .o .F90
+
+srcdir  = @srcdir@
+VPATH   = @srcdir@
+
+RM           = @RM@
+F90          = @MPIF90@
+
+FPPFLAGS     = @FPPFLAGS@ @FC_MODINC@@PNETCDF_INC@ -I$(srcdir) @NAGf90FPPFLAGS@
+FPPFLAGS    += @FC_DEFINE at N_DIM=3 @FC_DEFINE at MAXBLOCKS=100 @FC_DEFINE at IONMAX=13
+FPPFLAGS    += @NAG_FCFLAGS@
+
+FCFLAGS      = @FCFLAGS@
+COMPILE.F90  = $(F90) -c $(FCFLAGS) $(FPPFLAGS)
+FCLDFLAGS    = @PNETCDF_LIB@ @LDFLAGS@
+FCLIBS       = -lpnetcdf @LIBS@ @LCOV_LIB@
+LINK.F90     = $(F90) $(FCFLAGS) -o $@
+
+TEST_MPIRUN  = @TEST_MPIRUN@
+TEST_OUTDIR  = @TEST_OUTDIR@
+
+PROGS        = flash_benchmark_io
+
+SRCS         = get_mfluid_property.F90 \
+               flash_release.F90 \
+               flash_benchmark_io.F90 \
+               checkpoint_ncmpi_parallel.F90 \
+               plotfile_ncmpi_parallel.F90
+
+HEADERS      = block_boundary_data.fh \
+               common.fh \
+               definitions.fh \
+               numfluids.fh \
+               physicaldata.fh \
+               tree.fh
+
+PACKING_LIST = $(SRCS) $(HEADERS) configure.in Makefile.in README
+
+GARBAGE      = $(PROGS) *.nc
+DIST_GARBAGE = config.log config.status config.cache autom4te.cache \
+               Makefile
+
+OBJS         = $(SRCS:.F90=.o)
+
+all: $(PROGS)
+
+.F90.o:
+	$(COMPILE.F90) $<
+
+$(PROGS): $(OBJS)
+	$(LINK.F90) $(OBJS) $(FCLDFLAGS) $(FCLIBS)
+
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+
+ptest: $(PROGS)
+	$(TEST_MPIRUN_4) ./$(PROGS) $(TEST_OUTDIR)/flash_io_test_
+
+ptests:
+
+MANIFEST.echo: FORCE
+	echo $(PACKING_LIST) | fmt -1
+
+ensure_manifest:
+
+dist:
+	id=FLASH-IO-PnetCDF \
+	&& $(RM) -rf $$id \
+	&& mkdir $$id \
+        && cp $(PACKING_LIST) $$id \
+        && tar -c $$id | gzip > $$id.tar.gz \
+        && $(RM) -rf $$id
+
+install:
+
+uninstall:
+
+clean:
+	@$(RM) -f *.o core core.* $(GARBAGE) \
+        *.gcda *.gcno gmon.out
+
+distclean: clean
+	@$(RM) -rf $(DIST_GARBAGE)
+
+.PHONY: FORCE all clean distclean install uninstall dist ptest
+
diff --git a/benchmarks/FLASH-IO/README b/benchmarks/FLASH-IO/README
new file mode 100644
index 0000000..47bbee1
--- /dev/null
+++ b/benchmarks/FLASH-IO/README
@@ -0,0 +1,81 @@
+#
+#  Copyright (C) 2013, Northwestern University
+#  See COPYRIGHT notice in top-level directory.
+#
+#  $Id: README 1468 2013-10-26 16:53:18Z wkliao $
+
+This software benchmarks the performance of Parallel NetCDF method
+for the I/O and data partitioning pattern from the FLASH I/O benchmark,
+developed at the Flash Center for Computational Science, University of
+Chicago (http://flash.uchicago.edu/site). The URL of the FLASH I/O
+benchmark suite is available from the following URL.
+http://www.ucolick.org/~zingale/flash_benchmark_io/
+
+The FLASH I/O benchmark suite is the I/O kernel of a block-structured adaptive
+mesh hydrodynamics code developed mainly for the study of nuclear flashes on
+neutron stars and white dwarfs.  The computational domain is divided into
+blocks that are distributed across a number of MPI processes.  A block is a
+three-dimensional array with an additional 4 elements as guard cells in each
+dimension on both sides to hold information from its neighbors.  There are 24
+variables per array element, and about 80 blocks on each MPI process.  A
+variation in block numbers, 80, 81, or 82, per MPI process is used to simulate
+a slightly unbalanced I/O load in real runs.  Since the number of blocks is
+fixed for each process, increase in the number of MPI processes increases the
+aggregate I/O amount as well.  FLASH I/O produces a checkpoint file containing
+all 24 variables and two visualization files containing centered and corner
+data covering only four plot variables.  The largest file is the checkpoint
+and the I/O time of which dominates the entire benchmark.
+
+For some detailed description and an illustration of data partitioning pattern,
+please refer to the following paper.
+    Wei-keng Liao and Alok Choudhary. Dynamically Adapting File Domain
+    Partitioning Methods for Collective I/O Based on Underlying Parallel File
+    System Locking Protocols. In the Proceedings of International Conference
+    for High Performance Computing, Networking, Storage and Analysis, Austin,
+    Texas, November 2008.
+
+To compile:
+    run configure command first, eg.
+    autoreconf
+    ./configure --with-pnetcdf=/path/PnetCDF MPIF90=/path/mpi/F90/compiler
+    make
+
+To run:
+    mpiexec -n 512 flash_benchmark_io
+    (this will use the default file base name prefix: "")
+  or
+    mpiexec -n 512 flash_benchmark_io /pvfs2/flash_io_test_
+    (this will use file base name prefix: "/pvfs2/flash_io_test_")
+
+Example output from stdout:
+
+ number of guards      :             4
+ number of blocks      :            80
+ number of variables   :            24
+ checkpoint time       :             7.52  sec
+        max header     :             1.76  sec
+        max unknown    :             5.76  sec
+        max close      :             0.00  sec
+        I/O amount     :         31109.74  MiB
+ plot no corner        :             1.28  sec
+        max header     :             0.29  sec
+        max unknown    :             0.99  sec
+        max close      :             0.00  sec
+        I/O amount     :          5190.36  MiB
+ plot    corner        :             1.56  sec
+        max header     :             0.30  sec
+        max unknown    :             1.27  sec
+        max close      :             0.00  sec
+        I/O amount     :          6224.35  MiB
+ -------------------------------------------------------
+ File base name        : /scratch2/scratchdirs/wkliao/FS_1M_128/flash_io_test_
+   file striping count :           128
+   file striping size  :       1048576     bytes
+ Total I/O amount      :         42524.45  MiB
+ -------------------------------------------------------
+ nproc    array size      exec (sec)   bandwidth (MiB/s)
+  512    16 x  16 x  16     10.36     4103.52
+
+
+
+    
diff --git a/benchmarks/FLASH-IO/block_boundary_data.fh b/benchmarks/FLASH-IO/block_boundary_data.fh
new file mode 100644
index 0000000..d8f1e33
--- /dev/null
+++ b/benchmarks/FLASH-IO/block_boundary_data.fh
@@ -0,0 +1,83 @@
+!
+! This file defines a data structure to be used for quantities
+! which may need to be defined at grid block interfaces, eg fluxes,
+! pressures.
+!
+
+
+! storage used for fluxes at block boundaries. This is used when conservation
+! constraints need to be imposed.
+
+! updated 2-15-00 -- allocate storage for the internal energy flux
+      integer nfluxvar
+      parameter(nfluxvar=nuc2+7) !<<< USER EDIT
+
+      integer nfluxes
+      parameter(nfluxes=max(1,nfluxvar))
+
+      integer maxblocksfl
+      parameter(maxblocksfl= 1+(maxblocks-1)*min(1,nfluxvar) )
+
+
+
+!..in 1d the flux_y, flux_z, tflux_y, and tflux_z arrays are not used,
+!..but do need to be declared. thus, in 1d the parameter maxblocksfl
+!..has been replaced with a 1. this significantly reduces the
+!..memory footprint for 1d simulations.
+
+!..in 2d the flux_z and tflux_z arrays are not used,
+!..but do need to be declared. thus, in 2d the parameter maxblocksfl
+!..has been replaced with a 1. this significantly reduces the
+!..memory footprint for 2d simulations.
+
+
+
+! storage used for cell edges at block boundaries. 
+! This is used when quantities located at cell edge centers need to
+! be used consistently at the boundaries between blocks at different
+! refinement levels.
+
+      integer nedgevar
+      parameter(nedgevar=1)                                     !<<< USER EDIT
+
+      integer nedges
+      parameter(nedges=max(1,nedgevar))
+
+      integer maxblockse
+      parameter(maxblockse= 1+(maxblocks-1)*min(1,nedgevar) )
+
+
+
+
+
+! workspace arrays used for inter-block communications
+        integer nbndmax
+        parameter(nbndmax=max(nbndvar,nfluxes))
+        common/blockbnd/ &
+          recvarx1(nbndmax,1:2,jl_bnd:ju_bnd,kl_bnd:ku_bnd) &
+         ,recvary1(nbndmax,il_bnd:iu_bnd,1:2,kl_bnd:ku_bnd) &
+         ,recvarz1(nbndmax,il_bnd:iu_bnd,jl_bnd:ju_bnd,1:2) &
+         ,bndtempx1(nfluxes,1:2,jl_bnd:ju_bnd,kl_bnd:ku_bnd) &
+         ,bndtempy1(nfluxes,il_bnd:iu_bnd,1:2,kl_bnd:ku_bnd) &
+         ,bndtempz1(nfluxes,il_bnd:iu_bnd,jl_bnd:ju_bnd,1:2)
+        double precision    recvarx1,recvary1,recvarz1
+        double precision    bndtempx1,bndtempy1,bndtempz1
+
+
+
+
+! parameters used in communication calls
+      integer len_block_bndx,len_block_bndy,len_block_bndz
+      parameter(len_block_bndx=2*(nyb+2*nguard*k2d)* &
+                                      (nzb+2*nguard*k3d))
+      parameter(len_block_bndy=2*(nxb+2*nguard*k2d)* &
+                                      (nzb+2*nguard*k3d))
+      parameter(len_block_bndz=2*(nxb+2*nguard)*(nyb+2*nguard))
+
+      integer len_block_ex,len_block_ey,len_block_ez
+      parameter(len_block_ex=2*(nyb+k2d+2*nguard*k2d)* &
+                                      (nzb+k3d+2*nguard*k3d))
+      parameter(len_block_ey=2*(nxb+1+2*nguard)* &
+                                      (nzb+k3d+2*nguard*k3d))
+      parameter(len_block_ez=2*(nxb+1+2*nguard)* &
+                                      (nyb+k2d+2*nguard))
diff --git a/benchmarks/FLASH-IO/checkpoint_ncmpi_parallel.F90 b/benchmarks/FLASH-IO/checkpoint_ncmpi_parallel.F90
new file mode 100644
index 0000000..b602a3e
--- /dev/null
+++ b/benchmarks/FLASH-IO/checkpoint_ncmpi_parallel.F90
@@ -0,0 +1,639 @@
+#define MDIM 3
+! 3-d problem */
+#if N_DIM == 3 
+#define NDIM  3
+#define NGID 15
+! 2-d problem */
+#elif N_DIM == 2
+#define NDIM  2
+#define NGID 9
+! 1-d problem */
+#else
+#define NDIM 1
+#define NGID 5
+#endif
+
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+
+          integer err
+          character(len=*) message
+
+          ! It is a good idea to check returned value for possible error
+          write(6,*) trim(message), trim(nfmpi_strerror(err))
+          call MPI_Abort(MPI_COMM_WORLD, -1, err)
+      end subroutine check
+
+      subroutine write_header_info(nvar_out, ncid, file_creation_time, &
+                                   flash_version, total_blocks, time, &
+                                   nsteps, nzones_block, unk_labels, &
+                                   varid)
+          use mpi
+          use pnetcdf
+          implicit none
+
+          integer nvar_out                    ! num vars to store
+          integer ncid                        ! file handle
+          character(len=*) file_creation_time ! time and date stamp
+          character(len=*) flash_version      ! FLASH version num
+          integer total_blocks                ! total # of blocks
+          double precision time               ! simulation time
+          integer nsteps                      ! total # of timestep
+          integer nzones_block(3)             ! nxb, nyb, nzb
+          character(len=4) unk_labels(*)      ! unknown labels
+          integer varid(*)                    ! output: var ids
+
+          ! local variables
+          integer i, k, err
+          integer dim_tot_blocks, dim_nxb, dim_nyb, dim_nzb
+          integer dim_NGID, dim_NDIM, dim_2
+          integer dimids(4)
+          character(len=5) record_label
+          integer(kind=MPI_OFFSET_KIND) i8NDIM, i8NGID, i8total_blocks
+          integer(kind=MPI_OFFSET_KIND) i8nzones_block(3), string_size
+          integer atotal_blocks(1), ansteps(1)
+          double precision atime(1)
+
+          i8NDIM = NDIM
+          i8NGID = NGID
+          i8total_blocks = total_blocks
+          i8nzones_block(:) = nzones_block(:)
+          atotal_blocks(1) = total_blocks
+          ansteps(1) = nsteps
+
+          ! to avoid inconsistent header metadata warning from PnetCDF
+          atime(1) = time
+          call MPI_Bcast(atime, 1, MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD, err)
+
+          err = nfmpi_def_dim(ncid, "dim_tot_blocks", i8total_blocks, dim_tot_blocks)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_tot_blocks")
+          err = nfmpi_def_dim(ncid, "dim_nxb", i8nzones_block(1), dim_nxb)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_nxb")
+          err = nfmpi_def_dim(ncid, "dim_nyb", i8nzones_block(2), dim_nyb)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_nyb")
+          err = nfmpi_def_dim(ncid, "dim_nzb", i8nzones_block(3), dim_nzb)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_nzb")
+          err = nfmpi_def_dim(ncid, "dim_NGID", i8NGID, dim_NGID)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_NGID")
+          err = nfmpi_def_dim(ncid, "dim_NDIM", i8NDIM, dim_NDIM)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_NDIM")
+          err = nfmpi_def_dim(ncid, "dim_2", 2_MPI_OFFSET_KIND, dim_2)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_2")
+
+          dimids(1) = dim_tot_blocks
+
+          ! define var for refinement level
+          err = nfmpi_def_var(ncid, "lrefine", NF_INT, 1, dimids, varid(1))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: lrefine")
+
+          ! define var for nodetype
+          err = nfmpi_def_var(ncid, "nodetype", NF_INT, 1, dimids, varid(2))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: nodetype")
+
+          ! define var for global id
+          dimids(1) = dim_NGID
+          dimids(2) = dim_tot_blocks
+          err = nfmpi_def_var(ncid, "gid", NF_INT, 2, dimids, varid(3))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: grid")
+
+          ! define var for grid coordinates
+          dimids(1) = dim_NDIM
+          dimids(2) = dim_tot_blocks
+          err = nfmpi_def_var(ncid, "coordinates", NF_DOUBLE, 2, dimids, varid(4))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: coordinates")
+
+          ! define var for grid block size
+          dimids(1) = dim_NDIM
+          dimids(2) = dim_tot_blocks
+          err = nfmpi_def_var(ncid, "blocksize", NF_DOUBLE, 2, dimids, varid(5))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: blocksize")
+
+          ! define var for grid bounding box
+          dimids(1) = dim_2
+          dimids(2) = dim_NDIM
+          dimids(3) = dim_tot_blocks
+          err = nfmpi_def_var(ncid, "bndbox", NF_DOUBLE, 3, dimids, varid(6))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: bndbox")
+
+          ! define var for unknown array
+          dimids(1) = dim_nxb    
+          dimids(2) = dim_nyb
+          dimids(3) = dim_nzb
+          dimids(4) = dim_tot_blocks
+
+          do i=1, nvar_out
+              record_label = unk_labels(i)
+              do k=1, 4
+                 if (record_label(k:k) .EQ. ' ') record_label(k:k) = '_'
+              enddo
+              record_label(5:5) = char(0)  ! string terminate char
+              err = nfmpi_def_var(ncid, record_label, NF_DOUBLE, 4, dimids, varid(i+6))
+              if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: record_label")
+          enddo
+
+          string_size = LEN_TRIM(file_creation_time)
+          err = nfmpi_put_att_text(ncid, NF_GLOBAL, "file_creation_time", string_size, file_creation_time)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_text: file_creation_time")
+          string_size = LEN_TRIM(flash_version)
+          err = nfmpi_put_att_text(ncid, NF_GLOBAL, "flash_version",  string_size, flash_version)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_text: flash_version")
+          err = nfmpi_put_att_int(ncid, NF_GLOBAL, "total_blocks",  NF_INT, 1_MPI_OFFSET_KIND, atotal_blocks)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_int: total_blocks")
+          err = nfmpi_put_att_int(ncid, NF_GLOBAL, "nsteps", NF_INT, 1_MPI_OFFSET_KIND, ansteps)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_int: nsteps")
+          err = nfmpi_put_att_int(ncid, NF_GLOBAL, "nxb", NF_INT, 1_MPI_OFFSET_KIND, nzones_block(1))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_int: nxb")
+          err = nfmpi_put_att_int(ncid, NF_GLOBAL, "nyb", NF_INT, 1_MPI_OFFSET_KIND, nzones_block(2))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_int: nyb")
+          err = nfmpi_put_att_int(ncid, NF_GLOBAL, "nzb", NF_INT, 1_MPI_OFFSET_KIND, nzones_block(3))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_int: nzb")
+          err = nfmpi_put_att_double(ncid, NF_GLOBAL, "time", NF_DOUBLE, 1_MPI_OFFSET_KIND, atime)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_double: time")
+      
+          err = nfmpi_enddef(ncid)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_enddef")
+      end subroutine write_header_info
+
+!----------------------------------------------------------------------------
+! subroutine checkpoint_wr
+!----------------------------------------------------------------------------
+
+      double precision function checkpoint_wr_ncmpi_par (filenum, simtime)
+!
+! Do parallel i/o using Parallel netCDF
+!
+! MZ -- 2-20-00
+! Jianwei -- 11/15/02
+!
+! This version of checkpoint uses Parallel netCDF to store the PARAMESH data.
+! The IO is done in parallel -- no copying of the data to a single processor
+! to do the writing is performed.  
+!
+! Parallel netCDF uses MPI-IO (via ROMIO) to support parallel IO. Each
+! processor must open the file, define the dataspaces for each netCDF
+! variables.  
+!
+! A single record for each of the PARAMESH data structures is created.  A
+! processor only writes to a subset of this record.  Each record has a 
+! dimension with length = tot_blocks.  The offset of a processor into this 
+! dimension is computed by looking at the total number of blocks that are
+! below the current processor.
+!
+! In this version of the checkpoint, each variable is given its own 
+! record -- this makes it easier to change the variable list in the
+! future without disturbing the format of the file.
+!
+! The include file -- ncmpi_flash.h is used for the C routines and mirrors
+! the necessary data from physicaldata.fh
+!
+! written for netCDF 3.0
+!
+!---------------------------------------------------------------------------
+
+      use pnetcdf
+
+#include "common.fh"
+
+      integer filenum
+      double precision simtime
+      
+      integer block_no
+      integer i, j
+      integer ngid 
+      integer err
+
+      integer n_to_left(0:16383)  ! must extend from 0 to NumPEs-1
+
+! 2-20-00 -- we don't need to allocate more space than necessary
+!      integer gid(mfaces+1+mchild,maxblocks_tr)
+      integer gid(nfaces+1+nchild,maxblocks_tr)
+
+      integer tot_blocks
+
+      save gid, n_to_left
+
+      integer nzones_block(3)
+
+! create a character variable to hold the string representation of the block
+! number.  Note this is set to be 4 characters long (i.e. max = 9999).  
+      character*4  fnum_string
+      character*80 filename
+      character*8 str
+
+! create a temporary array to hold the 4 character variable names
+! this will include those defined in definitions.fh and network_common.fh
+      character*4 unklabels(nvar)
+
+! storage for the current date and time
+        character date_string*40
+
+      character(len=4) :: ionam(ionmax), record_label
+
+      integer varid(6+nvar)
+
+      integer global_offset
+
+      character (len=40) :: flash_release
+      double precision unk_buf(1,nxb,nyb,nzb,maxblocks)
+#ifdef TIMERS
+      double precision time_start, time_io
+#endif
+      double precision coord_buf(ndim,lnblocks)
+      double precision bs_buf(ndim,lnblocks)
+      double precision bb_buf(2,ndim,lnblocks)
+
+      integer ncid, cmode, file_info
+      integer(kind=MPI_OFFSET_KIND) starts(5), counts(4), put_size
+      integer gsizes(5), subsizes(5), buftype, reqs(nvar+6), stats(nvar+6)
+
+!-----------------------------------------------------------------------------
+! compute the total number of blocks left of a given processor number
+!-----------------------------------------------------------------------------
+      chk_t(1) = MPI_Wtime()
+
+! use an allgather routine here 
+      call MPI_Allgather(lnblocks, 1,MPI_INTEGER, & 
+                         n_to_left,1,MPI_INTEGER, & 
+                         MPI_COMM_WORLD,err)
+
+      
+! compute the total number of blocks
+      tot_blocks = 0
+
+      do i = 0,NumPEs-1
+         tot_blocks = tot_blocks + n_to_left(i)
+      end do
+      
+! compute the number of procssors to the left of a processor
+      do i = NumPEs-1,1,-1
+         n_to_left(i) = n_to_left(i-1)
+      end do
+
+      n_to_left(0) = 0
+      do i = 2,NumPEs-1
+         n_to_left(i) = n_to_left(i) + n_to_left(i-1)
+      end do
+
+
+!-----------------------------------------------------------------------------
+! compute the global id -- this is a single array which stores the 
+! neighbor block numbers, the parent, and the children of a given block
+!-----------------------------------------------------------------------------
+      do block_no = 1,lnblocks
+
+         ngid = 0
+
+! loop over the faces and store the neighbors
+         do j = 1,nfaces
+            ngid = ngid + 1
+
+! if the neighbor exists, then store the block number of the neighbor
+! -- take into account the number of blocks below the processor that the
+! neighbor is on, so the block number is global
+            if (neigh(1,j,block_no).gt.0) then
+               gid(ngid,block_no) = neigh(1,j,block_no) +  & 
+                    n_to_left(neigh(2,j,block_no))
+            else
+
+! the neighbor is either a physical boundary or does not exist at that 
+! level of refinement
+               gid(ngid,block_no) = neigh(1,j,block_no)
+            end if
+         end do
+        
+! store the parent of the current block
+         ngid = ngid + 1
+         if (parent(1,block_no).gt.0) then
+            gid(ngid,block_no) = parent(1,block_no) +  & 
+                 n_to_left(parent(2,block_no))
+         else
+            gid(ngid,block_no) = parent(1,block_no)
+         end if
+         
+! store the children of the current block
+         do j = 1,nchild
+            ngid = ngid + 1
+            if (child(1,j,block_no).gt.0) then
+               gid(ngid,block_no) = child(1,j,block_no) +  & 
+                    n_to_left(child(2,j,block_no))
+            else
+               gid(ngid,block_no) = child(1,j,block_no)
+            end if
+         end do
+
+      end do
+
+!-----------------------------------------------------------------------------
+! open the netCDF file
+!-----------------------------------------------------------------------------
+      write (fnum_string, '(i4.4)') filenum
+      filename = trim(basenm) // 'ncmpi_chk_'//fnum_string//'.nc'
+
+      ! set up MPI I/O hints for performance enhancement
+      call MPI_Info_create(file_info, err)
+
+      ! use some ROMIO hints
+      call MPI_Info_set(file_info, 'romio_no_indep_rw', 'true', err)
+
+      cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+      err = nfmpi_create(MPI_COMM_WORLD, trim(filename), cmode, &
+                          file_info, ncid)
+      if (err .NE. NF_NOERR) call check(err, "nfmpi_create")
+
+      call MPI_Info_free(file_info, err)
+
+      err = nfmpi_get_file_info(ncid, info_used)
+
+!-----------------------------------------------------------------------------
+! store the scalar information -- # of blocks, simulation time, etc
+!-----------------------------------------------------------------------------
+      
+! get the current time and date
+      date_string = 'now'      
+
+! store the number of zones / block in each direction
+      nzones_block(1) = nxb
+      nzones_block(2) = nyb
+      nzones_block(3) = nzb
+
+! get the names of the fluids being followed
+      call get_mfluid_property ("short name", ionam)
+
+! merge the two variable lists into one for storage
+      unklabels(1:nvar-nuc2)     = varnam(:)
+      unklabels(nvar-nuc2+1:nvar) = ionam(:)
+
+#ifdef TIMERS
+      time_start = MPI_Wtime()
+#endif
+
+      call write_header_info(nvar, & 
+                             ncid, & 
+                             date_string, &
+                             flash_release(), &
+                             tot_blocks, & 
+                             simtime, & 
+                             nstep, & 
+                             nzones_block, & 
+                             unklabels, &
+                             varid)
+
+#ifdef TIMERS
+      print *, 'header: MyPE = ', MyPE, ' time = ',  & 
+           MPI_Wtime() - time_start
+#endif
+
+      global_offset = n_to_left(MyPE)
+
+!-----------------------------------------------------------------------------
+! store the tree information
+!-----------------------------------------------------------------------------
+
+! store the refinement level
+#ifdef TIMERS
+      time_start = MPI_Wtime()
+#endif
+
+      starts(1) = global_offset+1
+      counts(1) = lnblocks
+      if (use_nonblocking_io) then
+          err = nfmpi_iput_vara_int(ncid, varid(1), starts, counts, lrefine, reqs(1))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_iput_vara_int: lrefine")
+      else
+          err = nfmpi_put_vara_int_all(ncid, varid(1), starts, counts, lrefine)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_int_all: lrefine")
+      endif
+
+#ifdef TIMERS
+      print *, 'lrefine: MyPE = ', MyPE, ' time = ',  & 
+           MPI_Wtime() - time_start
+#endif
+
+! store the nodetype
+#ifdef TIMERS
+      time_start = MPI_Wtime()
+#endif      
+
+      if (use_nonblocking_io) then
+          err = nfmpi_iput_vara_int(ncid, varid(2), starts, counts, nodetype, reqs(2))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_int: nodetype")
+      else
+          err = nfmpi_put_vara_int_all(ncid, varid(2), starts, counts, nodetype)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_int_all: nodetype")
+      endif
+
+#ifdef TIMERS
+      print *, 'nodetype: MyPE = ', MyPE, ' time = ',  & 
+           MPI_Wtime() - time_start
+#endif
+
+! store the global id
+#ifdef TIMERS
+      time_start = MPI_Wtime()
+#endif      
+
+      starts(1) = 1
+      starts(2) = global_offset+1
+      counts(1) = NGID
+      counts(2) = lnblocks
+      if (use_nonblocking_io) then
+          err = nfmpi_iput_vara_int(ncid, varid(3), starts, counts, gid, reqs(3))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_iput_vara_int: gid")
+      else
+          err = nfmpi_put_vara_int_all(ncid, varid(3), starts, counts, gid)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_int_all: gid")
+      endif
+
+#ifdef TIMERS
+      print *, 'gid: MyPE = ', MyPE, ' time = ',  & 
+           MPI_Wtime() - time_start
+#endif
+
+!-----------------------------------------------------------------------------
+! store the grid information
+!-----------------------------------------------------------------------------
+      
+! store the coordinates
+#ifdef TIMERS
+      time_start = MPI_Wtime()
+#endif
+      coord_buf(1:ndim,1:lnblocks) = coord(1:ndim,1:lnblocks)
+
+      starts(1) = 1
+      starts(2) = global_offset+1
+      counts(1) = NDIM
+      counts(2) = lnblocks
+      if (use_nonblocking_io) then
+          err = nfmpi_iput_vara_double(ncid, varid(4), starts, counts, coord_buf, reqs(4))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_iput_vara_double: coord")
+      else
+          err = nfmpi_put_vara_double_all(ncid, varid(4), starts, counts, coord_buf)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_double_all: coord")
+      endif
+
+#ifdef TIMERS
+      print *, 'coord: MyPE = ', MyPE, ' time = ',  & 
+           MPI_Wtime() - time_start
+#endif
+
+! store the block size
+#ifdef TIMERS
+      time_start = MPI_Wtime()
+#endif
+      bs_buf(1:ndim,1:lnblocks) = size(1:ndim,1:lnblocks)
+
+      starts(1) = 1
+      starts(2) = global_offset+1
+      counts(1) = NDIM
+      counts(2) = lnblocks
+      if (use_nonblocking_io) then
+          err = nfmpi_iput_vara_double(ncid, varid(5), starts, counts, bs_buf, reqs(5))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_iput_vara_double: size")
+      else
+          err = nfmpi_put_vara_double_all(ncid, varid(5), starts, counts, bs_buf)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_double_all: size")
+      endif
+
+#ifdef TIMERS
+      print *, 'size: MyPE = ', MyPE, ' time = ',  & 
+           MPI_Wtime() - time_start
+#endif
+
+! store the bounding box 
+#ifdef TIMERS
+      time_start = MPI_Wtime()
+#endif      
+      bb_buf(1:2,1:ndim,1:lnblocks) = bnd_box(1:2,1:ndim,1:lnblocks)
+
+      starts(1) = 1
+      starts(2) = 1
+      starts(3) = global_offset+1
+      counts(1) = 2
+      counts(2) = NDIM
+      counts(3) = lnblocks
+      if (use_nonblocking_io) then
+          err = nfmpi_iput_vara_double(ncid, varid(6), starts, counts, bb_buf, reqs(6))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_iput_vara_double: bnd_box")
+      else
+          err = nfmpi_put_vara_double_all(ncid, varid(6), starts, counts, bb_buf)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_double_all: bnd_box")
+      endif
+
+#ifdef TIMERS
+      print *, 'bb1: MyPE = ', MyPE, ' time = ',  & 
+           MPI_Wtime() - time_start
+#endif
+
+      chk_t(2) = MPI_Wtime()
+      chk_t(1) = chk_t(2) - chk_t(1)
+
+!-----------------------------------------------------------------------------
+! store the unknowns -- here we will pass the entire unk array on each 
+! processor.  The HDF 5 memory space functionality will pick just the 
+! interior cells to write to disk.
+!-----------------------------------------------------------------------------
+#ifdef TIMERS
+      time_io = 0.e0
+      time_start = MPI_Wtime()
+#endif
+
+      if (use_nonblocking_io) then
+         ! create a derive data type for buffer unk
+         gsizes(1) = nvar
+         gsizes(2) = iu_bnd - il_bnd + 1
+         gsizes(3) = ju_bnd - jl_bnd + 1
+         gsizes(4) = ku_bnd - kl_bnd + 1
+         gsizes(5) = maxblocks
+         subsizes(1) = 1
+         subsizes(2) = nxb
+         subsizes(3) = nyb
+         subsizes(4) = nzb
+         subsizes(5) = lnblocks
+         starts(1) = 0
+         starts(2) = nguard
+         starts(3) = nguard*k2d
+         starts(4) = nguard*k3d
+         starts(5) = 0
+         call MPI_Type_create_subarray(5, gsizes, subsizes, starts, &
+                                       MPI_ORDER_FORTRAN, &
+                                       MPI_DOUBLE_PRECISION, buftype, &
+                                       err)
+         call MPI_Type_commit(buftype, err)
+      endif
+
+      starts(1) = 1
+      starts(2) = 1
+      starts(3) = 1
+      starts(4) = global_offset+1
+      counts(1) = nxb
+      counts(2) = nyb
+      counts(3) = nzb
+      counts(4) = lnblocks
+
+      do i = 1, nvar
+         record_label = unklabels(i)
+
+         if (.NOT. use_nonblocking_io) then
+            ! when using nonblocking flexible API, we don't even need unk_buf
+            unk_buf(1, 1:nxb, 1:nyb, 1:nzb, :) =        &
+                unk(i, nguard+1     : nguard+nxb,       & 
+                       nguard*k2d+1 : nguard*k2d+nyb,   & 
+                       nguard*k3d+1 : nguard*k3d+nzb, :)
+         endif
+
+         if (use_nonblocking_io) then
+            err = nfmpi_iput_vara(ncid, varid(6+i), starts, counts, &
+                                  unk(i, 1, 1, 1, 1), 1_MPI_OFFSET_KIND, buftype, reqs(i+6))
+            if (err .NE. NF_NOERR) &
+                call check(err, "nfmpi_iput_vara: unknowns")
+         else
+            err = nfmpi_put_vara_double_all(ncid, varid(6+i), starts, counts, unk_buf)
+            if (err .NE. NF_NOERR) &
+                call check(err, "nfmpi_put_vara_double_all: unknowns")
+         endif
+      enddo
+
+      if (use_nonblocking_io) then
+          ! wait for the nonblocking I/O to complete
+          err = nfmpi_wait_all(ncid, nvar+6, reqs, stats)
+          if (err .NE. NF_NOERR) &
+              call check(err, "nfmpi_wait_all: unknowns")
+
+          ! check the status of each nonblocking request
+          do i=1, nvar+6
+             write(str,'(I2)') i
+             if (stats(i) .NE. NF_NOERR) &
+                 call check(stats(i), 'In nfmpi_wait_all req '//trim(str))
+          enddo
+          call MPI_Type_free(buftype, err)
+      endif
+
+#ifdef TIMERS
+      time_io = time_io + (MPI_Wtime() - time_start)
+      print *, 'unk: MyPE = ', MyPE, ' time = ', time_io
+#endif
+
+!-----------------------------------------------------------------------------
+! close the file
+!-----------------------------------------------------------------------------
+
+      chk_t(3) = MPI_Wtime()
+      chk_t(2) = chk_t(3) - chk_t(2)
+
+      err = nfmpi_inq_put_size(ncid, put_size)
+      if (err .NE. NF_NOERR) call check(err, "nfmpi_inq_put_size")
+
+      err = nfmpi_close(ncid);
+      if (err .NE. NF_NOERR) call check(err, "nfmpi_close")
+
+      chk_t(3) = MPI_Wtime() - chk_t(3)
+
+      checkpoint_wr_ncmpi_par = put_size
+
+      return
+      end
+
+
+
diff --git a/benchmarks/FLASH-IO/common.fh b/benchmarks/FLASH-IO/common.fh
new file mode 100644
index 0000000..2848d6e
--- /dev/null
+++ b/benchmarks/FLASH-IO/common.fh
@@ -0,0 +1,58 @@
+!******************************************************************************
+
+!  File:        common.fh
+
+!  Purpose:        This file is the global common, visible to all modules,
+!                containing such things as physical constants, runtime
+!                parameters, etc.
+
+        implicit none
+
+
+
+#include "physicaldata.fh"
+
+!                Simulation time and timestep
+
+        double precision        time, dt
+
+!                Simulation step number and beginning step number; my processing
+!                element (PE) number, the PE number of the "master" processor,
+!                and the total number of PEs
+
+        integer nstep, nbegin, MyPE, MasterPE, NumPEs
+
+        common /floats/ time, dt
+
+        common /intgrs/ nstep, nbegin, MyPE, MasterPE, NumPEs
+
+! add the runtime parameters needed explicitly        
+        character*128 basenm
+        
+        common /runtime_char/ basenm
+
+!==============================================================================
+
+!                Numerical constants
+
+        include 'definitions.fh'
+
+!==============================================================================
+
+!                PARAMESH adaptive mesh refinement (AMR) declarations
+
+        include 'tree.fh'
+
+!==============================================================================
+
+!                Message-Passing Interface (MPI) library subroutines & constants
+
+        include 'mpif.h'
+
+        integer info_used
+        logical use_nonblocking_io
+
+        double precision chk_t(3), corner_t(3), nocorner_t(3)
+        common /timers/ chk_t, corner_t, nocorner_t, info_used, use_nonblocking_io
+
+
diff --git a/benchmarks/FLASH-IO/configure.in b/benchmarks/FLASH-IO/configure.in
new file mode 100644
index 0000000..49593b4
--- /dev/null
+++ b/benchmarks/FLASH-IO/configure.in
@@ -0,0 +1,225 @@
+AC_REVISION($Id: configure.in 2281 2015-12-26 17:43:34Z wkliao $)dnl
+dnl -*- Mode: shell-script-mode; -*-
+dnl Process this file with GNU autoconf(1) to produce a configure script.
+dnl
+
+AC_PREREQ(2.69)
+AC_INIT([PnetCDF-FLASH-IO], [1.0.0], [parallel-netcdf at mcs.anl.gov])
+
+dnl user defined macro for printing messages for debugging
+_DEBUG=no
+AC_DEFUN([UD_MSG_DEBUG],
+         [if test "x${_DEBUG}" = xyes ; then
+             AC_MSG_NOTICE(DEBUG: $1)
+          fi
+         ]
+)
+
+dnl an option to use a customized rm command
+if test "x${RM}" != x ; then
+   AC_MSG_CHECKING(rm )
+   if ! test -f ${RM} ; then
+      AC_CHECK_PROG([rm_cmd], [${RM}], [yes], [no])
+      if test "x${rm_cmd}" = xyes ; then
+         RM=${RM}
+      fi
+   else
+      RM=${RM}
+   fi
+   AC_MSG_RESULT(using $RM)
+else
+   RM="rm"
+fi
+AC_SUBST(RM)
+
+AC_ARG_ENABLE(echo,
+   [AS_HELP_STRING([--enable-echo],
+                   [Turn on strong echoing. @<:@default: no@:>@])],
+   [set -x]
+)
+
+AC_ARG_VAR(MPIF90, MPI Fortran 90 compiler)
+# Check env variable $MPIF90 set by the users
+if test "x${MPIF90}" != x ; then
+    UD_MSG_DEBUG(MPIF90 is set to $MPIF90)
+    if test ! -x "${MPIF90}" ; then
+        UD_MSG_DEBUG(MPIF90 is defined as ${MPIF90} but file does not exist)
+        # MPIF90 may not be an absolute path, check MPIF90 from $PATH
+        MPIF90_ISVALID=""
+        AC_PATH_PROGS(MPIF90_ISVALID, [${MPIF90}])
+        if test "x${MPIF90_ISVALID}" = x ; then
+            AC_MSG_WARN(File ${MPIF90} does not exist)
+            MPIF90=""
+        else
+            MPIF90=$MPIF90_ISVALID
+        fi
+    fi
+fi
+
+dnl if MPIF90 is still empty, search under user's PATH
+CANDIDATE_MPIF90="mpif90 mpixlf90_r mpixlf90 blrts_xlf90 mpxlf90_r mpxlf90 mpxlf95_r mpxlf95 ftn mpiifort mpiifc mpifrtpx"
+if test "x${MPIF90}" = x ; then
+   UD_MSG_DEBUG(find possible MPIF90 under user's PATH)
+   AC_PATH_PROGS([MPIF90], [$CANDIDATE_MPIF90])
+fi
+
+if test "x${MPIF90}" = x ; then
+   AC_MSG_ERROR([
+   -----------------------------------------------------------------------
+    No MPI F90 compiler can be found. FLASH I/O kernel requires an MPI F90
+    compiler. Please specify the location of one with the MPIF90 environment
+    variable
+   -----------------------------------------------------------------------])
+fi
+
+dnl Check if MPIF90 is a valid MPI compiler
+FC=${MPIF90}
+AC_PROG_FC
+
+dnl Check if Fortran compiler is NAG
+dnl According to nagfor manual the command-line option to should version is -V
+dnl
+AC_DEFUN([UD_CHECK_FC_NAG],[
+    AC_CACHE_CHECK([if Fortran compiler is NAG], [ac_cv_fc_compiler_nag],
+    [ac_cv_fc_compiler_nag=no
+     eval $MPIF90 -V </dev/null >& conftest.ver
+     _FC_VENDOR=`head -c 3 conftest.ver`
+     if test "x${_FC_VENDOR}" = xNAG ; then
+        ac_cv_fc_compiler_nag=yes
+     fi
+     ${RM} -f conftest.ver
+     unset _FC_VENDOR
+    ])
+])
+
+dnl Check if the Fortran compiler is an NAG
+UD_CHECK_FC_NAG
+if test "x${ac_cv_fc_compiler_nag}" = xyes ; then
+   NAGf90FPPFLAGS="-DNAGf90Fortran"
+   NAG_FCFLAGS="-mismatch"
+   AC_SUBST(NAGf90FPPFLAGS)
+   AC_SUBST(NAG_FCFLAGS)
+fi
+
+dnl find compile flags for handling files with .F .F90 .f90 extensions
+dnl steal AC_FC_PP_SRCEXT from autoconf V2.69 to make AC_FC_PP_SRCEXT
+AC_FC_PP_SRCEXT([F90])
+AC_SUBST(FCFLAGS_F90)
+
+FPPFLAGS=${FPPFLAGS-}
+AC_SUBST(FPPFLAGS)
+
+dnl compiler command-line define preprocess flag, result in FC_DEFINE
+AC_FC_PP_DEFINE
+
+AC_LANG_PUSH([Fortran])
+AC_FC_SRCEXT([f90])
+AC_SUBST(FCFLAGS_f90)
+
+AC_COMPILE_IFELSE([AC_LANG_CALL([],[MPI_Comm_rank])],
+                  [valid_mpif90=yes],[valid_mpif90=no]
+)
+AC_LANG_POP([Fortran])
+if test "x${valid_mpif90}" = xno && test "x${enable_fortran}" = xyes ; then
+   AC_MSG_ERROR([
+      ------------------------------------------------------------
+        Invalid MPI Fortran 90 compiler specified: "${MPIF90}"
+        A working MPI compiler is required. Please specify the
+        location of one either with the MPIF90 environment
+        variable or the --with-mpi configure flag
+      ------------------------------------------------------------])
+fi
+AC_SUBST(MPIF90)
+FC=$MPIF90
+
+AC_FC_MODULE_FLAG
+dnl AC_FC_MODULE_FLAG defines FC_MODINC
+UD_MSG_DEBUG([FC_MODINC=$FC_MODINC])
+
+PNETCDF_INSTALL=""
+AC_ARG_WITH(pnetcdf,
+    [AS_HELP_STRING([--with-pnetcdf=/path/to/implementation],
+                    [installation prefix for PnetCDF implementation])],
+    if test "x${withval}" = xyes ; then
+        AC_MSG_ERROR(--with-pnetcdf must be given a pathname)
+    else
+        PNETCDF_INSTALL=${withval}
+    fi
+)
+
+AC_MSG_CHECKING(PnetCDF Fortran library)
+if test "x${PNETCDF_INSTALL}" != x ; then
+   PNETCDF_INC=${PNETCDF_INSTALL}/include
+   PNETCDF_LIB="-L${PNETCDF_INSTALL}/lib"
+fi
+
+have_pnetcdf=no
+
+AC_LANG_PUSH([Fortran])
+FCFLAGS_save=${FCFLAGS}
+LIBS_save=${LIBS}
+if test "x${PNETCDF_INC}" != x ; then
+   FCFLAGS="${FCFLAGS} ${FPPFLAGS} ${FC_MODINC}${PNETCDF_INC}"
+fi
+if test "x${PNETCDF_LIB}" != x ; then
+   LDFLAGS="${LDFLAGS} ${PNETCDF_LIB}"
+fi
+LIBS="-lpnetcdf ${LIBS}"
+AC_LINK_IFELSE([AC_LANG_CALL([], [nfmpi_create])],
+   [AC_MSG_RESULT(works)
+    have_pnetcdf=yes],
+   [AC_MSG_RESULT(failed to compile test program)
+    unset FC
+   ]
+)
+FCFLAGS=${FCFLAGS_save}
+LIBS=${LIBS_save}
+AC_LANG_POP([Fortran])
+AC_SUBST(PNETCDF_INC)
+AC_SUBST(PNETCDF_LIB)
+
+if test "x${have_pnetcdf}" = xno ; then
+    AC_MSG_ERROR([
+    ------------------------------------------------------------
+     The PnetCDF library and header file are required to build
+     the FLASH I/O kernel. Use option
+         --with-pnetcdf=/path/to/implementation
+     to specify the location of PnetCDF build.  Stopping ...
+     Check 'config.log' for more information.
+    ------------------------------------------------------------])
+fi
+
+AC_ARG_VAR(TEST_MPIRUN, [MPI run command for running test])
+AC_ARG_VAR(TEST_OUTDIR, [Output file directory for running test])
+if test "x${TEST_MPIRUN}" = x ; then
+    dnl set default to mpiexec
+    TEST_MPIRUN=mpiexec
+fi
+if test "x${TEST_OUTDIR}" = x ; then
+    dnl set default to current directory
+    TEST_OUTDIR=.
+fi
+AC_SUBST(TEST_MPIRUN)
+AC_SUBST(TEST_OUTDIR)
+
+LCOV_LIB=
+AC_SUBST(LCOV_LIB)
+
+AC_CONFIG_FILES(Makefile)
+AC_OUTPUT
+echo "--------------------------------------------------------------------"
+echo \
+"
+   FLASH I/O kernel with PnetCDF I/O method
+
+   Compilers: 
+              MPIF90      = ${MPIF90}
+              FFLAGS      = ${FFLAGS}
+              FCFLAGS     = ${FCFLAGS}
+              F90FLAGS    = ${F90FLAGS}
+              LDFLAGS     = ${LDFLAGS}
+              LIBS        = ${LIBS}
+
+   Now type 'make' to produce executable
+---------------------------------------------------------------------"
+
diff --git a/benchmarks/FLASH-IO/definitions.fh b/benchmarks/FLASH-IO/definitions.fh
new file mode 100644
index 0000000..0d29554
--- /dev/null
+++ b/benchmarks/FLASH-IO/definitions.fh
@@ -0,0 +1,98 @@
+!*******************************************************************************
+
+!  File:        definitions.h
+!  Purpose:        Define constants used for array indices, boundary conditions,
+!                geometries, etc.
+
+!                Pointers for the unk array (AMR fluid variable data structure)
+
+      integer idens, ivelx, ively, ivelz, ipres, iener, itemp, &
+             igame, igamc, ienuc, igpot, inuc_begin
+
+      parameter (idens = 1, &
+                ivelx = 2, &
+                      ively = 3, &
+                ivelz = 4, &
+                ipres = 5, &
+                iener = 6, &
+                itemp = 7, &
+                igamc = 8, &
+                igame = 9, &
+                ienuc = 10, &
+                      igpot = 11, &
+                inuc_begin = 12)
+
+! labels for the hydro variables, for storage in the HDF output files
+! the abundance labels are defined in the nuclear burner
+      character*4 varnam(nvar-nuc2)
+
+      data varnam /'dens', &
+                  'velx',  &
+                  'vely',  &
+                  'velz',  &
+                  'pres',  &
+                  'ener',  &
+                  'temp',  &
+                  'gamc',  & 
+                  'game',  &
+                  'enuc',  &
+                        'gpot'/
+
+!-------------------------------------------------------------------------------
+
+!                Pointers for the unk2 array (x coordinate information)
+
+      integer ixznl, ixzn, ixznr, iugridx
+
+      parameter (ixznl   = 1, &
+                ixzn    = 2, &
+                ixznr   = 3, &
+                iugridx = 4)
+
+!                Pointers for the unk3 array (y coordinate information)
+
+      integer iyznl, iyzn, iyznr, iugridy
+
+      parameter (iyznl   = 1, &
+                iyzn    = 2,  &
+                iyznr   = 3,  &
+                iugridy = 4)
+
+!                Pointers for the unk4 array (z coordinate information)
+
+      integer izznl, izzn, izznr, iugridz
+
+      parameter (izznl   = 1, &
+                izzn    = 2, &
+                izznr   = 3, &
+                iugridz = 4)
+
+
+!                Constants for use by geometry-dependent code
+
+      integer geom_cartesian, geom_planar, geom_cylrad, geom_sphrad, &
+                   geom_cylang, geom_sphtheta, geom_sphphi
+
+      parameter (geom_cartesian = 0, &
+                      geom_planar        = 0, &
+                      geom_cylrad        = 1, &
+                      geom_sphrad        = 2, &
+                      geom_cylang        = 3, &
+                      geom_sphtheta        = 4, &
+                      geom_sphphi        = 5)
+
+!-------------------------------------------------------------------------------
+
+!                Constants to indicate which sweep we're doing, for
+!                dimensionally split hydro solvers
+
+      integer sweep_x, sweep_y, sweep_z, sweep_order_xyz, &
+                   sweep_order_zyx, sweep_all
+
+      parameter (sweep_all         = 0, &
+                      sweep_x         = 1, &
+                      sweep_y         = 2, &
+                      sweep_z         = 3, &
+                      sweep_order_xyz = 1, &
+                      sweep_order_zyx = 2)
+
diff --git a/benchmarks/FLASH-IO/flash_benchmark_io.F90 b/benchmarks/FLASH-IO/flash_benchmark_io.F90
new file mode 100644
index 0000000..ce2195d
--- /dev/null
+++ b/benchmarks/FLASH-IO/flash_benchmark_io.F90
@@ -0,0 +1,273 @@
+      program flash_benchmark_io
+!
+! This is a sample program that setups the FLASH data structures and 
+! drives the I/O routines.  It is intended for benchmarking the I/O
+! performance.
+! 
+
+#ifdef NAGf90Fortran
+      USE F90_UNIX_ENV, only : iargc, getarg
+#endif
+
+! the main data structures are contained in common blocks, defined in the
+! include files
+
+#include "common.fh"
+
+#ifndef NAGf90Fortran
+      integer iargc
+#endif
+      integer i, argc, ierr
+      character(len=128) executable
+      logical isArgvRight
+
+      double precision time_io(3), time_begin
+      double precision chk_io, corner_io, nocorner_io
+      double precision checkpoint_wr_ncmpi_par
+      double precision plotfile_ncmpi_par
+
+      integer, parameter :: local_blocks = INT(0.8*maxblocks)
+
+! initialize MPI and get the rank and size
+      call MPI_INIT(ierr)
+      call MPI_Comm_Rank (MPI_Comm_World, MyPE, ierr)
+      call MPI_Comm_Size (MPI_Comm_World, NumPEs, ierr)
+
+      MasterPE = 0
+
+      ! root process reads command-line arguments
+      if (MyPE .EQ. MasterPE) then
+         isArgvRight = .TRUE.
+         argc = IARGC()
+         call getarg(0, executable)
+         if (argc .GT. 1) then
+            print *, &
+            'Usage: ',trim(executable),' <ouput file base name>'
+            isArgvRight = .FALSE.
+         else
+            if (argc .EQ. 1) then
+               call getarg(1, basenm)
+            else ! default file name prefix
+               basenm = "flash_io_test_"
+            endif
+         endif
+      endif
+
+      ! broadcast if command-line arguments are valid
+      call MPI_Bcast(isArgvRight, 1, MPI_LOGICAL, MasterPE, &
+                     MPI_COMM_WORLD, ierr)
+      if (.NOT. isArgvRight) goto 999
+
+      ! broadcast file base name prefix
+      call MPI_Bcast(basenm, 128, MPI_CHARACTER, MasterPE, &
+                     MPI_COMM_WORLD, ierr)
+
+! put ~100 blocks on each processor -- make it vary a little, since it does
+! in the real application.  This is the maximum that we can fit on Blue 
+! Pacific comfortably.
+      lnblocks = local_blocks + mod(MyPE,3)
+
+! just fill the tree stucture with dummy information -- we are just going to
+! dump it out
+      size(:,:) = 0.5e0
+      lrefine(:) = 1
+      nodetype(:) = 1
+      refine(:) = .FALSE.
+      derefine(:) = .FALSE.
+      parent(:,:) = -1
+      child(:,:,:) = -1
+      coord(:,:) = 0.25e0
+      bnd_box(:,:,:) = 0.e0
+      neigh(:,:,:) = -1
+      empty(:) = 0
+
+      ! use nonblocking APIs
+      use_nonblocking_io = .TRUE.
+
+! initialize the unknowns with the index of the variable
+      do i = 1, nvar
+        unk(i,:,:,:,:) = float(i)
+      enddo
+
+!---------------------------------------------------------------------------
+! netCDF checkpoint file
+!---------------------------------------------------------------------------
+      time_begin = MPI_Wtime()
+      chk_io = checkpoint_wr_ncmpi_par(0,0.e0)
+      time_io(1) = MPI_Wtime() - time_begin
+
+!---------------------------------------------------------------------------
+! netCDF plotfile -- no corners
+!---------------------------------------------------------------------------
+      time_begin = MPI_Wtime()
+      nocorner_io = plotfile_ncmpi_par(0,0.e0,.false.)
+      time_io(2) = MPI_Wtime() - time_begin
+    
+!---------------------------------------------------------------------------
+! netCDF plotfile -- corners
+!---------------------------------------------------------------------------
+      time_begin = MPI_Wtime()
+      corner_io = plotfile_ncmpi_par(0,0.e0,.true.)
+      time_io(3) = MPI_Wtime() - time_begin
+    
+      call report_io_performance(local_blocks, time_io, chk_io, &
+                                 corner_io, nocorner_io)
+
+ 999  call MPI_Finalize(ierr)
+
+      end program flash_benchmark_io
+
+
+! ---------------------------------------------------------------------------
+! get the file striping information from the MPI info objects
+! ---------------------------------------------------------------------------
+      subroutine get_file_striping(info, striping_factor, striping_unit)
+          implicit none
+          include 'mpif.h'
+          integer, intent(in)  :: info
+          integer, intent(out) :: striping_factor
+          integer, intent(out) :: striping_unit
+
+          ! local variables
+          character*(MPI_MAX_INFO_VAL) key, value
+          integer                      i, nkeys, valuelen, ierr
+          logical                      flag
+
+          call MPI_Info_get_nkeys(info, nkeys, ierr)
+          do i=0, nkeys-1
+              key(:) = ' '
+              call MPI_Info_get_nthkey(info, i, key, ierr)
+              call MPI_Info_get(info, key, MPI_MAX_INFO_VAL, value, &
+                                flag, ierr)
+              call MPI_Info_get_valuelen(info, key, valuelen, flag, &
+                                ierr)
+              value(valuelen+1:) = ' '
+              if (key(len_trim(key):len_trim(key)) .EQ. char(0)) &
+                  key(len_trim(key):) = ' '
+              if (trim(key) .EQ. 'striping_factor') &
+                  read(value, '(i10)') striping_factor
+              if (trim(key) .EQ. 'striping_unit') &
+                  read(value, '(i10)') striping_unit
+          enddo
+      end subroutine get_file_striping
+
+
+!---------------------------------------------------------------------------
+! print I/O performance numbers
+!---------------------------------------------------------------------------
+      subroutine report_io_performance(local_blocks, time_io, chk_io, &
+                                       corner_io, nocorner_io)
+       use pnetcdf
+#include "common.fh"
+
+       integer local_blocks
+       double precision time_io(3)
+       double precision chk_io, corner_io, nocorner_io
+
+       ! local variables
+       integer ierr, striping_factor, striping_unit
+       double precision tmax(3), time_total, io_amount, bw
+       integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+
+       call MPI_Reduce(chk_t, tmax, 3, MPI_DOUBLE_PRECISION, MPI_MAX, &
+                       MasterPE, MPI_COMM_WORLD, ierr)
+       chk_t(:) = tmax(:)
+
+       call MPI_Reduce(corner_t, tmax, 3, MPI_DOUBLE_PRECISION, MPI_MAX, &
+                       MasterPE, MPI_COMM_WORLD, ierr)
+       corner_t(:) = tmax(:)
+
+       call MPI_Reduce(nocorner_t, tmax, 3, MPI_DOUBLE_PRECISION, MPI_MAX, &
+                       MasterPE, MPI_COMM_WORLD, ierr)
+       nocorner_t(:) = tmax(:)
+
+       call MPI_Reduce(time_io, tmax, 3, MPI_DOUBLE_PRECISION, MPI_MAX, &
+                       MasterPE, MPI_COMM_WORLD, ierr)
+
+       call MPI_Reduce(chk_io, bw, 1, MPI_DOUBLE_PRECISION, MPI_SUM, &
+                       MasterPE, MPI_COMM_WORLD, ierr)
+       chk_io = bw
+       call MPI_Reduce(nocorner_io, bw, 1, MPI_DOUBLE_PRECISION, MPI_SUM, &
+                       MasterPE, MPI_COMM_WORLD, ierr)
+       nocorner_io = bw
+       call MPI_Reduce(corner_io, bw, 1, MPI_DOUBLE_PRECISION, MPI_SUM, &
+                       MasterPE, MPI_COMM_WORLD, ierr)
+       corner_io = bw
+
+      if (MyPE .EQ. MasterPE) then
+
+          striping_factor = 0
+          striping_unit   = 0
+          call get_file_striping(info_used, striping_factor, striping_unit)
+
+          time_total = tmax(1) + tmax(2) + tmax(3)
+          io_amount = chk_io + nocorner_io + corner_io
+          bw = io_amount / 1048576.0
+          io_amount = bw
+          bw = bw / time_total
+
+ 1001 format(A,I13)
+ 1002 format(A,I13,A)
+ 1003 format(A,F16.2,A)
+ 1004 format(' -------------------------------------------------------')
+ 1005 format(' nproc    array size      exec (sec)   bandwidth (MiB/s)')
+ 1006 format(I5, 3x, i3,' x ',i3,' x ',i3, 3x, F7.2 , 2x,F10.2 /)
+ 1007 format(A,A)
+
+          print 1001,' number of guards      : ',nguard
+          print 1001,' number of blocks      : ',local_blocks
+          print 1001,' number of variables   : ',nvar
+          print 1003,' checkpoint time       : ',tmax(1), '  sec'
+          print 1003,'        max header     : ',chk_t(1),'  sec'
+          print 1003,'        max unknown    : ',chk_t(2),'  sec'
+          print 1003,'        max close      : ',chk_t(3),'  sec'
+          print 1003,'        I/O amount     : ',chk_io/1048576, '  MiB'
+          print 1003,' plot no corner        : ',tmax(2),      '  sec'
+          print 1003,'        max header     : ',nocorner_t(1),'  sec'
+          print 1003,'        max unknown    : ',nocorner_t(2),'  sec'
+          print 1003,'        max close      : ',nocorner_t(3),'  sec'
+          print 1003,'        I/O amount     : ',nocorner_io/1048576, '  MiB'
+          print 1003,' plot    corner        : ',tmax(3),    '  sec'
+          print 1003,'        max header     : ',corner_t(1),'  sec'
+          print 1003,'        max unknown    : ',corner_t(2),'  sec'
+          print 1003,'        max close      : ',corner_t(3),'  sec'
+          print 1003,'        I/O amount     : ',corner_io/1048576, '  MiB'
+          print 1004
+          print 1007,' File base name        : ', trim(basenm)
+          if (striping_factor .GT. 0) then
+              print 1001,'   file striping count : ',striping_factor
+              print 1002,'   file striping size  : ',striping_unit, '     bytes'
+          endif
+          print 1003,' Total I/O amount      : ',io_amount,'  MiB'
+          print 1004
+          print 1005
+          print 1006, NumPEs, nxb, nyb, nzb, time_total, bw
+          print *
+
+      endif
+      call MPI_Info_free(info_used, ierr)
+
+      ! print info about PnetCDF internal malloc usage
+      ierr = nfmpi_inq_malloc_max_size(malloc_size)
+      if (ierr .EQ. NF_NOERR) then
+          call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, MPI_SUM, &
+                          MasterPE, MPI_COMM_WORLD, ierr)
+          if (MyPE .EQ. MasterPE) &
+              print 1002, &
+              'maximum heap memory allocted by PnetCDF internally is', &
+              sum_size/1048576, ' MiB'
+
+          ierr = nfmpi_inq_malloc_size(malloc_size)
+          call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, MPI_SUM, &
+                          MasterPE, MPI_COMM_WORLD, ierr)
+          if (MyPE .EQ. MasterPE .AND. sum_size .GT. 0_MPI_OFFSET_KIND) &
+              print 1002, &
+              'heap memory allocated by PnetCDF internally has ', &
+              sum_size/1048576, ' MiB yet to be freed'
+      endif
+
+      end subroutine report_io_performance
+
+
+
+
diff --git a/benchmarks/FLASH-IO/flash_release.F90 b/benchmarks/FLASH-IO/flash_release.F90
new file mode 100644
index 0000000..62937d9
--- /dev/null
+++ b/benchmarks/FLASH-IO/flash_release.F90
@@ -0,0 +1,10 @@
+      function flash_release()
+      
+      implicit none
+
+      character (len = 40) :: flash_release
+      
+      flash_release = 'FLASH I/O bench Parallel-Netcdf'
+       
+      return
+      end
diff --git a/benchmarks/FLASH-IO/get_mfluid_property.F90 b/benchmarks/FLASH-IO/get_mfluid_property.F90
new file mode 100644
index 0000000..dfa6c3b
--- /dev/null
+++ b/benchmarks/FLASH-IO/get_mfluid_property.F90
@@ -0,0 +1,34 @@
+subroutine get_mfluid_property(property, value)
+
+! stub function to fill the need for get_mfluid_property from the
+! FLASH I/O routines that are used in this benchmark.  All they need
+! is a routine to return the names of the isotopes, so do that here
+
+#include "common.fh"
+
+  character (len=*) :: property
+  character (len=4) :: value(ionmax)
+
+  if (ionmax == 2) then
+     value(1) = "f1"
+     value(2) = "f2"
+  else if (ionmax == 13) then
+     value(1) = "f1"
+     value(2) = "f2"
+     value(3) = "f3"
+     value(4) = "f4"
+     value(5) = "f5"
+     value(6) = "f6"
+     value(7) = "f7"
+     value(8) = "f8"
+     value(9) = "f9"
+     value(10) = "f10"
+     value(11) = "f11"
+     value(12) = "f12"
+     value(13) = "f13"
+  endif
+
+  return
+end subroutine get_mfluid_property
+
+
diff --git a/benchmarks/FLASH-IO/numfluids.fh b/benchmarks/FLASH-IO/numfluids.fh
new file mode 100644
index 0000000..2fc7709
--- /dev/null
+++ b/benchmarks/FLASH-IO/numfluids.fh
@@ -0,0 +1,3 @@
+!        Number of fluids to track.
+
+        integer, parameter        :: ionmax = IONMAX
diff --git a/benchmarks/FLASH-IO/physicaldata.fh b/benchmarks/FLASH-IO/physicaldata.fh
new file mode 100644
index 0000000..6055812
--- /dev/null
+++ b/benchmarks/FLASH-IO/physicaldata.fh
@@ -0,0 +1,196 @@
+!------------------------------------------------------------------------------
+! physicaldata.fh
+!------------------------------------------------------------------------------
+
+
+
+
+!Pre-Processor Control
+
+      integer k1d
+      parameter(k1d=1)
+
+!-----------------------------------------------------------------
+! physicaldata.fh
+
+
+! set physical dimension of model and number of edges on each grid block
+      integer ndim,nbedges
+#if N_DIM == 3
+      parameter(ndim=3)
+#endif
+#if N_DIM == 2
+      parameter(ndim=2)
+#endif
+#if N_DIM == 1
+      parameter(ndim=1)
+#endif
+
+! l2p5d needs to be declared not matter what the dimension of the
+! problem is set to !
+      integer l2p5d
+      parameter(l2p5d=0)                                        !<<< USER EDIT
+                                                                ! 1 if 2.5D
+                                                                ! 0 if 2 or 3D
+
+      parameter(nbedges=ndim*2**(ndim-1))
+
+
+
+! an increment variable for the z dimension to enable the same code to
+! work for 2D or 3D models.
+      integer k3d
+      parameter(k3d=(ndim-1)/2)
+
+      integer k2d
+      parameter(k2d=ndim/2)
+
+
+! set size of grid blocks
+! The spatial relationship between grid points in parents
+! and their children is subtly different depending on whether
+! the block dimensions (ie nxb,nyb,nzb) are even or odd. This has 
+! significant consequences when defining interpolation within
+! restriction or prolongation operations.
+
+      integer nxb,nyb,nzb,maxdim
+
+      parameter(nxb=16)                                        !<<< USER EDIT
+
+#if N_DIM >= 2
+      parameter(nyb=16)                                        !<<< USER EDIT
+#else
+      parameter(nyb=1)
+#endif
+
+#if N_DIM == 3
+      parameter(nzb=16)                                        !<<< USER EDIT
+#else
+      parameter(nzb=1)
+#endif
+
+      parameter(maxdim=max(nxb,nyb,nzb))
+
+
+! these guard cell offsets are required to accomodate differences
+! in cases when block dimensions are odd or even
+      integer gc_off_x,gc_off_y,gc_off_z
+      parameter(gc_off_x=mod(nxb,2))
+      parameter(gc_off_y=mod(nyb,2))
+      parameter(gc_off_z=mod(nzb,2))
+
+! set the maximum number of blocks per processor
+      integer maxblocks
+#ifdef MAXBLOCKS
+      parameter (maxblocks = MAXBLOCKS)
+#else
+#if N_DIM == 3
+      parameter (maxblocks = 200)              !<<< USER EDIT
+#else /* N_DIM < 3 */
+      parameter (maxblocks = 500)            !<<< USER EDIT 
+#endif /*N_DIM*/
+#endif /*MAXBLOCKS*/
+
+
+
+
+!..this include file is very important at this location, as it sets a 
+!..parameter (ionmax) that determines the array sizes and do-loop limits 
+!..of the mesh, hydro, eos and burn modules. it touches just about everything.
+
+#include "numfluids.fh"
+      integer nuc2
+      parameter (nuc2 = ionmax)
+
+
+! set number of unknowns associated with each grid cell
+      integer nvar
+      parameter(nvar=nuc2+11)                            !<<< USER EDIT
+      integer nvar2
+      parameter(nvar2=6)
+      integer nvarsm
+      parameter (nvarsm=2)
+
+! set the number of guard cell layers at each boundary
+      integer nguard
+      parameter(nguard=4)                                       !<<< USER EDIT
+
+
+! common block storing the solution for cell-centered quantities.
+! unksm stores copies of global variables which DO NOT need guard cells
+! AND do not need to be saved from one timestep to the next !!!
+
+      integer il_bnd,iu_bnd
+      integer jl_bnd,ju_bnd
+      integer kl_bnd,ku_bnd
+      parameter(il_bnd=1, iu_bnd=nxb+2*nguard)
+      parameter(jl_bnd=1, ju_bnd=nyb+2*nguard*k2d)
+      parameter(kl_bnd=1, ku_bnd=nzb+2*nguard*k3d)
+      integer nxlo,nylo,nzlo,nxhi,nyhi,nzhi
+      parameter (nxlo=nguard+1,nylo=nguard*k2d+1,nzlo=nguard*k3d+1)
+      parameter (nxhi=nguard+nxb)
+      parameter (nyhi=nguard*k2d+nyb)
+      parameter (nzhi=nguard*k3d+nzb)
+      common/solution_cc/ &
+      unk(nvar,il_bnd:iu_bnd,jl_bnd:ju_bnd,kl_bnd:ku_bnd,maxblocks), &
+      unk2(nvar2,il_bnd:iu_bnd,maxblocks), &
+      unk3(nvar2,jl_bnd:ju_bnd,maxblocks), &
+      unk4(nvar2,kl_bnd:ku_bnd,maxblocks), &
+      unksm(nvarsm,nxlo:nxhi,nylo:nyhi,nzlo:nzhi,maxblocks)
+      double precision unk,unk2,unk3,unk4,unksm
+
+
+
+! The number of data words needed on a cell face is set by nfacevar.
+!
+
+      integer nfacevar
+! 2 added to store strong fields at faces for all components of B
+      parameter(nfacevar=0)   !<<< USER EDIT
+      
+      integer nbndvar
+      parameter(nbndvar=max(1,nfacevar))
+
+      integer maxblocksf
+      parameter(maxblocksf= 1+(maxblocks-1)*min(1,nfacevar) )
+
+
+! set data length of grid blocks
+      integer len_block
+      parameter(len_block=iu_bnd*ju_bnd*ku_bnd*nvar)
+
+
+! common block for timestep control
+      integer maxlevels
+      parameter(maxlevels=20)
+      common/timecntl/ time_loc(maxblocks),dtlevel(maxlevels),ldtcomplete(maxblocks)
+      double precision time_loc,dtlevel
+      logical ldtcomplete
+
+
+
+! To average fluxes set red_f = .25.
+! To sum fluxes set red_f = 1.0.
+
+! changed -- 2-24-00 
+! we are now converting the flux densities to fluxes before the call to
+! amr_flux_conserve.  This is to get the proper geometry factors included
+! in non-cartesian cases.  The fluxes are converted back after the call.
+! 
+! red_f is set according to dimension, to sum instead of average
+      double precision red_f
+!      parameter(red_f = 0.25)   
+
+#if N_DIM == 1
+       parameter (red_f = 0.25)
+#elif N_DIM == 2
+       parameter (red_f = 0.5)
+#elif N_DIM == 3
+       parameter (red_f = 1.0)
+#endif
+
+!-----------------------------------------------------------------
+! include header file defining data structure on cell faces
+#include "block_boundary_data.fh"
+
+!-----------------------------------------------------------------
diff --git a/benchmarks/FLASH-IO/plotfile_ncmpi_parallel.F90 b/benchmarks/FLASH-IO/plotfile_ncmpi_parallel.F90
new file mode 100644
index 0000000..2b210d7
--- /dev/null
+++ b/benchmarks/FLASH-IO/plotfile_ncmpi_parallel.F90
@@ -0,0 +1,698 @@
+#define MDIM 3
+! 3-d problem */
+#if N_DIM == 3 
+#define NDIM  3
+#define NGID 15
+#define ik2d 1
+#define ik3d 1
+! 2-d problem */
+#elif N_DIM == 2
+#define NDIM  2
+#define NGID 9
+#define ik2d 1
+#define ik3d 0
+! 1-d problem */
+#else
+#define NDIM 1
+#define NGID 5
+#define ik2d 0
+#define ik3d 0
+#endif
+
+
+      subroutine write_header_info_sp(nvar_out, ncid, file_creation_time, &
+                                      flash_version, total_blocks, time, &
+                                      nsteps, nzones_block, unk_labels, &
+                                      varid)
+          use mpi
+          use pnetcdf
+          implicit none
+
+          integer nvar_out                    ! num vars to store
+          integer ncid                        ! file handle
+          character(len=*) file_creation_time ! time and date stamp
+          character(len=*) flash_version      ! FLASH version num
+          integer total_blocks                ! total # of blocks
+          real    time                        ! simulation time
+          integer nsteps                      ! total # of timestep
+          integer nzones_block(3)             ! nxb, nyb, nzb
+          character(len=4) unk_labels(*)      ! unknown labels
+          integer varid(*)                    ! output: var ids
+
+          ! local variables
+          integer i, k, err
+          integer dim_tot_blocks, dim_nxb, dim_nyb, dim_nzb
+          integer dim_NGID, dim_NDIM, dim_2
+          integer dimids(4)
+          character(len=5) record_label
+          integer(kind=MPI_OFFSET_KIND) i8NDIM, i8NGID, i8total_blocks
+          integer(kind=MPI_OFFSET_KIND) i8nzones_block(3), string_size
+          integer atotal_blocks(1), ansteps(1)
+          double precision atime(1)
+
+          i8NDIM = NDIM
+          i8NGID = NGID
+          i8total_blocks = total_blocks
+          i8nzones_block(:) = nzones_block(:)
+          atotal_blocks(1) = total_blocks
+          ansteps(1) = nsteps
+
+          ! to avoid inconsistent header metadata warning from PnetCDF
+          atime(1) = time
+          call MPI_Bcast(atime, 1, MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD, err)
+
+          err = nfmpi_def_dim(ncid, "dim_tot_blocks", i8total_blocks, dim_tot_blocks)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_tot_blocks")
+          err = nfmpi_def_dim(ncid, "dim_nxb", i8nzones_block(1), dim_nxb)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_nxb")
+          err = nfmpi_def_dim(ncid, "dim_nyb", i8nzones_block(2), dim_nyb)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_nyb")
+          err = nfmpi_def_dim(ncid, "dim_nzb", i8nzones_block(3), dim_nzb)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_nzb")
+          err = nfmpi_def_dim(ncid, "dim_NGID", i8NGID, dim_NGID)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_NGID")
+          err = nfmpi_def_dim(ncid, "dim_NDIM", i8NDIM, dim_NDIM)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_NDIM")
+          err = nfmpi_def_dim(ncid, "dim_2", 2_MPI_OFFSET_KIND, dim_2)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_dim: dim_2")
+
+          dimids(1) = dim_tot_blocks
+
+          ! define var for refinement level
+          err = nfmpi_def_var(ncid, "lrefine", NF_INT, 1, dimids, varid(1))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: lrefine")
+
+          ! define var for nodetype
+          err = nfmpi_def_var(ncid, "nodetype", NF_INT, 1, dimids, varid(2))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: nodetype")
+
+          ! define var for global id
+          dimids(1) = dim_NGID
+          dimids(2) = dim_tot_blocks
+          err = nfmpi_def_var(ncid, "gid", NF_INT, 2, dimids, varid(3))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: grid")
+
+          ! define var for grid coordinates
+          dimids(1) = dim_NDIM
+          dimids(2) = dim_tot_blocks
+          err = nfmpi_def_var(ncid, "coordinates", NF_FLOAT, 2, dimids, varid(4))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: coordinates")
+
+          ! define var for grid block size
+          dimids(1) = dim_NDIM
+          dimids(2) = dim_tot_blocks
+          err = nfmpi_def_var(ncid, "blocksize", NF_FLOAT, 2, dimids, varid(5))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: blocksize")
+
+          ! define var for grid bounding box
+          dimids(1) = dim_2
+          dimids(2) = dim_NDIM
+          dimids(3) = dim_tot_blocks
+          err = nfmpi_def_var(ncid, "bndbox", NF_FLOAT, 3, dimids, varid(6))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: bndbox")
+
+          ! define var for unknown array
+          dimids(1) = dim_nxb    
+          dimids(2) = dim_nyb
+          dimids(3) = dim_nzb
+          dimids(4) = dim_tot_blocks
+
+          do i=1, nvar_out
+              record_label = unk_labels(i)
+              do k=1, 4
+                 if (record_label(k:k) .EQ. ' ') record_label(k:k) = '_'
+              enddo
+              record_label(5:5) = char(0)
+              err = nfmpi_def_var(ncid, record_label, NF_FLOAT, 4, dimids, varid(i+6))
+              if (err .NE. NF_NOERR) call check(err, "nfmpi_def_var: record_label")
+          enddo
+
+          string_size = LEN_TRIM(file_creation_time)
+          err = nfmpi_put_att_text(ncid, NF_GLOBAL, "file_creation_time", string_size, file_creation_time)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_text: file_creation_time")
+          string_size = LEN_TRIM(flash_version)
+          err = nfmpi_put_att_text(ncid, NF_GLOBAL, "flash_version",  string_size, flash_version)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_text: flash_version")
+          err = nfmpi_put_att_int(ncid, NF_GLOBAL, "total_blocks",  NF_INT, 1_MPI_OFFSET_KIND, atotal_blocks)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_int: total_blocks")
+          err = nfmpi_put_att_int(ncid, NF_GLOBAL, "nsteps", NF_INT, 1_MPI_OFFSET_KIND, ansteps)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_int: nsteps")
+          err = nfmpi_put_att_int(ncid, NF_GLOBAL, "nxb", NF_INT, 1_MPI_OFFSET_KIND, nzones_block(1))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_int: nxb")
+          err = nfmpi_put_att_int(ncid, NF_GLOBAL, "nyb", NF_INT, 1_MPI_OFFSET_KIND, nzones_block(2))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_int: nyb")
+          err = nfmpi_put_att_int(ncid, NF_GLOBAL, "nzb", NF_INT, 1_MPI_OFFSET_KIND, nzones_block(3))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_int: nzb")
+          err = nfmpi_put_att_double(ncid, NF_GLOBAL, "time", NF_DOUBLE, 1_MPI_OFFSET_KIND, atime)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_att_double: time")
+
+          err = nfmpi_enddef(ncid)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_enddef")
+      end subroutine write_header_info_sp
+
+!----------------------------------------------------------------------------
+! subroutine plotfile
+!----------------------------------------------------------------------------
+
+      double precision function plotfile_ncmpi_par(filenum, simtime, corners)
+!
+! plotfile using parallel i/o using Parallel netCDF
+!
+! MZ -- 4-29-00
+! Jianwei -- 11/15/02
+!
+! This version of the plotfile routine is based on the Parallel netCDF
+! checkpoint.  The IO is done in parallel -- no copying of the data to 
+! a single processor to do the writing is performed.  
+!
+! This is the SINGLE PRECISION version of the plotfile -- temporary
+! storage is used to recast a variable (for every zone/block) into
+! single precision before passing it onto the SP version of the C netCDF
+! write routines.
+! 
+! The data for all blocks is recast and written together.  This makes the
+! amount of data that is written very large, which should perform better
+! on the parallel filesystems.  The overhead for storing an entire 
+! variable (with corners) is small, <~ 1%.
+!
+! Parallel netCDF uses MPI-IO (via ROMIO) to support parallel IO.  Each 
+! processor must open the file, define the dataspaces for each netCDF variable.
+!
+! A single record for each of the PARAMESH data structures is created.  A
+! processor only writes to a subset of this record.  Each record has a 
+! dimension with length = tot_blocks.  The offset of a processor into this 
+! dimension is computed by looking at the total number of blocks that are
+! below the current processor.
+!
+! In this version of the plotfile, each variable is given its own 
+! record -- this makes it easier to change the variable list in the
+! future without disturbing the format of the file.
+!
+! The include file -- ncmpi_flash.h is used for the C routines and mirrors
+! the necessary data from physicaldata.fh
+!
+! written for netCDF 3.0
+!
+!---------------------------------------------------------------------------
+
+      use pnetcdf
+
+#include "common.fh"
+
+      integer filenum
+      real simtime
+      
+      integer block_no
+      integer i, j, k, ivar, i_store, j_store, k_store
+      integer ngid 
+      integer err
+
+      integer n_to_left(0:16383)  ! must extend from 0 to NumPEs-1
+
+! 2-20-00 -- we don't need to allocate more space than necessary
+!      integer gid(mfaces+1+mchild,maxblocks_tr)
+      integer gid(nfaces+1+nchild,maxblocks_tr)
+
+      integer tot_blocks
+      
+      save gid, n_to_left
+
+      integer nzones_block(3)
+
+! create a character variable to hold the string representation of the block
+! number.  Note this is set to be 4 characters long (i.e. max = 9999).  
+      character*4  fnum_string
+      character*80 filename
+      character*8 str
+
+! set the number of variables we are going to write out
+      integer, parameter ::  num_out = 4
+
+! create a temporary array to hold the 4 character variable names
+! this will include those defined in definitions.fh and network_common.fh
+      character*4 unklabels(nvar), sunklabels(num_out)
+
+! storage for the current date and time
+      character date_string*40
+
+      character(len=4) :: ionam(ionmax), record_label
+      
+      integer varid(6+num_out)
+
+      integer global_offset
+
+
+! hold pointers to the location in unk of the variables we are writing out
+      integer iout(num_out)
+
+! allocate storage to hold a single variable information
+! this should only be a small memory overhead
+      integer, parameter :: single = SELECTED_REAL_KIND(p=6)
+      real (kind=single) :: unkt_crn(1,nxb+1,nyb+k2d,nzb+k3d,maxblocks)
+      real (kind=single) :: unkt(1,nxb,nyb,nzb,maxblocks)
+
+! allocate storage to hold the coordinate information and bounding box
+! information
+      real (kind=single) :: coord_single(mdim,maxblocks_tr)
+      real (kind=single) :: blk_sz_single(mdim,maxblocks_tr)
+      real (kind=single) :: bnd_single(2,mdim,maxblocks_tr)
+      real (kind=single) :: sp_var1, sp_var2
+
+      integer, parameter :: release_len = 40
+      character (len=release_len) :: flash_release
+
+      logical corners
+
+      integer ncid, cmode, file_info, reqs(num_out+6), stats(num_out+6)
+      integer(kind=MPI_OFFSET_KIND) starts(4), counts(4), put_size, buf_size
+
+      if (corners) then
+         corner_t(1) = MPI_Wtime()
+      else
+         nocorner_t(1) = MPI_Wtime()
+      endif
+
+!-----------------------------------------------------------------------------
+! set the variables we are going to store
+!-----------------------------------------------------------------------------
+      iout(1) = idens
+      iout(2) = itemp
+      iout(3) = ipres
+
+! store the first abundance
+      iout(4) = inuc_begin
+
+
+!-----------------------------------------------------------------------------
+! compute the total number of blocks left of a given processor number
+!-----------------------------------------------------------------------------
+
+! use an allgather routine here to get the number of blocks on each proc.
+      call MPI_Allgather(lnblocks, 1,MPI_INTEGER, & 
+                         n_to_left,1,MPI_INTEGER, & 
+                         MPI_COMM_WORLD,err)
+
+! compute the total number of blocks
+      tot_blocks = 0
+
+      do i = 0,NumPEs-1
+         tot_blocks = tot_blocks + n_to_left(i)
+      end do
+
+! compute the number of procssors to the left of a processor
+      do i = NumPEs-1,1,-1
+         n_to_left(i) = n_to_left(i-1)
+      end do
+
+      n_to_left(0) = 0
+      do i = 2,NumPEs-1
+         n_to_left(i) = n_to_left(i) + n_to_left(i-1)
+      end do
+
+
+!-----------------------------------------------------------------------------
+! compute the global id -- this is a single array which stores the 
+! neighbor block numbers, the parent, and the children of a given block
+!-----------------------------------------------------------------------------
+      do block_no = 1,lnblocks
+
+         ngid = 0
+
+! loop over the faces and store the neighbors
+         do j = 1,nfaces
+            ngid = ngid + 1
+
+! if the neighbor exists, then store the block number of the neighbor
+! -- take into account the number of blocks below the processor that the
+! neighbor is on, so the block number is global
+            if (neigh(1,j,block_no).gt.0) then
+               gid(ngid,block_no) = neigh(1,j,block_no) +  & 
+                    n_to_left(neigh(2,j,block_no))
+            else
+
+! the neighbor is either a physical boundary or does not exist at that 
+! level of refinement
+               gid(ngid,block_no) = neigh(1,j,block_no)
+            end if
+         end do
+
+! store the parent of the current block
+         ngid = ngid + 1
+         if (parent(1,block_no).gt.0) then
+            gid(ngid,block_no) = parent(1,block_no) +  & 
+                 n_to_left(parent(2,block_no))
+         else
+            gid(ngid,block_no) = parent(1,block_no)
+         end if
+
+! store the children of the current block
+         do j = 1,nchild
+            ngid = ngid + 1
+            if (child(1,j,block_no).gt.0) then
+               gid(ngid,block_no) = child(1,j,block_no) +  & 
+                    n_to_left(child(2,j,block_no))
+            else
+               gid(ngid,block_no) = child(1,j,block_no)
+            end if
+         end do
+
+      end do
+
+
+!-----------------------------------------------------------------------------
+! open the netCDF file
+!-----------------------------------------------------------------------------
+      write (fnum_string, '(i4.4)') filenum
+
+      if (corners) then
+         filename = trim(basenm)//'ncmpi_plt_crn_'//fnum_string//'.nc'
+      else
+         filename = trim(basenm)//'ncmpi_plt_cnt_'//fnum_string//'.nc'
+      endif
+
+      ! set up MPI I/O hints for performance enhancement
+      call MPI_Info_create(file_info, err)
+
+      ! use some ROMIO hints
+      call MPI_Info_set(file_info, 'romio_no_indep_rw', 'true', err)
+
+      cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+      err = nfmpi_create(MPI_COMM_WORLD, trim(filename), cmode, &
+                          file_info, ncid)
+      if (err .NE. NF_NOERR) call check(err, "nfmpi_create")
+
+      call MPI_Info_free(file_info, err)
+
+!-----------------------------------------------------------------------------
+! store the scalar information -- # of blocks, simulation time, etc
+!-----------------------------------------------------------------------------
+        date_string = 'now'      
+
+! store the number of zones / block in each direction
+      if (corners) then
+         nzones_block(1) = nxb+1
+         nzones_block(2) = nyb+k2d
+         nzones_block(3) = nzb+k3d
+      else
+         nzones_block(1) = nxb
+         nzones_block(2) = nyb
+         nzones_block(3) = nzb
+      endif
+
+! get the names of the fluids being followed
+      call get_mfluid_property ("short name", ionam)
+
+! merge the two variable lists into one for storage
+      unklabels(1:nvar-ionmax)     = varnam(:)
+      unklabels(nvar-ionmax+1:nvar) = ionam(:)
+
+! get the subset of the variable labels, corresponding to what we are storing
+      do i = 1, num_out
+         sunklabels(i) = unklabels(iout(i))
+      enddo
+
+      sp_var1 = real(simtime, kind = single)
+      sp_var2 = real(dt, kind = single)
+
+      call write_header_info_sp(num_out, &
+                                ncid, &
+                                date_string, &
+                                flash_release(), &
+                                tot_blocks, &
+                                sp_var1, &
+                                nstep, &
+                                nzones_block, &
+                                sunklabels, &
+                                varid)
+
+      global_offset = n_to_left(MyPE)
+!-----------------------------------------------------------------------------
+! store the tree information
+!-----------------------------------------------------------------------------
+
+! store the refinement level
+      starts(1) = global_offset+1
+      counts(1) = lnblocks
+      if (use_nonblocking_io) then
+          err = nfmpi_iput_vara_int(ncid, varid(1), starts, counts, lrefine, reqs(1))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_iput_vara_int: lrefine sp")
+      else
+          err = nfmpi_put_vara_int_all(ncid, varid(1), starts, counts, lrefine)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_int_all: lrefine sp")
+      endif
+
+! store the nodetype
+      if (use_nonblocking_io) then
+          err = nfmpi_iput_vara_int(ncid, varid(2), starts, counts, nodetype, reqs(2))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_iput_vara_int: nodetype sp")
+      else
+          err = nfmpi_put_vara_int_all(ncid, varid(2), starts, counts, nodetype)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_int_all: nodetype sp")
+      endif
+
+! store the global id
+      starts(1) = 1
+      starts(2) = global_offset+1
+      counts(1) = NGID
+      counts(2) = lnblocks
+      if (use_nonblocking_io) then
+          err = nfmpi_iput_vara_int(ncid, varid(3), starts, counts, gid, reqs(3))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_iput_vara_int: gid sp")
+      else
+          err = nfmpi_put_vara_int_all(ncid, varid(3), starts, counts, gid)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_int_all: gid sp")
+      endif
+
+!-----------------------------------------------------------------------------
+! store the grid information
+!-----------------------------------------------------------------------------
+      
+! store the coordinates
+      do block_no = 1, lnblocks
+         coord_single(:,block_no) = real(coord(:,block_no), kind = single)
+      enddo
+      starts(1) = 1
+      starts(2) = global_offset+1
+      counts(1) = NDIM
+      counts(2) = lnblocks
+      if (use_nonblocking_io) then
+          err = nfmpi_iput_vara_real(ncid, varid(4), starts, counts, coord_single, reqs(4))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_iput_vara_real: coord sp")
+      else
+          err = nfmpi_put_vara_real_all(ncid, varid(4), starts, counts, coord_single)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_read_all: coord sp")
+      endif
+
+! store the block size
+      do block_no = 1, lnblocks
+         blk_sz_single(:,block_no) = real(size(:,block_no), kind = single)
+      enddo
+
+      starts(1) = 1
+      starts(2) = global_offset+1
+      counts(1) = NDIM
+      counts(2) = lnblocks
+      if (use_nonblocking_io) then
+          err = nfmpi_iput_vara_real(ncid, varid(5), starts, counts, blk_sz_single, reqs(5))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_iput_vara_real: size sp")
+      else
+          err = nfmpi_put_vara_real_all(ncid, varid(5), starts, counts, blk_sz_single)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_real_all: size sp")
+      endif
+
+! store the bounding box
+
+      do block_no = 1, lnblocks
+         bnd_single(:,:,block_no) =  & 
+              real(bnd_box(:,:,block_no), kind = single)
+      enddo
+
+      starts(1) = 1
+      starts(2) = 1
+      starts(3) = global_offset+1
+      counts(1) = 2
+      counts(2) = NDIM
+      counts(3) = lnblocks
+      if (use_nonblocking_io) then
+          err = nfmpi_iput_vara_real(ncid, varid(6), starts, counts, bnd_single, reqs(6))
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_iput_vara_real: bnd_box")
+      else
+          err = nfmpi_put_vara_real_all(ncid, varid(6), starts, counts, bnd_single)
+          if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_real_all: bnd_box")
+      endif
+
+      if (use_nonblocking_io) then
+          ! calculate attach buffer size for using buffered PnetCDF APIs 
+          buf_size = (nxb+1) * (nyb+k2d) * (nzb+k3d) * maxblocks
+          buf_size = buf_size + nxb * nyb * nzb * maxblocks
+          buf_size = buf_size * num_out * 4
+          err = nfmpi_buffer_attach(ncid, buf_size)
+      endif
+
+!-----------------------------------------------------------------------------
+! store the unknowns -- here we will pass the entire unk array on each 
+! processor.  The HDF 5 memory space functionality will pick just the 
+! interior cells to write to disk.
+!-----------------------------------------------------------------------------
+
+      if (corners) then
+         corner_t(2) = MPI_Wtime()
+         corner_t(1) = corner_t(2) - corner_t(1)
+      else
+         nocorner_t(2) = MPI_Wtime()
+         nocorner_t(1) = nocorner_t(2) - nocorner_t(1)
+      endif
+
+      do ivar = 1, num_out
+         record_label = unklabels(iout(ivar))
+
+! put the data at the corners if necessary
+         if (corners) then
+
+! interpolate only the variable we are storing to the corners            
+
+! ** Important, the limits of the unkt_crn array do not include 
+!    guard cells, so we need to map the interior of the unk array
+!    into the unkt_crn array.
+            do block_no = 1, lnblocks
+            
+               do k = nguard*k3d+1,nguard*k3d+nzb+k3d
+                  k_store = k - nguard*k3d
+
+                  do j = nguard*k2d+1,nguard*k2d+nyb+k2d
+                     j_store = j - nguard*k2d
+                     
+                     do i = nguard+1,nguard+nxb+1
+                        i_store = i - nguard
+
+#if N_DIM == 2
+                        unkt_crn(1,i_store,j_store,k_store,block_no) =  & 
+                             real( & 
+                            .25*(unk(iout(ivar),i-1,j,  k,block_no) + & 
+                                 unk(iout(ivar),i  ,j,  k,block_no) + & 
+                                 unk(iout(ivar),i  ,j-1,k,block_no) + & 
+                                 unk(iout(ivar),i-1,j-1,k,block_no)), & 
+                             kind = single)
+#endif
+#if N_DIM == 3
+                        unkt_crn(1,i_store,j_store,k_store,block_no) =  & 
+                             real( & 
+                            .125*(unk(iout(ivar),i-1,j  ,k  ,block_no) + & 
+                                  unk(iout(ivar),i  ,j  ,k  ,block_no) + & 
+                                  unk(iout(ivar),i  ,j-1,k  ,block_no) + & 
+                                  unk(iout(ivar),i-1,j-1,k  ,block_no) + & 
+                                  unk(iout(ivar),i-1,j  ,k-1,block_no) + & 
+                                  unk(iout(ivar),i  ,j  ,k-1,block_no) + & 
+                                  unk(iout(ivar),i  ,j-1,k-1,block_no) + & 
+                                  unk(iout(ivar),i-1,j-1,k-1,block_no)), & 
+                             kind = single)
+#endif
+                        
+                     end do
+                  end do
+               end do
+               
+            enddo
+
+
+! we now have the data at the corners, in a 4-byte real array
+
+            starts(1) = 1
+            starts(2) = 1
+            starts(3) = 1
+            starts(4) = global_offset+1
+            counts(1) = nxb+1
+            counts(2) = nyb+ik2d
+            counts(3) = nzb+ik3d
+            counts(4) = lnblocks
+            if (use_nonblocking_io) then
+                err = nfmpi_bput_vara_real(ncid, varid(6+ivar), starts, counts, unkt_crn, reqs(ivar+6))
+                if (err .NE. NF_NOERR) call check(err, "nfmpi_bput_vara_real: unknowns sp")
+            else
+                err = nfmpi_put_vara_real_all(ncid, varid(6+ivar), starts, counts, unkt_crn)
+                if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_real_all: unknowns sp")
+            endif
+
+         else
+
+            unkt(1,:,:,:,:) = real(unk(iout(ivar), & 
+                                       nguard+1:nguard+nxb, & 
+                                       nguard*k2d+1:nguard*k2d+nyb, & 
+                                       nguard*k3d+1:nguard*k3d+nzb,:), & 
+                                   kind = single)
+
+            starts(1) = 1
+            starts(2) = 1
+            starts(3) = 1
+            starts(4) = global_offset+1
+            counts(1) = nxb
+            counts(2) = nyb
+            counts(3) = nzb
+            counts(4) = lnblocks
+            if (use_nonblocking_io) then
+                err = nfmpi_bput_vara_real(ncid, varid(6+ivar), starts, counts, unkt, reqs(ivar+6))
+                if (err .NE. NF_NOERR) call check(err, "nfmpi_bput_vara_real: unknowns sp")
+            else
+                err = nfmpi_put_vara_real_all(ncid, varid(6+ivar), starts, counts, unkt)
+                if (err .NE. NF_NOERR) call check(err, "nfmpi_put_vara_real_all: unknowns sp")
+            endif
+         endif
+
+      enddo
+
+      ! wait for all nonblocking requests to complete
+      if (use_nonblocking_io) then
+          ! wait for the nonblocking I/O to complete
+          err = nfmpi_wait_all(ncid, num_out+6, reqs, stats)
+          if (err .NE. NF_NOERR) &
+              call check(err, "(sp) nfmpi_wait_all: ")
+
+          ! check the status of each nonblocking request
+          do i=1, num_out+6
+             write(str,'(I2)') i
+             if (stats(i) .NE. NF_NOERR) &
+                 call check(stats(i), '(sp) nfmpi_wait_all req '//trim(str))
+          enddo
+
+          ! detach the temporary buffer
+          err = nfmpi_buffer_detach(ncid)
+          if (err .NE. NF_NOERR) &
+              call check(err, "(sp) nfmpi_buffer_detach: ")
+      endif
+
+!-----------------------------------------------------------------------------
+! close the file
+!-----------------------------------------------------------------------------
+
+      if (corners) then
+         corner_t(3) = MPI_Wtime()
+         corner_t(2) = corner_t(3) - corner_t(2)
+      else
+         nocorner_t(3) = MPI_Wtime()
+         nocorner_t(2) = nocorner_t(3) - nocorner_t(2)
+      endif
+
+      err = nfmpi_inq_put_size(ncid, put_size)
+      if (err .NE. NF_NOERR) &
+          call check(err, "(sp) nfmpi_inq_put_size: ")
+
+      err = nfmpi_close(ncid)
+      if (err .NE. NF_NOERR) call check(err, "nfmpi_close_file sp")
+
+      if (corners) then
+         corner_t(3) = MPI_Wtime() - corner_t(3)
+      else
+         nocorner_t(3) = MPI_Wtime() - nocorner_t(3)
+      endif
+
+      plotfile_ncmpi_par = put_size
+
+      return
+      end
+
+
+
+
+
+
+
diff --git a/benchmarks/FLASH-IO/tree.fh b/benchmarks/FLASH-IO/tree.fh
new file mode 100644
index 0000000..281075d
--- /dev/null
+++ b/benchmarks/FLASH-IO/tree.fh
@@ -0,0 +1,144 @@
+!-----------------------------------------------------------------
+! tree.fh
+
+
+
+! $RCSfile: tree.fh,v $
+! $Revision: 1468 $
+! $Date: 2013-10-26 11:53:18 -0500 (Sat, 26 Oct 2013) $
+
+
+
+      integer maxblocks_tr
+      parameter(maxblocks_tr=10*maxblocks)
+
+! Number of children of a node
+      integer nchild
+      parameter(nchild=2**ndim)
+
+! Number of faces on a grid block
+      integer nfaces
+      parameter(nfaces=2*ndim)
+
+! Parameters used to define array sizes
+      integer mdim,mchild,mfaces
+      parameter(mdim=3,mchild=2**mdim,mfaces=2*mdim)
+
+! Common block storing tree datastructure
+      common/tree/ neigh,child,parent,coord,size,bnd_box, &
+            lrefine,nodetype,empty, &
+            lnblocks,new_lnblocks,newchild,derefine,refine, &
+            stay,work_block, &
+            neigh_type,child_type
+
+      integer neigh(2,mfaces,maxblocks_tr)
+      integer child(2,mchild,maxblocks_tr)
+      integer parent(2,maxblocks_tr),lrefine(maxblocks_tr)
+      integer lnblocks,new_lnblocks
+
+      integer nodetype(maxblocks_tr)
+      integer neigh_type(mfaces,maxblocks_tr)
+      integer child_type(mchild,maxblocks_tr)
+      integer empty(maxblocks_tr)
+      logical newchild(maxblocks_tr)
+      logical derefine(maxblocks_tr),refine(maxblocks_tr)
+      logical stay(maxblocks_tr)
+
+      double precision work_block(maxblocks_tr)
+      double precision coord(mdim,maxblocks_tr)
+      double precision size(mdim,maxblocks_tr)
+      double precision bnd_box(2,mdim,maxblocks_tr)
+
+!--------------------------------------------
+!
+! A convention is established for numbering the neighbors (or faces
+! of a block. The first neighbor is at lower x coordinate, the 
+! second at higher x, the third at lower y, fourth at higher y, fifth
+! at lower z and the sixth at higher z.
+!
+! The convention by which the children of a block are numbered is the
+! same as the fortran array ordering, so that the first child is
+! at lower x, y and z coordinate, the second child is at upper x
+! but lower y and z, the third is at lower x, upper y and lower z,
+! and so on.
+!
+! When a block has a refined neighbor we will need to know which children
+! of this neighbor are to provide guard cell information. The id's of the
+! correct children are stored in kchild using the conventions described 
+! above. For example, if we are working on the 3rd neighbor of the
+! current block and it is at finer refinement level, then we must access
+! the children designated by kchild(:,3), in this case children 1, 2, 5
+! and 6.
+
+!--------------------------------------------
+!
+!
+! Description:
+! This is the include file for a quad or oct-tree data structure,
+! implemented on a parallel computer.
+!
+! The tree organizes a set of up to maxblocks_tr grids on each processor.
+! All the grids are assumed to be cartesian with a uniform size. Each 
+! grid has a level of refinement associated with it. The set of level 0
+! grids cover the computational domain without overlap. Each grid
+! can be the parent of 2**d offspring grids which completely cover 
+! the sub-domain of their parents, where d is the physical dimension
+! of the simulation. The linear resolution varies by a factor of 2 
+! between successive levels of refinement. At no point do we allow the
+! resolution to jump by more than one level of refinement.
+!
+!
+! In the following list the index i ranges from 1 to maxblocks. 
+!
+!       neigh(2,nfaces,i)     local and processor ids of block i's neighbors,
+!                               at i's refinement level. If a neighbor does 
+!                               not exist both values are set to -1, unless 
+!                               that face is at an external domain boundary
+!                               where non-periodic boundary conditions are to
+!                               be applied, in which case these are set to -20
+!                               or less, depending on the boundary conditions
+!                               to be applied on the boundary in question.
+!       child(2,nchild,i)     local and processor ids of block i's children
+!       parent(2,i)           local and processor ids of block i's parent
+!       coord(ndim,i)         array storing x,y and z coordinates of the
+!                               center of block i.
+!       bnd_box(2,ndim,i)     bounding box information for block i. The 
+!                               lower edge of block i along the j-th coordinate
+!                               axis is at bnd_box(1,j,i) and the upper edge
+!                               at bnd_box(2,j,i).
+!       size(ndim,i)          size of block i in the x, y and z directions.
+!       lrefine(i)            refinement level of block i.
+!       nodetype(i)           defines the node type, if 1 then the node is a
+!                               leaf node, if 2 then the node is a parent but
+!                               with at least 1 leaf child, otherwise it is
+!                               set to 3 and it does not have any up-to-date
+!                               data.
+!       empty(i)              used to designate empty blocks, for example
+!                               when an obstacle is inserted inside the
+!                               computational domain. normal blocks have
+!                               empty=0, empty blocks have empty=1.
+!       
+!       new_child(i)          if true then child has just been produced by
+!                               a refinement step, otherwise false.
+!       lnblocks              number of blocks on the local processor
+!       new_lnblocks          the new number of blocks on the local 
+!                               processor after a refinement or derefinement 
+!                               step.
+!       refine(i)             refinement flag. If set to .true. block i
+!                               will be refined during the next call to
+!                               REFINE_DEREFINE.
+!       derefine(i)           derefinement flag. If set to .true. block i
+!                               will be derefined during the next call to
+!                               REFINE_DEREFINE, provided this blocks parent
+!                               is not marked for refinement.
+! ADDED FOR EASIER AND MORE EFFICIENT MPI MESSAGING (KMO)
+!       neigh_type(nfaces,i)  types of the neighbors of block i
+!       child_type(nchild,i)  types of the children of block i
+!
+!
+!-----------------------------------------------------------------
+
+
+
+
+
diff --git a/benchmarks/Makefile.in b/benchmarks/Makefile.in
new file mode 100644
index 0000000..41e3bfd
--- /dev/null
+++ b/benchmarks/Makefile.in
@@ -0,0 +1,54 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2219 2015-12-11 22:30:03Z wkliao $
+#
+# @configure_input@
+
+srcdir  = @srcdir@
+VPATH   = @srcdir@
+
+include ../macros.make
+
+SUBDIRS = C
+
+ifeq (@has_fortran@, yes)
+SUBDIRS += FLASH-IO
+endif
+
+PACKING_LIST = Makefile.in README
+
+PACKING_SUBDIRS = C FLASH-IO
+
+GARBAGE =
+
+all: $(SUBDIRS)
+$(SUBDIRS):
+	$(MAKE) $(MFLAGS) -C $@
+
+PTEST_DIRS = $(SUBDIRS:%=ptest-%)
+ptest: all $(PTEST_DIRS)
+$(PTEST_DIRS):
+ifeq (@enable_coverage@, yes)
+	echo "Parallel test is disabled because coverage analysis was enabled"
+else
+	$(MAKE) $(MFLAGS) -C $(@:ptest-%=%) ptest
+endif
+# make sure ptest runs one directory after another
+ptest-FLASH-IO: ptest-C
+
+ptests: ptest
+
+INSTALLDIRS = $(SUBDIRS:%=install-%)
+install: all $(INSTALLDIRS)
+$(INSTALLDIRS): 
+	$(MAKE) $(MFLAGS) -C $(@:install-%=%) install
+
+UNINSTALLDIRS = $(SUBDIRS:%=uninstall-%)
+uninstall: $(UNINSTALLDIRS)
+$(UNINSTALLDIRS): 
+	$(MAKE) $(MFLAGS) -C $(@:uninstall-%=%) uninstall
+
+include $(srcdir)/../rules.make
+
diff --git a/benchmarks/README b/benchmarks/README
new file mode 100644
index 0000000..f90313d
--- /dev/null
+++ b/benchmarks/README
@@ -0,0 +1,29 @@
+# $Id: README 1468 2013-10-26 16:53:18Z wkliao $
+
+The programs in this directory are designed to measure the I/O performance for
+various of APIs as well as access patterns.
+
+C/aggregation.c
+   o This program writes a series of 2D variables with data partitioning
+     patterns of block-block, *-cyclic, block-*, and *-block, round-robinly.
+     The block-* partitioning case writes 1st half followed by 2nd half. The
+     same partitioning patterns are used for read. In both cases, nonblocking
+     APIs are used to evaluate the performance.
+   o Parameters:
+         * NVARS: a defined C macro, the number of variables
+         * len:   dimension size of local variables, len x len
+   o Write and read performance are measured and reported separately.
+
+
+C/write_block_read_column.c
+   o This program writes a series of 2D variables partitioned in a block-block
+     pattern into a new file. The file is re-opened to read all the 2D variables
+     but in a 2D *-block pattern.
+   o Write and read performance are measured and reported separately.
+   
+
+FLASH
+   o This benchmark is algorithmically identical to the FLASH-IO kernel.
+     FLASH is a reacting hydrodynamics code developed at University of Chicago.
+     http://flash.uchicago.edu
+   o This distribution contains only PnetCDF I/O method.
diff --git a/cobalt.script b/cobalt.script
new file mode 100755
index 0000000..69438d6
--- /dev/null
+++ b/cobalt.script
@@ -0,0 +1,16 @@
+#!/bin/sh
+echo "Starting Cobalt job script"
+# see runjob --help for more options
+
+
+# test seqential programs
+make check TEST_MPIRUN="runjob --block $COBALT_PARTNAME --ranks-per-node 1 --np NP : " \
+           TEST_SEQRUN="runjob --block $COBALT_PARTNAME --ranks-per-node 1 --np 1 : " \
+           TEST_OUTDIR=/path/to/GPFS/directory
+
+# test parallel programs
+make ptest TEST_MPIRUN="runjob --block $COBALT_PARTNAME --ranks-per-node 1 --np NP : " \
+           TEST_SEQRUN="runjob --block $COBALT_PARTNAME --ranks-per-node 1 --np 1 : " \
+           TEST_OUTDIR=/path/to/GPFS/directory
+
+
diff --git a/configure b/configure
new file mode 100755
index 0000000..fd3fafb
--- /dev/null
+++ b/configure
@@ -0,0 +1,15165 @@
+#! /bin/sh
+# From configure.in Id: configure.in 2304 2016-01-12 18:39:01Z wkliao .
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for parallel-netcdf 1.7.0.pre1.
+#
+# Report bugs to <parallel-netcdf at mcs.anl.gov>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf at gnu.org and
+$0: parallel-netcdf at mcs.anl.gov about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='parallel-netcdf'
+PACKAGE_TARNAME='parallel-netcdf'
+PACKAGE_VERSION='1.7.0.pre1'
+PACKAGE_STRING='parallel-netcdf 1.7.0.pre1'
+PACKAGE_BUGREPORT='parallel-netcdf at mcs.anl.gov'
+PACKAGE_URL=''
+
+ac_unique_file="src/lib/pnetcdf.h.in"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+SEQ_CC
+TEST_OUTDIR
+TEST_MPIRUN
+TEST_SEQRUN
+PNETCDF_LIB
+PNETCDF_INC
+large_file_test
+BUILDDIR
+has_latex
+DVIPDF
+LATEX
+enable_subfiling
+enable_coverage
+LCOV_LIB
+MAKEWHATIS_CMD
+WHATIS
+prog
+has_fortran
+F90LDFLAGS
+FLDFLAGS
+F90LIBS
+UPPER_CASE_MOD
+FC_MODOUT
+ac_empty
+FC_MODINC
+FC_MODEXT
+SIZEOF_MPI_OFFSET
+INTENTV
+is_bigendian
+SIZEOF_MPI_AINT_IS_4
+PNC_DEBUG
+CPP
+RANLIB
+NMFLAGS
+NM
+ARFLAGS
+AR
+M4FLAGS
+M4
+EGREP
+GREP
+SET_MAKE
+LN_S
+have_yacc_lex
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+PNF_X_UINT8_MAX
+PNF_X_INT8_MAX
+PNF_X_INT8_MIN
+PNF_X_UINT_MAX
+PNF_FILL_UINT64
+PNF_FILL_INT64
+PNF_FILL_UINT
+PNF_INT8_MODIFIER
+NAG_FCFLAGS
+NAGf90FPPFLAGS
+FFIXEDFORMFLAG
+F90FLAGS_F90
+F90FLAGS_f90
+F77FLAGS_F
+F77FLAGS_f
+FCFLAGS_F90
+FCFLAGS_f90
+FCFLAGS_F
+FCFLAGS_f
+FC_DEFINE
+FPPFLAGS
+FPP
+F90PPFLAGS_F90
+F90PPFLAGS_f90
+F77PPFLAGS_F
+F77PPFLAGS_f
+F77_SUPPORT_FREEFORM
+FFREEFORMFLAG
+F77FLAGS
+FLIBS
+ac_ct_F77
+F90FLAGS
+FCLIBS
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+ac_ct_FC
+CXXCPPFLAGS
+has_mpicxx
+ac_ct_CXX
+CC_MAKEDEPEND
+OBJEXT
+EXEEXT
+ac_ct_CC
+LDFLAGS
+FCFLAGS
+FFLAGS
+CXXFLAGS
+CPPFLAGS
+CFLAGS
+FC
+F77
+CXX
+CC
+MPIF90
+MPIF77
+MPICXX
+MPICC
+rm_cmd
+RM
+CONFIGURE_ARGS_CLEAN
+PNETCDF_RELEASE_DATE2
+PNETCDF_RELEASE_DATE
+PNETCDF_VERSION
+PNETCDF_VERSION_PRE
+PNETCDF_VERSION_SUB
+PNETCDF_VERSION_MINOR
+PNETCDF_VERSION_MAJOR
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_echo
+with_mpi
+enable_largefile
+enable_mpi_io_test
+enable_cxx
+enable_strict
+enable_fortran
+enable_debug
+enable_in_place_swap
+enable_coverage
+enable_subfiling
+enable_file_sync
+enable_large_file_test
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+RM
+MPICC
+MPICXX
+MPIF77
+MPIF90
+CC
+CXX
+F77
+FC
+CFLAGS
+CPPFLAGS
+CXXFLAGS
+FFLAGS
+FCFLAGS
+LDFLAGS
+LIBS
+CCC
+CPP
+TEST_SEQRUN
+TEST_MPIRUN
+TEST_OUTDIR'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures parallel-netcdf 1.7.0.pre1 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/parallel-netcdf]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of parallel-netcdf 1.7.0.pre1:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-echo           Turn on strong echoing. [default: disabled]
+  --disable-largefile     omit support for large files
+  --disable-mpi-io-test   Disable check for MPI-IO support in MPI
+                          implementation, if you know your MPI implementation
+                          has MPI-IO support but the configure test fails to
+                          find it. [default: enabled]
+  --disable-cxx           Turn off support for the C++ interface, if you only
+                          need the C interface. [default: enabled]
+  --enable-strict         Turn on strict debugging with gcc. [default:
+                          disabled]
+  --disable-fortran       Turn off support for the Fortran interface, if you
+                          only need the C interface. [default: enabled]
+  --enable-debug          Enable PnetCDF internal debug mode. This also
+                          enables safe mode. [default: disabled]
+  --disable-in-place-swap Disable memory in-place byte swap on Little Endian
+                          machines. [default: enabled]
+  --enable-coverage       Compile with coverage support (gcc-based only).
+                          [default: disabled]
+  --enable-subfiling      Enable subfiling support. [default: disabled]
+  --disable-file-sync     Disable MPI file sync if you know your file system
+                          can provide data consistency. [default: enabled]
+  --enable-large-file-test
+                          Enable testing for large (>4GB) file/variable I/O.
+                          Note "make testing" can run very slow. [default:
+                          disabled]
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-mpi=/path/to/implementation
+                          installation prefix for MPI implementation
+
+Some influential environment variables:
+  RM          Command for deleting files or directories. default: rm
+  MPICC       MPI C compiler
+  MPICXX      MPI C++ compiler
+  MPIF77      MPI Fortran 77 compiler
+  MPIF90      MPI Fortran 90 compiler
+  CC          Overwritten by MPICC if MPICC is set
+  CXX         Overwritten by MPICXX if MPICXX is set
+  F77         Overwritten by MPIF77 if MPIF77 is set
+  FC          Overwritten by MPIF90 if MPIF90 is set
+  CFLAGS      Debugging and optimization options for the C compiler
+  CPPFLAGS    Preprocessor options for the C and C++ compilers, e.g.
+              -I<include dir> if you have headers in a nonstandard directory
+              <include dir>
+  CXXFLAGS    Debugging and optimization options for the C compiler
+  FFLAGS      Debugging and optimization options for the Fortran 77 compiler
+  FCFLAGS     Debugging and optimization options for the Fortran 90 compiler
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPP         C preprocessor
+  TEST_SEQRUN Run command (on one process) for make target check on
+              cross-compile environment. Example: "aprun -n 1". [default:
+              none]
+  TEST_MPIRUN MPI run command for make target ptest, [default: mpiexec -n NP]
+  TEST_OUTDIR Output file directory for make target ptest, [default: ./]
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <parallel-netcdf at mcs.anl.gov>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+parallel-netcdf configure 1.7.0.pre1
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_link
+
+# ac_fn_cxx_check_func LINENO FUNC VAR
+# ------------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_cxx_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_func
+
+# ac_fn_fc_try_compile LINENO
+# ---------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_fc_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_fc_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_fc_try_compile
+
+# ac_fn_f77_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_f77_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_f77_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_f77_try_compile
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+if (sizeof ($2))
+	 return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+if (sizeof (($2)))
+	    return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## ------------------------------------------ ##
+## Report this to parallel-netcdf at mcs.anl.gov ##
+## ------------------------------------------ ##"
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
+# --------------------------------------------
+# Tries to find the compile-time value of EXPR in a program that includes
+# INCLUDES, setting VAR accordingly. Returns whether the value could be
+# computed
+ac_fn_c_compute_int ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if test "$cross_compiling" = yes; then
+    # Depending upon the size, compute the lo and hi bounds.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= 0)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=$ac_mid; break
+else
+  as_fn_arith $ac_mid + 1 && ac_lo=$as_val
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) < 0)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lo=$ac_mid; break
+else
+  as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  ac_lo= ac_hi=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=$ac_mid
+else
+  as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in #((
+?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
+'') ac_retval=1 ;;
+esac
+  else
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+static long int longval () { return $2; }
+static unsigned long int ulongval () { return $2; }
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (($2) < 0)
+    {
+      long int i = longval ();
+      if (i != ($2))
+	return 1;
+      fprintf (f, "%ld", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ($2))
+	return 1;
+      fprintf (f, "%lu", i);
+    }
+  /* Do not output a trailing newline, as this causes \r\n confusion
+     on some platforms.  */
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  echo >>conftest.val; read $3 <conftest.val; ac_retval=0
+else
+  ac_retval=1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f conftest.val
+
+  fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_compute_int
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by parallel-netcdf $as_me 1.7.0.pre1, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_config_headers="$ac_config_headers src/lib/ncconfig.h"
+
+
+
+ac_aux_dir=
+for ac_dir in ./scripts "$srcdir"/./scripts; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in ./scripts \"$srcdir\"/./scripts" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+
+CONFIGURE_ARGS_CLEAN=`echo $* | tr '"' ' '`
+
+PNETCDF_VERSION_MAJOR=`echo ${PACKAGE_VERSION} | cut -d. -f1`
+PNETCDF_VERSION_MINOR=`echo ${PACKAGE_VERSION} | cut -d. -f2`
+PNETCDF_VERSION_SUB=`echo ${PACKAGE_VERSION} | cut -d. -f3`
+PNETCDF_VERSION_PRE=`echo ${PACKAGE_VERSION} | cut -d. -f4`
+
+PNETCDF_VERSION=${PACKAGE_VERSION}
+
+SVN_DATE="$LastChangedDate: 2016-01-12 12:39:01 -0600 (Tue, 12 Jan 2016) $"
+PNETCDF_RELEASE_DATE2=`echo $SVN_DATE | cut -d' ' -f2`
+PNETCDF_RELEASE_DATE=`echo $SVN_DATE | cut -d' ' -f6,7,8 | cut -d')' -f1`
+
+_DEBUG=no
+
+
+if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: PNETCDF_VERSION_MAJOR=$PNETCDF_VERSION_MAJOR" >&5
+$as_echo "$as_me: DEBUG: PNETCDF_VERSION_MAJOR=$PNETCDF_VERSION_MAJOR" >&6;}
+          fi
+
+
+if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: PNETCDF_VERSION_MINOR=$PNETCDF_VERSION_MINOR" >&5
+$as_echo "$as_me: DEBUG: PNETCDF_VERSION_MINOR=$PNETCDF_VERSION_MINOR" >&6;}
+          fi
+
+
+if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: PNETCDF_VERSION_SUB=$PNETCDF_VERSION_SUB" >&5
+$as_echo "$as_me: DEBUG: PNETCDF_VERSION_SUB=$PNETCDF_VERSION_SUB" >&6;}
+          fi
+
+
+if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: PNETCDF_VERSION_PRE=$PNETCDF_VERSION_PRE" >&5
+$as_echo "$as_me: DEBUG: PNETCDF_VERSION_PRE=$PNETCDF_VERSION_PRE" >&6;}
+          fi
+
+
+if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: PNETCDF_VERSION=$PNETCDF_VERSION" >&5
+$as_echo "$as_me: DEBUG: PNETCDF_VERSION=$PNETCDF_VERSION" >&6;}
+          fi
+
+
+if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: PNETCDF_RELEASE_DATE=$PNETCDF_RELEASE_DATE" >&5
+$as_echo "$as_me: DEBUG: PNETCDF_RELEASE_DATE=$PNETCDF_RELEASE_DATE" >&6;}
+          fi
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define PNETCDF_VERSION_MAJOR $PNETCDF_VERSION_MAJOR
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PNETCDF_VERSION_MINOR $PNETCDF_VERSION_MINOR
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PNETCDF_VERSION_SUB $PNETCDF_VERSION_SUB
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PNETCDF_VERSION_PRE $PNETCDF_VERSION_PRE
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PNETCDF_VERSION "$PNETCDF_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PNETCDF_RELEASE_DATE "$PNETCDF_RELEASE_DATE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define CONFIGURE_ARGS_CLEAN "$CONFIGURE_ARGS_CLEAN"
+_ACEOF
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test "x${RM}" != x ; then
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking rm " >&5
+$as_echo_n "checking rm ... " >&6; }
+   if ! test -f ${RM} ; then
+      # Extract the first word of "${RM}", so it can be a program name with args.
+set dummy ${RM}; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_rm_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$rm_cmd"; then
+  ac_cv_prog_rm_cmd="$rm_cmd" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_rm_cmd="yes"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_prog_rm_cmd" && ac_cv_prog_rm_cmd="no"
+fi
+fi
+rm_cmd=$ac_cv_prog_rm_cmd
+if test -n "$rm_cmd"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $rm_cmd" >&5
+$as_echo "$rm_cmd" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+      if test "x${rm_cmd}" = xyes ; then
+         RM=${RM}
+      fi
+   else
+      RM=${RM}
+   fi
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: using $RM" >&5
+$as_echo "using $RM" >&6; }
+else
+   RM="rm"
+fi
+
+
+# Check whether --enable-echo was given.
+if test "${enable_echo+set}" = set; then :
+  enableval=$enable_echo; set -x
+
+fi
+
+
+MPI_INSTALL=
+
+# Check whether --with-mpi was given.
+if test "${with_mpi+set}" = set; then :
+  withval=$with_mpi; if test x"$withval" = xyes; then
+      as_fn_error $? "--with-mpi must be given a pathname" "$LINENO" 5
+   else
+      MPI_INSTALL=${withval}
+   fi
+
+fi
+
+if test "x${MPI_INSTALL}" != x && (! test -d "${MPI_INSTALL}") ; then
+   as_fn_error $? "Directory '${MPI_INSTALL}' specified in --with-mpi does not exist" "$LINENO" 5
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test "x$MPICC"  = x && test "x$CC"  != x ; then MPICC=$CC   ; fi
+if test "x$MPICXX" = x && test "x$CXX" != x ; then MPICXX=$CXX ; fi
+if test "x$MPIF77" = x && test "x$F77" != x ; then MPIF77=$F77 ; fi
+if test "x$MPIF77" = x && test "x$FC"  != x ; then MPIF77=$FC  ; fi
+if test "x$MPIF90" = x && test "x$F90" != x ; then MPIF90=$F90 ; fi
+if test "x$MPIF90" = x && test "x$FC"  != x ; then MPIF90=$FC  ; fi
+
+CANDIDATE_MPICC="${MPICC} mpicc"
+CANDIDATE_MPICXX="${MPICXX} mpicxx mpic++ mpiCC"
+CANDIDATE_MPIF77="${MPIF77} mpif77"
+CANDIDATE_MPIF90="${MPIF90} mpif90"
+
+CANDIDATE_MPICC="${CANDIDATE_MPICC} mpcc_r mpcc mpixlc_r mpixlc"
+CANDIDATE_MPICXX="${CANDIDATE_MPICXX} mpCC_r mpCC mpixlcxx_r mpixlcxx mpixlC_r mpixlC"
+CANDIDATE_MPIF77="${CANDIDATE_MPIF77} mpixlf77_r mpixlf77"
+CANDIDATE_MPIF90="${CANDIDATE_MPIF90} mpixlf90_r mpixlf90"
+
+CANDIDATE_MPICC="${CANDIDATE_MPICC} blrts_xlc mpxlc_r mpxlc"
+CANDIDATE_MPICXX="${CANDIDATE_MPICXX} blrts_xlC mpxlC_r mpxlC"
+CANDIDATE_MPIF77="${CANDIDATE_MPIF77} blrts_xlf mpxlf_r mpxlf"
+CANDIDATE_MPIF90="${CANDIDATE_MPIF90} blrts_xlf90 mpxlf90_r mpxlf90 mpxlf95_r mpxlf95"
+
+CANDIDATE_MPICC="${CANDIDATE_MPICC} mpifccpx"
+CANDIDATE_MPICXX="${CANDIDATE_MPICXX} mpiFCCpx"
+CANDIDATE_MPIF77="${CANDIDATE_MPIF77} mpifrtpx"
+CANDIDATE_MPIF90="${CANDIDATE_MPIF90} mpifrtpx"
+
+CANDIDATE_MPICC="${CANDIDATE_MPICC} cc"
+CANDIDATE_MPICXX="${CANDIDATE_MPICXX} CC"
+CANDIDATE_MPIF77="${CANDIDATE_MPIF77} ftn"
+CANDIDATE_MPIF90="${CANDIDATE_MPIF90} ftn"
+
+CANDIDATE_MPICC="${CANDIDATE_MPICC} mpiicc icc"
+CANDIDATE_MPICXX="${CANDIDATE_MPICXX} mpiicpc icpc"
+CANDIDATE_MPIF77="${CANDIDATE_MPIF77} mpiifort mpiifc ifort"
+CANDIDATE_MPIF90="${CANDIDATE_MPIF90} mpiifort mpiifc ifort"
+
+
+   if test "x$MPI_INSTALL" != x ; then
+      if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: --with-mpi=$MPI_INSTALL is used" >&5
+$as_echo "$as_me: DEBUG: --with-mpi=$MPI_INSTALL is used" >&6;}
+          fi
+
+
+      if test "x$MPICC" = x ; then
+         if test "x$MPICC" = x && (test -d "${MPI_INSTALL}/bin") ; then
+            if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: search possible MPICC under $MPI_INSTALL/bin" >&5
+$as_echo "$as_me: DEBUG: search possible MPICC under $MPI_INSTALL/bin" >&6;}
+          fi
+
+
+            for ac_prog in $CANDIDATE_MPICC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPICC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPICC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPICC="$MPICC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $MPI_INSTALL/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPICC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPICC=$ac_cv_path_MPICC
+if test -n "$MPICC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPICC" >&5
+$as_echo "$MPICC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPICC" && break
+done
+
+         fi
+         if test "x$MPICC" = x ; then
+             if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: search possible MPICC under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: search possible MPICC under $MPI_INSTALL" >&6;}
+          fi
+
+
+             for ac_prog in $CANDIDATE_MPICC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPICC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPICC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPICC="$MPICC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $MPI_INSTALL
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPICC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPICC=$ac_cv_path_MPICC
+if test -n "$MPICC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPICC" >&5
+$as_echo "$MPICC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPICC" && break
+done
+
+         fi
+      else
+         if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: check if file $MPICC exists" >&5
+$as_echo "$as_me: DEBUG: check if file $MPICC exists" >&6;}
+          fi
+
+
+         if ! test -f "$MPICC" ; then
+                        if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPICC= $MPICC cannot be found ... check under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: File MPICC= $MPICC cannot be found ... check under $MPI_INSTALL" >&6;}
+          fi
+
+
+            if test -f "$MPI_INSTALL/$MPICC" ; then
+               if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPICC= $MPICC is found under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: File MPICC= $MPICC is found under $MPI_INSTALL" >&6;}
+          fi
+
+
+               MPICC="$MPI_INSTALL/$MPICC"
+            elif test -f "$MPI_INSTALL/bin/$MPICC" ; then
+               if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPICC= $MPICC is found under $MPI_INSTALL/bin" >&5
+$as_echo "$as_me: DEBUG: File MPICC= $MPICC is found under $MPI_INSTALL/bin" >&6;}
+          fi
+
+
+               MPICC="$MPI_INSTALL/bin/$MPICC"
+            else
+               if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPICC= $MPICC cannot be found under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: File MPICC= $MPICC cannot be found under $MPI_INSTALL" >&6;}
+          fi
+
+
+               MPICC=
+            fi
+         fi
+      fi
+   else
+       if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: --with-mpi=$MPI_INSTALL is NOT used" >&5
+$as_echo "$as_me: DEBUG: --with-mpi=$MPI_INSTALL is NOT used" >&6;}
+          fi
+
+
+       if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: check if MPICC is defined. If yes, check if file exists" >&5
+$as_echo "$as_me: DEBUG: check if MPICC is defined. If yes, check if file exists" >&6;}
+          fi
+
+
+       if test "x$MPICC" != x && (! test -f "$MPICC") ; then
+          if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: check if file $MPICC exists under user's PATH" >&5
+$as_echo "$as_me: DEBUG: check if file $MPICC exists under user's PATH" >&6;}
+          fi
+
+
+          for ac_prog in $MPICC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPICC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPICC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPICC="$MPICC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPICC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPICC=$ac_cv_path_MPICC
+if test -n "$MPICC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPICC" >&5
+$as_echo "$MPICC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPICC" && break
+done
+
+       fi
+   fi
+         if test "x$MPICC" = x ; then
+      if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: find possible MPICC under user's PATH" >&5
+$as_echo "$as_me: DEBUG: find possible MPICC under user's PATH" >&6;}
+          fi
+
+
+      for ac_prog in $CANDIDATE_MPICC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPICC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPICC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPICC="$MPICC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPICC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPICC=$ac_cv_path_MPICC
+if test -n "$MPICC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPICC" >&5
+$as_echo "$MPICC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPICC" && break
+done
+
+   fi
+
+if test "x${MPICC}" = x ; then
+   as_fn_error $? "
+   -----------------------------------------------------------------------
+    No MPI C compiler can be found. Parallel netCDF requires an MPI C
+    compiler. Please specify the location of one either with the MPICC
+    environment variable or the --with-mpi configure flag
+   -----------------------------------------------------------------------" "$LINENO" 5
+fi
+
+CC=${MPICC}
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+  enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+	 # IRIX 6.2 and later do not support large files by default,
+	 # so use the C compiler's -n32 option if that helps.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+	 if ac_fn_c_try_compile "$LINENO"; then :
+  break
+fi
+rm -f core conftest.err conftest.$ac_objext
+	 CC="$CC -n32"
+	 if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext
+	 break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if ${ac_cv_sys_file_offset_bits+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_file_offset_bits=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  if test $ac_cv_sys_file_offset_bits = unknown; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if ${ac_cv_sys_large_files+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_large_files=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  fi
+
+
+fi
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to make dependencies" >&5
+$as_echo_n "checking how to make dependencies... " >&6; }
+    case `uname -s` in
+	IRIX*|OSF1)
+	    CC_MAKEDEPEND='cc -M'
+	    ;;
+	SunOS)
+	    case `uname -r` in
+		4*)
+		    CC_MAKEDEPEND='cc -M'
+		    ;;
+		5*|*)
+		    CC_MAKEDEPEND='cc -xM'
+		    ;;
+	    esac
+	    ;;
+	ULTRIX)
+	    case `uname -m` in
+		RISC)
+		    CC_MAKEDEPEND='cc -M'
+		    ;;
+		VAX)	# Can't handle prototypes in netcdf.h
+		    ;;
+	    esac
+	    ;;
+	AIX)	# Writes to .u files rather than standard out
+	    ;;
+	HP-UX)	# Writes escaped newlines to standard error
+	    ;;
+    esac
+    case "${CC_MAKEDEPEND}" in
+	'')
+	    CC_MAKEDEPEND=false
+	    ;;
+    esac
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC_MAKEDEPEND" >&5
+$as_echo "$CC_MAKEDEPEND" >&6; }
+
+
+
+
+# check if MPICC works for basic MPI call: MPI_Comm_rank()
+ac_fn_c_check_func "$LINENO" "MPI_Comm_rank" "ac_cv_func_MPI_Comm_rank"
+if test "x$ac_cv_func_MPI_Comm_rank" = xyes; then :
+
+else
+     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing MPI_Comm_rank" >&5
+$as_echo_n "checking for library containing MPI_Comm_rank... " >&6; }
+if ${ac_cv_search_MPI_Comm_rank+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char MPI_Comm_rank ();
+int
+main ()
+{
+return MPI_Comm_rank ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' mpi mpich; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_MPI_Comm_rank=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_MPI_Comm_rank+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_MPI_Comm_rank+:} false; then :
+
+else
+  ac_cv_search_MPI_Comm_rank=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_MPI_Comm_rank" >&5
+$as_echo "$ac_cv_search_MPI_Comm_rank" >&6; }
+ac_res=$ac_cv_search_MPI_Comm_rank
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+  as_fn_error $? "
+    ------------------------------------------------------------
+     Invalid MPI compiler specified or detected: \"${MPICC}\"
+     A working MPI compiler is required. Please specify the location
+     of one either with the MPICC environment variable or the
+     --with-mpi configure flag
+    ------------------------------------------------------------" "$LINENO" 5
+
+fi
+
+fi
+
+
+
+# Check whether --enable-mpi-io-test was given.
+if test "${enable_mpi_io_test+set}" = set; then :
+  enableval=$enable_mpi_io_test; enable_mpi_io_test=${enableval}
+else
+  enable_mpi_io_test=yes
+
+fi
+
+
+if test "x${enable_mpi_io_test}" = xyes ; then
+   ac_fn_c_check_func "$LINENO" "MPI_File_open" "ac_cv_func_MPI_File_open"
+if test "x$ac_cv_func_MPI_File_open" = xyes; then :
+
+else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing MPI_File_open" >&5
+$as_echo_n "checking for library containing MPI_File_open... " >&6; }
+if ${ac_cv_search_MPI_File_open+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char MPI_File_open ();
+int
+main ()
+{
+return MPI_File_open ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' mpio; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_MPI_File_open=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_MPI_File_open+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_MPI_File_open+:} false; then :
+
+else
+  ac_cv_search_MPI_File_open=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_MPI_File_open" >&5
+$as_echo "$ac_cv_search_MPI_File_open" >&6; }
+ac_res=$ac_cv_search_MPI_File_open
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+  as_fn_error $? "
+            ------------------------------------------------------------
+             MPI implementation does not support MPI-IO
+             PnetCDF requires MPI-IO support to work properly.
+            ------------------------------------------------------------" "$LINENO" 5
+
+fi
+
+fi
+
+fi
+
+# Check whether --enable-cxx was given.
+if test "${enable_cxx+set}" = set; then :
+  enableval=$enable_cxx; enable_cxx=${enableval}
+else
+  enable_cxx=auto
+
+fi
+
+
+if test "x${enable_cxx}" != xno ; then
+
+   if test "x$MPI_INSTALL" != x ; then
+      if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: --with-mpi=$MPI_INSTALL is used" >&5
+$as_echo "$as_me: DEBUG: --with-mpi=$MPI_INSTALL is used" >&6;}
+          fi
+
+
+      if test "x$MPICXX" = x ; then
+         if test "x$MPICXX" = x && (test -d "${MPI_INSTALL}/bin") ; then
+            if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: search possible MPICXX under $MPI_INSTALL/bin" >&5
+$as_echo "$as_me: DEBUG: search possible MPICXX under $MPI_INSTALL/bin" >&6;}
+          fi
+
+
+            for ac_prog in $CANDIDATE_MPICXX
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPICXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPICXX in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPICXX="$MPICXX" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $MPI_INSTALL/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPICXX="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPICXX=$ac_cv_path_MPICXX
+if test -n "$MPICXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPICXX" >&5
+$as_echo "$MPICXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPICXX" && break
+done
+
+         fi
+         if test "x$MPICXX" = x ; then
+             if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: search possible MPICXX under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: search possible MPICXX under $MPI_INSTALL" >&6;}
+          fi
+
+
+             for ac_prog in $CANDIDATE_MPICXX
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPICXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPICXX in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPICXX="$MPICXX" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $MPI_INSTALL
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPICXX="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPICXX=$ac_cv_path_MPICXX
+if test -n "$MPICXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPICXX" >&5
+$as_echo "$MPICXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPICXX" && break
+done
+
+         fi
+      else
+         if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: check if file $MPICXX exists" >&5
+$as_echo "$as_me: DEBUG: check if file $MPICXX exists" >&6;}
+          fi
+
+
+         if ! test -f "$MPICXX" ; then
+                        if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPICXX= $MPICXX cannot be found ... check under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: File MPICXX= $MPICXX cannot be found ... check under $MPI_INSTALL" >&6;}
+          fi
+
+
+            if test -f "$MPI_INSTALL/$MPICXX" ; then
+               if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPICXX= $MPICXX is found under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: File MPICXX= $MPICXX is found under $MPI_INSTALL" >&6;}
+          fi
+
+
+               MPICXX="$MPI_INSTALL/$MPICXX"
+            elif test -f "$MPI_INSTALL/bin/$MPICXX" ; then
+               if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPICXX= $MPICXX is found under $MPI_INSTALL/bin" >&5
+$as_echo "$as_me: DEBUG: File MPICXX= $MPICXX is found under $MPI_INSTALL/bin" >&6;}
+          fi
+
+
+               MPICXX="$MPI_INSTALL/bin/$MPICXX"
+            else
+               if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPICXX= $MPICXX cannot be found under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: File MPICXX= $MPICXX cannot be found under $MPI_INSTALL" >&6;}
+          fi
+
+
+               MPICXX=
+            fi
+         fi
+      fi
+   else
+       if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: --with-mpi=$MPI_INSTALL is NOT used" >&5
+$as_echo "$as_me: DEBUG: --with-mpi=$MPI_INSTALL is NOT used" >&6;}
+          fi
+
+
+       if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: check if MPICXX is defined. If yes, check if file exists" >&5
+$as_echo "$as_me: DEBUG: check if MPICXX is defined. If yes, check if file exists" >&6;}
+          fi
+
+
+       if test "x$MPICXX" != x && (! test -f "$MPICXX") ; then
+          if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: check if file $MPICXX exists under user's PATH" >&5
+$as_echo "$as_me: DEBUG: check if file $MPICXX exists under user's PATH" >&6;}
+          fi
+
+
+          for ac_prog in $MPICXX
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPICXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPICXX in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPICXX="$MPICXX" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPICXX="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPICXX=$ac_cv_path_MPICXX
+if test -n "$MPICXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPICXX" >&5
+$as_echo "$MPICXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPICXX" && break
+done
+
+       fi
+   fi
+         if test "x$MPICXX" = x ; then
+      if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: find possible MPICXX under user's PATH" >&5
+$as_echo "$as_me: DEBUG: find possible MPICXX under user's PATH" >&6;}
+          fi
+
+
+      for ac_prog in $CANDIDATE_MPICXX
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPICXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPICXX in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPICXX="$MPICXX" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPICXX="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPICXX=$ac_cv_path_MPICXX
+if test -n "$MPICXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPICXX" >&5
+$as_echo "$MPICXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPICXX" && break
+done
+
+   fi
+
+
+   if test "x${MPICXX}" = x ; then
+      as_fn_error $? "
+         ------------------------------------------------------------
+           configure cannot find a C++ compiler. Please specify the
+           locations of the compiler either with the MPICXX
+           environment variable or the --with-mpi configure flag.
+         ------------------------------------------------------------" "$LINENO" 5
+      has_mpicxx=no
+   else
+      CXX=${MPICXX}
+
+      has_mpicxx=yes
+
+            ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in ${MPICXX}
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in ${MPICXX}
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+else
+  CXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+            if test "x${enable_mpi_io_test}" = xyes ; then
+          ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+ac_fn_cxx_check_func "$LINENO" "MPI_File_close" "ac_cv_func_MPI_File_close"
+if test "x$ac_cv_func_MPI_File_close" = xyes; then :
+
+else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing MPI_File_close" >&5
+$as_echo_n "checking for library containing MPI_File_close... " >&6; }
+if ${ac_cv_search_MPI_File_close+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char MPI_File_close ();
+int
+main ()
+{
+return MPI_File_close ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' mpi++ mpichcxx mpi_cxx; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_cxx_try_link "$LINENO"; then :
+  ac_cv_search_MPI_File_close=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_MPI_File_close+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_MPI_File_close+:} false; then :
+
+else
+  ac_cv_search_MPI_File_close=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_MPI_File_close" >&5
+$as_echo "$ac_cv_search_MPI_File_close" >&6; }
+ac_res=$ac_cv_search_MPI_File_close
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+  has_mpicxx=no
+                  MPICXX=
+                  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+                  ----------------------------------------------------------
+                   MPI C++ implementation does not support MPI-IO
+                   Disabling C++ testing programs
+                  ----------------------------------------------------------" >&5
+$as_echo "$as_me: WARNING:
+                  ----------------------------------------------------------
+                   MPI C++ implementation does not support MPI-IO
+                   Disabling C++ testing programs
+                  ----------------------------------------------------------" >&2;}
+
+fi
+
+fi
+
+          ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+      fi
+   fi
+   if test "x${has_mpicxx}" = xyes ; then
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI C++ compiler redefines SEEK_SET " >&5
+$as_echo_n "checking if MPI C++ compiler redefines SEEK_SET ... " >&6; }
+   CXX=${MPICXX}
+   ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <stdio.h>
+          #include <mpi.h>
+          int main() { return 0; }
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_CHECK_MPI_CPP_SEEK_SET=no
+else
+  ac_cv_CHECK_MPI_CPP_SEEK_SET=yes
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_CHECK_MPI_CPP_SEEK_SET" >&5
+$as_echo "$ac_cv_CHECK_MPI_CPP_SEEK_SET" >&6; }
+   ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+      if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: ac_cv_CHECK_MPI_CPP_SEEK_SET=$ac_cv_CHECK_MPI_CPP_SEEK_SET" >&5
+$as_echo "$as_me: DEBUG: ac_cv_CHECK_MPI_CPP_SEEK_SET=$ac_cv_CHECK_MPI_CPP_SEEK_SET" >&6;}
+          fi
+
+
+      if test "x${ac_cv_CHECK_MPI_CPP_SEEK_SET}" = xyes ; then
+         CXXCPPFLAGS="${CXXCPPFLAGS} -DMPICH_IGNORE_CXX_SEEK -DMPICH_SKIP_MPICXX"
+      fi
+   fi
+else
+has_mpicxx=no
+fi
+
+
+# Check whether --enable-strict was given.
+if test "${enable_strict+set}" = set; then :
+  enableval=$enable_strict; enable_strict=${enableval}
+else
+  enable_strict=no
+
+fi
+
+
+if test "x${enable_strict}" = xyes; then
+   if test "x${GCC}" = xyes; then
+      CPPFLAGS="${CPPFLAGS} -Wall -Wstrict-prototypes -Wmissing-prototypes -Wundef -Wpointer-arith -Wbad-function-cast"
+      CXXCPPFLAGS="${CXXCPPFLAGS} -Wall -Wundef -Wpointer-arith"
+   else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-strict is for GNU compiler only" >&5
+$as_echo "$as_me: WARNING: --enable-strict is for GNU compiler only" >&2;}
+      enable_strict=no
+   fi
+fi
+
+
+# Check whether --enable-fortran was given.
+if test "${enable_fortran+set}" = set; then :
+  enableval=$enable_fortran; enable_fortran=${enableval}
+else
+  enable_fortran=auto
+
+fi
+
+
+if test "x${enable_fortran}" != xno ; then
+
+   if test "x$MPI_INSTALL" != x ; then
+      if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: --with-mpi=$MPI_INSTALL is used" >&5
+$as_echo "$as_me: DEBUG: --with-mpi=$MPI_INSTALL is used" >&6;}
+          fi
+
+
+      if test "x$MPIF77" = x ; then
+         if test "x$MPIF77" = x && (test -d "${MPI_INSTALL}/bin") ; then
+            if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: search possible MPIF77 under $MPI_INSTALL/bin" >&5
+$as_echo "$as_me: DEBUG: search possible MPIF77 under $MPI_INSTALL/bin" >&6;}
+          fi
+
+
+            for ac_prog in $CANDIDATE_MPIF77
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPIF77+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPIF77 in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPIF77="$MPIF77" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $MPI_INSTALL/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPIF77="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPIF77=$ac_cv_path_MPIF77
+if test -n "$MPIF77"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPIF77" >&5
+$as_echo "$MPIF77" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPIF77" && break
+done
+
+         fi
+         if test "x$MPIF77" = x ; then
+             if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: search possible MPIF77 under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: search possible MPIF77 under $MPI_INSTALL" >&6;}
+          fi
+
+
+             for ac_prog in $CANDIDATE_MPIF77
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPIF77+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPIF77 in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPIF77="$MPIF77" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $MPI_INSTALL
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPIF77="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPIF77=$ac_cv_path_MPIF77
+if test -n "$MPIF77"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPIF77" >&5
+$as_echo "$MPIF77" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPIF77" && break
+done
+
+         fi
+      else
+         if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: check if file $MPIF77 exists" >&5
+$as_echo "$as_me: DEBUG: check if file $MPIF77 exists" >&6;}
+          fi
+
+
+         if ! test -f "$MPIF77" ; then
+                        if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPIF77= $MPIF77 cannot be found ... check under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: File MPIF77= $MPIF77 cannot be found ... check under $MPI_INSTALL" >&6;}
+          fi
+
+
+            if test -f "$MPI_INSTALL/$MPIF77" ; then
+               if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPIF77= $MPIF77 is found under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: File MPIF77= $MPIF77 is found under $MPI_INSTALL" >&6;}
+          fi
+
+
+               MPIF77="$MPI_INSTALL/$MPIF77"
+            elif test -f "$MPI_INSTALL/bin/$MPIF77" ; then
+               if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPIF77= $MPIF77 is found under $MPI_INSTALL/bin" >&5
+$as_echo "$as_me: DEBUG: File MPIF77= $MPIF77 is found under $MPI_INSTALL/bin" >&6;}
+          fi
+
+
+               MPIF77="$MPI_INSTALL/bin/$MPIF77"
+            else
+               if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPIF77= $MPIF77 cannot be found under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: File MPIF77= $MPIF77 cannot be found under $MPI_INSTALL" >&6;}
+          fi
+
+
+               MPIF77=
+            fi
+         fi
+      fi
+   else
+       if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: --with-mpi=$MPI_INSTALL is NOT used" >&5
+$as_echo "$as_me: DEBUG: --with-mpi=$MPI_INSTALL is NOT used" >&6;}
+          fi
+
+
+       if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: check if MPIF77 is defined. If yes, check if file exists" >&5
+$as_echo "$as_me: DEBUG: check if MPIF77 is defined. If yes, check if file exists" >&6;}
+          fi
+
+
+       if test "x$MPIF77" != x && (! test -f "$MPIF77") ; then
+          if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: check if file $MPIF77 exists under user's PATH" >&5
+$as_echo "$as_me: DEBUG: check if file $MPIF77 exists under user's PATH" >&6;}
+          fi
+
+
+          for ac_prog in $MPIF77
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPIF77+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPIF77 in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPIF77="$MPIF77" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPIF77="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPIF77=$ac_cv_path_MPIF77
+if test -n "$MPIF77"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPIF77" >&5
+$as_echo "$MPIF77" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPIF77" && break
+done
+
+       fi
+   fi
+         if test "x$MPIF77" = x ; then
+      if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: find possible MPIF77 under user's PATH" >&5
+$as_echo "$as_me: DEBUG: find possible MPIF77 under user's PATH" >&6;}
+          fi
+
+
+      for ac_prog in $CANDIDATE_MPIF77
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPIF77+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPIF77 in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPIF77="$MPIF77" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPIF77="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPIF77=$ac_cv_path_MPIF77
+if test -n "$MPIF77"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPIF77" >&5
+$as_echo "$MPIF77" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPIF77" && break
+done
+
+   fi
+
+
+   if test "x$MPI_INSTALL" != x ; then
+      if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: --with-mpi=$MPI_INSTALL is used" >&5
+$as_echo "$as_me: DEBUG: --with-mpi=$MPI_INSTALL is used" >&6;}
+          fi
+
+
+      if test "x$MPIF90" = x ; then
+         if test "x$MPIF90" = x && (test -d "${MPI_INSTALL}/bin") ; then
+            if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: search possible MPIF90 under $MPI_INSTALL/bin" >&5
+$as_echo "$as_me: DEBUG: search possible MPIF90 under $MPI_INSTALL/bin" >&6;}
+          fi
+
+
+            for ac_prog in $CANDIDATE_MPIF90
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPIF90+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPIF90 in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPIF90="$MPIF90" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $MPI_INSTALL/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPIF90="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPIF90=$ac_cv_path_MPIF90
+if test -n "$MPIF90"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPIF90" >&5
+$as_echo "$MPIF90" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPIF90" && break
+done
+
+         fi
+         if test "x$MPIF90" = x ; then
+             if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: search possible MPIF90 under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: search possible MPIF90 under $MPI_INSTALL" >&6;}
+          fi
+
+
+             for ac_prog in $CANDIDATE_MPIF90
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPIF90+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPIF90 in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPIF90="$MPIF90" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $MPI_INSTALL
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPIF90="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPIF90=$ac_cv_path_MPIF90
+if test -n "$MPIF90"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPIF90" >&5
+$as_echo "$MPIF90" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPIF90" && break
+done
+
+         fi
+      else
+         if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: check if file $MPIF90 exists" >&5
+$as_echo "$as_me: DEBUG: check if file $MPIF90 exists" >&6;}
+          fi
+
+
+         if ! test -f "$MPIF90" ; then
+                        if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPIF90= $MPIF90 cannot be found ... check under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: File MPIF90= $MPIF90 cannot be found ... check under $MPI_INSTALL" >&6;}
+          fi
+
+
+            if test -f "$MPI_INSTALL/$MPIF90" ; then
+               if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPIF90= $MPIF90 is found under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: File MPIF90= $MPIF90 is found under $MPI_INSTALL" >&6;}
+          fi
+
+
+               MPIF90="$MPI_INSTALL/$MPIF90"
+            elif test -f "$MPI_INSTALL/bin/$MPIF90" ; then
+               if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPIF90= $MPIF90 is found under $MPI_INSTALL/bin" >&5
+$as_echo "$as_me: DEBUG: File MPIF90= $MPIF90 is found under $MPI_INSTALL/bin" >&6;}
+          fi
+
+
+               MPIF90="$MPI_INSTALL/bin/$MPIF90"
+            else
+               if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: File MPIF90= $MPIF90 cannot be found under $MPI_INSTALL" >&5
+$as_echo "$as_me: DEBUG: File MPIF90= $MPIF90 cannot be found under $MPI_INSTALL" >&6;}
+          fi
+
+
+               MPIF90=
+            fi
+         fi
+      fi
+   else
+       if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: --with-mpi=$MPI_INSTALL is NOT used" >&5
+$as_echo "$as_me: DEBUG: --with-mpi=$MPI_INSTALL is NOT used" >&6;}
+          fi
+
+
+       if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: check if MPIF90 is defined. If yes, check if file exists" >&5
+$as_echo "$as_me: DEBUG: check if MPIF90 is defined. If yes, check if file exists" >&6;}
+          fi
+
+
+       if test "x$MPIF90" != x && (! test -f "$MPIF90") ; then
+          if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: check if file $MPIF90 exists under user's PATH" >&5
+$as_echo "$as_me: DEBUG: check if file $MPIF90 exists under user's PATH" >&6;}
+          fi
+
+
+          for ac_prog in $MPIF90
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPIF90+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPIF90 in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPIF90="$MPIF90" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPIF90="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPIF90=$ac_cv_path_MPIF90
+if test -n "$MPIF90"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPIF90" >&5
+$as_echo "$MPIF90" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPIF90" && break
+done
+
+       fi
+   fi
+         if test "x$MPIF90" = x ; then
+      if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: find possible MPIF90 under user's PATH" >&5
+$as_echo "$as_me: DEBUG: find possible MPIF90 under user's PATH" >&6;}
+          fi
+
+
+      for ac_prog in $CANDIDATE_MPIF90
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MPIF90+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MPIF90 in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MPIF90="$MPIF90" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_MPIF90="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MPIF90=$ac_cv_path_MPIF90
+if test -n "$MPIF90"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MPIF90" >&5
+$as_echo "$MPIF90" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$MPIF90" && break
+done
+
+   fi
+
+fi
+if test "x${enable_fortran}" = xyes ; then
+      if test "x${MPIF77}" = x && test "x${MPIF90}" = x ; then
+      as_fn_error $? "
+         ------------------------------------------------------------
+           Fortran support is explicitly requested, but configure
+           cannot find a Fortran77 or Fortran90 compiler. Please
+           specify the locations of the compilers either with the
+           MPIF77 MPIF90 environment variables or the --with-mpi
+           configure flag.
+         ------------------------------------------------------------" "$LINENO" 5
+   fi
+fi
+
+
+if test "x${MPIF90}" != x ; then
+   FC=${MPIF90}
+   ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn nagfor xlf90 f90 pgf90 pghpf epcf90 g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_FC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$FC"; then
+  ac_cv_prog_FC="$FC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_FC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+FC=$ac_cv_prog_FC
+if test -n "$FC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FC" >&5
+$as_echo "$FC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$FC" && break
+  done
+fi
+if test -z "$FC"; then
+  ac_ct_FC=$FC
+  for ac_prog in gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn nagfor xlf90 f90 pgf90 pghpf epcf90 g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_FC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_FC"; then
+  ac_cv_prog_ac_ct_FC="$ac_ct_FC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_FC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_FC=$ac_cv_prog_ac_ct_FC
+if test -n "$ac_ct_FC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FC" >&5
+$as_echo "$ac_ct_FC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_FC" && break
+done
+
+  if test "x$ac_ct_FC" = x; then
+    FC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    FC=$ac_ct_FC
+  fi
+fi
+
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+rm -f a.out
+
+# If we don't use `.F' as extension, the preprocessor is not run on the
+# input file.  (Note that this only needs to work for GNU compilers.)
+ac_save_ext=$ac_ext
+ac_ext=F
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU Fortran compiler" >&5
+$as_echo_n "checking whether we are using the GNU Fortran compiler... " >&6; }
+if ${ac_cv_fc_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+#ifndef __GNUC__
+       choke me
+#endif
+
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_fc_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_compiler_gnu" >&5
+$as_echo "$ac_cv_fc_compiler_gnu" >&6; }
+ac_ext=$ac_save_ext
+ac_test_FCFLAGS=${FCFLAGS+set}
+ac_save_FCFLAGS=$FCFLAGS
+FCFLAGS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $FC accepts -g" >&5
+$as_echo_n "checking whether $FC accepts -g... " >&6; }
+if ${ac_cv_prog_fc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  FCFLAGS=-g
+cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_cv_prog_fc_g=yes
+else
+  ac_cv_prog_fc_g=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_fc_g" >&5
+$as_echo "$ac_cv_prog_fc_g" >&6; }
+if test "$ac_test_FCFLAGS" = set; then
+  FCFLAGS=$ac_save_FCFLAGS
+elif test $ac_cv_prog_fc_g = yes; then
+  if test "x$ac_cv_fc_compiler_gnu" = xyes; then
+    FCFLAGS="-g -O2"
+  else
+    FCFLAGS="-g"
+  fi
+else
+  if test "x$ac_cv_fc_compiler_gnu" = xyes; then
+    FCFLAGS="-O2"
+  else
+    FCFLAGS=
+  fi
+fi
+
+if test $ac_compiler_gnu = yes; then
+  GFC=yes
+else
+  GFC=
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+   FCLIBS_save="$FCLIBS"
+   FCLIBS=""
+   # Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to get verbose linking output from $FC" >&5
+$as_echo_n "checking how to get verbose linking output from $FC... " >&6; }
+if ${ac_cv_prog_fc_v+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_cv_prog_fc_v=
+# Try some options frequently used verbose output
+for ac_verb in -v -verbose -V -\#\#\# --verbose; do
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+
+# Compile and link our simple test program by passing a flag (argument
+# 1 to this macro) to the Fortran compiler in order to get
+# "verbose" output that we can then parse for the Fortran linker
+# flags.
+ac_save_FCFLAGS=$FCFLAGS
+FCFLAGS="$FCFLAGS $ac_verb"
+eval "set x $ac_link"
+shift
+$as_echo "$as_me:${as_lineno-$LINENO}: $*" >&5
+# gfortran 4.3 outputs lines setting COLLECT_GCC_OPTIONS, COMPILER_PATH,
+# LIBRARY_PATH; skip all such settings.
+ac_fc_v_output=`eval $ac_link 5>&1 2>&1 |
+  sed '/^Driving:/d; /^Configured with:/d;
+      '"/^[_$as_cr_Letters][_$as_cr_alnum]*=/d"`
+$as_echo "$ac_fc_v_output" >&5
+FCFLAGS=$ac_save_FCFLAGS
+
+rm -rf conftest*
+
+# On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where
+# /foo, /bar, and /baz are search directories for the Fortran linker.
+# Here, we change these into -L/foo -L/bar -L/baz (and put it first):
+ac_fc_v_output="`echo $ac_fc_v_output |
+	grep 'LPATH is:' |
+	sed 's|.*LPATH is\(: *[^ ]*\).*|\1|;s|: */| -L/|g'` $ac_fc_v_output"
+
+# FIXME: we keep getting bitten by quoted arguments; a more general fix
+#        that detects unbalanced quotes in FLIBS should be implemented
+#        and (ugh) tested at some point.
+case $ac_fc_v_output in
+  # With xlf replace commas with spaces,
+  # and remove "-link" and closing parenthesis.
+  *xlfentry*)
+    ac_fc_v_output=`echo $ac_fc_v_output |
+      sed '
+        s/,/ /g
+        s/ -link / /g
+        s/) *$//
+      '
+    ` ;;
+
+  # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted
+  # $LIBS confuse us, and the libraries appear later in the output anyway).
+  *mGLOB_options_string*)
+    ac_fc_v_output=`echo $ac_fc_v_output | sed 's/"-mGLOB[^"]*"/ /g'` ;;
+
+  # Portland Group compiler has singly- or doubly-quoted -cmdline argument
+  # Singly-quoted arguments were reported for versions 5.2-4 and 6.0-4.
+  # Doubly-quoted arguments were reported for "PGF90/x86 Linux/x86 5.0-2".
+  *-cmdline\ * | *-ignore\ * | *-def\ *)
+    ac_fc_v_output=`echo $ac_fc_v_output | sed "\
+	s/-cmdline  *'[^']*'/ /g; s/-cmdline  *\"[^\"]*\"/ /g
+	s/-ignore  *'[^']*'/ /g; s/-ignore  *\"[^\"]*\"/ /g
+	s/-def  *'[^']*'/ /g; s/-def  *\"[^\"]*\"/ /g"` ;;
+
+  # If we are using fort77 (the f2c wrapper) then filter output and delete quotes.
+  *fort77*f2c*gcc*)
+    ac_fc_v_output=`echo "$ac_fc_v_output" | sed -n '
+        /:[	 ]\+Running[	 ]\{1,\}"gcc"/{
+          /"-c"/d
+          /[.]c"*/d
+          s/^.*"gcc"/"gcc"/
+          s/"//gp
+        }'` ;;
+
+  # If we are using Cray Fortran then delete quotes.
+  *cft90*)
+    ac_fc_v_output=`echo $ac_fc_v_output | sed 's/"//g'` ;;
+esac
+
+
+  # look for -l* and *.a constructs in the output
+  for ac_arg in $ac_fc_v_output; do
+     case $ac_arg in
+	[\\/]*.a | ?:[\\/]*.a | -[lLRu]*)
+	  ac_cv_prog_fc_v=$ac_verb
+	  break 2 ;;
+     esac
+  done
+done
+if test -z "$ac_cv_prog_fc_v"; then
+   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine how to obtain linking information from $FC" >&5
+$as_echo "$as_me: WARNING: cannot determine how to obtain linking information from $FC" >&2;}
+fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: compilation failed" >&5
+$as_echo "$as_me: WARNING: compilation failed" >&2;}
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_fc_v" >&5
+$as_echo "$ac_cv_prog_fc_v" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran libraries of $FC" >&5
+$as_echo_n "checking for Fortran libraries of $FC... " >&6; }
+if ${ac_cv_fc_libs+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$FCLIBS" != "x"; then
+  ac_cv_fc_libs="$FCLIBS" # Let the user override the test.
+else
+
+cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+
+# Compile and link our simple test program by passing a flag (argument
+# 1 to this macro) to the Fortran compiler in order to get
+# "verbose" output that we can then parse for the Fortran linker
+# flags.
+ac_save_FCFLAGS=$FCFLAGS
+FCFLAGS="$FCFLAGS $ac_cv_prog_fc_v"
+eval "set x $ac_link"
+shift
+$as_echo "$as_me:${as_lineno-$LINENO}: $*" >&5
+# gfortran 4.3 outputs lines setting COLLECT_GCC_OPTIONS, COMPILER_PATH,
+# LIBRARY_PATH; skip all such settings.
+ac_fc_v_output=`eval $ac_link 5>&1 2>&1 |
+  sed '/^Driving:/d; /^Configured with:/d;
+      '"/^[_$as_cr_Letters][_$as_cr_alnum]*=/d"`
+$as_echo "$ac_fc_v_output" >&5
+FCFLAGS=$ac_save_FCFLAGS
+
+rm -rf conftest*
+
+# On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where
+# /foo, /bar, and /baz are search directories for the Fortran linker.
+# Here, we change these into -L/foo -L/bar -L/baz (and put it first):
+ac_fc_v_output="`echo $ac_fc_v_output |
+	grep 'LPATH is:' |
+	sed 's|.*LPATH is\(: *[^ ]*\).*|\1|;s|: */| -L/|g'` $ac_fc_v_output"
+
+# FIXME: we keep getting bitten by quoted arguments; a more general fix
+#        that detects unbalanced quotes in FLIBS should be implemented
+#        and (ugh) tested at some point.
+case $ac_fc_v_output in
+  # With xlf replace commas with spaces,
+  # and remove "-link" and closing parenthesis.
+  *xlfentry*)
+    ac_fc_v_output=`echo $ac_fc_v_output |
+      sed '
+        s/,/ /g
+        s/ -link / /g
+        s/) *$//
+      '
+    ` ;;
+
+  # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted
+  # $LIBS confuse us, and the libraries appear later in the output anyway).
+  *mGLOB_options_string*)
+    ac_fc_v_output=`echo $ac_fc_v_output | sed 's/"-mGLOB[^"]*"/ /g'` ;;
+
+  # Portland Group compiler has singly- or doubly-quoted -cmdline argument
+  # Singly-quoted arguments were reported for versions 5.2-4 and 6.0-4.
+  # Doubly-quoted arguments were reported for "PGF90/x86 Linux/x86 5.0-2".
+  *-cmdline\ * | *-ignore\ * | *-def\ *)
+    ac_fc_v_output=`echo $ac_fc_v_output | sed "\
+	s/-cmdline  *'[^']*'/ /g; s/-cmdline  *\"[^\"]*\"/ /g
+	s/-ignore  *'[^']*'/ /g; s/-ignore  *\"[^\"]*\"/ /g
+	s/-def  *'[^']*'/ /g; s/-def  *\"[^\"]*\"/ /g"` ;;
+
+  # If we are using fort77 (the f2c wrapper) then filter output and delete quotes.
+  *fort77*f2c*gcc*)
+    ac_fc_v_output=`echo "$ac_fc_v_output" | sed -n '
+        /:[	 ]\+Running[	 ]\{1,\}"gcc"/{
+          /"-c"/d
+          /[.]c"*/d
+          s/^.*"gcc"/"gcc"/
+          s/"//gp
+        }'` ;;
+
+  # If we are using Cray Fortran then delete quotes.
+  *cft90*)
+    ac_fc_v_output=`echo $ac_fc_v_output | sed 's/"//g'` ;;
+esac
+
+
+
+ac_cv_fc_libs=
+
+# Save positional arguments (if any)
+ac_save_positional="$@"
+
+set X $ac_fc_v_output
+while test $# != 1; do
+  shift
+  ac_arg=$1
+  case $ac_arg in
+	[\\/]*.a | ?:[\\/]*.a)
+	    ac_exists=false
+  for ac_i in $ac_cv_fc_libs; do
+    if test x"$ac_arg" = x"$ac_i"; then
+      ac_exists=true
+      break
+    fi
+  done
+
+  if test x"$ac_exists" = xtrue; then :
+
+else
+  ac_cv_fc_libs="$ac_cv_fc_libs $ac_arg"
+fi
+	  ;;
+	-bI:*)
+	    ac_exists=false
+  for ac_i in $ac_cv_fc_libs; do
+    if test x"$ac_arg" = x"$ac_i"; then
+      ac_exists=true
+      break
+    fi
+  done
+
+  if test x"$ac_exists" = xtrue; then :
+
+else
+  if test "$ac_compiler_gnu" = yes; then
+  for ac_link_opt in $ac_arg; do
+    ac_cv_fc_libs="$ac_cv_fc_libs -Xlinker $ac_link_opt"
+  done
+else
+  ac_cv_fc_libs="$ac_cv_fc_libs $ac_arg"
+fi
+fi
+	  ;;
+	  # Ignore these flags.
+	-lang* | -lcrt*.o | -lc | -lgcc* | -lSystem | -libmil | -little \
+	  |-LANG:=* | -LIST:* | -LNO:* | -link)
+	  ;;
+	-lkernel32)
+	  case $host_os in
+	  *cygwin*) ;;
+	  *) ac_cv_fc_libs="$ac_cv_fc_libs $ac_arg"
+	    ;;
+	  esac
+	  ;;
+	-[LRuYz])
+	  # These flags, when seen by themselves, take an argument.
+	  # We remove the space between option and argument and re-iterate
+	  # unless we find an empty arg or a new option (starting with -)
+	  case $2 in
+	     "" | -*);;
+	     *)
+		ac_arg="$ac_arg$2"
+		shift; shift
+		set X $ac_arg "$@"
+		;;
+	  esac
+	  ;;
+	-YP,*)
+	  for ac_j in `$as_echo "$ac_arg" | sed -e 's/-YP,/-L/;s/:/ -L/g'`; do
+	      ac_exists=false
+  for ac_i in $ac_cv_fc_libs; do
+    if test x"$ac_j" = x"$ac_i"; then
+      ac_exists=true
+      break
+    fi
+  done
+
+  if test x"$ac_exists" = xtrue; then :
+
+else
+  ac_arg="$ac_arg $ac_j"
+			       ac_cv_fc_libs="$ac_cv_fc_libs $ac_j"
+fi
+	  done
+	  ;;
+	-[lLR]*)
+	    ac_exists=false
+  for ac_i in $ac_cv_fc_libs; do
+    if test x"$ac_arg" = x"$ac_i"; then
+      ac_exists=true
+      break
+    fi
+  done
+
+  if test x"$ac_exists" = xtrue; then :
+
+else
+  ac_cv_fc_libs="$ac_cv_fc_libs $ac_arg"
+fi
+	  ;;
+	-zallextract*| -zdefaultextract)
+	  ac_cv_fc_libs="$ac_cv_fc_libs $ac_arg"
+	  ;;
+	  # Ignore everything else.
+  esac
+done
+# restore positional arguments
+set X $ac_save_positional; shift
+
+# We only consider "LD_RUN_PATH" on Solaris systems.  If this is seen,
+# then we insist that the "run path" must be an absolute path (i.e. it
+# must begin with a "/").
+case `(uname -sr) 2>/dev/null` in
+   "SunOS 5"*)
+      ac_ld_run_path=`$as_echo "$ac_fc_v_output" |
+			sed -n 's,^.*LD_RUN_PATH *= *\(/[^ ]*\).*$,-R\1,p'`
+      test "x$ac_ld_run_path" != x &&
+	if test "$ac_compiler_gnu" = yes; then
+  for ac_link_opt in $ac_ld_run_path; do
+    ac_cv_fc_libs="$ac_cv_fc_libs -Xlinker $ac_link_opt"
+  done
+else
+  ac_cv_fc_libs="$ac_cv_fc_libs $ac_ld_run_path"
+fi
+      ;;
+esac
+fi # test "x$[]_AC_LANG_PREFIX[]LIBS" = "x"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_libs" >&5
+$as_echo "$ac_cv_fc_libs" >&6; }
+FCLIBS="$ac_cv_fc_libs"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+   if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: before FCLIBS=$FCLIBS" >&5
+$as_echo "$as_me: DEBUG: before FCLIBS=$FCLIBS" >&6;}
+          fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC links with FCLIBS found by autoconf" >&5
+$as_echo_n "checking whether $CC links with FCLIBS found by autoconf... " >&6; }
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+# Create a simple C program for the tests.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+int a;
+  ;
+  return 0;
+}
+
+_ACEOF
+# Try to link a C program with all of these libraries
+saved_LIBS="$LIBS"
+LIBS="$FCLIBS $saved_LIBS"
+if ac_fn_c_try_link "$LINENO"; then :
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for which libraries can be used" >&5
+$as_echo_n "checking for which libraries can be used... " >&6; }
+    pac_ldirs=""
+    pac_libs=""
+    pac_other=""
+    for name in $FCLIBS ; do
+        case $name in
+        -l*) pac_libs="$pac_libs $name"   ;;
+        -L*) pac_ldirs="$pac_ldirs $name" ;;
+          *) pac_other="$pac_other $name" ;;
+        esac
+    done
+    keep_libs=""
+    for name in $pac_libs ; do
+        LIBS="$saved_LIBS $pac_ldirs $pac_other $name"
+        if ac_fn_c_try_link "$LINENO"; then :
+
+            keep_libs="$keep_libs $name"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+    done
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $keep_libs" >&5
+$as_echo "$keep_libs" >&6; }
+    FCLIBS="$pac_ldirs $pac_other $keep_libs"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+LIBS="$saved_LIBS"
+rm -f conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+      if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: after FCLIBS=$FCLIBS" >&5
+$as_echo "$as_me: DEBUG: after FCLIBS=$FCLIBS" >&6;}
+          fi
+
+
+   FLIBS="$FCLIBS"
+   F90LIBS="$FCLIBS"
+
+      F90FLAGS=${FCFLAGS}
+
+
+   ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+   cat > conftest.$ac_ext <<_ACEOF
+      program main
+      call MPI_Comm_rank
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  valid_mpif90=yes
+else
+  valid_mpif90=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if mpi.mod is valid" >&5
+$as_echo_n "checking if mpi.mod is valid... " >&6; }
+   cat > conftest.$ac_ext <<_ACEOF
+      program main
+        use mpi
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  valid_mpi_mod=yes
+else
+  valid_mpi_mod=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $valid_mpi_mod" >&5
+$as_echo "$valid_mpi_mod" >&6; }
+   ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+   if test "x${valid_mpif90}" = xno && test "x${enable_fortran}" = xyes ; then
+      as_fn_error $? "
+         ------------------------------------------------------------
+           Invalid MPI Fortran 90 compiler specified: \"${MPIF90}\"
+           A working MPI compiler is required. Please specify the
+           location of one either with the MPIF90 environment
+           variable or the --with-mpi configure flag.
+         ------------------------------------------------------------" "$LINENO" 5
+   fi
+   if test "x${valid_mpi_mod}" = xno && test "x${enable_fortran}" = xyes ; then
+      as_fn_error $? "
+         ------------------------------------------------------------
+           Invalid MPI Fortran module. The mpi.mod file in the include path
+           may not be generated by the same Fortran compiler used to build
+           \"${MPIF90}\". Please make sure the same Fortran compiler is used.
+         ------------------------------------------------------------" "$LINENO" 5
+   fi
+fi
+
+F77_SUPPORT_FREEFORM=no
+if test "x${MPIF77}" != x ; then
+   F77=${MPIF77}
+   ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn nagfor
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_F77+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$F77"; then
+  ac_cv_prog_F77="$F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+F77=$ac_cv_prog_F77
+if test -n "$F77"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $F77" >&5
+$as_echo "$F77" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$F77" && break
+  done
+fi
+if test -z "$F77"; then
+  ac_ct_F77=$F77
+  for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn nagfor
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_F77+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_F77"; then
+  ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_F77="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_F77=$ac_cv_prog_ac_ct_F77
+if test -n "$ac_ct_F77"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_F77" >&5
+$as_echo "$ac_ct_F77" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_F77" && break
+done
+
+  if test "x$ac_ct_F77" = x; then
+    F77=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    F77=$ac_ct_F77
+  fi
+fi
+
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran 77 compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+rm -f a.out
+
+# If we don't use `.F' as extension, the preprocessor is not run on the
+# input file.  (Note that this only needs to work for GNU compilers.)
+ac_save_ext=$ac_ext
+ac_ext=F
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU Fortran 77 compiler" >&5
+$as_echo_n "checking whether we are using the GNU Fortran 77 compiler... " >&6; }
+if ${ac_cv_f77_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+#ifndef __GNUC__
+       choke me
+#endif
+
+      end
+_ACEOF
+if ac_fn_f77_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_f77_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_f77_compiler_gnu" >&5
+$as_echo "$ac_cv_f77_compiler_gnu" >&6; }
+ac_ext=$ac_save_ext
+ac_test_FFLAGS=${FFLAGS+set}
+ac_save_FFLAGS=$FFLAGS
+FFLAGS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $F77 accepts -g" >&5
+$as_echo_n "checking whether $F77 accepts -g... " >&6; }
+if ${ac_cv_prog_f77_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  FFLAGS=-g
+cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+if ac_fn_f77_try_compile "$LINENO"; then :
+  ac_cv_prog_f77_g=yes
+else
+  ac_cv_prog_f77_g=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_f77_g" >&5
+$as_echo "$ac_cv_prog_f77_g" >&6; }
+if test "$ac_test_FFLAGS" = set; then
+  FFLAGS=$ac_save_FFLAGS
+elif test $ac_cv_prog_f77_g = yes; then
+  if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+    FFLAGS="-g -O2"
+  else
+    FFLAGS="-g"
+  fi
+else
+  if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+    FFLAGS="-O2"
+  else
+    FFLAGS=
+  fi
+fi
+
+if test $ac_compiler_gnu = yes; then
+  G77=yes
+else
+  G77=
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to get verbose linking output from $F77" >&5
+$as_echo_n "checking how to get verbose linking output from $F77... " >&6; }
+if ${ac_cv_prog_f77_v+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+if ac_fn_f77_try_compile "$LINENO"; then :
+  ac_cv_prog_f77_v=
+# Try some options frequently used verbose output
+for ac_verb in -v -verbose -V -\#\#\# --verbose; do
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+
+# Compile and link our simple test program by passing a flag (argument
+# 1 to this macro) to the Fortran compiler in order to get
+# "verbose" output that we can then parse for the Fortran linker
+# flags.
+ac_save_FFLAGS=$FFLAGS
+FFLAGS="$FFLAGS $ac_verb"
+eval "set x $ac_link"
+shift
+$as_echo "$as_me:${as_lineno-$LINENO}: $*" >&5
+# gfortran 4.3 outputs lines setting COLLECT_GCC_OPTIONS, COMPILER_PATH,
+# LIBRARY_PATH; skip all such settings.
+ac_f77_v_output=`eval $ac_link 5>&1 2>&1 |
+  sed '/^Driving:/d; /^Configured with:/d;
+      '"/^[_$as_cr_Letters][_$as_cr_alnum]*=/d"`
+$as_echo "$ac_f77_v_output" >&5
+FFLAGS=$ac_save_FFLAGS
+
+rm -rf conftest*
+
+# On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where
+# /foo, /bar, and /baz are search directories for the Fortran linker.
+# Here, we change these into -L/foo -L/bar -L/baz (and put it first):
+ac_f77_v_output="`echo $ac_f77_v_output |
+	grep 'LPATH is:' |
+	sed 's|.*LPATH is\(: *[^ ]*\).*|\1|;s|: */| -L/|g'` $ac_f77_v_output"
+
+# FIXME: we keep getting bitten by quoted arguments; a more general fix
+#        that detects unbalanced quotes in FLIBS should be implemented
+#        and (ugh) tested at some point.
+case $ac_f77_v_output in
+  # With xlf replace commas with spaces,
+  # and remove "-link" and closing parenthesis.
+  *xlfentry*)
+    ac_f77_v_output=`echo $ac_f77_v_output |
+      sed '
+        s/,/ /g
+        s/ -link / /g
+        s/) *$//
+      '
+    ` ;;
+
+  # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted
+  # $LIBS confuse us, and the libraries appear later in the output anyway).
+  *mGLOB_options_string*)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"-mGLOB[^"]*"/ /g'` ;;
+
+  # Portland Group compiler has singly- or doubly-quoted -cmdline argument
+  # Singly-quoted arguments were reported for versions 5.2-4 and 6.0-4.
+  # Doubly-quoted arguments were reported for "PGF90/x86 Linux/x86 5.0-2".
+  *-cmdline\ * | *-ignore\ * | *-def\ *)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed "\
+	s/-cmdline  *'[^']*'/ /g; s/-cmdline  *\"[^\"]*\"/ /g
+	s/-ignore  *'[^']*'/ /g; s/-ignore  *\"[^\"]*\"/ /g
+	s/-def  *'[^']*'/ /g; s/-def  *\"[^\"]*\"/ /g"` ;;
+
+  # If we are using fort77 (the f2c wrapper) then filter output and delete quotes.
+  *fort77*f2c*gcc*)
+    ac_f77_v_output=`echo "$ac_f77_v_output" | sed -n '
+        /:[	 ]\+Running[	 ]\{1,\}"gcc"/{
+          /"-c"/d
+          /[.]c"*/d
+          s/^.*"gcc"/"gcc"/
+          s/"//gp
+        }'` ;;
+
+  # If we are using Cray Fortran then delete quotes.
+  *cft90*)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"//g'` ;;
+esac
+
+
+  # look for -l* and *.a constructs in the output
+  for ac_arg in $ac_f77_v_output; do
+     case $ac_arg in
+	[\\/]*.a | ?:[\\/]*.a | -[lLRu]*)
+	  ac_cv_prog_f77_v=$ac_verb
+	  break 2 ;;
+     esac
+  done
+done
+if test -z "$ac_cv_prog_f77_v"; then
+   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine how to obtain linking information from $F77" >&5
+$as_echo "$as_me: WARNING: cannot determine how to obtain linking information from $F77" >&2;}
+fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: compilation failed" >&5
+$as_echo "$as_me: WARNING: compilation failed" >&2;}
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_f77_v" >&5
+$as_echo "$ac_cv_prog_f77_v" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran 77 libraries of $F77" >&5
+$as_echo_n "checking for Fortran 77 libraries of $F77... " >&6; }
+if ${ac_cv_f77_libs+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$FLIBS" != "x"; then
+  ac_cv_f77_libs="$FLIBS" # Let the user override the test.
+else
+
+cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+
+# Compile and link our simple test program by passing a flag (argument
+# 1 to this macro) to the Fortran compiler in order to get
+# "verbose" output that we can then parse for the Fortran linker
+# flags.
+ac_save_FFLAGS=$FFLAGS
+FFLAGS="$FFLAGS $ac_cv_prog_f77_v"
+eval "set x $ac_link"
+shift
+$as_echo "$as_me:${as_lineno-$LINENO}: $*" >&5
+# gfortran 4.3 outputs lines setting COLLECT_GCC_OPTIONS, COMPILER_PATH,
+# LIBRARY_PATH; skip all such settings.
+ac_f77_v_output=`eval $ac_link 5>&1 2>&1 |
+  sed '/^Driving:/d; /^Configured with:/d;
+      '"/^[_$as_cr_Letters][_$as_cr_alnum]*=/d"`
+$as_echo "$ac_f77_v_output" >&5
+FFLAGS=$ac_save_FFLAGS
+
+rm -rf conftest*
+
+# On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where
+# /foo, /bar, and /baz are search directories for the Fortran linker.
+# Here, we change these into -L/foo -L/bar -L/baz (and put it first):
+ac_f77_v_output="`echo $ac_f77_v_output |
+	grep 'LPATH is:' |
+	sed 's|.*LPATH is\(: *[^ ]*\).*|\1|;s|: */| -L/|g'` $ac_f77_v_output"
+
+# FIXME: we keep getting bitten by quoted arguments; a more general fix
+#        that detects unbalanced quotes in FLIBS should be implemented
+#        and (ugh) tested at some point.
+case $ac_f77_v_output in
+  # With xlf replace commas with spaces,
+  # and remove "-link" and closing parenthesis.
+  *xlfentry*)
+    ac_f77_v_output=`echo $ac_f77_v_output |
+      sed '
+        s/,/ /g
+        s/ -link / /g
+        s/) *$//
+      '
+    ` ;;
+
+  # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted
+  # $LIBS confuse us, and the libraries appear later in the output anyway).
+  *mGLOB_options_string*)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"-mGLOB[^"]*"/ /g'` ;;
+
+  # Portland Group compiler has singly- or doubly-quoted -cmdline argument
+  # Singly-quoted arguments were reported for versions 5.2-4 and 6.0-4.
+  # Doubly-quoted arguments were reported for "PGF90/x86 Linux/x86 5.0-2".
+  *-cmdline\ * | *-ignore\ * | *-def\ *)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed "\
+	s/-cmdline  *'[^']*'/ /g; s/-cmdline  *\"[^\"]*\"/ /g
+	s/-ignore  *'[^']*'/ /g; s/-ignore  *\"[^\"]*\"/ /g
+	s/-def  *'[^']*'/ /g; s/-def  *\"[^\"]*\"/ /g"` ;;
+
+  # If we are using fort77 (the f2c wrapper) then filter output and delete quotes.
+  *fort77*f2c*gcc*)
+    ac_f77_v_output=`echo "$ac_f77_v_output" | sed -n '
+        /:[	 ]\+Running[	 ]\{1,\}"gcc"/{
+          /"-c"/d
+          /[.]c"*/d
+          s/^.*"gcc"/"gcc"/
+          s/"//gp
+        }'` ;;
+
+  # If we are using Cray Fortran then delete quotes.
+  *cft90*)
+    ac_f77_v_output=`echo $ac_f77_v_output | sed 's/"//g'` ;;
+esac
+
+
+
+ac_cv_f77_libs=
+
+# Save positional arguments (if any)
+ac_save_positional="$@"
+
+set X $ac_f77_v_output
+while test $# != 1; do
+  shift
+  ac_arg=$1
+  case $ac_arg in
+	[\\/]*.a | ?:[\\/]*.a)
+	    ac_exists=false
+  for ac_i in $ac_cv_f77_libs; do
+    if test x"$ac_arg" = x"$ac_i"; then
+      ac_exists=true
+      break
+    fi
+  done
+
+  if test x"$ac_exists" = xtrue; then :
+
+else
+  ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+fi
+	  ;;
+	-bI:*)
+	    ac_exists=false
+  for ac_i in $ac_cv_f77_libs; do
+    if test x"$ac_arg" = x"$ac_i"; then
+      ac_exists=true
+      break
+    fi
+  done
+
+  if test x"$ac_exists" = xtrue; then :
+
+else
+  if test "$ac_compiler_gnu" = yes; then
+  for ac_link_opt in $ac_arg; do
+    ac_cv_f77_libs="$ac_cv_f77_libs -Xlinker $ac_link_opt"
+  done
+else
+  ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+fi
+fi
+	  ;;
+	  # Ignore these flags.
+	-lang* | -lcrt*.o | -lc | -lgcc* | -lSystem | -libmil | -little \
+	  |-LANG:=* | -LIST:* | -LNO:* | -link)
+	  ;;
+	-lkernel32)
+	  case $host_os in
+	  *cygwin*) ;;
+	  *) ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+	    ;;
+	  esac
+	  ;;
+	-[LRuYz])
+	  # These flags, when seen by themselves, take an argument.
+	  # We remove the space between option and argument and re-iterate
+	  # unless we find an empty arg or a new option (starting with -)
+	  case $2 in
+	     "" | -*);;
+	     *)
+		ac_arg="$ac_arg$2"
+		shift; shift
+		set X $ac_arg "$@"
+		;;
+	  esac
+	  ;;
+	-YP,*)
+	  for ac_j in `$as_echo "$ac_arg" | sed -e 's/-YP,/-L/;s/:/ -L/g'`; do
+	      ac_exists=false
+  for ac_i in $ac_cv_f77_libs; do
+    if test x"$ac_j" = x"$ac_i"; then
+      ac_exists=true
+      break
+    fi
+  done
+
+  if test x"$ac_exists" = xtrue; then :
+
+else
+  ac_arg="$ac_arg $ac_j"
+			       ac_cv_f77_libs="$ac_cv_f77_libs $ac_j"
+fi
+	  done
+	  ;;
+	-[lLR]*)
+	    ac_exists=false
+  for ac_i in $ac_cv_f77_libs; do
+    if test x"$ac_arg" = x"$ac_i"; then
+      ac_exists=true
+      break
+    fi
+  done
+
+  if test x"$ac_exists" = xtrue; then :
+
+else
+  ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+fi
+	  ;;
+	-zallextract*| -zdefaultextract)
+	  ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg"
+	  ;;
+	  # Ignore everything else.
+  esac
+done
+# restore positional arguments
+set X $ac_save_positional; shift
+
+# We only consider "LD_RUN_PATH" on Solaris systems.  If this is seen,
+# then we insist that the "run path" must be an absolute path (i.e. it
+# must begin with a "/").
+case `(uname -sr) 2>/dev/null` in
+   "SunOS 5"*)
+      ac_ld_run_path=`$as_echo "$ac_f77_v_output" |
+			sed -n 's,^.*LD_RUN_PATH *= *\(/[^ ]*\).*$,-R\1,p'`
+      test "x$ac_ld_run_path" != x &&
+	if test "$ac_compiler_gnu" = yes; then
+  for ac_link_opt in $ac_ld_run_path; do
+    ac_cv_f77_libs="$ac_cv_f77_libs -Xlinker $ac_link_opt"
+  done
+else
+  ac_cv_f77_libs="$ac_cv_f77_libs $ac_ld_run_path"
+fi
+      ;;
+esac
+fi # test "x$[]_AC_LANG_PREFIX[]LIBS" = "x"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_f77_libs" >&5
+$as_echo "$ac_cv_f77_libs" >&6; }
+FLIBS="$ac_cv_f77_libs"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+      F77FLAGS=${FFLAGS}
+
+
+      FC_saved=${FC}
+   FC=${F77}
+   ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran flag needed to accept free-form source" >&5
+$as_echo_n "checking for Fortran flag needed to accept free-form source... " >&6; }
+if ${ac_cv_fc_freeform+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_fc_freeform=unknown
+ac_fc_freeform_FCFLAGS_save=$FCFLAGS
+for ac_flag in none -ffree-form -FR -free -qfree=f90 -qfree -Mfree -Mfreeform \
+	       -freeform "-f free" -8 +source=free -nfix --nfix -Free
+do
+  test "x$ac_flag" != xnone && FCFLAGS="$ac_fc_freeform_FCFLAGS_save $ac_flag"
+  cat > conftest.$ac_ext <<_ACEOF
+
+  program freeform
+       ! FIXME: how to best confuse non-freeform compilers?
+       print *, 'Hello ', &
+          'world.'
+       end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_cv_fc_freeform=$ac_flag; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+${RM} -f conftest.err conftest.$ac_objext conftest.$ac_ext
+FCFLAGS=$ac_fc_freeform_FCFLAGS_save
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_freeform" >&5
+$as_echo "$ac_cv_fc_freeform" >&6; }
+if test "x$ac_cv_fc_freeform" = xunknown; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Fortran $FC does not accept free-form source" >&5
+$as_echo "$as_me: WARNING: Fortran $FC does not accept free-form source" >&2;}
+else
+          if test "x$ac_cv_fc_freeform" = xnone; then
+     ac_cv_fc_freeform=
+  fi
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+   if test "x${ac_cv_fc_freeform}" != xunknown ; then
+      F77_SUPPORT_FREEFORM=yes
+      FFREEFORMFLAG=${ac_cv_fc_freeform}
+   fi
+   if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: FC=$FC F90FLAGS=$F90FLAGS FFREEFORMFLAG=$FFREEFORMFLAG" >&5
+$as_echo "$as_me: DEBUG: FC=$FC F90FLAGS=$F90FLAGS FFREEFORMFLAG=$FFREEFORMFLAG" >&6;}
+          fi
+
+
+
+   FC=${FC_saved}
+
+   ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+   cat > conftest.$ac_ext <<_ACEOF
+      program main
+      call MPI_Comm_rank
+      end
+_ACEOF
+if ac_fn_f77_try_compile "$LINENO"; then :
+  valid_mpif77=yes
+else
+  valid_mpif77=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+   if test "x${valid_mpif77}" = xno && test "x${enable_fortran}" = xyes ; then
+      as_fn_error $? "
+         ------------------------------------------------------------
+           Invalid MPI Fortran 77 compiler specified: \"${MPIF77}\"
+           A working MPI compiler is required. Please specify the
+           location of one either with the MPIF77 environment
+           variable or the --with-mpi configure flag
+         ------------------------------------------------------------" "$LINENO" 5
+   fi
+fi
+
+
+if test "x${enable_fortran}" = xauto ; then
+   if test "x${valid_mpif77}" = xyes && test "x${valid_mpif90}" = xyes ; then
+      enable_fortran=yes
+   else
+      enable_fortran=no
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+         ------------------------------------------------------------
+           Either MPI Fortran 77 or 90 compiler is not working:
+               \"MPIF77 = ${MPIF77}\"
+               \"MPIF90 = ${MPIF90}\"
+           Disable Fortran feature ...
+         ------------------------------------------------------------" >&5
+$as_echo "$as_me: WARNING:
+         ------------------------------------------------------------
+           Either MPI Fortran 77 or 90 compiler is not working:
+               \"MPIF77 = ${MPIF77}\"
+               \"MPIF90 = ${MPIF90}\"
+           Disable Fortran feature ...
+         ------------------------------------------------------------" >&2;}
+   fi
+fi
+
+if test "x${enable_fortran}" = xyes ; then
+                     ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran flag to compile preprocessed .f files" >&5
+$as_echo_n "checking for Fortran flag to compile preprocessed .f files... " >&6; }
+if ${ac_cv_fc_pp_srcext_f+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=f
+FCFLAGS_SRCEXT_save=$FCFLAGS_SRCEXT
+FCFLAGS_SRCEXT=
+ac_fcflags_pp_srcext_save=$ac_fcflags_srcext
+ac_fcflags_srcext=
+ac_cv_fc_pp_srcext_f=unknown
+case $ac_ext in #(
+  [fF]77) ac_try=f77-cpp-input;; #(
+  [fF]) ac_try=f77-cpp-input;; #(
+  *) ac_try=f95-cpp-input;;
+esac
+for ac_flag in none -ftpp -fpp -Tf "-fpp -Tf" -xpp=fpp -Mpreprocess "-e Z" \
+               -cpp -xpp=cpp -qsuffix=cpp=f "-x $ac_try" +cpp -Cpp; do
+  test "x$ac_flag" != xnone && FCFLAGS_SRCEXT="$ac_flag" && ac_fcflags_srcext="$ac_flag"
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+#if 0
+#include <ac_nonexistent.h>
+      choke me
+#endif
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+#if 1
+#include <ac_nonexistent.h>
+      choke me
+#endif
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+
+else
+  ac_cv_fc_pp_srcext_f=$ac_flag; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+${RM} -f conftest.$ac_objext conftest.f
+FCFLAGS_SRCEXT=$FCFLAGS_SRCEXT_save
+ac_fcflags_srcext=$ac_fcflags_pp_srcext_save
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_pp_srcext_f" >&5
+$as_echo "$ac_cv_fc_pp_srcext_f" >&6; }
+if test "x$ac_cv_fc_pp_srcext_f" = xunknown; then
+  as_fn_error $? "Fortran could not compile preprocessed .f files" "$LINENO" 5
+else
+  ac_fc_srcext=f
+  if test "x$ac_cv_fc_pp_srcext_f" = xnone; then
+    FCFLAGS_SRCEXT=""
+    ac_cv_fc_pp_srcext_f=""
+      else
+    FCFLAGS_SRCEXT=$ac_cv_fc_pp_srcext_f
+      fi
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+       ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran flag to compile preprocessed .F files" >&5
+$as_echo_n "checking for Fortran flag to compile preprocessed .F files... " >&6; }
+if ${ac_cv_fc_pp_srcext_F+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=F
+FCFLAGS_SRCEXT_save=$FCFLAGS_SRCEXT
+FCFLAGS_SRCEXT=
+ac_fcflags_pp_srcext_save=$ac_fcflags_srcext
+ac_fcflags_srcext=
+ac_cv_fc_pp_srcext_F=unknown
+case $ac_ext in #(
+  [fF]77) ac_try=f77-cpp-input;; #(
+  [fF]) ac_try=f77-cpp-input;; #(
+  *) ac_try=f95-cpp-input;;
+esac
+for ac_flag in none -ftpp -fpp -Tf "-fpp -Tf" -xpp=fpp -Mpreprocess "-e Z" \
+               -cpp -xpp=cpp -qsuffix=cpp=F "-x $ac_try" +cpp -Cpp; do
+  test "x$ac_flag" != xnone && FCFLAGS_SRCEXT="$ac_flag" && ac_fcflags_srcext="$ac_flag"
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+#if 0
+#include <ac_nonexistent.h>
+      choke me
+#endif
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+#if 1
+#include <ac_nonexistent.h>
+      choke me
+#endif
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+
+else
+  ac_cv_fc_pp_srcext_F=$ac_flag; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+${RM} -f conftest.$ac_objext conftest.F
+FCFLAGS_SRCEXT=$FCFLAGS_SRCEXT_save
+ac_fcflags_srcext=$ac_fcflags_pp_srcext_save
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_pp_srcext_F" >&5
+$as_echo "$ac_cv_fc_pp_srcext_F" >&6; }
+if test "x$ac_cv_fc_pp_srcext_F" = xunknown; then
+  as_fn_error $? "Fortran could not compile preprocessed .F files" "$LINENO" 5
+else
+  ac_fc_srcext=F
+  if test "x$ac_cv_fc_pp_srcext_F" = xnone; then
+    FCFLAGS_SRCEXT=""
+    ac_cv_fc_pp_srcext_F=""
+      else
+    FCFLAGS_SRCEXT=$ac_cv_fc_pp_srcext_F
+      fi
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+       ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran flag to compile preprocessed .f90 files" >&5
+$as_echo_n "checking for Fortran flag to compile preprocessed .f90 files... " >&6; }
+if ${ac_cv_fc_pp_srcext_f90+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=f90
+FCFLAGS_SRCEXT_save=$FCFLAGS_SRCEXT
+FCFLAGS_SRCEXT=
+ac_fcflags_pp_srcext_save=$ac_fcflags_srcext
+ac_fcflags_srcext=
+ac_cv_fc_pp_srcext_f90=unknown
+case $ac_ext in #(
+  [fF]77) ac_try=f77-cpp-input;; #(
+  [fF]) ac_try=f77-cpp-input;; #(
+  *) ac_try=f95-cpp-input;;
+esac
+for ac_flag in none -ftpp -fpp -Tf "-fpp -Tf" -xpp=fpp -Mpreprocess "-e Z" \
+               -cpp -xpp=cpp -qsuffix=cpp=f90 "-x $ac_try" +cpp -Cpp; do
+  test "x$ac_flag" != xnone && FCFLAGS_SRCEXT="$ac_flag" && ac_fcflags_srcext="$ac_flag"
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+#if 0
+#include <ac_nonexistent.h>
+      choke me
+#endif
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+#if 1
+#include <ac_nonexistent.h>
+      choke me
+#endif
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+
+else
+  ac_cv_fc_pp_srcext_f90=$ac_flag; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+${RM} -f conftest.$ac_objext conftest.f90
+FCFLAGS_SRCEXT=$FCFLAGS_SRCEXT_save
+ac_fcflags_srcext=$ac_fcflags_pp_srcext_save
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_pp_srcext_f90" >&5
+$as_echo "$ac_cv_fc_pp_srcext_f90" >&6; }
+if test "x$ac_cv_fc_pp_srcext_f90" = xunknown; then
+  as_fn_error $? "Fortran could not compile preprocessed .f90 files" "$LINENO" 5
+else
+  ac_fc_srcext=f90
+  if test "x$ac_cv_fc_pp_srcext_f90" = xnone; then
+    FCFLAGS_SRCEXT=""
+    ac_cv_fc_pp_srcext_f90=""
+      else
+    FCFLAGS_SRCEXT=$ac_cv_fc_pp_srcext_f90
+      fi
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+     ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran flag to compile preprocessed .F90 files" >&5
+$as_echo_n "checking for Fortran flag to compile preprocessed .F90 files... " >&6; }
+if ${ac_cv_fc_pp_srcext_F90+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=F90
+FCFLAGS_SRCEXT_save=$FCFLAGS_SRCEXT
+FCFLAGS_SRCEXT=
+ac_fcflags_pp_srcext_save=$ac_fcflags_srcext
+ac_fcflags_srcext=
+ac_cv_fc_pp_srcext_F90=unknown
+case $ac_ext in #(
+  [fF]77) ac_try=f77-cpp-input;; #(
+  [fF]) ac_try=f77-cpp-input;; #(
+  *) ac_try=f95-cpp-input;;
+esac
+for ac_flag in none -ftpp -fpp -Tf "-fpp -Tf" -xpp=fpp -Mpreprocess "-e Z" \
+               -cpp -xpp=cpp -qsuffix=cpp=F90 "-x $ac_try" +cpp -Cpp; do
+  test "x$ac_flag" != xnone && FCFLAGS_SRCEXT="$ac_flag" && ac_fcflags_srcext="$ac_flag"
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+#if 0
+#include <ac_nonexistent.h>
+      choke me
+#endif
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+#if 1
+#include <ac_nonexistent.h>
+      choke me
+#endif
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+
+else
+  ac_cv_fc_pp_srcext_F90=$ac_flag; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+${RM} -f conftest.$ac_objext conftest.F90
+FCFLAGS_SRCEXT=$FCFLAGS_SRCEXT_save
+ac_fcflags_srcext=$ac_fcflags_pp_srcext_save
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_pp_srcext_F90" >&5
+$as_echo "$ac_cv_fc_pp_srcext_F90" >&6; }
+if test "x$ac_cv_fc_pp_srcext_F90" = xunknown; then
+  as_fn_error $? "Fortran could not compile preprocessed .F90 files" "$LINENO" 5
+else
+  ac_fc_srcext=F90
+  if test "x$ac_cv_fc_pp_srcext_F90" = xnone; then
+    FCFLAGS_SRCEXT=""
+    ac_cv_fc_pp_srcext_F90=""
+      else
+    FCFLAGS_SRCEXT=$ac_cv_fc_pp_srcext_F90
+      fi
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+   F77PPFLAGS_f=${ac_cv_fc_pp_srcext_f}
+   F77PPFLAGS_F=${ac_cv_fc_pp_srcext_F}
+   F90PPFLAGS_f90=${ac_cv_fc_pp_srcext_f90}
+   F90PPFLAGS_F90=${ac_cv_fc_pp_srcext_F90}
+
+
+
+
+
+   FPPFLAGS=${FPPFLAGS-}
+
+
+
+      ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+ac_fc_pp_define_srcext_save=$ac_fc_srcext
+ac_ext_saved=$ac_ext
+ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran flag to compile preprocessed .F files" >&5
+$as_echo_n "checking for Fortran flag to compile preprocessed .F files... " >&6; }
+if ${ac_cv_fc_pp_srcext_F+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=F
+FCFLAGS_SRCEXT_save=$FCFLAGS_SRCEXT
+FCFLAGS_SRCEXT=
+ac_fcflags_pp_srcext_save=$ac_fcflags_srcext
+ac_fcflags_srcext=
+ac_cv_fc_pp_srcext_F=unknown
+case $ac_ext in #(
+  [fF]77) ac_try=f77-cpp-input;; #(
+  [fF]) ac_try=f77-cpp-input;; #(
+  *) ac_try=f95-cpp-input;;
+esac
+for ac_flag in none -ftpp -fpp -Tf "-fpp -Tf" -xpp=fpp -Mpreprocess "-e Z" \
+               -cpp -xpp=cpp -qsuffix=cpp=F "-x $ac_try" +cpp -Cpp; do
+  test "x$ac_flag" != xnone && FCFLAGS_SRCEXT="$ac_flag" && ac_fcflags_srcext="$ac_flag"
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+#if 0
+#include <ac_nonexistent.h>
+      choke me
+#endif
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+#if 1
+#include <ac_nonexistent.h>
+      choke me
+#endif
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+
+else
+  ac_cv_fc_pp_srcext_F=$ac_flag; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+${RM} -f conftest.$ac_objext conftest.F
+FCFLAGS_SRCEXT=$FCFLAGS_SRCEXT_save
+ac_fcflags_srcext=$ac_fcflags_pp_srcext_save
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_pp_srcext_F" >&5
+$as_echo "$ac_cv_fc_pp_srcext_F" >&6; }
+if test "x$ac_cv_fc_pp_srcext_F" = xunknown; then
+  as_fn_error $? "Fortran could not compile preprocessed .F files" "$LINENO" 5
+else
+  ac_fc_srcext=F
+  if test "x$ac_cv_fc_pp_srcext_F" = xnone; then
+    FCFLAGS_SRCEXT=""
+    ac_cv_fc_pp_srcext_F=""
+      else
+    FCFLAGS_SRCEXT=$ac_cv_fc_pp_srcext_F
+      fi
+
+fi
+ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+ac_ext=F
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to define symbols for preprocessed Fortran" >&5
+$as_echo_n "checking how to define symbols for preprocessed Fortran... " >&6; }
+if ${ac_cv_fc_pp_define+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_fc_pp_define_srcext_save=$ac_fc_srcext
+ac_cv_fc_pp_define=unknown
+ac_fc_pp_define_FCFLAGS_save=$FCFLAGS
+for ac_flag in -D -WF,-D -Wp,-D -Wc,-D
+do
+  FCFLAGS="$ac_fc_pp_define_FCFLAGS_save ${ac_flag}FOOBAR ${ac_flag}ZORK=42"
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+#ifndef FOOBAR
+      choke me
+#endif
+#if ZORK != 42
+      choke me
+#endif
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_cv_fc_pp_define=$ac_flag
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test x"$ac_cv_fc_pp_define" != xunknown && break
+done
+FCFLAGS=$ac_fc_pp_define_FCFLAGS_save
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_pp_define" >&5
+$as_echo "$ac_cv_fc_pp_define" >&6; }
+ac_fc_srcext=$ac_fc_pp_define_srcext_save
+if test "x$ac_cv_fc_pp_define" = xunknown; then
+  FC_DEFINE=
+  as_fn_error 77 "Fortran does not allow to define preprocessor symbols" "$LINENO" 5
+else
+  FC_DEFINE=$ac_cv_fc_pp_define
+
+fi
+ac_ext=$ac_ext_saved
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+      ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+   ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran flag to compile .f files" >&5
+$as_echo_n "checking for Fortran flag to compile .f files... " >&6; }
+if ${ac_cv_fc_srcext_f+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=f
+ac_fcflags_srcext_save=$ac_fcflags_srcext
+ac_fcflags_srcext=
+ac_cv_fc_srcext_f=unknown
+case $ac_ext in #(
+  [fF]77) ac_try=f77;; #(
+  *) ac_try=f95;;
+esac
+for ac_flag in none -qsuffix=f=f -Tf "-x $ac_try"; do
+  test "x$ac_flag" != xnone && ac_fcflags_srcext="$ac_flag"
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_cv_fc_srcext_f=$ac_flag; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest.$ac_objext conftest.f
+ac_fcflags_srcext=$ac_fcflags_srcext_save
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_srcext_f" >&5
+$as_echo "$ac_cv_fc_srcext_f" >&6; }
+if test "x$ac_cv_fc_srcext_f" = xunknown; then
+  as_fn_error $? "Fortran could not compile .f files" "$LINENO" 5
+else
+  ac_fc_srcext=f
+  if test "x$ac_cv_fc_srcext_f" = xnone; then
+    ac_fcflags_srcext=""
+    FCFLAGS_f=""
+  else
+    ac_fcflags_srcext=$ac_cv_fc_srcext_f
+    FCFLAGS_f=$ac_cv_fc_srcext_f
+  fi
+
+
+fi
+ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+   ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran flag to compile .F files" >&5
+$as_echo_n "checking for Fortran flag to compile .F files... " >&6; }
+if ${ac_cv_fc_srcext_F+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=F
+ac_fcflags_srcext_save=$ac_fcflags_srcext
+ac_fcflags_srcext=
+ac_cv_fc_srcext_F=unknown
+case $ac_ext in #(
+  [fF]77) ac_try=f77;; #(
+  *) ac_try=f95;;
+esac
+for ac_flag in none -qsuffix=f=F -Tf "-x $ac_try"; do
+  test "x$ac_flag" != xnone && ac_fcflags_srcext="$ac_flag"
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_cv_fc_srcext_F=$ac_flag; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest.$ac_objext conftest.F
+ac_fcflags_srcext=$ac_fcflags_srcext_save
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_srcext_F" >&5
+$as_echo "$ac_cv_fc_srcext_F" >&6; }
+if test "x$ac_cv_fc_srcext_F" = xunknown; then
+  as_fn_error $? "Fortran could not compile .F files" "$LINENO" 5
+else
+  ac_fc_srcext=F
+  if test "x$ac_cv_fc_srcext_F" = xnone; then
+    ac_fcflags_srcext=""
+    FCFLAGS_F=""
+  else
+    ac_fcflags_srcext=$ac_cv_fc_srcext_F
+    FCFLAGS_F=$ac_cv_fc_srcext_F
+  fi
+
+
+fi
+ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+   ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran flag to compile .f90 files" >&5
+$as_echo_n "checking for Fortran flag to compile .f90 files... " >&6; }
+if ${ac_cv_fc_srcext_f90+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=f90
+ac_fcflags_srcext_save=$ac_fcflags_srcext
+ac_fcflags_srcext=
+ac_cv_fc_srcext_f90=unknown
+case $ac_ext in #(
+  [fF]77) ac_try=f77;; #(
+  *) ac_try=f95;;
+esac
+for ac_flag in none -qsuffix=f=f90 -Tf "-x $ac_try"; do
+  test "x$ac_flag" != xnone && ac_fcflags_srcext="$ac_flag"
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_cv_fc_srcext_f90=$ac_flag; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest.$ac_objext conftest.f90
+ac_fcflags_srcext=$ac_fcflags_srcext_save
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_srcext_f90" >&5
+$as_echo "$ac_cv_fc_srcext_f90" >&6; }
+if test "x$ac_cv_fc_srcext_f90" = xunknown; then
+  as_fn_error $? "Fortran could not compile .f90 files" "$LINENO" 5
+else
+  ac_fc_srcext=f90
+  if test "x$ac_cv_fc_srcext_f90" = xnone; then
+    ac_fcflags_srcext=""
+    FCFLAGS_f90=""
+  else
+    ac_fcflags_srcext=$ac_cv_fc_srcext_f90
+    FCFLAGS_f90=$ac_cv_fc_srcext_f90
+  fi
+
+
+fi
+ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+   ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran flag to compile .F90 files" >&5
+$as_echo_n "checking for Fortran flag to compile .F90 files... " >&6; }
+if ${ac_cv_fc_srcext_F90+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=F90
+ac_fcflags_srcext_save=$ac_fcflags_srcext
+ac_fcflags_srcext=
+ac_cv_fc_srcext_F90=unknown
+case $ac_ext in #(
+  [fF]77) ac_try=f77;; #(
+  *) ac_try=f95;;
+esac
+for ac_flag in none -qsuffix=f=F90 -Tf "-x $ac_try"; do
+  test "x$ac_flag" != xnone && ac_fcflags_srcext="$ac_flag"
+  cat > conftest.$ac_ext <<_ACEOF
+      program main
+
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_cv_fc_srcext_F90=$ac_flag; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest.$ac_objext conftest.F90
+ac_fcflags_srcext=$ac_fcflags_srcext_save
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_srcext_F90" >&5
+$as_echo "$ac_cv_fc_srcext_F90" >&6; }
+if test "x$ac_cv_fc_srcext_F90" = xunknown; then
+  as_fn_error $? "Fortran could not compile .F90 files" "$LINENO" 5
+else
+  ac_fc_srcext=F90
+  if test "x$ac_cv_fc_srcext_F90" = xnone; then
+    ac_fcflags_srcext=""
+    FCFLAGS_F90=""
+  else
+    ac_fcflags_srcext=$ac_cv_fc_srcext_F90
+    FCFLAGS_F90=$ac_cv_fc_srcext_F90
+  fi
+
+
+fi
+ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+
+
+
+
+   ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+      ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran flag needed to accept fixed-form source" >&5
+$as_echo_n "checking for Fortran flag needed to accept fixed-form source... " >&6; }
+if ${ac_cv_fc_fixedform+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_fc_fixedform=unknown
+ac_fc_fixedform_FCFLAGS_save=$FCFLAGS
+for ac_flag in none -ffixed-form -fixed -qfixed -Mfixed -fixedform "-f fixed" \
+               +source=fixed -fix --fix -Fixed
+do
+  test "x$ac_flag" != xnone && FCFLAGS="$ac_fc_fixedform_FCFLAGS_save $ac_flag"
+  cat > conftest.$ac_ext <<_ACEOF
+
+C     This comment should confuse free-form compilers.
+      program main
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_cv_fc_fixedform=$ac_flag; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+${RM} -f conftest.err conftest.$ac_objext conftest.$ac_ext
+FCFLAGS=$ac_fc_fixedform_FCFLAGS_save
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_fixedform" >&5
+$as_echo "$ac_cv_fc_fixedform" >&6; }
+if test "x$ac_cv_fc_fixedform" = xunknown; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Fortran does not accept fixed-form source" >&5
+$as_echo "$as_me: WARNING: Fortran does not accept fixed-form source" >&2;}
+  ac_cv_fc_fixedform=
+else
+          if test "x$ac_cv_fc_fixedform" = xnone; then
+     ac_cv_fc_fixedform=
+  fi
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+   FFIXEDFORMFLAG=${ac_cv_fc_fixedform}
+   if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: FC=$FC F90FLAGS=$F90FLAGS FFIXEDFORMFLAG=$FFIXEDFORMFLAG" >&5
+$as_echo "$as_me: DEBUG: FC=$FC F90FLAGS=$F90FLAGS FFIXEDFORMFLAG=$FFIXEDFORMFLAG" >&6;}
+          fi
+
+
+
+
+   # Checking for Fortran types also determines the Fortran name mangling
+   # and places the value into FCALLSCSUB as the C name corresponding
+   # to the Fortran name SUB
+   ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dummy main to link with Fortran libraries" >&5
+$as_echo_n "checking for dummy main to link with Fortran libraries... " >&6; }
+if ${ac_cv_fc_dummy_main+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_fc_dm_save_LIBS=$LIBS
+ LIBS="$LIBS $FCLIBS"
+ ac_fortran_dm_var=FC_DUMMY_MAIN
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ # First, try linking without a dummy main:
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_fortran_dummy_main=none
+else
+  ac_cv_fortran_dummy_main=unknown
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+ if test $ac_cv_fortran_dummy_main = unknown; then
+   for ac_func in MAIN__ MAIN_ __main MAIN _MAIN __MAIN main_ main__ _main; do
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define $ac_fortran_dm_var $ac_func
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_fortran_dummy_main=$ac_func; break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+   done
+ fi
+ ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+ ac_cv_fc_dummy_main=$ac_cv_fortran_dummy_main
+ rm -rf conftest*
+ LIBS=$ac_fc_dm_save_LIBS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_dummy_main" >&5
+$as_echo "$ac_cv_fc_dummy_main" >&6; }
+FC_DUMMY_MAIN=$ac_cv_fc_dummy_main
+if test "$FC_DUMMY_MAIN" != unknown; then :
+  if test $FC_DUMMY_MAIN != none; then
+
+cat >>confdefs.h <<_ACEOF
+#define FC_DUMMY_MAIN $FC_DUMMY_MAIN
+_ACEOF
+
+  if test "x$ac_cv_fc_dummy_main" = "x$ac_cv_f77_dummy_main"; then
+
+$as_echo "#define FC_DUMMY_MAIN_EQ_F77 1" >>confdefs.h
+
+  fi
+fi
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "linking to Fortran libraries from C fails
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran name-mangling scheme" >&5
+$as_echo_n "checking for Fortran name-mangling scheme... " >&6; }
+if ${ac_cv_fc_mangling+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.$ac_ext <<_ACEOF
+      subroutine foobar()
+      return
+      end
+      subroutine foo_bar()
+      return
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  mv conftest.$ac_objext cfortran_test.$ac_objext
+
+  ac_save_LIBS=$LIBS
+  LIBS="cfortran_test.$ac_objext $LIBS $FCLIBS"
+
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+  ac_success=no
+  for ac_foobar in foobar FOOBAR; do
+    for ac_underscore in "" "_"; do
+      ac_func="$ac_foobar$ac_underscore"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_success=yes; break 2
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    done
+  done
+  ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+  if test "$ac_success" = "yes"; then
+     case $ac_foobar in
+	foobar)
+	   ac_case=lower
+	   ac_foo_bar=foo_bar
+	   ;;
+	FOOBAR)
+	   ac_case=upper
+	   ac_foo_bar=FOO_BAR
+	   ;;
+     esac
+
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+     ac_success_extra=no
+     for ac_extra in "" "_"; do
+	ac_func="$ac_foo_bar$ac_underscore$ac_extra"
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_success_extra=yes; break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     done
+     ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+     if test "$ac_success_extra" = "yes"; then
+	ac_cv_fc_mangling="$ac_case case"
+	if test -z "$ac_underscore"; then
+	   ac_cv_fc_mangling="$ac_cv_fc_mangling, no underscore"
+	else
+	   ac_cv_fc_mangling="$ac_cv_fc_mangling, underscore"
+	fi
+	if test -z "$ac_extra"; then
+	   ac_cv_fc_mangling="$ac_cv_fc_mangling, no extra underscore"
+	else
+	   ac_cv_fc_mangling="$ac_cv_fc_mangling, extra underscore"
+	fi
+      else
+	ac_cv_fc_mangling="unknown"
+      fi
+  else
+     ac_cv_fc_mangling="unknown"
+  fi
+
+  LIBS=$ac_save_LIBS
+  rm -rf conftest*
+  rm -f cfortran_test*
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compile a simple Fortran program
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_mangling" >&5
+$as_echo "$ac_cv_fc_mangling" >&6; }
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+case $ac_cv_fc_mangling in
+  upper*) ac_val="SUB" ;;
+  lower*) ac_val="sub" ;;
+  *)      ac_val="unknown" ;;
+esac
+case $ac_cv_fc_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac
+
+FCALLSCSUB="$ac_val"
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+   # determine the correct name mapping
+   case $FCALLSCSUB in
+       SUB)
+
+$as_echo "#define F77_NAME_UPPER /**/" >>confdefs.h
+
+           ;;
+       sub_)
+           # This is the hard case.  Gcc uses one _ unless the name includes
+           # an underscore, in which case it gets two trailing underscores.
+           # Use essentially the same configure code that the original configure
+           # used to determine SUB
+           { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C-equivalent to Fortran routine \"SUB_A\"" >&5
+$as_echo_n "checking for C-equivalent to Fortran routine \"SUB_A\"... " >&6; }
+                              ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+case $ac_cv_fc_mangling in
+  upper*) ac_val="SUB_A" ;;
+  lower*) ac_val="sub_a" ;;
+  *)      ac_val="unknown" ;;
+esac
+case $ac_cv_fc_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac
+case $ac_cv_fc_mangling in *," extra underscore"*) ac_val="$ac_val"_ ;; esac
+
+FCALLSCSUBA="$ac_val"
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+           { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FCALLSCSUBA" >&5
+$as_echo "$FCALLSCSUBA" >&6; }
+           case $FCALLSCSUBA in
+               sub_a__)
+
+$as_echo "#define F77_NAME_LOWER_2USCORE /**/" >>confdefs.h
+
+                   ;;
+               sub_a_)
+
+$as_echo "#define F77_NAME_LOWER_USCORE /**/" >>confdefs.h
+
+                   ;;
+               *)
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unrecognized Fortran name mapping" >&5
+$as_echo "$as_me: WARNING: Unrecognized Fortran name mapping" >&2;}
+                   ;;
+           esac
+           ;;
+       sub)
+
+$as_echo "#define F77_NAME_LOWER /**/" >>confdefs.h
+
+           ;;
+       *)
+           { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unrecognized Fortran name mapping" >&5
+$as_echo "$as_me: WARNING: Unrecognized Fortran name mapping" >&2;}
+           ;;
+   esac
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Fortran compiler is NAG" >&5
+$as_echo_n "checking if Fortran compiler is NAG... " >&6; }
+if ${ac_cv_fc_compiler_nag+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_fc_compiler_nag=no
+     eval $MPIF90 -V </dev/null >& conftest.ver
+     _FC_VENDOR=`head -c 3 conftest.ver`
+     if test "x${_FC_VENDOR}" = xNAG ; then
+        ac_cv_fc_compiler_nag=yes
+     fi
+     ${RM} -f conftest.ver
+     unset _FC_VENDOR
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_compiler_nag" >&5
+$as_echo "$ac_cv_fc_compiler_nag" >&6; }
+
+   if test "x${ac_cv_fc_compiler_nag}" = xyes ; then
+      NAGf90FPPFLAGS="-DNAGf90Fortran"
+      NAG_FCFLAGS="-mismatch"
+
+
+   fi
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking Fortran compiler treating constant modifier" >&5
+$as_echo_n "checking Fortran compiler treating constant modifier... " >&6; }
+if ${ac_cv_fc_constant_modifier+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+        cat > conftest.$ac_ext <<_ACEOF
+
+         program main
+         integer*8  nf_fill_uint
+         integer*8  nf_fill_int64
+         parameter (nf_fill_uint  = 4294967295_8)
+         parameter (nf_fill_int64 = -9223372036854775806_8)
+         end
+_ACEOF
+if ac_fn_f77_try_compile "$LINENO"; then :
+  ac_cv_fc_constant_modifier=8
+else
+  cat > conftest.$ac_ext <<_ACEOF
+
+         program main
+         integer*8  nf_fill_uint
+         integer*8  nf_fill_int64
+         parameter (nf_fill_uint  = 4294967295)
+         parameter (nf_fill_int64 = -9223372036854775806)
+         end
+_ACEOF
+if ac_fn_f77_try_compile "$LINENO"; then :
+  ac_cv_fc_constant_modifier=none
+else
+  cat > conftest.$ac_ext <<_ACEOF
+
+         program main
+         integer, parameter :: EightByteInt = selected_int_kind(18)
+         integer*8  nf_fill_uint
+         integer*8  nf_fill_int64
+         parameter (nf_fill_uint  = 4294967295_EightByteInt)
+         parameter (nf_fill_int64 = -9223372036854775806_EightByteInt)
+         end
+_ACEOF
+if ac_fn_f77_try_compile "$LINENO"; then :
+  ac_cv_fc_constant_modifier=EightByteInt
+else
+  as_fn_error $? "no appropriate modifier found" "$LINENO" 5
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_constant_modifier" >&5
+$as_echo "$ac_cv_fc_constant_modifier" >&6; }
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+   if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: ac_cv_fc_constant_modifier=$ac_cv_fc_constant_modifier" >&5
+$as_echo "$as_me: DEBUG: ac_cv_fc_constant_modifier=$ac_cv_fc_constant_modifier" >&6;}
+          fi
+
+
+   PNF_INT8_MODIFIER=""
+   if test "x${ac_cv_fc_constant_modifier}" = xnone ; then
+      PNF_FILL_UINT=4294967295
+      PNF_FILL_INT64=-9223372036854775806
+      PNF_FILL_UINT64=18446744073709551614
+      PNF_X_UINT_MAX=4294967295
+      PNF_X_INT8_MIN=-9223372036854775807
+      PNF_X_INT8_MAX=9223372036854775807
+      PNF_X_UINT8_MAX=18446744073709551615
+   else
+      if test "x${ac_cv_fc_constant_modifier}" = xEightByteInt ; then
+         PNF_INT8_MODIFIER="      integer, parameter :: EightByteInt = selected_int_kind(18)"
+      fi
+      PNF_FILL_UINT=4294967295_${ac_cv_fc_constant_modifier}
+      PNF_FILL_INT64=-9223372036854775806_${ac_cv_fc_constant_modifier}
+      PNF_FILL_UINT64=18446744073709551614_${ac_cv_fc_constant_modifier}
+      PNF_X_UINT_MAX=4294967295_${ac_cv_fc_constant_modifier}
+      PNF_X_INT8_MIN=-9223372036854775807_${ac_cv_fc_constant_modifier}
+      PNF_X_INT8_MAX=9223372036854775807_${ac_cv_fc_constant_modifier}
+      PNF_X_UINT8_MAX=18446744073709551615_${ac_cv_fc_constant_modifier}
+   fi
+
+
+
+
+
+
+
+
+
+
+
+fi
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+have_yacc_lex=no
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+
+
+
+
+        case "${M4-unset}" in
+	unset) for ac_prog in m4 gm4
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_M4+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$M4"; then
+  ac_cv_prog_M4="$M4" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_M4="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+M4=$ac_cv_prog_M4
+if test -n "$M4"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $M4" >&5
+$as_echo "$M4" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$M4" && break
+done
+test -n "$M4" || M4="m4"
+ ;;
+	*) for ac_prog in $M4 m4 gm4
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_M4+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$M4"; then
+  ac_cv_prog_M4="$M4" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_M4="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+M4=$ac_cv_prog_M4
+if test -n "$M4"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $M4" >&5
+$as_echo "$M4" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$M4" && break
+done
+test -n "$M4" || M4="m4"
+ ;;
+    esac
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking m4 flags" >&5
+$as_echo_n "checking m4 flags... " >&6; }
+    case "${M4FLAGS-unset}" in
+	unset)                `${M4} /dev/null > conftest.err 2>&1`
+               ac_cv_m4_stdout=`cat conftest.err`
+               if test "x$ac_cv_m4_stdout" != x; then
+                  M4FLAGS=-B10000
+               fi
+               ${RM} -f conftest.err
+               ;;
+    esac
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $M4FLAGS" >&5
+$as_echo "$M4FLAGS" >&6; }
+
+
+
+        case "${AR-unset}" in
+	unset) for ac_prog in ar
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AR="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AR" && break
+done
+test -n "$AR" || AR="ar"
+ ;;
+	*) for ac_prog in $AR ar
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AR="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AR" && break
+done
+test -n "$AR" || AR="ar"
+ ;;
+    esac
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking ar flags" >&5
+$as_echo_n "checking ar flags... " >&6; }
+    case "${ARFLAGS-unset}" in
+	unset) ARFLAGS=cru ;;
+    esac
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ARFLAGS" >&5
+$as_echo "$ARFLAGS" >&6; }
+
+
+
+        case "${NM-unset}" in
+	unset) for ac_prog in nm
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_NM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NM"; then
+  ac_cv_prog_NM="$NM" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_NM="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+NM=$ac_cv_prog_NM
+if test -n "$NM"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NM" >&5
+$as_echo "$NM" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$NM" && break
+done
+test -n "$NM" || NM="nm"
+ ;;
+	*) for ac_prog in $NM nm
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_NM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NM"; then
+  ac_cv_prog_NM="$NM" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_NM="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+NM=$ac_cv_prog_NM
+if test -n "$NM"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NM" >&5
+$as_echo "$NM" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$NM" && break
+done
+test -n "$NM" || NM="nm"
+ ;;
+    esac
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking nm flags" >&5
+$as_echo_n "checking nm flags... " >&6; }
+    case "${NMFLAGS-unset}" in
+	unset) NMFLAGS= ;;
+    esac
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMFLAGS" >&5
+$as_echo "$NMFLAGS" >&6; }
+
+
+# We could use the PAC check for ranlib (it also makes sure that ranlib works,
+# which is not always true, particularly when GNU tools are installed on
+# a system that doesn't have (or need) ranlib
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
+$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
+if ${ac_cv_header_stdbool_h+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+             #include <stdbool.h>
+             #ifndef bool
+              "error: bool is not defined"
+             #endif
+             #ifndef false
+              "error: false is not defined"
+             #endif
+             #if false
+              "error: false is not 0"
+             #endif
+             #ifndef true
+              "error: true is not defined"
+             #endif
+             #if true != 1
+              "error: true is not 1"
+             #endif
+             #ifndef __bool_true_false_are_defined
+              "error: __bool_true_false_are_defined is not defined"
+             #endif
+
+             struct s { _Bool s: 1; _Bool t; } s;
+
+             char a[true == 1 ? 1 : -1];
+             char b[false == 0 ? 1 : -1];
+             char c[__bool_true_false_are_defined == 1 ? 1 : -1];
+             char d[(bool) 0.5 == true ? 1 : -1];
+             /* See body of main program for 'e'.  */
+             char f[(_Bool) 0.0 == false ? 1 : -1];
+             char g[true];
+             char h[sizeof (_Bool)];
+             char i[sizeof s.t];
+             enum { j = false, k = true, l = false * true, m = true * 256 };
+             /* The following fails for
+                HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
+             _Bool n[m];
+             char o[sizeof n == m * sizeof n[0] ? 1 : -1];
+             char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
+             /* Catch a bug in an HP-UX C compiler.  See
+                http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+                http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+              */
+             _Bool q = true;
+             _Bool *pq = &q;
+
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+
+             bool e = &s;
+             *pq |= q;
+             *pq |= ! q;
+             /* Refer to every declared value, to avoid compiler optimizations.  */
+             return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
+                     + !m + !n + !o + !p + !q + !pq);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdbool_h=yes
+else
+  ac_cv_header_stdbool_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
+$as_echo "$ac_cv_header_stdbool_h" >&6; }
+   ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
+if test "x$ac_cv_type__Bool" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE__BOOL 1
+_ACEOF
+
+
+fi
+
+
+if test $ac_cv_header_stdbool_h = yes; then
+
+$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if ${ac_cv_c_inline+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for IEEE floating point format" >&5
+$as_echo_n "checking for IEEE floating point format... " >&6; }
+if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef NO_FLOAT_H
+#include <float.h>
+#endif
+
+#define EXIT_NOTIEEE	1
+#define EXIT_MAYBEIEEE	0
+
+int
+main()
+{
+#if	defined(FLT_RADIX)	&& FLT_RADIX != 2
+		return EXIT_NOTIEEE;
+#elif	defined(DBL_MAX_EXP)	&& DBL_MAX_EXP != 1024
+		return EXIT_NOTIEEE;
+#elif	defined(DBL_MANT_DIG)	&& DBL_MANT_DIG != 53
+		return EXIT_NOTIEEE;
+#elif 	defined(FLT_MAX_EXP)	&& !(FLT_MAX_EXP == 1024 || FLT_MAX_EXP == 128)
+		return EXIT_NOTIEEE;
+#elif	defined(FLT_MANT_DIG)	&& !(FLT_MANT_DIG == 53 || FLT_MANT_DIG == 24)
+		return EXIT_NOTIEEE;
+#else
+	/* (assuming eight bit char) */
+	if(sizeof(double) != 8)
+		return EXIT_NOTIEEE;
+	if(!(sizeof(float) == 4 || sizeof(float) == 8))
+		return EXIT_NOTIEEE;
+
+	return EXIT_MAYBEIEEE;
+#endif
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_c_ieeefloat=yes
+else
+  ac_cv_c_ieeefloat=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_ieeefloat" >&5
+$as_echo "$ac_cv_c_ieeefloat" >&6; }
+if test x$ac_cv_c_ieeefloat = xno; then
+  $as_echo "#define NO_IEEE_FLOAT 1" >>confdefs.h
+
+fi
+
+
+
+for ac_func in strerror access unlink
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then :
+  enableval=$enable_debug; debug=${enableval}
+else
+  debug=no
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking PnetCDF debug mode" >&5
+$as_echo_n "checking PnetCDF debug mode... " >&6; }
+if test "x${debug}" = xyes; then
+   $as_echo "#define PNC_DEBUG 1" >>confdefs.h
+
+
+      for ac_header in search.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "search.h" "ac_cv_header_search_h" "$ac_includes_default"
+if test "x$ac_cv_header_search_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SEARCH_H 1
+_ACEOF
+
+fi
+
+done
+
+   for ac_func in tsearch tdelete
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+      if (test "x${ac_cv_func_tsearch}" = xyes) &&
+      (test "x${ac_cv_func_tdelete}" = xyes) ; then
+      $as_echo "#define PNC_MALLOC_TRACE 1" >>confdefs.h
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $debug" >&5
+$as_echo "$debug" >&6; }
+PNC_DEBUG=${debug}
+
+
+ac_fn_c_check_type "$LINENO" "MPI_Offset" "ac_cv_type_MPI_Offset" "#include <mpi.h>
+"
+if test "x$ac_cv_type_MPI_Offset" = xyes; then :
+
+fi
+
+if test "x${ac_cv_type_MPI_Offset}" = xyes; then
+   # The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of MPI_Offset" >&5
+$as_echo_n "checking size of MPI_Offset... " >&6; }
+if ${ac_cv_sizeof_MPI_Offset+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (MPI_Offset))" "ac_cv_sizeof_MPI_Offset"        "#include <mpi.h>
+"; then :
+
+else
+  if test "$ac_cv_type_MPI_Offset" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (MPI_Offset)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_MPI_Offset=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_MPI_Offset" >&5
+$as_echo "$ac_cv_sizeof_MPI_Offset" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_MPI_OFFSET $ac_cv_sizeof_MPI_Offset
+_ACEOF
+
+
+else
+   as_fn_error $? "Unable to find type MPI_Offset in mpi.h" "$LINENO" 5
+fi
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of MPI_Aint" >&5
+$as_echo_n "checking size of MPI_Aint... " >&6; }
+if ${ac_cv_sizeof_MPI_Aint+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (MPI_Aint))" "ac_cv_sizeof_MPI_Aint"        "#include <mpi.h>
+"; then :
+
+else
+  if test "$ac_cv_type_MPI_Aint" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (MPI_Aint)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_MPI_Aint=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_MPI_Aint" >&5
+$as_echo "$ac_cv_sizeof_MPI_Aint" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_MPI_AINT $ac_cv_sizeof_MPI_Aint
+_ACEOF
+
+
+
+if test "$ac_cv_sizeof_MPI_Offset" -lt "8"; then
+   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"Unable to support CDF-5 format\"" >&5
+$as_echo "$as_me: WARNING: \"Unable to support CDF-5 format\"" >&2;};
+   enable_cdf5=no
+else
+
+$as_echo "#define ENABLE_CDF5 /**/" >>confdefs.h
+
+   enable_cdf5=yes
+fi
+
+SIZEOF_MPI_AINT_IS_4=no
+if test "x$ac_cv_sizeof_MPI_Aint" = x4; then
+   SIZEOF_MPI_AINT_IS_4=yes
+fi
+
+
+if test "$ac_cv_sizeof_MPI_Offset" -ne "$ac_cv_sizeof_MPI_Aint"; then
+   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: MPI_Offset and MPI_Aint have different sizes: non-blocking APIs now behave like blocking ones" >&5
+$as_echo "$as_me: WARNING: MPI_Offset and MPI_Aint have different sizes: non-blocking APIs now behave like blocking ones" >&2;}
+   enable_nonblocking=no
+else
+
+$as_echo "#define ENABLE_NONBLOCKING /**/" >>confdefs.h
+
+   enable_nonblocking=yes
+fi
+
+# check for MPI-2 only functions
+for ac_func in MPI_Info_dup MPI_Info_free MPI_Get_address
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_func in MPI_Type_create_subarray MPI_Type_create_hvector MPI_Type_create_hindexed MPI_Type_create_struct MPI_Type_create_resized MPI_Type_get_extent
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_COMBINER_DUP is defined " >&5
+$as_echo_n "checking if MPI constant MPI_COMBINER_DUP is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_COMBINER_DUP;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMBINER_DUP 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_COMBINER_HVECTOR_INTEGER is defined " >&5
+$as_echo_n "checking if MPI constant MPI_COMBINER_HVECTOR_INTEGER is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_COMBINER_HVECTOR_INTEGER;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMBINER_HVECTOR_INTEGER 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_COMBINER_HINDEXED_INTEGER is defined " >&5
+$as_echo_n "checking if MPI constant MPI_COMBINER_HINDEXED_INTEGER is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_COMBINER_HINDEXED_INTEGER;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMBINER_HINDEXED_INTEGER 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_COMBINER_SUBARRAY is defined " >&5
+$as_echo_n "checking if MPI constant MPI_COMBINER_SUBARRAY is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_COMBINER_SUBARRAY;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMBINER_SUBARRAY 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_COMBINER_DARRAY is defined " >&5
+$as_echo_n "checking if MPI constant MPI_COMBINER_DARRAY is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_COMBINER_DARRAY;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMBINER_DARRAY 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_COMBINER_RESIZED is defined " >&5
+$as_echo_n "checking if MPI constant MPI_COMBINER_RESIZED is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_COMBINER_RESIZED;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMBINER_RESIZED 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_COMBINER_STRUCT_INTEGER is defined " >&5
+$as_echo_n "checking if MPI constant MPI_COMBINER_STRUCT_INTEGER is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_COMBINER_STRUCT_INTEGER;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMBINER_STRUCT_INTEGER 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_COMBINER_INDEXED_BLOCK is defined " >&5
+$as_echo_n "checking if MPI constant MPI_COMBINER_INDEXED_BLOCK is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_COMBINER_INDEXED_BLOCK;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMBINER_INDEXED_BLOCK 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_COMBINER_F90_REAL is defined " >&5
+$as_echo_n "checking if MPI constant MPI_COMBINER_F90_REAL is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_COMBINER_F90_REAL;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMBINER_F90_REAL 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_COMBINER_F90_INTEGER is defined " >&5
+$as_echo_n "checking if MPI constant MPI_COMBINER_F90_INTEGER is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_COMBINER_F90_INTEGER;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMBINER_F90_INTEGER 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_COMBINER_F90_COMPLEX is defined " >&5
+$as_echo_n "checking if MPI constant MPI_COMBINER_F90_COMPLEX is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_COMBINER_F90_COMPLEX;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMBINER_F90_COMPLEX 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_ERR_FILE_EXISTS is defined " >&5
+$as_echo_n "checking if MPI constant MPI_ERR_FILE_EXISTS is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_ERR_FILE_EXISTS;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_ERR_FILE_EXISTS 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_ERR_NO_SUCH_FILE is defined " >&5
+$as_echo_n "checking if MPI constant MPI_ERR_NO_SUCH_FILE is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_ERR_NO_SUCH_FILE;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_ERR_NO_SUCH_FILE 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_ERR_AMODE is defined " >&5
+$as_echo_n "checking if MPI constant MPI_ERR_AMODE is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_ERR_AMODE;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_ERR_AMODE 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_ERR_NOT_SAME is defined " >&5
+$as_echo_n "checking if MPI constant MPI_ERR_NOT_SAME is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_ERR_NOT_SAME;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_ERR_NOT_SAME 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_ERR_BAD_FILE is defined " >&5
+$as_echo_n "checking if MPI constant MPI_ERR_BAD_FILE is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_ERR_BAD_FILE;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_ERR_BAD_FILE 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_ERR_READ_ONLY is defined " >&5
+$as_echo_n "checking if MPI constant MPI_ERR_READ_ONLY is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_ERR_READ_ONLY;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_ERR_READ_ONLY 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_ERR_ACCESS is defined " >&5
+$as_echo_n "checking if MPI constant MPI_ERR_ACCESS is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_ERR_ACCESS;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_ERR_ACCESS 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_ERR_NO_SPACE is defined " >&5
+$as_echo_n "checking if MPI constant MPI_ERR_NO_SPACE is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_ERR_NO_SPACE;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_ERR_NO_SPACE 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI constant MPI_ERR_QUOTA is defined " >&5
+$as_echo_n "checking if MPI constant MPI_ERR_QUOTA is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          int dummy = MPI_ERR_QUOTA;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_ERR_QUOTA 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_CHAR is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_CHAR is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_CHAR;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_CHAR 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_BYTE is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_BYTE is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_BYTE;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_BYTE 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_SIGNED_CHAR is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_SIGNED_CHAR is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_SIGNED_CHAR;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_SIGNED_CHAR 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_UNSIGNED_CHAR is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_UNSIGNED_CHAR is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_UNSIGNED_CHAR;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_UNSIGNED_CHAR 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_SHORT is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_SHORT is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_SHORT;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_SHORT 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_UNSIGNED_SHORT is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_UNSIGNED_SHORT is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_UNSIGNED_SHORT;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_UNSIGNED_SHORT 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_INT is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_INT is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_INT;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_INT 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_UNSIGNED is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_UNSIGNED is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_UNSIGNED;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_UNSIGNED 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_LONG is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_LONG is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_LONG;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_LONG 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_FLOAT is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_FLOAT is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_FLOAT;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_FLOAT 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_DOUBLE is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_DOUBLE is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_DOUBLE;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_DOUBLE 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_LONG_LONG_INT is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_LONG_LONG_INT is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_LONG_LONG_INT;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_LONG_LONG_INT 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_UNSIGNED_LONG_LONG is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_UNSIGNED_LONG_LONG is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_UNSIGNED_LONG_LONG;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_UNSIGNED_LONG_LONG 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_UB is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_UB is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_UB;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_UB 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_LB is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_LB is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_LB;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_LB 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_OFFSET is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_OFFSET is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_OFFSET;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_OFFSET_DATATYPE 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+if test "x${enable_fortran}" = xyes ; then
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_CHARACTER is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_CHARACTER is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_CHARACTER;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_CHARACTER 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_REAL is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_REAL is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_REAL;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_REAL 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_INTEGER is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_INTEGER is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_INTEGER;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_INTEGER 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_DOUBLE_PRECISION is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_DOUBLE_PRECISION is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_DOUBLE_PRECISION;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_DOUBLE_PRECISION 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_INTEGER1 is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_INTEGER1 is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_INTEGER1;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_INTEGER1 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_INTEGER2 is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_INTEGER2 is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_INTEGER2;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_INTEGER2 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_INTEGER4 is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_INTEGER4 is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_INTEGER4;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_INTEGER4 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_INTEGER8 is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_INTEGER8 is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_INTEGER8;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_INTEGER8 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_INTEGER16 is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_INTEGER16 is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_INTEGER16;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_INTEGER16 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_REAL4 is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_REAL4 is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_REAL4;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_REAL4 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_REAL8 is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_REAL8 is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_REAL8;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_REAL8 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_REAL16 is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_REAL16 is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_REAL16;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_REAL16 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_COMPLEX8 is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_COMPLEX8 is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_COMPLEX8;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMPLEX8 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_COMPLEX16 is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_COMPLEX16 is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_COMPLEX16;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMPLEX16 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MPI datatype MPI_COMPLEX32 is defined " >&5
+$as_echo_n "checking if MPI datatype MPI_COMPLEX32 is defined ... " >&6; }
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+          #include <mpi.h>
+          MPI_Datatype dummy = MPI_COMPLEX32;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_MPI_COMPLEX32 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+
+# Check whether --enable-in-place-swap was given.
+if test "${enable_in_place_swap+set}" = set; then :
+  enableval=$enable_in_place_swap; in_place_swap=${enableval}
+else
+  in_place_swap=yes
+
+fi
+
+if test "x${in_place_swap}" = xno ; then
+    $as_echo "#define DISABLE_IN_PLACE_SWAP 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5
+$as_echo_n "checking whether char is unsigned... " >&6; }
+if ${ac_cv_c_char_unsigned+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(((char) -1) < 0)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_char_unsigned=no
+else
+  ac_cv_c_char_unsigned=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_char_unsigned" >&5
+$as_echo "$ac_cv_c_char_unsigned" >&6; }
+if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then
+  $as_echo "#define __CHAR_UNSIGNED__ 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_bigendian=unknown
+    # See if we're dealing with a universal compiler.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __APPLE_CC__
+	       not a universal capable compiler
+	     #endif
+	     typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+	# Check for potential -arch flags.  It is not universal unless
+	# there are at least two -arch flags with different values.
+	ac_arch=
+	ac_prev=
+	for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+	 if test -n "$ac_prev"; then
+	   case $ac_word in
+	     i?86 | x86_64 | ppc | ppc64)
+	       if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+		 ac_arch=$ac_word
+	       else
+		 ac_cv_c_bigendian=universal
+		 break
+	       fi
+	       ;;
+	   esac
+	   ac_prev=
+	 elif test "x$ac_word" = "x-arch"; then
+	   ac_prev=arch
+	 fi
+       done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if sys/param.h defines the BYTE_ORDER macro.
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+	     #include <sys/param.h>
+
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+		     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+		     && LITTLE_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+		#include <sys/param.h>
+
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to _BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # Compile a test program.
+      if test "$cross_compiling" = yes; then :
+  # Try to guess by grepping values from an object file.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+short int ascii_mm[] =
+		  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+		short int ascii_ii[] =
+		  { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+		int use_ascii (int i) {
+		  return ascii_mm[i] + ascii_ii[i];
+		}
+		short int ebcdic_ii[] =
+		  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+		short int ebcdic_mm[] =
+		  { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+		int use_ebcdic (int i) {
+		  return ebcdic_mm[i] + ebcdic_ii[i];
+		}
+		extern int foo;
+
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+	      ac_cv_c_bigendian=yes
+	    fi
+	    if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+	      if test "$ac_cv_c_bigendian" = unknown; then
+		ac_cv_c_bigendian=no
+	      else
+		# finding both strings is unlikely to happen, but who knows?
+		ac_cv_c_bigendian=unknown
+	      fi
+	    fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+
+	     /* Are we little or big endian?  From Harbison&Steele.  */
+	     union
+	     {
+	       long int l;
+	       char c[sizeof (long int)];
+	     } u;
+	     u.l = 1;
+	     return u.c[sizeof (long int) - 1] == 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_c_bigendian=no
+else
+  ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+   yes)
+     $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+   no)
+      ;; #(
+   universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+     ;; #(
+   *)
+     as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+is_bigendian=no
+if test "x${ac_cv_c_bigendian}" = xyes ; then
+   is_bigendian=yes
+fi
+
+
+if test "x${ac_cv_c_bigendian}" = xyes  || (test "x${in_place_swap}" = xno) ; then
+   INTENTV="IN"
+else
+   INTENTV="INOUT"
+fi
+
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default"
+if test "x$ac_cv_type_off_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default"
+if test "x$ac_cv_type_ssize_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SSIZE_T 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "ptrdiff_t" "ac_cv_type_ptrdiff_t" "$ac_includes_default"
+if test "x$ac_cv_type_ptrdiff_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_PTRDIFF_T 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "uchar" "ac_cv_type_uchar" "$ac_includes_default"
+if test "x$ac_cv_type_uchar" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_UCHAR 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "ushort" "ac_cv_type_ushort" "$ac_includes_default"
+if test "x$ac_cv_type_ushort" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_USHORT 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "uint" "ac_cv_type_uint" "$ac_includes_default"
+if test "x$ac_cv_type_uint" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_UINT 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "longlong" "ac_cv_type_longlong" "$ac_includes_default"
+if test "x$ac_cv_type_longlong" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LONGLONG 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "ulonglong" "ac_cv_type_ulonglong" "$ac_includes_default"
+if test "x$ac_cv_type_ulonglong" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ULONGLONG 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "int64" "ac_cv_type_int64" "$ac_includes_default"
+if test "x$ac_cv_type_int64" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_INT64 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "uint64" "ac_cv_type_uint64" "$ac_includes_default"
+if test "x$ac_cv_type_uint64" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_UINT64 1
+_ACEOF
+
+
+fi
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5
+$as_echo_n "checking size of size_t... " >&6; }
+if ${ac_cv_sizeof_size_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_size_t" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (size_t)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_size_t=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5
+$as_echo "$ac_cv_sizeof_size_t" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SIZE_T $ac_cv_sizeof_size_t
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of off_t" >&5
+$as_echo_n "checking size of off_t... " >&6; }
+if ${ac_cv_sizeof_off_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (off_t))" "ac_cv_sizeof_off_t"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_off_t" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (off_t)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_off_t=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_off_t" >&5
+$as_echo "$ac_cv_sizeof_off_t" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_OFF_T $ac_cv_sizeof_off_t
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of signed char" >&5
+$as_echo_n "checking size of signed char... " >&6; }
+if ${ac_cv_sizeof_signed_char+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (signed char))" "ac_cv_sizeof_signed_char"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_signed_char" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (signed char)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_signed_char=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_signed_char" >&5
+$as_echo "$ac_cv_sizeof_signed_char" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SIGNED_CHAR $ac_cv_sizeof_signed_char
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned char" >&5
+$as_echo_n "checking size of unsigned char... " >&6; }
+if ${ac_cv_sizeof_unsigned_char+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned char))" "ac_cv_sizeof_unsigned_char"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_unsigned_char" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (unsigned char)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_unsigned_char=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_char" >&5
+$as_echo "$ac_cv_sizeof_unsigned_char" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UNSIGNED_CHAR $ac_cv_sizeof_unsigned_char
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5
+$as_echo_n "checking size of short... " >&6; }
+if ${ac_cv_sizeof_short+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_short" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (short)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_short=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5
+$as_echo "$ac_cv_sizeof_short" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned short" >&5
+$as_echo_n "checking size of unsigned short... " >&6; }
+if ${ac_cv_sizeof_unsigned_short+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned short))" "ac_cv_sizeof_unsigned_short"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_unsigned_short" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (unsigned short)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_unsigned_short=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_short" >&5
+$as_echo "$ac_cv_sizeof_unsigned_short" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UNSIGNED_SHORT $ac_cv_sizeof_unsigned_short
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
+$as_echo_n "checking size of int... " >&6; }
+if ${ac_cv_sizeof_int+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_int" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (int)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_int=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
+$as_echo "$ac_cv_sizeof_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned int" >&5
+$as_echo_n "checking size of unsigned int... " >&6; }
+if ${ac_cv_sizeof_unsigned_int+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned int))" "ac_cv_sizeof_unsigned_int"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_unsigned_int" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (unsigned int)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_unsigned_int=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_int" >&5
+$as_echo "$ac_cv_sizeof_unsigned_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UNSIGNED_INT $ac_cv_sizeof_unsigned_int
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
+$as_echo_n "checking size of long... " >&6; }
+if ${ac_cv_sizeof_long+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_long" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (long)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_long=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
+$as_echo "$ac_cv_sizeof_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of float" >&5
+$as_echo_n "checking size of float... " >&6; }
+if ${ac_cv_sizeof_float+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (float))" "ac_cv_sizeof_float"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_float" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (float)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_float=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_float" >&5
+$as_echo "$ac_cv_sizeof_float" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_FLOAT $ac_cv_sizeof_float
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of double" >&5
+$as_echo_n "checking size of double... " >&6; }
+if ${ac_cv_sizeof_double+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (double))" "ac_cv_sizeof_double"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_double" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (double)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_double=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_double" >&5
+$as_echo "$ac_cv_sizeof_double" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_DOUBLE $ac_cv_sizeof_double
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
+$as_echo_n "checking size of long long... " >&6; }
+if ${ac_cv_sizeof_long_long+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_long_long" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (long long)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_long_long=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
+$as_echo "$ac_cv_sizeof_long_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long long" >&5
+$as_echo_n "checking size of unsigned long long... " >&6; }
+if ${ac_cv_sizeof_unsigned_long_long+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long long))" "ac_cv_sizeof_unsigned_long_long"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_unsigned_long_long" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (unsigned long long)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_unsigned_long_long=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long_long" >&5
+$as_echo "$ac_cv_sizeof_unsigned_long_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UNSIGNED_LONG_LONG $ac_cv_sizeof_unsigned_long_long
+_ACEOF
+
+
+
+if test "$ac_cv_type_ushort" = yes ; then
+    # The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of ushort" >&5
+$as_echo_n "checking size of ushort... " >&6; }
+if ${ac_cv_sizeof_ushort+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (ushort))" "ac_cv_sizeof_ushort"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_ushort" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (ushort)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_ushort=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_ushort" >&5
+$as_echo "$ac_cv_sizeof_ushort" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_USHORT $ac_cv_sizeof_ushort
+_ACEOF
+
+
+fi
+if test "$ac_cv_type_uint" = yes ; then
+    # The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of uint" >&5
+$as_echo_n "checking size of uint... " >&6; }
+if ${ac_cv_sizeof_uint+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (uint))" "ac_cv_sizeof_uint"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_uint" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (uint)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_uint=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_uint" >&5
+$as_echo "$ac_cv_sizeof_uint" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_UINT $ac_cv_sizeof_uint
+_ACEOF
+
+
+fi
+if test "$ac_cv_type_longlong" = yes ; then
+    # The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of longlong" >&5
+$as_echo_n "checking size of longlong... " >&6; }
+if ${ac_cv_sizeof_longlong+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (longlong))" "ac_cv_sizeof_longlong"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_longlong" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (longlong)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_longlong=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_longlong" >&5
+$as_echo "$ac_cv_sizeof_longlong" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONGLONG $ac_cv_sizeof_longlong
+_ACEOF
+
+
+fi
+if test "$ac_cv_type_ulonglong" = yes ; then
+    # The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of ulonglong" >&5
+$as_echo_n "checking size of ulonglong... " >&6; }
+if ${ac_cv_sizeof_ulonglong+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (ulonglong))" "ac_cv_sizeof_ulonglong"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_ulonglong" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (ulonglong)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_ulonglong=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_ulonglong" >&5
+$as_echo "$ac_cv_sizeof_ulonglong" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_ULONGLONG $ac_cv_sizeof_ulonglong
+_ACEOF
+
+
+fi
+
+if test "x${enable_fortran}" = xyes ; then
+    if test "$cross_compiling" = yes; then
+
+    ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+    for ftype in integer*1 byte "integer(kind=1)"; do
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran \"$ftype\"" >&5
+$as_echo_n "checking for Fortran \"$ftype\"... " >&6; }
+        cat > conftest.$ac_ext <<_ACEOF
+
+               subroutine sub(value)
+               $ftype value
+               end
+
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	    NF_INT1_T=$ftype
+	    cat >>confdefs.h <<_ACEOF
+#define NF_INT1_T $ftype
+_ACEOF
+
+            break
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    done
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+    ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+    for ftype in integer*2 "integer(kind=2)"; do
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran \"$ftype\"" >&5
+$as_echo_n "checking for Fortran \"$ftype\"... " >&6; }
+        cat > conftest.$ac_ext <<_ACEOF
+
+               subroutine sub(value)
+               $ftype value
+               end
+
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	    NF_INT2_T=$ftype
+	    cat >>confdefs.h <<_ACEOF
+#define NF_INT2_T $ftype
+_ACEOF
+
+            break
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    done
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+    ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+    for ftype in integer*8 "integer(kind=8)"; do
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran \"$ftype\"" >&5
+$as_echo_n "checking for Fortran \"$ftype\"... " >&6; }
+        cat > conftest.$ac_ext <<_ACEOF
+
+               subroutine sub(value)
+               $ftype value
+               end
+
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	    NF_INT8_T=$ftype
+	    cat >>confdefs.h <<_ACEOF
+#define NF_INT8_T $ftype
+_ACEOF
+
+            break
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    done
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+    else
+
+        case "$FC" in
+	'') ;;
+	*)
+
+
+
+	    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C-equivalent to Fortran routine \"SUB\"" >&5
+$as_echo_n "checking for C-equivalent to Fortran routine \"SUB\"... " >&6; }
+            ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+case $ac_cv_fc_mangling in
+  upper*) ac_val="SUB" ;;
+  lower*) ac_val="sub" ;;
+  *)      ac_val="unknown" ;;
+esac
+case $ac_cv_fc_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac
+
+FCALLSCSUB="$ac_val"
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FCALLSCSUB" >&5
+$as_echo "$FCALLSCSUB" >&6; }
+	    ;;
+    esac
+
+
+        case "$FC" in
+    '')
+	;;
+    *)
+
+
+    ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+    for ftype in integer*1 byte "integer(kind=1)"; do
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran \"$ftype\"" >&5
+$as_echo_n "checking for Fortran \"$ftype\"... " >&6; }
+        cat > conftest.$ac_ext <<_ACEOF
+
+               subroutine sub(value)
+               $ftype value
+               end
+
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	    NF_INT1_T=$ftype
+	    cat >>confdefs.h <<_ACEOF
+#define NF_INT1_T $ftype
+_ACEOF
+
+            break
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    done
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+    ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+    for ftype in integer*2 "integer(kind=2)"; do
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran \"$ftype\"" >&5
+$as_echo_n "checking for Fortran \"$ftype\"... " >&6; }
+        cat > conftest.$ac_ext <<_ACEOF
+
+               subroutine sub(value)
+               $ftype value
+               end
+
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	    NF_INT2_T=$ftype
+	    cat >>confdefs.h <<_ACEOF
+#define NF_INT2_T $ftype
+_ACEOF
+
+            break
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    done
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+    ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+    for ftype in integer*8 "integer(kind=8)"; do
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran \"$ftype\"" >&5
+$as_echo_n "checking for Fortran \"$ftype\"... " >&6; }
+        cat > conftest.$ac_ext <<_ACEOF
+
+               subroutine sub(value)
+               $ftype value
+               end
+
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	    NF_INT8_T=$ftype
+	    cat >>confdefs.h <<_ACEOF
+#define NF_INT8_T $ftype
+_ACEOF
+
+            break
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    done
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+	case "${NF_INT1_T}" in
+	    '') ;;
+	    *)
+    cat >conftestf.f <<EOF
+           $NF_INT1_T values(4)
+           integer status, sub
+           data values /-1, -2, -3, -4/
+           status = sub(values)
+           end
+EOF
+    ac_cv_ctype_fortran=no
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Fortran \"$NF_INT1_T\" is " >&5
+$as_echo_n "checking if Fortran \"$NF_INT1_T\" is ... " >&6; }
+    for ctype in "signed char" short int long; do
+		cat >conftest.c <<EOF
+	    int $FCALLSCSUB($ctype values[4])
+	    {
+		return(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LDFLAGS} ${LIBS}'
+	        if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+		    doit=./conftest
+		    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+		        		        { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$ctype\" in C" >&5
+$as_echo "\"$ctype\" in C" >&6; }
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >>confdefs.h <<_ACEOF
+#define NF_INT1_IS_C_$cname 1
+_ACEOF
+
+                        ac_cv_ctype_fortran=yes
+		        break
+		    fi
+	        else
+		    as_fn_error $? "Could not link conftestf.o and conftest.o" "$LINENO" 5
+	        fi
+	    else
+		as_fn_error $? "Could not compile conftestf.f" "$LINENO" 5
+	    fi
+	else
+	    as_fn_error $? "Could not compile conftest.c" "$LINENO" 5
+	fi
+    done
+    ${RM} -f conftest*
+
+    if test "$ac_cv_ctype_fortran" = no ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no correspond data type in C" >&5
+$as_echo "no correspond data type in C" >&6; }
+    fi
+    unset ac_cv_ctype_fortran
+
+		;;
+	esac
+	case "${NF_INT2_T}" in
+	    '') ;;
+	    *)
+    cat >conftestf.f <<EOF
+           $NF_INT2_T values(4)
+           integer status, sub
+           data values /-1, -2, -3, -4/
+           status = sub(values)
+           end
+EOF
+    ac_cv_ctype_fortran=no
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Fortran \"$NF_INT2_T\" is " >&5
+$as_echo_n "checking if Fortran \"$NF_INT2_T\" is ... " >&6; }
+    for ctype in short int long; do
+		cat >conftest.c <<EOF
+	    int $FCALLSCSUB($ctype values[4])
+	    {
+		return(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LDFLAGS} ${LIBS}'
+	        if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+		    doit=./conftest
+		    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+		        		        { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$ctype\" in C" >&5
+$as_echo "\"$ctype\" in C" >&6; }
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >>confdefs.h <<_ACEOF
+#define NF_INT2_IS_C_$cname 1
+_ACEOF
+
+                        ac_cv_ctype_fortran=yes
+		        break
+		    fi
+	        else
+		    as_fn_error $? "Could not link conftestf.o and conftest.o" "$LINENO" 5
+	        fi
+	    else
+		as_fn_error $? "Could not compile conftestf.f" "$LINENO" 5
+	    fi
+	else
+	    as_fn_error $? "Could not compile conftest.c" "$LINENO" 5
+	fi
+    done
+    ${RM} -f conftest*
+
+    if test "$ac_cv_ctype_fortran" = no ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no correspond data type in C" >&5
+$as_echo "no correspond data type in C" >&6; }
+    fi
+    unset ac_cv_ctype_fortran
+
+		;;
+	esac
+	case "${NF_INT8_T}" in
+	    '') ;;
+	    *)
+    cat >conftestf.f <<EOF
+           $NF_INT8_T values(4)
+           integer status, sub
+           data values /-1, -2, -3, -4/
+           status = sub(values)
+           end
+EOF
+    ac_cv_ctype_fortran=no
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Fortran \"$NF_INT8_T\" is " >&5
+$as_echo_n "checking if Fortran \"$NF_INT8_T\" is ... " >&6; }
+    for ctype in int long "long long"; do
+		cat >conftest.c <<EOF
+	    int $FCALLSCSUB($ctype values[4])
+	    {
+		return(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LDFLAGS} ${LIBS}'
+	        if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+		    doit=./conftest
+		    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+		        		        { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$ctype\" in C" >&5
+$as_echo "\"$ctype\" in C" >&6; }
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >>confdefs.h <<_ACEOF
+#define NF_INT8_IS_C_$cname 1
+_ACEOF
+
+                        ac_cv_ctype_fortran=yes
+		        break
+		    fi
+	        else
+		    as_fn_error $? "Could not link conftestf.o and conftest.o" "$LINENO" 5
+	        fi
+	    else
+		as_fn_error $? "Could not compile conftestf.f" "$LINENO" 5
+	    fi
+	else
+	    as_fn_error $? "Could not compile conftest.c" "$LINENO" 5
+	fi
+    done
+    ${RM} -f conftest*
+
+    if test "$ac_cv_ctype_fortran" = no ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no correspond data type in C" >&5
+$as_echo "no correspond data type in C" >&6; }
+    fi
+    unset ac_cv_ctype_fortran
+
+		;;
+	esac
+
+    cat >conftestf.f <<EOF
+           integer values(4)
+           integer status, sub
+           data values /-1, -2, -3, -4/
+           status = sub(values)
+           end
+EOF
+    ac_cv_ctype_fortran=no
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Fortran \"integer\" is " >&5
+$as_echo_n "checking if Fortran \"integer\" is ... " >&6; }
+    for ctype in int long; do
+		cat >conftest.c <<EOF
+	    int $FCALLSCSUB($ctype values[4])
+	    {
+		return(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LDFLAGS} ${LIBS}'
+	        if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+		    doit=./conftest
+		    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+		        		        { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$ctype\" in C" >&5
+$as_echo "\"$ctype\" in C" >&6; }
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >>confdefs.h <<_ACEOF
+#define NF_INT_IS_C_$cname 1
+_ACEOF
+
+                        ac_cv_ctype_fortran=yes
+		        break
+		    fi
+	        else
+		    as_fn_error $? "Could not link conftestf.o and conftest.o" "$LINENO" 5
+	        fi
+	    else
+		as_fn_error $? "Could not compile conftestf.f" "$LINENO" 5
+	    fi
+	else
+	    as_fn_error $? "Could not compile conftest.c" "$LINENO" 5
+	fi
+    done
+    ${RM} -f conftest*
+
+    if test "$ac_cv_ctype_fortran" = no ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no correspond data type in C" >&5
+$as_echo "no correspond data type in C" >&6; }
+    fi
+    unset ac_cv_ctype_fortran
+
+
+    cat >conftestf.f <<EOF
+           real values(4)
+           integer status, sub
+           data values /-1, -2, -3, -4/
+           status = sub(values)
+           end
+EOF
+    ac_cv_ctype_fortran=no
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Fortran \"real\" is " >&5
+$as_echo_n "checking if Fortran \"real\" is ... " >&6; }
+    for ctype in float double; do
+		cat >conftest.c <<EOF
+	    int $FCALLSCSUB($ctype values[4])
+	    {
+		return(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LDFLAGS} ${LIBS}'
+	        if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+		    doit=./conftest
+		    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+		        		        { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$ctype\" in C" >&5
+$as_echo "\"$ctype\" in C" >&6; }
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >>confdefs.h <<_ACEOF
+#define NF_REAL_IS_C_$cname 1
+_ACEOF
+
+                        ac_cv_ctype_fortran=yes
+		        break
+		    fi
+	        else
+		    as_fn_error $? "Could not link conftestf.o and conftest.o" "$LINENO" 5
+	        fi
+	    else
+		as_fn_error $? "Could not compile conftestf.f" "$LINENO" 5
+	    fi
+	else
+	    as_fn_error $? "Could not compile conftest.c" "$LINENO" 5
+	fi
+    done
+    ${RM} -f conftest*
+
+    if test "$ac_cv_ctype_fortran" = no ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no correspond data type in C" >&5
+$as_echo "no correspond data type in C" >&6; }
+    fi
+    unset ac_cv_ctype_fortran
+
+
+    cat >conftestf.f <<EOF
+           doubleprecision values(4)
+           integer status, sub
+           data values /-1, -2, -3, -4/
+           status = sub(values)
+           end
+EOF
+    ac_cv_ctype_fortran=no
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Fortran \"doubleprecision\" is " >&5
+$as_echo_n "checking if Fortran \"doubleprecision\" is ... " >&6; }
+    for ctype in double float; do
+		cat >conftest.c <<EOF
+	    int $FCALLSCSUB($ctype values[4])
+	    {
+		return(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LDFLAGS} ${LIBS}'
+	        if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+		    doit=./conftest
+		    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$doit\""; } >&5
+  (eval $doit) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+		        		        { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$ctype\" in C" >&5
+$as_echo "\"$ctype\" in C" >&6; }
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >>confdefs.h <<_ACEOF
+#define NF_DOUBLEPRECISION_IS_C_$cname 1
+_ACEOF
+
+                        ac_cv_ctype_fortran=yes
+		        break
+		    fi
+	        else
+		    as_fn_error $? "Could not link conftestf.o and conftest.o" "$LINENO" 5
+	        fi
+	    else
+		as_fn_error $? "Could not compile conftestf.f" "$LINENO" 5
+	    fi
+	else
+	    as_fn_error $? "Could not compile conftest.c" "$LINENO" 5
+	fi
+    done
+    ${RM} -f conftest*
+
+    if test "$ac_cv_ctype_fortran" = no ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no correspond data type in C" >&5
+$as_echo "no correspond data type in C" >&6; }
+    fi
+    unset ac_cv_ctype_fortran
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran-equivalent to netCDF \"byte\"" >&5
+$as_echo_n "checking for Fortran-equivalent to netCDF \"byte\"... " >&6; }
+
+    ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+    for type in byte integer*1 integer; do
+        cat > conftest.$ac_ext <<_ACEOF
+
+               $type foo
+               end
+
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  break
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    done
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+    cat >>confdefs.h <<_ACEOF
+#define NCBYTE_T $type
+_ACEOF
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $type" >&5
+$as_echo "$type" >&6; }
+    NCBYTE_T=$type
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran-equivalent to netCDF \"short\"" >&5
+$as_echo_n "checking for Fortran-equivalent to netCDF \"short\"... " >&6; }
+
+    ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+    for type in integer*2 integer; do
+        cat > conftest.$ac_ext <<_ACEOF
+
+               $type foo
+               end
+
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  break
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    done
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+    cat >>confdefs.h <<_ACEOF
+#define NCSHORT_T $type
+_ACEOF
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $type" >&5
+$as_echo "$type" >&6; }
+    NCSHORT_T=$type
+
+
+
+
+	;;
+    esac
+
+    fi
+
+    NFMPI_OFFSET="integer*$ac_cv_sizeof_MPI_Offset"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran NFMPI_OFFSET \"$NFMPI_OFFSET\"" >&5
+$as_echo_n "checking for Fortran NFMPI_OFFSET \"$NFMPI_OFFSET\"... " >&6; }
+        ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+    cat > conftest.$ac_ext <<_ACEOF
+
+            subroutine sub(value)
+            $NFMPI_OFFSET value
+            end
+
+_ACEOF
+if ac_fn_f77_try_compile "$LINENO"; then :
+  ac_cv_NFMPI_OFFSET=yes
+else
+  ac_cv_NFMPI_OFFSET=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+    if test "$ac_cv_NFMPI_OFFSET" = yes ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+        as_fn_error $? "F77 does not support \"$NFMPI_OFFSET\"" "$LINENO" 5
+            fi
+    ${RM} -rf conftest*
+fi
+
+SIZEOF_MPI_OFFSET=$ac_cv_sizeof_MPI_Offset
+
+
+if test "x${enable_fortran}" = xyes ; then
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking Fortran 90 module extension" >&5
+$as_echo_n "checking Fortran 90 module extension... " >&6; }
+if ${ac_cv_fc_module_ext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+mkdir conftest.dir
+cd conftest.dir
+ac_cv_fc_module_ext=unknown
+cat > conftest.$ac_ext <<_ACEOF
+
+      module conftest_module
+      contains
+      subroutine conftest_routine
+      write(*,'(a)') 'gotcha!'
+      end subroutine
+      end module
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_cv_fc_module_ext=`ls | sed -n 's,conftest_module\.,,p'`
+   if test x$ac_cv_fc_module_ext = x; then
+     ac_cv_fc_module_ext=`ls | sed -n 's,CONFTEST_MODULE\.,,p'`
+   fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cd ..
+${RM} -rf conftest.dir
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_module_ext" >&5
+$as_echo "$ac_cv_fc_module_ext" >&6; }
+FC_MODEXT=$ac_cv_fc_module_ext
+if test "$FC_MODEXT" = unknown; then
+  FC_MODEXT=
+fi
+
+      if test "x${FC_MODEXT}" = x ; then
+      as_fn_error $? "cannot determine Fortran module file extension!" "$LINENO" 5
+   fi
+   if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: FC_MODEXT=$FC_MODEXT" >&5
+$as_echo "$as_me: DEBUG: FC_MODEXT=$FC_MODEXT" >&6;}
+          fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Fortran 90 module inclusion flag" >&5
+$as_echo_n "checking Fortran 90 module inclusion flag... " >&6; }
+if ${ac_cv_fc_module_flag+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+ac_cv_fc_module_flag=unknown
+mkdir conftest.dir
+cd conftest.dir
+cat > conftest.$ac_ext <<_ACEOF
+
+      module conftest_module
+      contains
+      subroutine conftest_routine
+      write(*,'(a)') 'gotcha!'
+      end subroutine
+      end module
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  cd ..
+   ac_fc_module_flag_FCFLAGS_save=$FCFLAGS
+   # Flag ordering is significant for gfortran and Sun.
+   for ac_flag in -I '-I ' -M '-M ' -p '-mod ' '-mdir ' '-module ' '-Am -I'; do
+     # Add the flag twice to prevent matching an output flag.
+     FCFLAGS="$ac_fc_module_flag_FCFLAGS_save ${ac_flag}conftest.dir ${ac_flag}conftest.dir"
+     cat > conftest.$ac_ext <<_ACEOF
+
+      program main
+      use conftest_module
+      call conftest_routine
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_cv_fc_module_flag="$ac_flag"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+     if test "$ac_cv_fc_module_flag" != unknown; then
+       break
+     fi
+   done
+   FCFLAGS=$ac_fc_module_flag_FCFLAGS_save
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+${RM} -rf conftest.dir
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_module_flag" >&5
+$as_echo "$ac_cv_fc_module_flag" >&6; }
+if test "$ac_cv_fc_module_flag" != unknown; then
+  FC_MODINC=$ac_cv_fc_module_flag
+
+else
+  FC_MODINC=
+  as_fn_error $? "unable to find compiler flag for module search path" "$LINENO" 5
+fi
+
+# Ensure trailing whitespace is preserved in a Makefile.
+ac_empty=""
+
+
+      if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: FC_MODINC=$FC_MODINC" >&5
+$as_echo "$as_me: DEBUG: FC_MODINC=$FC_MODINC" >&6;}
+          fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Fortran 90 module output flag" >&5
+$as_echo_n "checking Fortran 90 module output flag... " >&6; }
+if ${ac_cv_fc_module_output_flag+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+mkdir conftest.dir conftest.dir/sub
+cd conftest.dir
+ac_cv_fc_module_output_flag=unknown
+ac_fc_module_output_flag_FCFLAGS_save=$FCFLAGS
+# Flag ordering is significant: put flags late which some compilers use
+# for the search path.
+for ac_flag in -J '-J ' -fmod= -moddir= +moddir= -qmoddir= '-mod ' \
+	      '-mdir ' '-module ' -M '-Am -M' '-e m -J '; do
+  FCFLAGS="$ac_fc_module_output_flag_FCFLAGS_save ${ac_flag}sub"
+  cat > conftest.$ac_ext <<_ACEOF
+
+      module conftest_module
+      contains
+      subroutine conftest_routine
+      write(*,'(a)') 'gotcha!'
+      end subroutine
+      end module
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  cd sub
+     cat > conftest.$ac_ext <<_ACEOF
+
+      program main
+      use conftest_module
+      call conftest_routine
+      end
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+  ac_cv_fc_module_output_flag="$ac_flag"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+     cd ..
+     if test "$ac_cv_fc_module_output_flag" != unknown; then
+       break
+     fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+FCFLAGS=$ac_fc_module_output_flag_FCFLAGS_save
+cd ..
+${RM} -rf conftest.dir
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fc_module_output_flag" >&5
+$as_echo "$ac_cv_fc_module_output_flag" >&6; }
+if test "$ac_cv_fc_module_output_flag" != unknown; then
+  FC_MODOUT=$ac_cv_fc_module_output_flag
+
+else
+  FC_MODOUT=
+  as_fn_error $? "unable to find compiler flag to write module information to" "$LINENO" 5
+fi
+
+# Ensure trailing whitespace is preserved in a Makefile.
+ac_empty=""
+
+
+      if test "x${_DEBUG}" = xyes ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: DEBUG: FC_MODOUT=$FC_MODOUT" >&5
+$as_echo "$as_me: DEBUG: FC_MODOUT=$FC_MODOUT" >&6;}
+          fi
+
+
+fi
+
+if test "x${enable_fortran}" = xyes ; then
+
+
+ac_ext=${ac_fc_srcext-f}
+ac_compile='$FC -c $FCFLAGS $ac_fcflags_srcext conftest.$ac_ext >&5'
+ac_link='$FC -o conftest$ac_exeext $FCFLAGS $LDFLAGS $ac_fcflags_srcext conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_fc_compiler_gnu
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if Fortran 90 compiler capitalizes .mod filenames" >&5
+$as_echo_n "checking if Fortran 90 compiler capitalizes .mod filenames... " >&6; }
+cat > conftest.$ac_ext <<_ACEOF
+
+        module conftest
+        end module conftest
+
+
+_ACEOF
+if ac_fn_fc_try_compile "$LINENO"; then :
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test -f conftest.${FC_MODEXT} ; then
+   ac_cv_prog_f90_uppercase_mod=no
+else
+   ac_cv_prog_f90_uppercase_mod=yes
+   ${RM} -f CONFTEST.${FC_MODEXT}
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_f90_uppercase_mod" >&5
+$as_echo "$ac_cv_prog_f90_uppercase_mod" >&6; }
+${RM} -f conftest*
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+UPPER_CASE_MOD=no
+if test "x$ac_cv_prog_f90_uppercase_mod" = xyes ; then
+   UPPER_CASE_MOD=yes
+fi
+
+
+if test "x${enable_fortran}" = xyes ; then
+   if test "x${enable_strict}" = xyes; then
+      FPPFLAGS="${FPPFLAGS} -Wall"
+   fi
+
+
+
+
+
+fi
+
+has_fortran=${enable_fortran}
+
+
+
+    #
+    # NB: We always want to define WHATIS to prevent the
+    # $(MANDIR)/$(WHATIS) make(1) target from being just $(MANDIR)/ and
+    # conflicting with the (directory creation) target with the same name.
+    #
+    WHATIS=whatis
+    case `uname -sr` in
+	BSD/OS*|FreeBSD*)
+	    # Can't generate a user-database -- only /usr/share/man/whatis.db.
+	    MAKEWHATIS_CMD=
+	    ;;
+	'IRIX64 6.5'|'IRIX 6.5')
+	    MAKEWHATIS_CMD='/usr/lib/makewhatis -M $(MANDIR) $(MANDIR)/whatis'
+	    ;;
+	'IRIX 6'*)
+	    # Can't generate a user-database.
+	    MAKEWHATIS_CMD=
+	    ;;
+	HP-UX*)
+	    # Can't generate a user-database -- only /usr/lib/whatis.
+	    MAKEWHATIS_CMD=
+	    ;;
+	'Linux '*)
+	    # /usr/sbin/makewhatis doesn't work
+	    MAKEWHATIS_CMD=
+	    ;;
+	ULTRIX*)
+	    # Can't generate a user-database -- only /usr/lib/whatis.
+	    MAKEWHATIS_CMD=
+	    ;;
+	*)
+	    if test -r /usr/man/windex; then
+		WHATIS=windex
+	    fi
+	    for ac_prog in catman makewhatis /usr/lib/makewhatis
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_prog+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$prog"; then
+  ac_cv_prog_prog="$prog" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_prog="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+prog=$ac_cv_prog_prog
+if test -n "$prog"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $prog" >&5
+$as_echo "$prog" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$prog" && break
+done
+
+	    case "$prog" in
+		*catman*)
+		    MAKEWHATIS_CMD=$prog' -w -M $(MANDIR)'
+		    ;;
+		*makewhatis*)
+		    MAKEWHATIS_CMD=$prog' $(MANDIR)'
+		    ;;
+	    esac
+	    ;;
+    esac
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for manual-page index command" >&5
+$as_echo_n "checking for manual-page index command... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKEWHATIS_CMD" >&5
+$as_echo "$MAKEWHATIS_CMD" >&6; }
+
+
+# Check whether --enable-coverage was given.
+if test "${enable_coverage+set}" = set; then :
+  enableval=$enable_coverage; enable_coverage=${enableval}
+else
+  enable_coverage=no
+
+fi
+
+if test "x${enable_coverage}" = xyes; then
+   if test "x${GCC}" = xyes; then
+              LCOV_FLAGS="-pg -fprofile-arcs -ftest-coverage --coverage -O0"
+       CFLAGS="${CFLAGS} ${LCOV_FLAGS}"
+       if test "x${has_mpicxx}" = xyes ; then
+          CXXFLAGS="${CXXFLAGS} ${LCOV_FLAGS}"
+       fi
+       if test "x${enable_fortran}" = xyes ; then
+           FCFLAGS="${FCFLAGS}  ${LCOV_FLAGS}"
+          F77FLAGS="${F77FLAGS} ${LCOV_FLAGS}"
+          F90FLAGS="${F90FLAGS} ${LCOV_FLAGS}"
+       fi
+       LCOV_LIB=-lgcov
+
+   else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-coverage is for GNU compiler only" >&5
+$as_echo "$as_me: WARNING: --enable-coverage is for GNU compiler only" >&2;}
+      enable_coverage=no
+   fi
+fi
+
+
+if test "x${has_mpicxx}" = xyes ; then
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if C++ macro __func__ or __FUNCTION__ is defined" >&5
+$as_echo_n "checking if C++ macro __func__ or __FUNCTION__ is defined... " >&6; }
+if ${ac_cv_cxx_macro_func+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_cxx_macro_func=no
+    ac_cv_cxx_macro_function=no
+    ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <iostream>
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+std::cout << __func__;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_cxx_macro_func=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <iostream>
+#ifdef FC_DUMMY_MAIN
+#ifndef FC_DUMMY_MAIN_EQ_F77
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int FC_DUMMY_MAIN() { return 1; }
+#endif
+#endif
+int
+main ()
+{
+std::cout << __FUNCTION__;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_cxx_macro_function=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_macro_func" >&5
+$as_echo "$ac_cv_cxx_macro_func" >&6; }
+
+   if test "x${ac_cv_cxx_macro_func}" == xyes ; then
+      $as_echo "#define HAVE_FUNC_MACRO 1" >>confdefs.h
+
+   fi
+   if test "x${ac_cv_cxx_macro_function}" == xyes ; then
+      $as_echo "#define HAVE_FUNCTION_MACRO 1" >>confdefs.h
+
+   fi
+fi
+
+if test "x${debug}" = xyes; then
+            if ! echo "${CFLAGS}" | ${EGREP} -q -- "-g" ; then
+      CFLAGS="${CFLAGS} -g"
+   fi
+   CFLAGS=`echo $CFLAGS | sed 's/-O. *//g' | sed 's/-fast *//g'`
+   CFLAGS="${CFLAGS} -O0"
+
+   if test "x${has_mpicxx}" = xyes ; then
+      if ! echo "${CXXFLAGS}" | ${EGREP} -q -- "-g" ; then
+         CXXFLAGS="${CXXFLAGS} -g"
+      fi
+      CXXFLAGS=`echo $CXXFLAGS | sed 's/-O. *//g' | sed 's/-fast *//g'`
+      CXXFLAGS="${CXXFLAGS} -O0"
+   fi
+
+   if test "x${enable_fortran}" = xyes ; then
+      if ! echo "${FCFLAGS}" | ${EGREP} -q -- "-g" ; then
+         FCFLAGS="${FCFLAGS} -g"
+      fi
+      if ! echo "${F77FLAGS}" | ${EGREP} -q -- "-g" ; then
+         F77FLAGS="${F77FLAGS} -g"
+      fi
+      if ! echo "${F90FLAGS}" | ${EGREP} -q -- "-g" ; then
+         F90FLAGS="${F90FLAGS} -g"
+      fi
+
+       FCFLAGS=`echo $FCFLAGS | sed 's/-O. *//g' | sed 's/-fast *//g'`
+      F77FLAGS=`echo $F77FLAGS | sed 's/-O. *//g' | sed 's/-fast *//g'`
+      F90FLAGS=`echo $F90FLAGS | sed 's/-O. *//g' | sed 's/-fast *//g'`
+       FCFLAGS="${FCFLAGS}  -O0"
+      F77FLAGS="${F77FLAGS} -O0"
+      F90FLAGS="${F90FLAGS} -O0"
+   fi
+fi
+
+chmod u+x ${srcdir}/scripts/install-sh
+
+# Check whether --enable-subfiling was given.
+if test "${enable_subfiling+set}" = set; then :
+  enableval=$enable_subfiling; enable_subfiling=${enableval}
+else
+  enable_subfiling=no
+
+fi
+
+if test "x$enable_subfiling" = "xyes" ; then
+   $as_echo "#define ENABLE_SUBFILING 1" >>confdefs.h
+
+
+fi
+
+# Extract the first word of "latex", so it can be a program name with args.
+set dummy latex; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_LATEX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $LATEX in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LATEX="$LATEX" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_LATEX="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+LATEX=$ac_cv_path_LATEX
+if test -n "$LATEX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LATEX" >&5
+$as_echo "$LATEX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "dvipdf", so it can be a program name with args.
+set dummy dvipdf; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_DVIPDF+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $DVIPDF in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_DVIPDF="$DVIPDF" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_DVIPDF="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+DVIPDF=$ac_cv_path_DVIPDF
+if test -n "$DVIPDF"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DVIPDF" >&5
+$as_echo "$DVIPDF" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+has_latex=no
+if test "x${LATEX}" != x ; then
+    has_latex=yes
+fi
+
+
+
+
+BUILDDIR=`pwd`
+
+
+# Check whether --enable-file-sync was given.
+if test "${enable_file_sync+set}" = set; then :
+  enableval=$enable_file_sync; file_sync=${enableval}
+else
+  file_sync=yes
+
+fi
+
+if test "x${file_sync}" = xno ; then
+    $as_echo "#define DISABLE_FILE_SYNC 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-large-file-test was given.
+if test "${enable_large_file_test+set}" = set; then :
+  enableval=$enable_large_file_test; large_file_test=${enableval}
+else
+  large_file_test=no
+
+fi
+
+
+
+PNETCDF_INC=${BUILDDIR}/src/libf90
+PNETCDF_LIB="-L${BUILDDIR}/src/lib"
+
+
+
+
+
+
+if test "x${TEST_MPIRUN}" = x ; then
+        TEST_MPIRUN="mpiexec -n NP"
+fi
+if test "x${TEST_OUTDIR}" = x ; then
+        TEST_OUTDIR=.
+fi
+
+
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_SEQ_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $SEQ_CC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_SEQ_CC="$SEQ_CC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_SEQ_CC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_SEQ_CC" && ac_cv_path_SEQ_CC="$MPICC"
+  ;;
+esac
+fi
+SEQ_CC=$ac_cv_path_SEQ_CC
+if test -n "$SEQ_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SEQ_CC" >&5
+$as_echo "$SEQ_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+ac_config_headers="$ac_config_headers src/libf/nfconfig_inc"
+
+ac_config_files="$ac_config_files macros.make Makefile src/Makefile src/lib/Makefile src/lib/pnetcdf.h src/utils/Makefile src/utils/ncmpidump/Makefile src/utils/ncmpidiff/Makefile src/utils/ncmpigen/Makefile src/utils/ncmpivalid/Makefile src/utils/pnetcdf_version/Makefile src/utils/ncoffsets/Makefile test/Makefile test/common/Makefile test/nc_test/Makefile test/C/Makefile test/fandc/Makefile test/testcases/Makefile test/nonblocking/Makefile test/header/Makefile test/cdf_format/Makefile t [...]
+
+
+# The following dependency is for configure.in and configure
+# See autoconf manual 2.69, Section 4.8.5 Automatic Remaking
+ac_config_files="$ac_config_files stamp-h"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+case $FC_MODINC in #(
+  *\ ) FC_MODINC=$FC_MODINC'${ac_empty}' ;;
+esac
+case $FC_MODOUT in #(
+  *\ ) FC_MODOUT=$FC_MODOUT'${ac_empty}' ;;
+esac
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by parallel-netcdf $as_me 1.7.0.pre1, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <parallel-netcdf at mcs.anl.gov>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+parallel-netcdf config.status 1.7.0.pre1
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "src/lib/ncconfig.h") CONFIG_HEADERS="$CONFIG_HEADERS src/lib/ncconfig.h" ;;
+    "src/libf/nfconfig_inc") CONFIG_HEADERS="$CONFIG_HEADERS src/libf/nfconfig_inc" ;;
+    "macros.make") CONFIG_FILES="$CONFIG_FILES macros.make" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+    "src/lib/Makefile") CONFIG_FILES="$CONFIG_FILES src/lib/Makefile" ;;
+    "src/lib/pnetcdf.h") CONFIG_FILES="$CONFIG_FILES src/lib/pnetcdf.h" ;;
+    "src/utils/Makefile") CONFIG_FILES="$CONFIG_FILES src/utils/Makefile" ;;
+    "src/utils/ncmpidump/Makefile") CONFIG_FILES="$CONFIG_FILES src/utils/ncmpidump/Makefile" ;;
+    "src/utils/ncmpidiff/Makefile") CONFIG_FILES="$CONFIG_FILES src/utils/ncmpidiff/Makefile" ;;
+    "src/utils/ncmpigen/Makefile") CONFIG_FILES="$CONFIG_FILES src/utils/ncmpigen/Makefile" ;;
+    "src/utils/ncmpivalid/Makefile") CONFIG_FILES="$CONFIG_FILES src/utils/ncmpivalid/Makefile" ;;
+    "src/utils/pnetcdf_version/Makefile") CONFIG_FILES="$CONFIG_FILES src/utils/pnetcdf_version/Makefile" ;;
+    "src/utils/ncoffsets/Makefile") CONFIG_FILES="$CONFIG_FILES src/utils/ncoffsets/Makefile" ;;
+    "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
+    "test/common/Makefile") CONFIG_FILES="$CONFIG_FILES test/common/Makefile" ;;
+    "test/nc_test/Makefile") CONFIG_FILES="$CONFIG_FILES test/nc_test/Makefile" ;;
+    "test/C/Makefile") CONFIG_FILES="$CONFIG_FILES test/C/Makefile" ;;
+    "test/fandc/Makefile") CONFIG_FILES="$CONFIG_FILES test/fandc/Makefile" ;;
+    "test/testcases/Makefile") CONFIG_FILES="$CONFIG_FILES test/testcases/Makefile" ;;
+    "test/nonblocking/Makefile") CONFIG_FILES="$CONFIG_FILES test/nonblocking/Makefile" ;;
+    "test/header/Makefile") CONFIG_FILES="$CONFIG_FILES test/header/Makefile" ;;
+    "test/cdf_format/Makefile") CONFIG_FILES="$CONFIG_FILES test/cdf_format/Makefile" ;;
+    "test/largefile/Makefile") CONFIG_FILES="$CONFIG_FILES test/largefile/Makefile" ;;
+    "examples/C/Makefile") CONFIG_FILES="$CONFIG_FILES examples/C/Makefile" ;;
+    "examples/tutorial/Makefile") CONFIG_FILES="$CONFIG_FILES examples/tutorial/Makefile" ;;
+    "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;;
+    "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
+    "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
+    "scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
+    "benchmarks/Makefile") CONFIG_FILES="$CONFIG_FILES benchmarks/Makefile" ;;
+    "benchmarks/C/Makefile") CONFIG_FILES="$CONFIG_FILES benchmarks/C/Makefile" ;;
+    "test/nf_test/Makefile") CONFIG_FILES="$CONFIG_FILES test/nf_test/Makefile" ;;
+    "test/nf_test/tests.inc") CONFIG_FILES="$CONFIG_FILES test/nf_test/tests.inc" ;;
+    "test/nf90_test/Makefile") CONFIG_FILES="$CONFIG_FILES test/nf90_test/Makefile" ;;
+    "test/F90/Makefile") CONFIG_FILES="$CONFIG_FILES test/F90/Makefile" ;;
+    "examples/F77/Makefile") CONFIG_FILES="$CONFIG_FILES examples/F77/Makefile" ;;
+    "examples/F90/Makefile") CONFIG_FILES="$CONFIG_FILES examples/F90/Makefile" ;;
+    "src/libf90/Makefile") CONFIG_FILES="$CONFIG_FILES src/libf90/Makefile" ;;
+    "src/libf90/api.f90") CONFIG_FILES="$CONFIG_FILES src/libf90/api.f90" ;;
+    "src/libf90/nfmpi_constants.f90") CONFIG_FILES="$CONFIG_FILES src/libf90/nfmpi_constants.f90" ;;
+    "src/libf/Makefile") CONFIG_FILES="$CONFIG_FILES src/libf/Makefile" ;;
+    "src/libf/pnetcdf.inc") CONFIG_FILES="$CONFIG_FILES src/libf/pnetcdf.inc" ;;
+    "src/libcxx/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcxx/Makefile" ;;
+    "examples/CXX/Makefile") CONFIG_FILES="$CONFIG_FILES examples/CXX/Makefile" ;;
+    "test/CXX/Makefile") CONFIG_FILES="$CONFIG_FILES test/CXX/Makefile" ;;
+    "benchmarks/FLASH-IO/Makefile") CONFIG_FILES="$CONFIG_FILES benchmarks/FLASH-IO/Makefile" ;;
+    "test/subfile/Makefile") CONFIG_FILES="$CONFIG_FILES test/subfile/Makefile" ;;
+    "stamp-h") CONFIG_FILES="$CONFIG_FILES stamp-h" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+ ;;
+
+
+  esac
+
+
+  case $ac_file$ac_mode in
+    "stamp-h":F) echo timestamp > stamp-h ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+echo "--------------------------------------------------------------------"
+
+if test "x${enable_mpi_io_test}" = xno ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+       NOTE: disabling the MPI-IO test is a VERY bad idea.
+       Please make sure you know what you are doing" >&5
+$as_echo "$as_me: WARNING:
+       NOTE: disabling the MPI-IO test is a VERY bad idea.
+       Please make sure you know what you are doing" >&2;}
+fi
+
+msg_large_files=no
+if test "$ac_cv_sizeof_off_t" -gt 4 ; then
+   msg_large_files=yes
+fi
+
+echo \
+"
+   ${PACKAGE_NAME} Version ${PACKAGE_VERSION}
+
+   Features:  Support for large files (> 4 GB) - ${msg_large_files}
+              Build C++ APIs                   - ${has_mpicxx}
+              Build Fortran APIs               - ${enable_fortran}
+              Build nonblocking APIs           - ${enable_nonblocking}
+              Build CDF-5 support              - ${enable_cdf5}
+              Build subfiling support          - ${enable_subfiling}"
+if test "x${ac_cv_c_bigendian}" = xno  && (test "x${in_place_swap}" = xno) ; then
+   echo "\
+              Memory in-place byte swap        - disabled"
+fi
+if test "x${large_file_test}" = xyes; then
+   echo "\
+              Testing large file/variable I/O  - enabled"
+fi
+if test "x${debug}" = xyes; then
+   echo "\
+              PnetCDF internal debug mode      - enabled"
+fi
+if test "x${enable_fortran}" = xyes && (test "x${F77_SUPPORT_FREEFORM}" = xno) ; then
+   echo "\
+              Support free form in Fortran 77  - no"
+fi
+
+echo "\
+
+   Compilers: MPICC       = ${MPICC}"
+if test "${has_mpicxx}" = yes ; then
+   echo "\
+              MPICXX      = ${MPICXX}"
+fi
+if test "${enable_fortran}" = yes ; then
+   echo "\
+              MPIF77      = ${MPIF77}
+              MPIF90      = ${MPIF90}"
+fi
+echo "\
+              CFLAGS      = ${CFLAGS}"
+if test "x${CPPFLAGS}" != x ; then
+   echo "\
+              CPPFLAGS    = ${CPPFLAGS}"
+fi
+if test "${has_mpicxx}" = yes ; then
+   echo "\
+              CXXFLAGS    = ${CXXFLAGS}"
+   if test "x${CXXCPPFLAGS}" != x ; then
+      echo "\
+              CXXCPPFLAGS = ${CXXCPPFLAGS}"
+   fi
+fi
+if test "${enable_fortran}" = yes ; then
+   echo "\
+              F77FLAGS    = ${F77FLAGS}
+              F90FLAGS    = ${F90FLAGS}"
+   if test "x${FPPFLAGS}" != x ; then
+      echo "\
+              FPPFLAGS    = ${FPPFLAGS}"
+   fi
+fi
+if test "x${LDFLAGS}" != x ; then
+   echo "\
+              LDFLAGS     = ${LDFLAGS}"
+fi
+if test "x${LIBS}" != x ; then
+   echo "\
+              LIBS        = ${LIBS}"
+fi
+echo "\
+
+   Now type 'make' to build the library and utility tools.
+   Type 'make [<target>]'
+       where the optional <target> is:
+           testing          - test PnetCDF build for sequential run
+           ptest            - test PnetCDF build for parallel run
+           install          - install PnetCDF
+---------------------------------------------------------------------"
+
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..3a5dff8
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,1269 @@
+AC_REVISION($Id: configure.in 2304 2016-01-12 18:39:01Z wkliao $)dnl
+dnl -*- Mode: shell-script-mode; -*-
+dnl Process this file with GNU autoconf(1) to produce a configure script.
+dnl
+
+AC_PREREQ([2.59])
+AC_INIT([parallel-netcdf],[1.7.0.pre1],[parallel-netcdf at mcs.anl.gov])
+
+dnl ncconfig.h.in will be created by autoreconf (autoheader)
+AC_CONFIG_HEADERS([src/lib/ncconfig.h])
+AC_CONFIG_SRCDIR([src/lib/pnetcdf.h.in])
+
+AC_CONFIG_AUX_DIR([./scripts])
+
+CONFIGURE_ARGS_CLEAN=`echo $* | tr '"' ' '`
+
+dnl parse the version numbers to 4 env variables
+PNETCDF_VERSION_MAJOR=`echo ${PACKAGE_VERSION} | cut -d. -f1`
+PNETCDF_VERSION_MINOR=`echo ${PACKAGE_VERSION} | cut -d. -f2`
+PNETCDF_VERSION_SUB=`echo ${PACKAGE_VERSION} | cut -d. -f3`
+PNETCDF_VERSION_PRE=`echo ${PACKAGE_VERSION} | cut -d. -f4`
+
+dnl Note major, minor, and sub are required, but pre is not.
+PNETCDF_VERSION=${PACKAGE_VERSION}
+
+dnl Do not change the following line, It is set by SVN automatically.
+dnl It defines PNETCDF_RELEASE_DATE, a string that will be used in
+dnl ncmpi_inq_libvers() to generate release date
+SVN_DATE="$LastChangedDate: 2016-01-12 12:39:01 -0600 (Tue, 12 Jan 2016) $"
+PNETCDF_RELEASE_DATE2=`echo $SVN_DATE | cut -d' ' -f2`
+PNETCDF_RELEASE_DATE=`echo $SVN_DATE | cut -d' ' -f6,7,8 | cut -d')' -f1`
+
+dnl user defined macro for printing messages for debugging
+_DEBUG=no
+AC_DEFUN([UD_MSG_DEBUG],
+         [if test "x${_DEBUG}" = xyes ; then
+             AC_MSG_NOTICE([DEBUG: $1])
+          fi
+         ]
+)
+
+UD_MSG_DEBUG([PNETCDF_VERSION_MAJOR=$PNETCDF_VERSION_MAJOR])
+UD_MSG_DEBUG([PNETCDF_VERSION_MINOR=$PNETCDF_VERSION_MINOR])
+UD_MSG_DEBUG([PNETCDF_VERSION_SUB=$PNETCDF_VERSION_SUB])
+UD_MSG_DEBUG([PNETCDF_VERSION_PRE=$PNETCDF_VERSION_PRE])
+UD_MSG_DEBUG([PNETCDF_VERSION=$PNETCDF_VERSION])
+UD_MSG_DEBUG([PNETCDF_RELEASE_DATE=$PNETCDF_RELEASE_DATE])
+
+AC_DEFINE_UNQUOTED(PNETCDF_VERSION_MAJOR, $PNETCDF_VERSION_MAJOR, major version number)
+AC_DEFINE_UNQUOTED(PNETCDF_VERSION_MINOR, $PNETCDF_VERSION_MINOR, minor version number)
+AC_DEFINE_UNQUOTED(PNETCDF_VERSION_SUB, $PNETCDF_VERSION_SUB, sub version number)
+AC_DEFINE_UNQUOTED(PNETCDF_VERSION_PRE, $PNETCDF_VERSION_PRE, pre-release string)
+AC_DEFINE_UNQUOTED(PNETCDF_VERSION, ["$PNETCDF_VERSION"], full PnetCDF version string)
+AC_DEFINE_UNQUOTED(PNETCDF_RELEASE_DATE, ["$PNETCDF_RELEASE_DATE"], PnetCDF release date string)
+AC_DEFINE_UNQUOTED(CONFIGURE_ARGS_CLEAN, ["$CONFIGURE_ARGS_CLEAN"], configure command-line arguments used)
+
+AC_SUBST(PNETCDF_VERSION_MAJOR)
+AC_SUBST(PNETCDF_VERSION_MINOR)
+AC_SUBST(PNETCDF_VERSION_SUB)
+AC_SUBST(PNETCDF_VERSION_PRE)
+AC_SUBST(PNETCDF_VERSION)
+AC_SUBST(PNETCDF_RELEASE_DATE)
+AC_SUBST(PNETCDF_RELEASE_DATE2)
+AC_SUBST(PACKAGE_VERSION)
+AC_SUBST(CONFIGURE_ARGS_CLEAN)
+
+dnl these used to live in acconfig.h
+dnl autoheader only adds these templates to the first invocation of AC_CONFIG_HEADERS
+AH_TEMPLATE([NCBYTE_T],                 [Type of NC_BYTE])
+AH_TEMPLATE([NCSHORT_T],                [Type of NC_SHORT])
+AH_TEMPLATE([NF_DOUBLEPRECISION_IS_C_], [C type for Fortran double])
+AH_TEMPLATE([NF_INT1_IS_C_],            [C type for Fortran INT1])
+AH_TEMPLATE([NF_INT1_T],                [Type for Fortran INT1])
+AH_TEMPLATE([NF_INT2_IS_C_],            [C type for Fortran INT2])
+AH_TEMPLATE([NF_INT2_T],                [Type for Fortran INT2])
+AH_TEMPLATE([NF_INT_IS_C_],             [C type for Fortran INT])
+AH_TEMPLATE([NF_INT8_IS_C_],            [C type for Fortran INT8])
+AH_TEMPLATE([NF_INT8_T],                [Type for Fortran INT8])
+AH_TEMPLATE([NF_REAL_IS_C_],            [C type for Fortran REAL])
+AH_TEMPLATE([NO_IEEE_FLOAT],            [Does system have IEEE FLOAT])
+AH_TEMPLATE([DISABLE_FILE_SYNC],        [Define if to disable MPI_File_sync])
+AH_TEMPLATE([DISABLE_IN_PLACE_SWAP],    [Define if to disable in-place byte swap])
+AH_TEMPLATE([ENABLE_SUBFILING],         [Define if to enable subfiling feature])
+AH_TEMPLATE([PNC_DEBUG],                [Define if to enable debugging])
+AH_TEMPLATE([PNC_MALLOC_TRACE],         [Define if to enable malloc tracing])
+AH_TEMPLATE([HAVE_FUNC_MACRO],          [Define if C++ macro __func__ is defined])
+AH_TEMPLATE([HAVE_FUNCTION_MACRO],      [Define if C++ macro __FUNCTION__ is defined])
+
+dnl an option to use a customized rm command
+AC_ARG_VAR(RM, Command for deleting files or directories. default: rm)
+if test "x${RM}" != x ; then
+   AC_MSG_CHECKING(rm )
+   if ! test -f ${RM} ; then
+      AC_CHECK_PROG([rm_cmd], [${RM}], [yes], [no])
+      if test "x${rm_cmd}" = xyes ; then
+         RM=${RM}
+      fi
+   else
+      RM=${RM}
+   fi
+   AC_MSG_RESULT(using $RM)
+else
+   RM="rm"
+fi
+AC_SUBST(RM)
+
+AC_ARG_ENABLE(echo,
+   [AS_HELP_STRING([--enable-echo],
+                   [Turn on strong echoing. @<:@default: disabled@:>@])],
+   [set -x]
+)
+
+MPI_INSTALL=
+AC_ARG_WITH(mpi,
+   [AS_HELP_STRING([--with-mpi=/path/to/implementation],
+                   [installation prefix for MPI implementation])],
+   if test x"$withval" = xyes; then
+      AC_MSG_ERROR(--with-mpi must be given a pathname)
+   else
+      MPI_INSTALL=${withval}
+   fi
+)
+if test "x${MPI_INSTALL}" != x && (! test -d "${MPI_INSTALL}") ; then
+   AC_MSG_ERROR(Directory '${MPI_INSTALL}' specified in --with-mpi does not exist)
+fi
+
+AC_ARG_VAR(MPICC,  MPI C compiler)
+AC_ARG_VAR(MPICXX, MPI C++ compiler)
+AC_ARG_VAR(MPIF77, MPI Fortran 77 compiler)
+AC_ARG_VAR(MPIF90, MPI Fortran 90 compiler)
+AC_ARG_VAR(CC,     Overwritten by MPICC  if MPICC is set)
+AC_ARG_VAR(CXX,    Overwritten by MPICXX if MPICXX is set)
+AC_ARG_VAR(F77,    Overwritten by MPIF77 if MPIF77 is set)
+AC_ARG_VAR(FC,     Overwritten by MPIF90 if MPIF90 is set)
+AC_ARG_VAR(CFLAGS, Debugging and optimization options for the C compiler)
+AC_ARG_VAR(CPPFLAGS, [Preprocessor options for the C and C++ compilers, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir>])
+AC_ARG_VAR(CXXFLAGS, Debugging and optimization options for the C compiler)
+AC_ARG_VAR(FFLAGS, Debugging and optimization options for the Fortran 77 compiler)
+AC_ARG_VAR(FCFLAGS, Debugging and optimization options for the Fortran 90 compiler)
+
+dnl Check if MPICC, MPICXX, MPIF77, MPIF90 are set by the user.
+dnl If not, set MPICC equal to CC. Similarly, for MPICXX, MPIF77, and MPIF90
+if test "x$MPICC"  = x && test "x$CC"  != x ; then MPICC=$CC   ; fi
+if test "x$MPICXX" = x && test "x$CXX" != x ; then MPICXX=$CXX ; fi
+if test "x$MPIF77" = x && test "x$F77" != x ; then MPIF77=$F77 ; fi
+if test "x$MPIF77" = x && test "x$FC"  != x ; then MPIF77=$FC  ; fi
+if test "x$MPIF90" = x && test "x$F90" != x ; then MPIF90=$F90 ; fi
+if test "x$MPIF90" = x && test "x$FC"  != x ; then MPIF90=$FC  ; fi
+
+CANDIDATE_MPICC="${MPICC} mpicc"
+CANDIDATE_MPICXX="${MPICXX} mpicxx mpic++ mpiCC"
+CANDIDATE_MPIF77="${MPIF77} mpif77"
+CANDIDATE_MPIF90="${MPIF90} mpif90"
+
+dnl add IBM MPI compilers
+CANDIDATE_MPICC="${CANDIDATE_MPICC} mpcc_r mpcc mpixlc_r mpixlc"
+CANDIDATE_MPICXX="${CANDIDATE_MPICXX} mpCC_r mpCC mpixlcxx_r mpixlcxx mpixlC_r mpixlC"
+CANDIDATE_MPIF77="${CANDIDATE_MPIF77} mpixlf77_r mpixlf77"
+CANDIDATE_MPIF90="${CANDIDATE_MPIF90} mpixlf90_r mpixlf90"
+
+dnl add IBM BGL MPI compilers
+CANDIDATE_MPICC="${CANDIDATE_MPICC} blrts_xlc mpxlc_r mpxlc"
+CANDIDATE_MPICXX="${CANDIDATE_MPICXX} blrts_xlC mpxlC_r mpxlC"
+CANDIDATE_MPIF77="${CANDIDATE_MPIF77} blrts_xlf mpxlf_r mpxlf"
+CANDIDATE_MPIF90="${CANDIDATE_MPIF90} blrts_xlf90 mpxlf90_r mpxlf90 mpxlf95_r mpxlf95"
+
+dnl add Fujitsu MPI compilers
+CANDIDATE_MPICC="${CANDIDATE_MPICC} mpifccpx"
+CANDIDATE_MPICXX="${CANDIDATE_MPICXX} mpiFCCpx"
+CANDIDATE_MPIF77="${CANDIDATE_MPIF77} mpifrtpx"
+CANDIDATE_MPIF90="${CANDIDATE_MPIF90} mpifrtpx"
+
+dnl add Cray MPI compiler wrappers
+CANDIDATE_MPICC="${CANDIDATE_MPICC} cc"
+CANDIDATE_MPICXX="${CANDIDATE_MPICXX} CC"
+CANDIDATE_MPIF77="${CANDIDATE_MPIF77} ftn"
+CANDIDATE_MPIF90="${CANDIDATE_MPIF90} ftn"
+
+dnl add Intel MPI compiler wrappers
+CANDIDATE_MPICC="${CANDIDATE_MPICC} mpiicc icc"
+CANDIDATE_MPICXX="${CANDIDATE_MPICXX} mpiicpc icpc"
+CANDIDATE_MPIF77="${CANDIDATE_MPIF77} mpiifort mpiifc ifort"
+CANDIDATE_MPIF90="${CANDIDATE_MPIF90} mpiifort mpiifc ifort"
+
+UD_CHECK_MPI_COMPILER([MPICC], [$CANDIDATE_MPICC])
+if test "x${MPICC}" = x ; then
+   AC_MSG_ERROR([
+   -----------------------------------------------------------------------
+    No MPI C compiler can be found. Parallel netCDF requires an MPI C
+    compiler. Please specify the location of one either with the MPICC
+    environment variable or the --with-mpi configure flag
+   -----------------------------------------------------------------------])
+fi
+
+CC=${MPICC}
+AC_SUBST(MPICC)
+
+dnl Now MPICC is configured, let's do some basic compiler tests
+AC_PROG_CC
+
+dnl this call needs at least autoconf version 2.60
+dnl AC_USE_SYSTEM_EXTENSIONS
+
+dnl enable large file support
+AC_SYS_LARGEFILE
+
+UD_PROG_CC_MAKEDEPEND
+
+dnl AC_HEADER_STDC
+dnl AC_CHECK_HEADERS([malloc.h])
+
+# check if MPICC works for basic MPI call: MPI_Comm_rank()
+AC_CHECK_FUNC([MPI_Comm_rank], [],
+   dnl maybe -lmpi is needed at link stage
+   [AC_SEARCH_LIBS([MPI_Comm_rank], [mpi mpich], [],
+                 [AC_MSG_ERROR([
+    ------------------------------------------------------------
+     Invalid MPI compiler specified or detected: "${MPICC}"
+     A working MPI compiler is required. Please specify the location
+     of one either with the MPICC environment variable or the
+     --with-mpi configure flag
+    ------------------------------------------------------------])
+])])
+
+
+AC_ARG_ENABLE([mpi-io-test],
+   [AS_HELP_STRING([--disable-mpi-io-test],
+                   [Disable check for MPI-IO support in MPI implementation,
+                    if you know your MPI implementation has MPI-IO support
+                    but the configure test fails to find it.
+                    @<:@default: enabled@:>@])],
+   [enable_mpi_io_test=${enableval}], [enable_mpi_io_test=yes]
+)
+
+if test "x${enable_mpi_io_test}" = xyes ; then
+   AC_CHECK_FUNC([MPI_File_open], [],
+      dnl maybe -lmpio is needed at link stage
+      [AC_SEARCH_LIBS([MPI_File_open], [mpio], [],
+                    [AC_MSG_ERROR([
+            ------------------------------------------------------------
+             MPI implementation does not support MPI-IO
+             PnetCDF requires MPI-IO support to work properly.
+            ------------------------------------------------------------])]
+   )])
+fi
+
+dnl check MPI C++ compiler
+AC_ARG_ENABLE(cxx,
+    [AS_HELP_STRING([--disable-cxx],
+                    [Turn off support for the C++ interface,
+                     if you only need the C interface. @<:@default: enabled@:>@])],
+    [enable_cxx=${enableval}], [enable_cxx=auto]
+)
+
+if test "x${enable_cxx}" != xno ; then
+   UD_CHECK_MPI_COMPILER([MPICXX], [$CANDIDATE_MPICXX])
+
+   if test "x${MPICXX}" = x ; then
+      AC_MSG_ERROR([
+         ------------------------------------------------------------
+           configure cannot find a C++ compiler. Please specify the
+           locations of the compiler either with the MPICXX
+           environment variable or the --with-mpi configure flag.
+         ------------------------------------------------------------])
+      has_mpicxx=no
+   else
+      CXX=${MPICXX}
+      AC_SUBST(MPICXX)
+      has_mpicxx=yes
+
+      dnl UD_PROG_CXX
+      AC_PROG_CXX(${MPICXX})
+      dnl autoconf 2.5.9 has not yet implemented AC_PROG_CXX_C_O
+      dnl AC_PROG_CXX_C_O
+
+      dnl test if MPICXX can compile an MPI-IO program
+      if test "x${enable_mpi_io_test}" = xyes ; then
+          AC_LANG_PUSH(C++)
+          AC_CHECK_FUNC([MPI_File_close], [],
+             dnl maybe -lmpi++ is needed at link stage
+             [AC_SEARCH_LIBS([MPI_File_close], [mpi++ mpichcxx mpi_cxx], [],
+                 [has_mpicxx=no
+                  MPICXX=
+                  AC_MSG_WARN([
+                  ----------------------------------------------------------
+                   MPI C++ implementation does not support MPI-IO
+                   Disabling C++ testing programs
+                  ----------------------------------------------------------])]
+          )])
+          AC_LANG_POP(C++)
+      fi
+   fi
+   if test "x${has_mpicxx}" = xyes ; then
+      UD_CHECK_MPI_CPP_SEEK_SET
+      UD_MSG_DEBUG(ac_cv_CHECK_MPI_CPP_SEEK_SET=$ac_cv_CHECK_MPI_CPP_SEEK_SET)
+      if test "x${ac_cv_CHECK_MPI_CPP_SEEK_SET}" = xyes ; then
+         CXXCPPFLAGS="${CXXCPPFLAGS} -DMPICH_IGNORE_CXX_SEEK -DMPICH_SKIP_MPICXX"
+      fi
+   fi
+else
+has_mpicxx=no
+fi
+AC_SUBST(has_mpicxx)
+
+dnl I took the "-ansi" off the CFLAGS for the strict case, as it was
+dnl preventing PATH_MAX from being defined for some of the test files,
+dnl and I was having a tough time figuring out how to get it back! -- RobR
+dnl Note this must be done after the type of C compiler is determined
+AC_ARG_ENABLE(strict,
+    [AS_HELP_STRING([--enable-strict],
+                    [Turn on strict debugging with gcc. @<:@default: disabled@:>@])],
+    [enable_strict=${enableval}], [enable_strict=no]
+)
+
+if test "x${enable_strict}" = xyes; then
+   if test "x${GCC}" = xyes; then
+      CPPFLAGS="${CPPFLAGS} -Wall -Wstrict-prototypes -Wmissing-prototypes -Wundef -Wpointer-arith -Wbad-function-cast"
+      CXXCPPFLAGS="${CXXCPPFLAGS} -Wall -Wundef -Wpointer-arith"
+   else
+      AC_MSG_WARN([--enable-strict is for GNU compiler only])
+      enable_strict=no
+   fi
+fi
+AC_SUBST(CXXCPPFLAGS)
+
+AC_ARG_ENABLE(fortran,
+    [AS_HELP_STRING([--disable-fortran],
+                    [Turn off support for the Fortran interface,
+                     if you only need the C interface. @<:@default: enabled@:>@])],
+    [enable_fortran=${enableval}], [enable_fortran=auto]
+)
+
+if test "x${enable_fortran}" != xno ; then
+    UD_CHECK_MPI_COMPILER([MPIF77], [$CANDIDATE_MPIF77])
+    UD_CHECK_MPI_COMPILER([MPIF90], [$CANDIDATE_MPIF90])
+fi
+if test "x${enable_fortran}" = xyes ; then
+   dnl user explicitly requests to build Fortran APIs
+   if test "x${MPIF77}" = x && test "x${MPIF90}" = x ; then
+      AC_MSG_ERROR([
+         ------------------------------------------------------------
+           Fortran support is explicitly requested, but configure
+           cannot find a Fortran77 or Fortran90 compiler. Please
+           specify the locations of the compilers either with the
+           MPIF77 MPIF90 environment variables or the --with-mpi
+           configure flag.
+         ------------------------------------------------------------])
+   fi
+fi
+
+dnl AC_MSG_NOTICE(enable_fortran=${enable_fortran})
+
+dnl Check if MPIF90 is a valid MPI compiler
+if test "x${MPIF90}" != x ; then
+   FC=${MPIF90}
+   AC_PROG_FC
+   dnl FCFLAGS is set in AC_PROG_FC
+
+   FCLIBS_save="$FCLIBS"
+   FCLIBS=""
+   AC_FC_LIBRARY_LDFLAGS
+   UD_MSG_DEBUG([before FCLIBS=$FCLIBS])
+   dnl The autoconf macro for finding FCLIBS sometimes makes mistakes
+   dnl (particularly with the Fujitsu frt compiler).  This next step
+   dnl first sees if the FCLIBS is valid with the Fortran compiler
+   dnl This also happens to Solaris Studio Fortran compilers
+   dnl AC_PROG_FC_FCLIBS_VALID
+   dnl Now see if FCLIBS works with the C compiler (remove invalid ones)
+   PAC_PROG_FC_CHECK_FCLIBS
+
+   dnl replace FLIBS and F90LIBS with FCLIBS
+   UD_MSG_DEBUG([after FCLIBS=$FCLIBS])
+   FLIBS="$FCLIBS"
+   F90LIBS="$FCLIBS"
+
+   dnl We use F90FLAGS for debugging and optimization options for Fortran 90 programs
+   F90FLAGS=${FCFLAGS}
+   AC_SUBST(F90FLAGS)
+
+   AC_LANG_PUSH([Fortran])
+   AC_COMPILE_IFELSE([AC_LANG_CALL([],[MPI_Comm_rank])],
+                     [valid_mpif90=yes],[valid_mpif90=no]
+   )
+   AC_MSG_CHECKING([if mpi.mod is valid])
+   AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[        use mpi]])],
+                     [valid_mpi_mod=yes], [valid_mpi_mod=no]
+   )
+   AC_MSG_RESULT($valid_mpi_mod)
+   AC_LANG_POP([Fortran])
+   if test "x${valid_mpif90}" = xno && test "x${enable_fortran}" = xyes ; then
+      AC_MSG_ERROR([
+         ------------------------------------------------------------
+           Invalid MPI Fortran 90 compiler specified: "${MPIF90}"
+           A working MPI compiler is required. Please specify the
+           location of one either with the MPIF90 environment
+           variable or the --with-mpi configure flag.
+         ------------------------------------------------------------])
+   fi
+   if test "x${valid_mpi_mod}" = xno && test "x${enable_fortran}" = xyes ; then
+      AC_MSG_ERROR([
+         ------------------------------------------------------------
+           Invalid MPI Fortran module. The mpi.mod file in the include path
+           may not be generated by the same Fortran compiler used to build
+           "${MPIF90}". Please make sure the same Fortran compiler is used.
+         ------------------------------------------------------------])
+   fi
+fi
+
+dnl Check if MPIF77 is a valid MPI compiler
+F77_SUPPORT_FREEFORM=no
+if test "x${MPIF77}" != x ; then
+   F77=${MPIF77}
+   AC_PROG_F77
+   dnl FFLAGS is set in AC_PROG_F77
+
+   AC_F77_LIBRARY_LDFLAGS
+
+   dnl We use F77FLAGS for debugging and optimization options for Fortran 77 programs
+   F77FLAGS=${FFLAGS}
+   AC_SUBST(F77FLAGS)
+
+   dnl get flag for Fortran free form (this flag is only used in testing)
+   FC_saved=${FC}
+   FC=${F77}
+   UD_FC_FREEFORM
+   if test "x${ac_cv_fc_freeform}" != xunknown ; then
+      F77_SUPPORT_FREEFORM=yes
+      FFREEFORMFLAG=${ac_cv_fc_freeform}
+   fi
+   UD_MSG_DEBUG([FC=$FC F90FLAGS=$F90FLAGS FFREEFORMFLAG=$FFREEFORMFLAG])
+   AC_SUBST(FFREEFORMFLAG)
+   FC=${FC_saved}
+
+   AC_LANG_PUSH([Fortran 77])
+   AC_COMPILE_IFELSE([AC_LANG_CALL([],[MPI_Comm_rank])],
+                     [valid_mpif77=yes],[valid_mpif77=no]
+   )
+   AC_LANG_POP([Fortran 77])
+   if test "x${valid_mpif77}" = xno && test "x${enable_fortran}" = xyes ; then
+      AC_MSG_ERROR([
+         ------------------------------------------------------------
+           Invalid MPI Fortran 77 compiler specified: "${MPIF77}"
+           A working MPI compiler is required. Please specify the
+           location of one either with the MPIF77 environment
+           variable or the --with-mpi configure flag
+         ------------------------------------------------------------])
+   fi
+fi
+AC_SUBST(F77_SUPPORT_FREEFORM)
+
+if test "x${enable_fortran}" = xauto ; then
+   if test "x${valid_mpif77}" = xyes && test "x${valid_mpif90}" = xyes ; then
+      enable_fortran=yes
+   else
+      enable_fortran=no
+      AC_MSG_WARN([
+         ------------------------------------------------------------
+           Either MPI Fortran 77 or 90 compiler is not working:
+               "MPIF77 = ${MPIF77}"
+               "MPIF90 = ${MPIF90}"
+           Disable Fortran feature ...
+         ------------------------------------------------------------])
+   fi
+fi
+
+if test "x${enable_fortran}" = xyes ; then
+   dnl GNU Fortran compiler automatically invokes preprocessor for files with
+   dnl extension .F and .F90. To manually invoke the preprocessor on any file,
+   dnl use compiler flag -cpp. To disable, use -nocpp.
+   dnl For other compilers, we need to find the compile flags for Fortran
+   dnl preprocessor.
+   dnl steal AC_FC_PP_SRCEXT from autoconf V2.69 to make UD_FC_PP_SRCEXT
+   UD_FC_PP_SRCEXT([f])    dnl sets ac_cv_fc_pp_srcext_f
+   UD_FC_PP_SRCEXT([F])    dnl sets ac_cv_fc_pp_srcext_F
+   UD_FC_PP_SRCEXT([f90])  dnl sets ac_cv_fc_pp_srcext_f90
+   UD_FC_PP_SRCEXT([F90])  dnl sets ac_cv_fc_pp_srcext_F90
+
+   F77PPFLAGS_f=${ac_cv_fc_pp_srcext_f}
+   F77PPFLAGS_F=${ac_cv_fc_pp_srcext_F}
+   F90PPFLAGS_f90=${ac_cv_fc_pp_srcext_f90}
+   F90PPFLAGS_F90=${ac_cv_fc_pp_srcext_F90}
+   AC_SUBST(F77PPFLAGS_f)
+   AC_SUBST(F77PPFLAGS_F)
+   AC_SUBST(F90PPFLAGS_f90)
+   AC_SUBST(F90PPFLAGS_F90)
+
+   FPPFLAGS=${FPPFLAGS-}
+   AC_SUBST(FPP)
+   AC_SUBST(FPPFLAGS)
+
+   dnl compiler command-line define preprocess flag, result in FC_DEFINE
+   UD_FC_PP_DEFINE
+
+   dnl check compiler flags for file extensions in .f .F .f90 .F90
+   AC_LANG_PUSH([Fortran])
+   AC_FC_SRCEXT([f])
+   AC_FC_SRCEXT([F])
+   AC_FC_SRCEXT([f90])
+   AC_FC_SRCEXT([F90])
+   AC_SUBST(F77FLAGS_f)
+   AC_SUBST(F77FLAGS_F)
+   AC_SUBST(F90FLAGS_f90)
+   AC_SUBST(F90FLAGS_F90)
+   AC_LANG_POP([Fortran])
+
+   dnl get flag for Fortran fixed form (this flag is only used in testing)
+   UD_FC_FIXEDFORM
+   FFIXEDFORMFLAG=${ac_cv_fc_fixedform}
+   UD_MSG_DEBUG([FC=$FC F90FLAGS=$F90FLAGS FFIXEDFORMFLAG=$FFIXEDFORMFLAG])
+   AC_SUBST(FFIXEDFORMFLAG)
+
+   # Checking for Fortran types also determines the Fortran name mangling
+   # and places the value into FCALLSCSUB as the C name corresponding
+   # to the Fortran name SUB 
+   AC_FC_FUNC(sub, [FCALLSCSUB])
+
+   # determine the correct name mapping
+   case $FCALLSCSUB in
+       SUB)
+           AC_DEFINE(F77_NAME_UPPER,,[Define if Fortran names are uppercase])
+           ;;
+       sub_)
+           # This is the hard case.  Gcc uses one _ unless the name includes
+           # an underscore, in which case it gets two trailing underscores.
+           # Use essentially the same configure code that the original configure
+           # used to determine SUB
+           AC_MSG_CHECKING([for C-equivalent to Fortran routine "SUB_A"]) 
+                   dnl "
+           AC_FC_FUNC(sub_a, [FCALLSCSUBA])
+           AC_MSG_RESULT($FCALLSCSUBA)
+           case $FCALLSCSUBA in
+               sub_a__)
+                   AC_DEFINE(F77_NAME_LOWER_2USCORE,,[Define if Fortran names are lower case with two trailing underscore2])
+                   ;;
+               sub_a_)
+                   AC_DEFINE(F77_NAME_LOWER_USCORE,,[Define if Fortran names are lower case with one trailing underscore])
+                   ;;
+               *)
+                   AC_MSG_WARN([Unrecognized Fortran name mapping])
+                   ;;
+           esac
+           ;;
+       sub)
+           AC_DEFINE(F77_NAME_LOWER,,[Define if Fortran names are lower case])
+           ;;
+       *)
+           AC_MSG_WARN([Unrecognized Fortran name mapping])
+           ;;
+   esac
+
+   dnl Some Fortran 77 compilers, such as pgf77, do not allow "_8" modifier,
+   dnl because _8 modifier is a Fortran 90 feature
+   dnl UD_CHECK_PGF77
+   dnl UD_MSG_DEBUG([ac_cv_fc_compiler_pgf77=$ac_cv_fc_compiler_pgf77])
+
+   dnl Check if the Fortran compiler is an NAG
+   UD_CHECK_FC_NAG
+   if test "x${ac_cv_fc_compiler_nag}" = xyes ; then
+      NAGf90FPPFLAGS="-DNAGf90Fortran"
+      NAG_FCFLAGS="-mismatch"
+      AC_SUBST(NAGf90FPPFLAGS)
+      AC_SUBST(NAG_FCFLAGS)
+   fi
+
+   dnl check Fortran parameter modifier for 8-byte integer type
+   dnl We need this to set the max constants for UINT INT64 and UINT64
+   UD_FC_CONSTANT_MODIFIER
+   UD_MSG_DEBUG([ac_cv_fc_constant_modifier=$ac_cv_fc_constant_modifier])
+   PNF_INT8_MODIFIER=""
+   if test "x${ac_cv_fc_constant_modifier}" = xnone ; then
+      PNF_FILL_UINT=4294967295
+      PNF_FILL_INT64=-9223372036854775806
+      PNF_FILL_UINT64=18446744073709551614
+      PNF_X_UINT_MAX=4294967295
+      PNF_X_INT8_MIN=-9223372036854775807
+      PNF_X_INT8_MAX=9223372036854775807
+      PNF_X_UINT8_MAX=18446744073709551615
+   else
+      if test "x${ac_cv_fc_constant_modifier}" = xEightByteInt ; then
+         PNF_INT8_MODIFIER="      integer, parameter :: EightByteInt = selected_int_kind(18)"
+      fi
+      PNF_FILL_UINT=4294967295_${ac_cv_fc_constant_modifier}
+      PNF_FILL_INT64=-9223372036854775806_${ac_cv_fc_constant_modifier}
+      PNF_FILL_UINT64=18446744073709551614_${ac_cv_fc_constant_modifier}
+      PNF_X_UINT_MAX=4294967295_${ac_cv_fc_constant_modifier}
+      PNF_X_INT8_MIN=-9223372036854775807_${ac_cv_fc_constant_modifier}
+      PNF_X_INT8_MAX=9223372036854775807_${ac_cv_fc_constant_modifier}
+      PNF_X_UINT8_MAX=18446744073709551615_${ac_cv_fc_constant_modifier}
+   fi
+   AC_SUBST(PNF_INT8_MODIFIER)
+   AC_SUBST(PNF_FILL_UINT)
+   AC_SUBST(PNF_FILL_INT64)
+   AC_SUBST(PNF_FILL_UINT64)
+   AC_SUBST(PNF_X_UINT_MAX)
+   AC_SUBST(PNF_X_INT8_MIN)
+   AC_SUBST(PNF_X_INT8_MAX)
+   AC_SUBST(PNF_X_UINT8_MAX)
+
+   AC_SUBST(MPIF77)
+   AC_SUBST(MPIF90)
+fi
+
+AC_PROG_INSTALL
+
+have_yacc_lex=no
+dnl Starting from PnetCDF 1.5.0, yacc and lex is no longer needed
+dnl see comments in src/utils/ncmpigen/Makefile.in for build rules for
+dnl ncmpigenyy.c and ncmpigentab.c. If rebuild is desired, uncomment
+dnl below checking to check availability of yacc/lex/bison
+dnl AC_PROG_YACC
+dnl dnl if neither bison nor byacc is found, YACC will be set to yacc
+dnl have_yacc_lex=yes
+dnl if test "x$YACC" = xyacc; then
+dnl    AC_CHECK_PROGS(YACC_PATH, yacc)
+dnl    if test "x$YACC_PATH" = x; then
+dnl       dnl cannot find bison or yacc required to build ncmpigentab.c
+dnl       have_yacc_lex=no
+dnl    fi
+dnl fi
+dnl 
+dnl AC_PROG_LEX
+dnl if (test "x$LEX" != xflex) && (test "x$LEX" != xlex) ; then
+dnl    dnl cannot find flex or lex required to build ncmpigenyy.c
+dnl    have_yacc_lex=no
+dnl fi
+AC_SUBST(have_yacc_lex)
+
+dnl AC_PROG_AWK
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_SUBST(SET_MAKE)
+AC_PROG_EGREP
+
+dnl AC_PROG_SED and AC_PROG_GREP are only available on autoconf 2.60 and later
+dnl AC_PROG_SED
+dnl AC_PROG_GREP
+
+dnl YACC and LEX are required to build PnetCDF utility tool ncmpigen
+dnl if configure finds bison then YACC is set to bison -y, so we need to clean
+dnl up the output a bit before testing 
+dnl Below checks commands yacc and lex availability under PATH. However, this
+dnl checking is redundant, as AC_PROG_* did that already
+dnl YACC_CMD="${YACC% *}"
+dnl AC_CHECK_PROG([yacc_cmd], [${YACC_CMD}], [yes], [no])
+dnl AC_CHECK_PROG([lex_cmd],  [${LEX}],      [yes], [no])
+dnl if test "x${yacc_cmd}" = no ; then
+dnl     AC_MSG_ERROR([could not find bison/yacc required by PnetCDF])
+dnl fi
+dnl if test "x${lex_cmd}" = no ; then
+dnl     AC_MSG_ERROR([could not find flex/lex required by PnetCDF])
+dnl fi
+
+UD_PROG_M4
+UD_PROG_AR()
+UD_PROG_NM()
+# We could use the PAC check for ranlib (it also makes sure that ranlib works,
+# which is not always true, particularly when GNU tools are installed on 
+# a system that doesn't have (or need) ranlib
+AC_PROG_RANLIB
+
+dnl Check for <stdbool.h> that conforms to C99 requirements
+dnl this is also for using bool type in utf8proc.h/utf8proc.c to support
+dnl special characters in CDF-2 and CDF-5
+AC_HEADER_STDBOOL
+
+dnl AC_C_CONST
+AC_C_INLINE
+
+dnl we do not use struct stat yet
+dnl AC_CHECK_MEMBERS([struct stat.st_blksize])
+
+UD_CHECK_IEEE
+
+dnl cross compile fails with undefined reference to rpl_realloc and rpl_malloc
+dnl AC_FUNC_MALLOC
+dnl AC_FUNC_REALLOC
+
+dnl below checks availability of a bunch C functions, but we have not yet
+dnl implemented alternative calls
+dnl AC_FUNC_ERROR_AT_LINE
+dnl AC_FUNC_MEMCMP
+dnl AC_FUNC_STRTOD
+dnl AC_FUNC_VPRINTF
+dnl AC_CHECK_FUNCS([memset setlocale sqrt strchr strrchr strtol])
+dnl AC_CHECK_LIB([m], [tanh])
+dnl UD_CHECK_LIB_MATH
+AC_CHECK_FUNCS([strerror access unlink])
+
+AC_ARG_ENABLE([debug],
+    [AS_HELP_STRING([--enable-debug],
+                    [Enable PnetCDF internal debug mode. This also enables safe mode.
+                     @<:@default: disabled@:>@])],
+    [debug=${enableval}], [debug=no]
+)
+AC_MSG_CHECKING(PnetCDF debug mode)
+if test "x${debug}" = xyes; then
+   AC_DEFINE(PNC_DEBUG)
+
+   dnl malloc memory allocation tracing relies on tdelete and tsearch
+   AC_CHECK_HEADERS([search.h])
+   AC_CHECK_FUNCS([tsearch tdelete])
+
+   dnl check required functions for enabling malloc tracing
+   if (test "x${ac_cv_func_tsearch}" = xyes) &&
+      (test "x${ac_cv_func_tdelete}" = xyes) ; then
+      AC_DEFINE(PNC_MALLOC_TRACE)
+   fi
+fi
+AC_MSG_RESULT($debug)
+PNC_DEBUG=${debug}
+AC_SUBST(PNC_DEBUG)
+
+AC_CHECK_TYPE([MPI_Offset], [], [], [#include <mpi.h>])
+if test "x${ac_cv_type_MPI_Offset}" = xyes; then
+   AC_CHECK_SIZEOF([MPI_Offset], [], [#include <mpi.h>])
+else
+   AC_MSG_ERROR([Unable to find type MPI_Offset in mpi.h])
+fi
+AC_CHECK_SIZEOF([MPI_Aint], [], [#include <mpi.h>])
+
+dnl ok, now we know how big MPI_Offset is.  If it's less than 8 bytes 
+dnl we have to disable the new "CDF-5" (variables larger than 4gb) support
+if test "$ac_cv_sizeof_MPI_Offset" -lt "8"; then
+   AC_MSG_WARN("Unable to support CDF-5 format");
+   enable_cdf5=no
+else
+   AC_DEFINE(ENABLE_CDF5,,[Define if able to support CDF-5 file format])
+   enable_cdf5=yes
+fi
+
+SIZEOF_MPI_AINT_IS_4=no
+if test "x$ac_cv_sizeof_MPI_Aint" = x4; then
+   SIZEOF_MPI_AINT_IS_4=yes
+fi
+AC_SUBST(SIZEOF_MPI_AINT_IS_4)
+
+dnl the nonblocking routines build up lists of requests with MPI_Type_struct.
+dnl If MPI_Offset not the same size as MPI_Aint, the arrays passed around will
+dnl get mangled. 
+if test "$ac_cv_sizeof_MPI_Offset" -ne "$ac_cv_sizeof_MPI_Aint"; then
+   AC_MSG_WARN(MPI_Offset and MPI_Aint have different sizes: non-blocking APIs now behave like blocking ones)
+   enable_nonblocking=no
+else
+   AC_DEFINE(ENABLE_NONBLOCKING,,[Define if able to support nonblocking routines])
+   enable_nonblocking=yes
+fi
+
+# check for MPI-2 only functions
+AC_CHECK_FUNCS(MPI_Info_dup MPI_Info_free MPI_Get_address)
+AC_CHECK_FUNCS(MPI_Type_create_subarray MPI_Type_create_hvector MPI_Type_create_hindexed MPI_Type_create_struct MPI_Type_create_resized MPI_Type_get_extent)
+
+dnl Check for presence of MPI COMBINERS.
+UD_HAS_MPI_CONST(MPI_COMBINER_DUP)
+UD_HAS_MPI_CONST(MPI_COMBINER_HVECTOR_INTEGER)
+UD_HAS_MPI_CONST(MPI_COMBINER_HINDEXED_INTEGER)
+UD_HAS_MPI_CONST(MPI_COMBINER_SUBARRAY)
+UD_HAS_MPI_CONST(MPI_COMBINER_DARRAY)
+UD_HAS_MPI_CONST(MPI_COMBINER_RESIZED)
+UD_HAS_MPI_CONST(MPI_COMBINER_STRUCT_INTEGER)
+UD_HAS_MPI_CONST(MPI_COMBINER_INDEXED_BLOCK)
+UD_HAS_MPI_CONST(MPI_COMBINER_F90_REAL)
+UD_HAS_MPI_CONST(MPI_COMBINER_F90_INTEGER)
+UD_HAS_MPI_CONST(MPI_COMBINER_F90_COMPLEX)
+
+dnl Check for presence of various MPI error classes.
+dnl These could be enums, so we have to do compile checks.
+UD_HAS_MPI_CONST(MPI_ERR_FILE_EXISTS)
+UD_HAS_MPI_CONST(MPI_ERR_NO_SUCH_FILE)
+UD_HAS_MPI_CONST(MPI_ERR_AMODE)
+UD_HAS_MPI_CONST(MPI_ERR_NOT_SAME)
+UD_HAS_MPI_CONST(MPI_ERR_BAD_FILE)
+UD_HAS_MPI_CONST(MPI_ERR_READ_ONLY)
+UD_HAS_MPI_CONST(MPI_ERR_ACCESS)
+UD_HAS_MPI_CONST(MPI_ERR_NO_SPACE)
+UD_HAS_MPI_CONST(MPI_ERR_QUOTA)
+
+dnl Check for presence of C types
+UD_HAS_MPI_DATATYPE(MPI_CHAR)
+UD_HAS_MPI_DATATYPE(MPI_BYTE)
+UD_HAS_MPI_DATATYPE(MPI_SIGNED_CHAR)
+UD_HAS_MPI_DATATYPE(MPI_UNSIGNED_CHAR)
+UD_HAS_MPI_DATATYPE(MPI_SHORT)
+UD_HAS_MPI_DATATYPE(MPI_UNSIGNED_SHORT)
+UD_HAS_MPI_DATATYPE(MPI_INT)
+UD_HAS_MPI_DATATYPE(MPI_UNSIGNED)
+UD_HAS_MPI_DATATYPE(MPI_LONG)
+UD_HAS_MPI_DATATYPE(MPI_FLOAT)
+UD_HAS_MPI_DATATYPE(MPI_DOUBLE)
+UD_HAS_MPI_DATATYPE(MPI_LONG_LONG_INT)
+UD_HAS_MPI_DATATYPE(MPI_UNSIGNED_LONG_LONG)
+UD_HAS_MPI_DATATYPE(MPI_UB)
+UD_HAS_MPI_DATATYPE(MPI_LB)
+dnl UD_HAS_MPI_DATATYPE(MPI_OFFSET)
+dnl HAVE_MPI_OFFSET might have already been defined in mpi.h
+dnl Add "_DATATYPE" suffix to distinguish from checking MPI_Offset
+UD_HAS_MPI_DATATYPE(MPI_OFFSET, _DATATYPE)
+
+dnl Check for presence of Fortran types
+dnl These could be enums, so we have to do compile checks.
+dnl
+dnl We do this for a couple of reasons.  First, the MPI might have been
+dnl built without Fortran support, in which case these types might not
+dnl exist.  Second, we need to map these types to corresponding C types
+dnl where possible to simplify processing at run time.
+if test "x${enable_fortran}" = xyes ; then
+    UD_HAS_MPI_DATATYPE(MPI_CHARACTER)
+    UD_HAS_MPI_DATATYPE(MPI_REAL)
+    UD_HAS_MPI_DATATYPE(MPI_INTEGER)
+    UD_HAS_MPI_DATATYPE(MPI_DOUBLE_PRECISION)
+    UD_HAS_MPI_DATATYPE(MPI_INTEGER1)
+    UD_HAS_MPI_DATATYPE(MPI_INTEGER2)
+    UD_HAS_MPI_DATATYPE(MPI_INTEGER4)
+    UD_HAS_MPI_DATATYPE(MPI_INTEGER8)
+    UD_HAS_MPI_DATATYPE(MPI_INTEGER16)
+    UD_HAS_MPI_DATATYPE(MPI_REAL4)
+    UD_HAS_MPI_DATATYPE(MPI_REAL8)
+    UD_HAS_MPI_DATATYPE(MPI_REAL16)
+    UD_HAS_MPI_DATATYPE(MPI_COMPLEX8)
+    UD_HAS_MPI_DATATYPE(MPI_COMPLEX16)
+    UD_HAS_MPI_DATATYPE(MPI_COMPLEX32)
+fi
+
+AC_ARG_ENABLE([in-place-swap],
+    [AS_HELP_STRING([--disable-in-place-swap],
+                    [Disable memory in-place byte swap on Little Endian
+                     machines. @<:@default: enabled@:>@])],
+    [in_place_swap=${enableval}], [in_place_swap=yes]
+)
+if test "x${in_place_swap}" = xno ; then
+    AC_DEFINE(DISABLE_IN_PLACE_SWAP)
+fi
+
+AC_C_CHAR_UNSIGNED
+AC_C_BIGENDIAN
+is_bigendian=no
+if test "x${ac_cv_c_bigendian}" = xyes ; then
+   is_bigendian=yes
+fi
+AC_SUBST(is_bigendian)
+
+dnl For big endian, put buffer needs no byte swap and hence can be declared as
+dnl INTENT(IN). For little endian, put buffer may be used for byte swap in
+dnl place and hence must be declared as INTENT(INOUT).
+dnl This will configure/produce the file src/libf90/api.f90
+if test "x${ac_cv_c_bigendian}" = xyes  || (test "x${in_place_swap}" = xno) ; then
+   INTENTV="IN"
+else
+   INTENTV="INOUT"
+fi
+AC_SUBST(INTENTV)
+
+AC_TYPE_SIZE_T
+AC_TYPE_OFF_T
+AC_CHECK_TYPES([ssize_t, ptrdiff_t, uchar, ushort, uint, longlong, ulonglong, int64, uint64])
+
+AC_CHECK_SIZEOF(size_t)
+AC_CHECK_SIZEOF(off_t)
+AC_CHECK_SIZEOF(signed char)
+AC_CHECK_SIZEOF(unsigned char)
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(unsigned short)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(unsigned int)
+AC_CHECK_SIZEOF(long)
+AC_CHECK_SIZEOF(float)
+AC_CHECK_SIZEOF(double)
+AC_CHECK_SIZEOF(long long)
+AC_CHECK_SIZEOF(unsigned long long)
+
+if test "$ac_cv_type_ushort" = yes ; then 
+    AC_CHECK_SIZEOF(ushort) 
+fi 
+if test "$ac_cv_type_uint" = yes ; then 
+    AC_CHECK_SIZEOF(uint) 
+fi 
+if test "$ac_cv_type_longlong" = yes ; then 
+    AC_CHECK_SIZEOF(longlong) 
+fi 
+if test "$ac_cv_type_ulonglong" = yes ; then 
+    AC_CHECK_SIZEOF(ulonglong) 
+fi 
+
+if test "x${enable_fortran}" = xyes ; then
+    if test "$cross_compiling" = yes; then
+        UD_CHECK_FORTRAN_TYPE([NF_INT1_T], [integer*1 byte "integer(kind=1)"])
+        UD_CHECK_FORTRAN_TYPE([NF_INT2_T], [integer*2 "integer(kind=2)"])
+        UD_CHECK_FORTRAN_TYPE([NF_INT8_T], [integer*8 "integer(kind=8)"])
+    else
+        UD_FORTRAN_TYPES
+    fi
+
+    NFMPI_OFFSET="integer*$ac_cv_sizeof_MPI_Offset"
+    AC_MSG_CHECKING([for Fortran NFMPI_OFFSET "$NFMPI_OFFSET"])
+    dnl "
+    AC_LANG_PUSH([Fortran 77])
+    AC_COMPILE_IFELSE(
+        [AC_LANG_SOURCE([
+            subroutine sub(value)
+            $NFMPI_OFFSET value
+            end
+        ])],
+        [ac_cv_NFMPI_OFFSET=yes], [ac_cv_NFMPI_OFFSET=no]
+    )
+    AC_LANG_POP([Fortran 77])
+    if test "$ac_cv_NFMPI_OFFSET" = yes ; then
+        AC_MSG_RESULT(yes)
+    else
+        AC_MSG_RESULT(no)
+        AC_MSG_ERROR([F77 does not support "$NFMPI_OFFSET"])
+        dnl "
+    fi
+    ${RM} -rf conftest*
+fi
+
+SIZEOF_MPI_OFFSET=$ac_cv_sizeof_MPI_Offset
+AC_SUBST(SIZEOF_MPI_OFFSET)
+
+if test "x${enable_fortran}" = xyes ; then
+
+   UD_FC_MODULE_EXTENSION
+   dnl UD_FC_MODULE_EXTENSION defines FC_MODEXT
+   if test "x${FC_MODEXT}" = x ; then
+      AC_MSG_ERROR([cannot determine Fortran module file extension!])
+   fi
+   UD_MSG_DEBUG([FC_MODEXT=$FC_MODEXT])
+
+   UD_FC_MODULE_FLAG
+   dnl UD_FC_MODULE_FLAG defines FC_MODINC
+   UD_MSG_DEBUG([FC_MODINC=$FC_MODINC])
+
+   UD_FC_MODULE_OUTPUT_FLAG
+   dnl UD_FC_MODULE_OUTPUT_FLAG defines FC_MODOUT
+   UD_MSG_DEBUG([FC_MODOUT=$FC_MODOUT])
+fi
+
+dnl
+dnl Below is to check if a Fortran compiler produces module files with upper
+dnl case file name, eg. PNETCDF.mod. However, this does not work for Mac OSX
+dnl file system which is case insensitive
+dnl
+if test "x${enable_fortran}" = xyes ; then
+   UD_PROG_FC_UPPERCASE_MOD
+fi
+UPPER_CASE_MOD=no
+if test "x$ac_cv_prog_f90_uppercase_mod" = xyes ; then
+   UPPER_CASE_MOD=yes
+fi
+AC_SUBST(UPPER_CASE_MOD)
+
+if test "x${enable_fortran}" = xyes ; then
+   if test "x${enable_strict}" = xyes; then
+      FPPFLAGS="${FPPFLAGS} -Wall"
+   fi
+   AC_SUBST(FLIBS)
+   AC_SUBST(FCLIBS)
+   AC_SUBST(F90LIBS)
+   AC_SUBST(FLDFLAGS)
+   AC_SUBST(F90LDFLAGS)
+fi
+
+has_fortran=${enable_fortran}
+AC_SUBST(has_fortran)
+
+UD_MAKEWHATIS
+
+dnl
+dnl GNU coverage
+dnl
+dnl This is for internal testing only. It should not be enabled for building a
+dnl production PnetCDF. This is because when run an executable compiled with
+dnl coverage will produce an output file named "gmon.out". Since coverage is
+dnl not parallelized, running a program compiled with coverage may cause
+dnl problems on concurrently writing to gmon.out in conflicts, possible
+dnl corrupting the file or program hanging. Thus, make target "ptest" should
+dnl also be disabled when coverage is enabled.
+dnl
+dnl After all other tests, optionally enable coverage,  we do this last
+dnl because legend has it that sometimes on some compilers the coverage flags
+dnl mess up other checks
+dnl
+AC_ARG_ENABLE([coverage],
+   [AS_HELP_STRING([--enable-coverage],
+       [Compile with coverage support (gcc-based only). @<:@default: disabled@:>@])],
+   [enable_coverage=${enableval}], [enable_coverage=no]
+)
+if test "x${enable_coverage}" = xyes; then
+   if test "x${GCC}" = xyes; then
+       dnl it is GNU compiler
+       LCOV_FLAGS="-pg -fprofile-arcs -ftest-coverage --coverage -O0"
+       CFLAGS="${CFLAGS} ${LCOV_FLAGS}"
+       if test "x${has_mpicxx}" = xyes ; then
+          CXXFLAGS="${CXXFLAGS} ${LCOV_FLAGS}"
+       fi
+       if test "x${enable_fortran}" = xyes ; then
+           FCFLAGS="${FCFLAGS}  ${LCOV_FLAGS}"
+          F77FLAGS="${F77FLAGS} ${LCOV_FLAGS}"
+          F90FLAGS="${F90FLAGS} ${LCOV_FLAGS}"
+       fi
+       LCOV_LIB=-lgcov
+       AC_SUBST(LCOV_LIB)
+   else
+      AC_MSG_WARN([--enable-coverage is for GNU compiler only])
+      enable_coverage=no
+   fi
+fi
+AC_SUBST(enable_coverage)
+
+if test "x${has_mpicxx}" = xyes ; then
+   UD_CXX_MACRO_FUNC
+   if test "x${ac_cv_cxx_macro_func}" == xyes ; then
+      AC_DEFINE(HAVE_FUNC_MACRO)
+   fi
+   if test "x${ac_cv_cxx_macro_function}" == xyes ; then
+      AC_DEFINE(HAVE_FUNCTION_MACRO)
+   fi
+fi
+
+if test "x${debug}" = xyes; then
+   dnl add -g flag if not presented
+   dnl remove all -O and -fast flags
+   dnl add -O0 to all flags
+   if ! echo "${CFLAGS}" | ${EGREP} -q -- "-g" ; then
+      CFLAGS="${CFLAGS} -g"
+   fi
+   CFLAGS=`echo $CFLAGS | sed 's/-O. *//g' | sed 's/-fast *//g'`
+   CFLAGS="${CFLAGS} -O0"
+
+   if test "x${has_mpicxx}" = xyes ; then
+      if ! echo "${CXXFLAGS}" | ${EGREP} -q -- "-g" ; then
+         CXXFLAGS="${CXXFLAGS} -g"
+      fi
+      CXXFLAGS=`echo $CXXFLAGS | sed 's/-O. *//g' | sed 's/-fast *//g'`
+      CXXFLAGS="${CXXFLAGS} -O0"
+   fi
+
+   if test "x${enable_fortran}" = xyes ; then
+      if ! echo "${FCFLAGS}" | ${EGREP} -q -- "-g" ; then
+         FCFLAGS="${FCFLAGS} -g"
+      fi
+      if ! echo "${F77FLAGS}" | ${EGREP} -q -- "-g" ; then
+         F77FLAGS="${F77FLAGS} -g"
+      fi
+      if ! echo "${F90FLAGS}" | ${EGREP} -q -- "-g" ; then
+         F90FLAGS="${F90FLAGS} -g"
+      fi
+
+       FCFLAGS=`echo $FCFLAGS | sed 's/-O. *//g' | sed 's/-fast *//g'`
+      F77FLAGS=`echo $F77FLAGS | sed 's/-O. *//g' | sed 's/-fast *//g'`
+      F90FLAGS=`echo $F90FLAGS | sed 's/-O. *//g' | sed 's/-fast *//g'`
+       FCFLAGS="${FCFLAGS}  -O0"
+      F77FLAGS="${F77FLAGS} -O0"
+      F90FLAGS="${F90FLAGS} -O0"
+   fi
+fi
+
+chmod u+x ${srcdir}/scripts/install-sh
+
+AC_ARG_ENABLE([subfiling],
+   [AS_HELP_STRING([--enable-subfiling],
+                   [Enable subfiling support. @<:@default: disabled@:>@])],
+   [enable_subfiling=${enableval}], [enable_subfiling=no]
+)
+if test "x$enable_subfiling" = "xyes" ; then
+   AC_DEFINE(ENABLE_SUBFILING)
+   AC_SUBST(enable_subfiling)
+fi
+
+AC_PATH_PROG([LATEX],  [latex])
+AC_PATH_PROG([DVIPDF], [dvipdf])
+has_latex=no
+if test "x${LATEX}" != x ; then
+    has_latex=yes
+fi
+AC_SUBST(LATEX)
+AC_SUBST(DVIPDF)
+AC_SUBST(has_latex)
+
+BUILDDIR=`pwd`
+AC_SUBST(BUILDDIR)
+
+AC_ARG_ENABLE([file-sync],
+    [AS_HELP_STRING([--disable-file-sync],
+                    [Disable MPI file sync if you know your file system can
+                     provide data consistency. @<:@default: enabled@:>@])],
+    [file_sync=${enableval}], [file_sync=yes]
+)
+if test "x${file_sync}" = xno ; then
+    AC_DEFINE(DISABLE_FILE_SYNC)
+fi
+
+AC_ARG_ENABLE([large-file-test],
+    [AS_HELP_STRING([--enable-large-file-test],
+                    [Enable testing for large (>4GB) file/variable I/O. Note
+                     "make testing" can run very slow. @<:@default: disabled@:>@])],
+    [large_file_test=${enableval}], [large_file_test=no]
+)
+AC_SUBST(large_file_test)
+
+dnl PNETCDF_INC and PNETCDF_LIB are for benchmark programs use only
+PNETCDF_INC=${BUILDDIR}/src/libf90
+PNETCDF_LIB="-L${BUILDDIR}/src/lib"
+AC_SUBST(PNETCDF_INC)
+AC_SUBST(PNETCDF_LIB)
+
+AC_ARG_VAR(TEST_SEQRUN, [Run command (on one process) for make target check on cross-compile environment. Example: "aprun -n 1". @<:@default: none@:>@])
+AC_ARG_VAR(TEST_MPIRUN, [MPI run command for make target ptest, @<:@default: mpiexec -n NP@:>@])
+AC_ARG_VAR(TEST_OUTDIR, [Output file directory for make target ptest, @<:@default: ./@:>@])
+if test "x${TEST_MPIRUN}" = x ; then
+    dnl set default to mpiexec
+    TEST_MPIRUN="mpiexec -n NP"
+fi
+if test "x${TEST_OUTDIR}" = x ; then
+    dnl set default to current directory
+    TEST_OUTDIR=.
+fi
+AC_SUBST(TEST_SEQRUN)
+AC_SUBST(TEST_MPIRUN)
+AC_SUBST(TEST_OUTDIR)
+
+dnl find if gcc is available for compiling ncoffsets to run in sequential
+AC_PATH_PROG([SEQ_CC], [gcc], [$MPICC])
+AC_SUBST(SEQ_CC)
+
+AC_CONFIG_HEADERS([src/libf/nfconfig_inc])
+AC_CONFIG_FILES(macros.make \
+                Makefile \
+                src/Makefile \
+                src/lib/Makefile \
+                src/lib/pnetcdf.h \
+                src/utils/Makefile \
+                src/utils/ncmpidump/Makefile \
+                src/utils/ncmpidiff/Makefile \
+                src/utils/ncmpigen/Makefile \
+                src/utils/ncmpivalid/Makefile \
+                src/utils/pnetcdf_version/Makefile \
+                src/utils/ncoffsets/Makefile \
+                test/Makefile \
+                test/common/Makefile \
+                test/nc_test/Makefile \
+                test/C/Makefile \
+                test/fandc/Makefile \
+                test/testcases/Makefile \
+                test/nonblocking/Makefile \
+                test/header/Makefile \
+                test/cdf_format/Makefile \
+                test/largefile/Makefile \
+                examples/C/Makefile \
+                examples/tutorial/Makefile \
+                examples/Makefile \
+                doc/Makefile \
+                man/Makefile \
+                scripts/Makefile \
+                benchmarks/Makefile \
+                benchmarks/C/Makefile \
+                test/nf_test/Makefile \
+                test/nf_test/tests.inc \
+                test/nf90_test/Makefile \
+                test/F90/Makefile \
+                examples/F77/Makefile \
+                examples/F90/Makefile \
+                src/libf90/Makefile \
+                src/libf90/api.f90 \
+                src/libf90/nfmpi_constants.f90 \
+                src/libf/Makefile \
+                src/libf/pnetcdf.inc \
+                src/libcxx/Makefile \
+                examples/CXX/Makefile \
+                test/CXX/Makefile \
+                benchmarks/FLASH-IO/Makefile \
+                test/subfile/Makefile)
+
+# The following dependency is for configure.in and configure
+# See autoconf manual 2.69, Section 4.8.5 Automatic Remaking
+AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h])
+
+AC_OUTPUT
+echo "--------------------------------------------------------------------"
+
+if test "x${enable_mpi_io_test}" = xno ; then
+    AC_MSG_WARN([
+       NOTE: disabling the MPI-IO test is a VERY bad idea.
+       Please make sure you know what you are doing])
+fi
+
+msg_large_files=no
+if test "$ac_cv_sizeof_off_t" -gt 4 ; then
+   msg_large_files=yes
+fi
+
+echo \
+"
+   ${PACKAGE_NAME} Version ${PACKAGE_VERSION}
+
+   Features:  Support for large files (> 4 GB) - ${msg_large_files}
+              Build C++ APIs                   - ${has_mpicxx}
+              Build Fortran APIs               - ${enable_fortran}
+              Build nonblocking APIs           - ${enable_nonblocking}
+              Build CDF-5 support              - ${enable_cdf5}
+              Build subfiling support          - ${enable_subfiling}"
+if test "x${ac_cv_c_bigendian}" = xno  && (test "x${in_place_swap}" = xno) ; then
+   echo "\
+              Memory in-place byte swap        - disabled"
+fi
+if test "x${large_file_test}" = xyes; then
+   echo "\
+              Testing large file/variable I/O  - enabled"
+fi
+if test "x${debug}" = xyes; then
+   echo "\
+              PnetCDF internal debug mode      - enabled"
+fi
+if test "x${enable_fortran}" = xyes && (test "x${F77_SUPPORT_FREEFORM}" = xno) ; then
+   echo "\
+              Support free form in Fortran 77  - no"
+fi
+
+echo "\
+
+   Compilers: MPICC       = ${MPICC}"
+if test "${has_mpicxx}" = yes ; then
+   echo "\
+              MPICXX      = ${MPICXX}"
+fi
+if test "${enable_fortran}" = yes ; then
+   echo "\
+              MPIF77      = ${MPIF77}
+              MPIF90      = ${MPIF90}"
+fi
+echo "\
+              CFLAGS      = ${CFLAGS}"
+if test "x${CPPFLAGS}" != x ; then
+   echo "\
+              CPPFLAGS    = ${CPPFLAGS}"
+fi
+if test "${has_mpicxx}" = yes ; then
+   echo "\
+              CXXFLAGS    = ${CXXFLAGS}"
+   if test "x${CXXCPPFLAGS}" != x ; then
+      echo "\
+              CXXCPPFLAGS = ${CXXCPPFLAGS}"
+   fi
+fi
+if test "${enable_fortran}" = yes ; then
+   echo "\
+              F77FLAGS    = ${F77FLAGS}
+              F90FLAGS    = ${F90FLAGS}"
+   if test "x${FPPFLAGS}" != x ; then
+      echo "\
+              FPPFLAGS    = ${FPPFLAGS}"
+   fi
+fi
+if test "x${LDFLAGS}" != x ; then
+   echo "\
+              LDFLAGS     = ${LDFLAGS}"
+fi
+if test "x${LIBS}" != x ; then
+   echo "\
+              LIBS        = ${LIBS}"
+fi
+echo "\
+
+   Now type 'make' to build the library and utility tools.
+   Type 'make @<:@<target>@:>@'
+       where the optional <target> is:
+           testing          - test PnetCDF build for sequential run
+           ptest            - test PnetCDF build for parallel run
+           install          - install PnetCDF
+---------------------------------------------------------------------"
+
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644
index 0000000..1880b80
--- /dev/null
+++ b/doc/Makefile.in
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 1468 2013-10-26 16:53:18Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include ../macros.make
+
+LATEX  = @LATEX@
+DVIPDF = @DVIPDF@
+ifeq (@has_latex@, yes)
+    API_GUIDE = pnetcdf-api.pdf
+else
+    API_GUIDE =
+endif
+
+all: $(API_GUIDE)
+
+pnetcdf-api.pdf: $(srcdir)/pnetcdf-api.tex
+	$(LATEX) $<
+	$(LATEX) $<
+	$(DVIPDF) pnetcdf-api
+
+PACKING_LIST = Makefile.in \
+               c_api.tex \
+               data_mode_api.tex \
+               flexible_api.tex \
+               latex8.sty \
+               Makefile.in \
+               multiple_io.tex \
+               nonblocking.tex \
+               pnetcdf-api.bbl \
+               pnetcdf-api.tex \
+               porting_notes.txt \
+               symbol_renaming.txt
+
+GARBAGE = *.dvi *.log *.aux *.ps $(API_GUIDE)
+
+include $(srcdir)/../rules.make
+
diff --git a/doc/c_api.tex b/doc/c_api.tex
new file mode 100644
index 0000000..9e1b1ef
--- /dev/null
+++ b/doc/c_api.tex
@@ -0,0 +1,203 @@
+%
+% DATASET FUNCTIONS
+%
+\subsection*{A.1  Dataset Functions}
+
+\begin{verbatim}
+int ncmpi_create(MPI_Comm comm, const char *path, int cmode, MPI_Info info, int *ncidp);
+
+int ncmpi_open(MPI_Comm comm, const char *path, int omode, MPI_Info info, int *ncidp);
+
+int ncmpi_enddef(int ncid);
+
+int ncmpi_redef(int ncid);
+
+int ncmpi_get_file_info(int ncid, MPI_Info *info_used);
+
+int ncmpi_sync(int ncid);
+
+int ncmpi_abort(int ncid);
+
+int ncmpi_begin_indep_data(int ncid);
+
+int ncmpi_end_indep_data(int ncid);
+
+int ncmpi_close(int ncid);
+\end{verbatim}
+
+% ncmpi_set_fill has not yet implemented
+% int ncmpi_set_fill(int ncid, int fillmode, int *old_modep);
+
+%
+% DEFINE FUNCTIONS
+%
+\subsection*{A.2  Define Mode Functions}
+
+\begin{verbatim}
+int ncmpi_def_dim(int ncid, const char *name, MPI_Offset len, int *idp);
+
+int ncmpi_def_var(int ncid, const char *name, nc_type xtype, int ndims, 
+                  const int *dimidsp, int *varidp);
+
+int ncmpi_rename_dim(int ncid, int dimid, const char *name);
+
+int ncmpi_rename_var(int ncid, int varid, const char *name);
+\end{verbatim}
+
+%
+% INQUIRY FUNCTIONS
+%
+\subsection*{A.3  Inquiry Functions}
+
+\begin{verbatim}
+int ncmpi_inq(int ncid, int *ndimsp, int *nvarsp, int *ngattsp, int *unlimdimidp); 
+
+int ncmpi_inq_ndims(int ncid, int *ndimsp);
+
+int ncmpi_inq_nvars(int ncid, int *nvarsp);
+
+int ncmpi_inq_natts(int ncid, int *ngattsp);
+
+int ncmpi_inq_unlimdim(int ncid, int *unlimdimidp);
+
+int ncmpi_inq_dimid(int ncid, const char *name, int *idp);
+
+int ncmpi_inq_dim(int ncid, int dimid, char *name, MPI_Offset *lenp);
+
+int ncmpi_inq_dimname(int ncid, int dimid, char *name);
+
+int ncmpi_inq_dimlen(int ncid, int dimid, MPI_Offset *lenp);
+
+int ncmpi_inq_var(int ncid, int varid, char *name, nc_type *xtypep, 
+                  int *ndimsp, int *dimidsp, int *nattsp);
+
+int ncmpi_inq_varid(int ncid, const char *name, int *varidp);
+
+int ncmpi_inq_varname(int ncid, int varid, char *name);
+
+int ncmpi_inq_vartype(int ncid, int varid, nc_type *xtypep);
+
+int ncmpi_inq_varndims(int ncid, int varid, int *ndimsp);
+
+int ncmpi_inq_vardimid(int ncid, int varid, int *dimidsp);
+
+int ncmpi_inq_varnatts(int ncid, int varid, int *nattsp);
+
+\end{verbatim}
+
+%
+% ATTRIBUTE FUNCTIONS
+%
+\subsection*{A.4  Attribute Functions}
+
+\begin{verbatim}
+int ncmpi_inq_att(int ncid, int varid, const char *name, nc_type *xtypep,
+                  MPI_Offset *lenp);
+
+int ncmpi_inq_attid(int ncid, int varid, const char *name, int *idp);
+
+int ncmpi_inq_atttype(int ncid, int varid, const char *name, nc_type *xtypep);
+
+int ncmpi_inq_attlen(int ncid, int varid, const char *name, MPI_Offset *lenp);
+
+int ncmpi_inq_attname(int ncid, int varid, int attnum, char *name);
+
+int ncmpi_copy_att(int ncid_in, int varid_in, const char *name, int ncid_out,
+                   int varid_out);
+
+int ncmpi_rename_att(int ncid, int varid, const char *name, const char *newname);
+
+int ncmpi_del_att(int ncid, int varid, const char *name);
+
+int ncmpi_put_att_text(int ncid, int varid, const char *name, MPI_Offset len,
+                       const char *op);
+
+int ncmpi_get_att_text(int ncid, int varid, const char *name, char *ip);
+
+int ncmpi_put_att_uchar(int ncid, int varid, const char *name, nc_type xtype,
+                        MPI_Offset len, const unsigned char *op);
+
+int ncmpi_get_att_uchar(int ncid, int varid, const char *name, unsigned char *ip);
+
+int ncmpi_put_att_schar(int ncid, int varid, const char *name, nc_type xtype, 
+                        MPI_Offset len, const signed char *op);
+
+int ncmpi_get_att_schar(int ncid, int varid, const char *name, signed char *ip);
+
+int ncmpi_put_att_short(int ncid, int varid, const char *name, nc_type xtype,
+                        MPI_Offset len, const short *op);
+
+int ncmpi_get_att_short(int ncid, int varid, const char *name, short *ip);
+
+int ncmpi_put_att_int(int ncid, int varid, const char *name, nc_type xtype, 
+                      MPI_Offset len, const int *op);
+
+int ncmpi_get_att_int(int ncid, int varid, const char *name, int *ip);
+
+int ncmpi_put_att_long(int ncid, int varid, const char *name,
+                       nc_type xtype, MPI_Offset len, const long *op);
+
+int ncmpi_get_att_long(int ncid, int varid, const char *name, long *ip);
+
+int ncmpi_put_att_float(int ncid, int varid, const char *name,
+                        nc_type xtype, MPI_Offset len, const float *op);
+
+int ncmpi_get_att_float(int ncid, int varid, const char *name, float *ip);
+
+int ncmpi_put_att_double(int ncid, int varid, const char *name, nc_type xtype,
+                         MPI_Offset len, const double *op);
+
+int ncmpi_get_att_double(int ncid, int varid, const char *name, double *ip);
+\end{verbatim}
+
+%
+% DATA FUNCTIONS
+%
+\subsection*{A.5  Data Mode Functions}
+
+Recall that the data mode functions are split into the High Level data mode interface and the
+Flexible data mode interface.
+
+\subsubsection*{A.5.1  High Level Data Mode Interface}
+
+The High Level functions most closely mimic the original NetCDF data mode interface.
+
+% \emph{What about the single variable and varm functions?  Are they important?}
+
+\input data_mode_api
+
+\subsubsection*{A.5.2  Flexible Data Mode Interface}
+
+Note that there are considerably fewer functions in the flexible data mode
+inteface, because these functions can handle all different types with the same
+call.  All of the high level functions are written in terms of these
+functions.
+
+\input flexible_api
+
+\subsubsection*{A.5.3  Multiple Variable Data Mode Interface}
+
+\input multiple_io
+
+\subsubsection*{A.5.4  Nonblocking Data Mode Interface}
+
+\input nonblocking
+
+\subsubsection*{A.6  Other Utility Interface}
+
+\begin{verbatim}
+const char* ncmpi_strerror(int err);
+
+int ncmpi_delete(char *filename, MPI_Info info);
+
+int ncmpi_set_default_format(int format, int *old_formatp);
+
+const char* ncmpi_inq_libvers(void);
+
+int ncmpi_inq_format(int ncid, int *formatp);
+
+int ncmpi_inq_file_format(char *filename, int *formatp);
+
+int ncmpi_inq_version(int ncid, int *NC_mode);
+\end{verbatim}
+
diff --git a/doc/data_mode_api.tex b/doc/data_mode_api.tex
new file mode 100644
index 0000000..1ec38da
--- /dev/null
+++ b/doc/data_mode_api.tex
@@ -0,0 +1,513 @@
+{\bf ncmpi\_put\_var1\_TYPE()}: Write a Single Data Value
+
+\begin{verbatim}
+int ncmpi_put_var1_schar(int ncid, int varid, const MPI_Offset index[],
+                    const signed char *op);
+
+int ncmpi_put_var1_text(int ncid, int varid, const MPI_Offset index[],
+                    const char *op);
+
+int ncmpi_put_var1_short(int ncid, int varid, const MPI_Offset index[],
+                     const short *op);
+
+int ncmpi_put_var1_int(int ncid, int varid, const MPI_Offset index[],
+                   const int *op);
+
+int ncmpi_put_var1_uchar(int ncid, int varid, const MPI_Offset index[],
+                    const unsigned char *op);
+
+int ncmpi_put_var1_long(int ncid, int varid, const MPI_Offset index[],
+                   const long *ip);
+
+int ncmpi_put_var1_float(int ncid, int varid, const MPI_Offset index[],
+                     const float *op);
+
+int ncmpi_put_var1_double(int ncid, int varid, const MPI_Offset index[],
+                      const double *op);
+\end{verbatim}
+
+
+{\bf ncmpi\_get\_var1\_TYPE()}: Read a Single Data Value
+
+\begin{verbatim}
+int ncmpi_get_var1_schar(int ncid, int varid, const MPI_Offset index[],
+                    signed char *ip);
+
+int ncmpi_get_var1_text(int ncid, int varid, const MPI_Offset index[],
+                    char *ip);
+
+int ncmpi_get_var1_short(int ncid, int varid, const MPI_Offset index[],
+                     short *ip);
+
+int ncmpi_get_var1_int(int ncid, int varid, const MPI_Offset index[],
+                   int *ip);
+
+int ncmpi_get_var1_uchar(int ncid, int varid, const MPI_Offset index[],
+                    unsigned char *ip);
+
+int ncmpi_get_var1_long(int ncid, int varid, const MPI_Offset index[],
+                   long *ip);
+
+int ncmpi_get_var1_float(int ncid, int varid, const MPI_Offset index[],
+                     float *ip);
+
+int ncmpi_get_var1_double(int ncid, int varid, const MPI_Offset index[],
+                      double *ip);
+\end{verbatim}
+
+
+{\bf ncmpi\_put\_var\_TYPE()}: Write an Entire Variable
+
+\begin{verbatim}
+int ncmpi_put_var_schar(int ncid, int varid, const signed char *op);
+
+int ncmpi_put_var_schar_all(int ncid, int varid, const signed char *op);
+
+int ncmpi_put_var_text(int ncid, int varid, const char *op);
+
+int ncmpi_put_var_text_all(int ncid, int varid, const char *op);
+
+int ncmpi_put_var_short(int ncid, int varid, const short *op);
+
+int ncmpi_put_var_short_all(int ncid, int varid, const short *op);
+
+int ncmpi_put_var_int(int ncid, int varid, const int *op);
+
+int ncmpi_put_var_int_all(int ncid, int varid, const int *op);
+
+int ncmpi_put_var_uchar(int ncid, int varid, const unsigned char *op);
+
+int ncmpi_put_var_uchar_all(int ncid, int varid, const unsigned char *op);
+
+int ncmpi_put_var_long(int ncid, int varid, const long *op);
+
+int ncmpi_put_var_long_all(int ncid, int varid, const long *op);
+
+int ncmpi_put_var_float(int ncid, int varid, const float *op);
+
+int ncmpi_put_var_float_all(int ncid, int varid, const float *op);
+
+int ncmpi_put_var_double(int ncid, int varid, const double *op);
+
+int ncmpi_put_var_double_all(int ncid, int varid, const double *op);
+
+\end{verbatim}
+
+
+{\bf ncmpi\_get\_var\_TYPE()}: Read an Entire Variable
+
+\begin{verbatim}
+int ncmpi_get_var_schar(int ncid, int varid, signed char *ip);
+
+int ncmpi_get_var_schar_all(int ncid, int varid, signed char *ip);
+
+int ncmpi_get_var_text(int ncid, int varid, char *ip);
+
+int ncmpi_get_var_text_all(int ncid, int varid, char *ip);
+
+int ncmpi_get_var_short(int ncid, int varid, short *ip);
+
+int ncmpi_get_var_short_all(int ncid, int varid, short *ip);
+
+int ncmpi_get_var_int(int ncid, int varid, int *ip);
+
+int ncmpi_get_var_int_all(int ncid, int varid, int *ip);
+
+int ncmpi_get_var_uchar(int ncid, int varid, unsigned char *ip);
+
+int ncmpi_get_var_uchar_all(int ncid, int varid, unsigned char *ip);
+
+int ncmpi_get_var_long(int ncid, int varid, long *ip);
+
+int ncmpi_get_var_long_all(int ncid, int varid, long *ip);
+
+int ncmpi_get_var_float(int ncid, int varid, float *ip);
+
+int ncmpi_get_var_float_all(int ncid, int varid, float *ip);
+
+int ncmpi_get_var_double(int ncid, int varid, double *ip);
+
+int ncmpi_get_var_double_all(int ncid, int varid, double *ip);
+\end{verbatim}
+
+
+{\bf ncmpi\_put\_vara\_TYPE()}: Write an Array of Values
+
+\begin{verbatim}
+int ncmpi_put_vara_schar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const signed char *op);
+
+int ncmpi_put_vara_schar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const signed char *op);
+
+int ncmpi_put_vara_text(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const char *op);
+
+int ncmpi_put_vara_text_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const char *op);
+
+int ncmpi_put_vara_short(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const short *op);
+
+int ncmpi_put_vara_short_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const short *op);
+
+int ncmpi_put_vara_int(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const int *op);
+
+int ncmpi_put_vara_int_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const int *op);
+
+int ncmpi_put_vara_uchar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const unsigned char *op);
+
+int ncmpi_put_vara_uchar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const unsigned char *op);
+
+int ncmpi_put_vara_long(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const long *op);
+
+int ncmpi_put_vara_long_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const long *op);
+
+int ncmpi_put_vara_float(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const float *op); 
+
+int ncmpi_put_vara_float_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const float *op); 
+
+int ncmpi_put_vara_double(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const double *op); 
+
+int ncmpi_put_vara_double_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const double *op); 
+\end{verbatim}
+
+
+{\bf ncmpi\_get\_vara\_TYPE()}: Read an Array of Values
+
+\begin{verbatim}
+int ncmpi_get_vara_schar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], signed char *ip);
+
+int ncmpi_get_vara_schar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], signed char *ip);
+
+int ncmpi_get_vara_text(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], char *ip); 
+
+int ncmpi_get_vara_text_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], char *ip); 
+
+int ncmpi_get_vara_short(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], short *ip); 
+
+int ncmpi_get_vara_short_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], short *ip); 
+
+int ncmpi_get_vara_int(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], int *ip); 
+
+int ncmpi_get_vara_int_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], int *ip); 
+
+int ncmpi_get_vara_uchar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], unsigned char *ip);
+
+int ncmpi_get_vara_uchar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], unsigned char *ip); 
+
+int ncmpi_get_vara_long(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], long *ip);
+
+int ncmpi_get_vara_long_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], long *ip); 
+
+int ncmpi_get_vara_float(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], float *ip); 
+
+int ncmpi_get_vara_float_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], float *ip);
+
+int ncmpi_get_vara_double(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], double *ip);
+
+int ncmpi_get_vara_double_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], double *ip); 
+\end{verbatim}
+
+
+{\bf ncmpi\_put\_vars\_TYPE()}: Write a Subsampled Array of Values
+
+\begin{verbatim}
+int ncmpi_put_vars_schar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const signed char *op); 
+
+int ncmpi_put_vars_schar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const signed char *op); 
+
+int ncmpi_put_vars_text(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const char *op); 
+
+int ncmpi_put_vars_text_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const char *op); 
+
+int ncmpi_put_vars_short(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const short *op); 
+
+int ncmpi_put_vars_short_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const short *op); 
+
+int ncmpi_put_vars_int(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const int *op); 
+
+int ncmpi_put_vars_int_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const int *op); 
+
+int ncmpi_put_vars_uchar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const unsigned char *op);
+
+int ncmpi_put_vars_uchar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const unsigned char *op); 
+
+int ncmpi_put_vars_long(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const long *op);
+
+int ncmpi_put_vars_long_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const long *op); 
+
+int ncmpi_put_vars_float(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const float *op); 
+
+int ncmpi_put_vars_float_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const float *op);
+
+int ncmpi_put_vars_double(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const double *op); 
+
+int ncmpi_put_vars_double_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const double *op); 
+\end{verbatim}
+
+
+{\bf ncmpi\_get\_vars\_TYPE()}: Read a Subsampled Array of Values
+
+\begin{verbatim}
+int ncmpi_get_vars_schar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   signed char *ip); 
+
+int ncmpi_get_vars_schar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   signed char *ip); 
+
+int ncmpi_get_vars_text(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   char *ip); 
+
+int ncmpi_get_vars_text_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   char *ip); 
+
+int ncmpi_get_vars_short(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   short *ip); 
+
+int ncmpi_get_vars_short_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   short *ip); 
+
+int ncmpi_get_vars_int(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   int *ip); 
+
+int ncmpi_get_vars_int_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   int *ip); 
+
+int ncmpi_get_vars_uchar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   unsigned char *ip);
+
+int ncmpi_get_vars_uchar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   unsigned char *ip); 
+
+int ncmpi_get_vars_long(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   long *ip);
+
+int ncmpi_get_vars_long_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   long *ip); 
+
+int ncmpi_get_vars_float(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   float *ip); 
+
+int ncmpi_get_vars_float_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   float *ip); 
+
+int ncmpi_get_vars_double(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   double *ip);
+
+int ncmpi_get_vars_double_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   double *ip); 
+\end{verbatim}
+
+
+{\bf ncmpi\_put\_varm\_TYPE()}: Write a Mapped Array of Values
+
+\begin{verbatim}
+int ncmpi_put_varm_schar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const signed char *op); 
+
+int ncmpi_put_varm_schar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const signed char *op); 
+
+int ncmpi_put_varm_text(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const char *op); 
+
+int ncmpi_put_varm_text_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const char *op); 
+
+int ncmpi_put_varm_short(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const short *op); 
+
+int ncmpi_put_varm_short_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const short *op); 
+
+int ncmpi_put_varm_int(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const int *op);
+
+int ncmpi_put_varm_int_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const int *op); 
+
+int ncmpi_put_varm_uchar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const unsigned char *op);
+
+int ncmpi_put_varm_uchar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const unsigned char *op); 
+
+int ncmpi_put_varm_long(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const long *op);
+
+int ncmpi_put_varm_long_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const long *op); 
+
+int ncmpi_put_varm_float(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const float *op); 
+
+int ncmpi_put_varm_float_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const float *op); 
+
+int ncmpi_put_varm_double(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const double *op); 
+
+int ncmpi_put_varm_double_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const double *op); 
+\end{verbatim}
+
+
+{\bf ncmpi\_get\_varm\_TYPE()}: Read a Mapped Array of Values
+
+\begin{verbatim}
+int ncmpi_get_varm_schar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], signed char *ip); 
+
+int ncmpi_get_varm_schar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], signed char *ip); 
+
+int ncmpi_get_varm_text(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], char *ip); 
+
+int ncmpi_get_varm_text_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], char *ip); 
+
+int ncmpi_get_varm_short(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], short *ip); 
+
+int ncmpi_get_varm_short_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], short *ip); 
+
+int ncmpi_get_varm_int(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], int *ip); 
+
+int ncmpi_get_varm_int_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], int *ip); 
+
+int ncmpi_get_varm_uchar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], unsigned char *ip); 
+
+int ncmpi_get_varm_uchar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], unsigned char *ip); 
+
+int ncmpi_get_varm_long(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], long *ip);
+
+int ncmpi_get_varm_long_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], long *ip); 
+
+int ncmpi_get_varm_float(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], float *ip); 
+
+int ncmpi_get_varm_float_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], float *ip); 
+
+int ncmpi_get_varm_double(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], double *ip);
+
+int ncmpi_get_varm_double_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], double *ip); 
+\end{verbatim}
diff --git a/doc/flexible_api.tex b/doc/flexible_api.tex
new file mode 100644
index 0000000..ddd5deb
--- /dev/null
+++ b/doc/flexible_api.tex
@@ -0,0 +1,73 @@
+\begin{verbatim}
+int ncmpi_put_var1(int ncid, int varid, const MPI_Offset index[],
+               const void *buf, MPI_Offset bufcount, MPI_Datatype datatype);
+
+int ncmpi_get_var1(int ncid, int varid, const MPI_Offset index[],
+               void *buf, MPI_Offset bufcount, MPI_Datatype datatype);
+
+int ncmpi_put_var(int ncid, int varid, const void *buf, MPI_Offset bufcount,
+                  MPI_Datatype datatype);
+
+int ncmpi_put_var_all(int ncid, int varid, const void *buf, MPI_Offset bufcount,
+                  MPI_Datatype datatype);
+
+int ncmpi_get_var(int ncid, int varid, void *buf, MPI_Offset bufcount,
+                  MPI_Datatype datatype);
+
+int ncmpi_get_var_all(int ncid, int varid, void *buf, MPI_Offset bufcount,
+                  MPI_Datatype datatype);
+
+int ncmpi_put_vara(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const void *buf,
+                   MPI_Offset bufcount, MPI_Datatype datatype);
+int ncmpi_put_vara_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const void *buf,
+                   MPI_Offset bufcount, MPI_Datatype datatype);
+
+int ncmpi_get_vara(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], void *buf, MPI_Offset bufcount,
+                   MPI_Datatype datatype);
+
+int ncmpi_get_vara_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], void *buf, MPI_Offset bufcount,
+                   MPI_Datatype datatype);
+
+int ncmpi_put_vars(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const void *buf, MPI_Offset bufcount,
+                   MPI_Datatype datatype); 
+
+int ncmpi_put_vars_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const void *buf, MPI_Offset bufcount,
+                   MPI_Datatype datatype); 
+
+int ncmpi_get_vars(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   void *buf, MPI_Offset bufcount, MPI_Datatype datatype); 
+
+int ncmpi_get_vars_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   void *buf, MPI_Offset bufcount, MPI_Datatype datatype); 
+
+int ncmpi_put_varm(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const void *buf,
+                   MPI_Offset bufcount, MPI_Datatype datatype); 
+
+int ncmpi_put_varm_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const void *buf,
+                   MPI_Offset bufcount, MPI_Datatype datatype); 
+
+int ncmpi_get_varm(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], void *buf, MPI_Offset bufcount,
+                   MPI_Datatype datatype); 
+
+int ncmpi_get_varm_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], void *buf, MPI_Offset bufcount,
+                   MPI_Datatype datatype); 
+\end{verbatim}
+
diff --git a/doc/latex8.sty b/doc/latex8.sty
new file mode 100644
index 0000000..c9e4df3
--- /dev/null
+++ b/doc/latex8.sty
@@ -0,0 +1,175 @@
+% --------------------------------------------------------------- 
+%
+% $Id: latex8.sty 93 2003-04-14 15:00:43Z robl $
+% 
+% by Paolo.Ienne at di.epfl.ch 
+%
+% --------------------------------------------------------------- 
+%
+% no guarantee is given that the format corresponds perfectly to 
+% IEEE 8.5" x 11" Proceedings, but most features should be ok.
+%
+% --------------------------------------------------------------- 
+% with LaTeX2e:
+% =============
+%
+% use as 
+%   \documentclass[10pt,twocolumn]{article} 
+%   \usepackage{latex8}
+%   \usepackage{times}
+%
+% --------------------------------------------------------------- 
+
+% with LaTeX 2.09:
+% ================
+%
+% use as 
+%   \documentstyle[times,twocolumn,latex8]{article}
+%
+% --------------------------------------------------------------- 
+% with both versions:
+% ===================
+%
+% specify \pagestyle{empty} to omit page numbers in the final 
+% version
+%
+% specify references as
+%   \bibliographystyle{latex8}
+%   \bibliography{...your files...}
+%
+% use Section{} and SubSection{} instead of standard section{} 
+%    and subsection{} to obtain headings in the form 
+%    "1.3. My heading"
+%
+% ---------------------------------------------------------------
+
+\typeout{IEEE 8.5 x 11-Inch Proceedings Style `latex8.sty'.}
+
+% ten point helvetica bold required for captions
+% in some sites the name of the helvetica bold font may differ, 
+% change the name here:
+\font\tenhv  = phvb at 10pt
+%\font\tenhv  = phvb7t at 10pt
+
+% eleven point times bold required for second-order headings 
+% \font\elvbf  = cmbx10 scaled 1100
+\font\elvbf  = ptmb scaled 1100
+
+% set dimensions of columns, gap between columns, and paragraph indent 
+\setlength{\textheight}{8.875in}
+\setlength{\textwidth}{6.875in}
+\setlength{\columnsep}{0.3125in}
+\setlength{\topmargin}{0in}
+\setlength{\headheight}{0in}
+\setlength{\headsep}{0in}
+\setlength{\parindent}{1pc}
+\setlength{\oddsidemargin}{-.19in}
+\setlength{\evensidemargin}{-.19in}
+%\setlength{\evensidemargin}{-.304in}
+
+% memento from size10.clo
+% \normalsize{\@setfontsize\normalsize\@xpt\@xiipt} 
+% \small{\@setfontsize\small\@ixpt{11}}
+% \footnotesize{\@setfontsize\footnotesize\@viiipt{9.5}} 
+% \scriptsize{\@setfontsize\scriptsize\@viipt\@viiipt}
+% \tiny{\@setfontsize\tiny\@vpt\@vipt}
+% \large{\@setfontsize\large\@xiipt{14}} 
+% \Large{\@setfontsize\Large\@xivpt{18}} 
+% \LARGE{\@setfontsize\LARGE\@xviipt{22}} 
+% \huge{\@setfontsize\huge\@xxpt{25}}
+% \Huge{\@setfontsize\Huge\@xxvpt{30}}
+
+\def\@maketitle
+   {
+   \newpage
+   \null
+   \vskip .375in 
+   \begin{center}
+      {\Large \bf \@title \par} 
+      % additional two empty lines at the end of the title 
+      \vspace*{24pt} 
+      {
+      \large 
+      \lineskip .5em
+      \begin{tabular}[t]{c}
+         \@author 
+      \end{tabular}
+      \par
+      } 
+      % additional small space at the end of the author name 
+      \vskip .5em 
+      {
+       \large 
+      \begin{tabular}[t]{c}
+         \@affiliation 
+      \end{tabular}
+      \par 
+      \ifx \@empty \@email
+      \else
+         \begin{tabular}{r@{~}l}
+            E-mail: & {\tt \@email}
+         \end{tabular}
+         \par
+      \fi
+      }
+      % additional empty line at the end of the title block 
+      \vspace*{12pt} 
+   \end{center}
+   } 
+
+\def\abstract
+   {%
+   \centerline{\large\bf Abstract}%
+   \vspace*{12pt}%
+   \it%
+   }
+
+\def\endabstract
+   {
+   % additional empty line at the end of the abstract 
+   \vspace*{12pt} 
+   }
+
+\def\affiliation#1{\gdef\@affiliation{#1}} \gdef\@affiliation{}
+
+\def\email#1{\gdef\@email{#1}}
+\gdef\@email{}
+
+\newlength{\@ctmp}
+\newlength{\@figindent}
+\setlength{\@figindent}{1pc}
+
+\long\def\@makecaption#1#2{
+   \vskip 10pt
+   \setbox\@tempboxa\hbox{\tenhv\noindent #1.~#2} 
+   \setlength{\@ctmp}{\hsize}
+   \addtolength{\@ctmp}{-\@figindent}\addtolength{\@ctmp}{-\@figindent} 
+   % IF longer than one indented paragraph line
+   \ifdim \wd\@tempboxa >\@ctmp
+      % THEN set as an indented paragraph
+      \begin{list}{}{\leftmargin\@figindent \rightmargin\leftmargin} 
+         \item[]\tenhv #1.~#2\par
+      \end{list}
+   \else
+      % ELSE center
+      \hbox to\hsize{\hfil\box\@tempboxa\hfil} 
+   \fi}
+
+% correct heading spacing and type
+\def\section{\@startsection {section}{1}{\z@}
+   {14pt plus 1pt minus 1pt}{14pt plus 1pt minus 1pt} {\large\bf}} 
+\def\subsection{\@startsection {subsection}{2}{\z@}
+   {13pt plus 1pt minus 1pt}{13pt plus 1pt minus 1pt} {\elvbf}}
+\def\subsubsection{\@startsection {subsubsection}{3}{\z@}{12pt plus 1pt minus 1pt}
+{12pt plus 1pt minus 1pt}{\normalsize\bf}}
+\def\subsubsubsection{\@startsection {paragraph}{3}{\z@}{11pt plus 1pt minus 1pt}
+{11pt plus 1pt minus 1pt}{\small\bf}}
+
+% add the period after section numbers 
+\newcommand{\Section}[1]{\section{\hskip -1em.~#1}} 
+\newcommand{\SubSection}[1]{\subsection{\hskip -1em.~#1}}
+\newcommand{\SubSubSection}[1]{\subsubsection{\hskip -1em.~#1}}
+\newcommand{\SubSubSubSection}[1]{\subsubsubsection{\hskip -1em.~#1}}
+
+% end of file latex8.sty
+% ---------------------------------------------------------------
diff --git a/doc/multiple_io.tex b/doc/multiple_io.tex
new file mode 100644
index 0000000..66ab26e
--- /dev/null
+++ b/doc/multiple_io.tex
@@ -0,0 +1,152 @@
+{\bf ncmpi\_mput\_var1()}: Write Multiple Single Data Values
+
+\begin{verbatim}
+int ncmpi_mput_var1(int ncid, int ntimes, int varids[],
+                   MPI_Offset* const starts[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+
+int ncmpi_mput_var1_all(int ncid, int ntimes, int varids[], 
+                   MPI_Offset* const starts[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+\end{verbatim}
+
+
+{\bf ncmpi\_mget\_var1()}: Read Multiple Single Data Values
+
+\begin{verbatim}
+int ncmpi_mget_var1(int ncid, int ntimes, int varids[], 
+                   MPI_Offset* const starts[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+
+int ncmpi_mget_var1_all(int ncid, int ntimes, int varids[], 
+                   MPI_Offset* const starts[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+\end{verbatim}
+
+
+{\bf ncmpi\_mput\_var()}: Write Multiple Entire Variables
+
+\begin{verbatim}
+int ncmpi_mput_var(int ncid, int ntimes, int varids[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+
+int ncmpi_mput_var_all(int ncid, int ntimes, int varids[], 
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+\end{verbatim}
+
+
+{\bf ncmpi\_mget\_var()}: Read Multiple Entire Variables
+
+\begin{verbatim}
+int ncmpi_mget_var(int ncid, int ntimes, int varids[], 
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+
+int ncmpi_mget_var_all(int ncid, int ntimes, int varids[], 
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+\end{verbatim}
+
+
+{\bf ncmpi\_mput\_vara()}: Write Multiple Arrays of Values
+
+\begin{verbatim}
+int ncmpi_mput_vara(int ncid, int ntimes, int varids[],
+                   MPI_Offset* const starts[], MPI_Offset* const counts[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+
+int ncmpi_mput_vara_all(int ncid, int ntimes, int varids[], 
+                   MPI_Offset* const starts[], MPI_Offset* const counts[], 
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+\end{verbatim}
+
+
+{\bf ncmpi\_mget\_vara()}: Read Multiple Arrays of Values
+
+\begin{verbatim}
+int ncmpi_mget_vara(int ncid, int ntimes, int varids[], 
+                   MPI_Offset* const starts[], MPI_Offset* const counts[], 
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+
+int ncmpi_mget_vara_all(int ncid, int ntimes, int varids[], 
+                   MPI_Offset* const starts[], MPI_Offset* const counts[], 
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+\end{verbatim}
+
+
+{\bf ncmpi\_mput\_vars()}: Write Multiple Subsampled Arrays of Values
+
+\begin{verbatim}
+int ncmpi_mput_vars(int ncid, int ntimes, int varids[],
+                   MPI_Offset* const starts[], MPI_Offset* const counts[],
+                   MPI_Offset* const strides[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+
+int ncmpi_mput_vars_all(int ncid, int ntimes, int varids[], 
+                   MPI_Offset* const starts[], MPI_Offset* const counts[], 
+                   MPI_Offset* const strides[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+\end{verbatim}
+
+
+{\bf ncmpi\_mget\_vars()}: Read Multiple Subsampled Arrays of Values
+
+\begin{verbatim}
+int ncmpi_mget_vars(int ncid, int ntimes, int varids[], 
+                   MPI_Offset* const starts[], MPI_Offset* const counts[], 
+                   MPI_Offset* const strides[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+
+int ncmpi_mget_vars_all(int ncid, int ntimes, int varids[], 
+                   MPI_Offset* const starts[], MPI_Offset* const counts[], 
+                   MPI_Offset* const strides[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+\end{verbatim}
+
+
+{\bf ncmpi\_mput\_varm()}: Write Multiple Mapped Arrays of Values
+
+\begin{verbatim}
+int ncmpi_mput_varm(int ncid, int ntimes, int varids[],
+                   MPI_Offset* const starts[], MPI_Offset* const counts[],
+                   MPI_Offset* const strides[], MPI_Offset* const imaps[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+
+int ncmpi_mput_varm_all(int ncid, int ntimes, int varids[], 
+                   MPI_Offset* const starts[], MPI_Offset* const counts[], 
+                   MPI_Offset* const strides[], MPI_Offset* const imaps[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+\end{verbatim}
+
+
+{\bf ncmpi\_mget\_varm()}: Read Multiple Mapped Arrays of Values
+
+\begin{verbatim}
+int ncmpi_mget_varm(int ncid, int ntimes, int varids[], 
+                   MPI_Offset* const starts[], MPI_Offset* const counts[], 
+                   MPI_Offset* const strides[], MPI_Offset* const imaps[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+
+int ncmpi_mget_varm_all(int ncid, int ntimes, int varids[], 
+                   MPI_Offset* const starts[], MPI_Offset* const counts[], 
+                   MPI_Offset* const strides[], MPI_Offset* const imaps[],
+                   void *bufs[], MPI_Offset bufcounts[],
+                   MPI_Datatype datatypes[]);
+\end{verbatim}
diff --git a/doc/nonblocking.tex b/doc/nonblocking.tex
new file mode 100644
index 0000000..4efac66
--- /dev/null
+++ b/doc/nonblocking.tex
@@ -0,0 +1,362 @@
+\begin{verbatim}
+int ncmpi_wait(int ncid, int count, int array_of_requests[],
+                   int array_of_statuses[]);
+
+int ncmpi_wait_all(int ncid, int count, int array_of_requests[],
+                   int array_of_statuses[]);
+
+int ncmpi_cancel(int ncid, int num, int *requests, int *statuses);
+\end{verbatim}
+
+
+{\bf ncmpi\_iput\_var1\_TYPE()}: Post a Nonblocking Write for a Single Data Value
+
+\begin{verbatim}
+int ncmpi_iput_var1(int ncid, int varid, const MPI_Offset index[],
+                    const void *buf, MPI_Offset bufcount,
+                    MPI_Datatype datatype, int *request); 
+
+int ncmpi_iput_var1_schar(int ncid, int varid, const MPI_Offset index[],
+                    const signed char *op, int *request); 
+
+int ncmpi_iput_var1_text(int ncid, int varid, const MPI_Offset index[],
+                    const char *op, int *request); 
+
+int ncmpi_iput_var1_short(int ncid, int varid, const MPI_Offset index[],
+                    const short *op, int *request); 
+
+int ncmpi_iput_var1_int(int ncid, int varid, const MPI_Offset index[],
+                    const int *op, int *request); 
+
+int ncmpi_iput_var1_uchar(int ncid, int varid, const MPI_Offset index[],
+                    const unsigned char *op, int *request);
+
+int ncmpi_iput_var1_long(int ncid, int varid, const MPI_Offset index[],
+                    const long *ip, int *request);
+
+int ncmpi_iput_var1_float(int ncid, int varid, const MPI_Offset index[],
+                    const float *op, int *request); 
+
+int ncmpi_iput_var1_double(int ncid, int varid, const MPI_Offset index[],
+                    const double *op, int *request); 
+\end{verbatim}
+
+
+{\bf ncmpi\_iget\_var1\_TYPE()}: Post a Nonblocking Read for a Single Data Value
+
+\begin{verbatim}
+int ncmpi_iget_var1(int ncid, int varid, const MPI_Offset index[], void *buf,
+                    MPI_Offset bufcount, MPI_Datatype datatype, int *request); 
+
+int ncmpi_iget_var1_schar(int ncid, int varid, const MPI_Offset index[],
+                    signed char *ip, int *request); 
+
+int ncmpi_iget_var1_text(int ncid, int varid, const MPI_Offset index[],
+                    char *ip, int *request); 
+
+int ncmpi_iget_var1_short(int ncid, int varid, const MPI_Offset index[],
+                    short *ip, int *request); 
+
+int ncmpi_iget_var1_int(int ncid, int varid, const MPI_Offset index[],
+                    int *ip, int *request); 
+
+int ncmpi_iget_var1_uchar(int ncid, int varid, const MPI_Offset index[],
+                    unsigned char *ip, int *request);
+
+int ncmpi_iget_var1_long(int ncid, int varid, const MPI_Offset index[],
+                    long *ip, int *request);
+
+int ncmpi_iget_var1_float(int ncid, int varid, const MPI_Offset index[],
+                    float *ip, int *request); 
+
+int ncmpi_iget_var1_double(int ncid, int varid, const MPI_Offset index[],
+                    double *ip, int *request);
+\end{verbatim}
+
+
+{\bf ncmpi\_iput\_var\_TYPE()}: Post a Nonblocking Write for an Entire Variable
+
+\begin{verbatim}
+int ncmpi_iput_var(int ncid, int varid, const void *buf, MPI_Offset bufcount,
+                    MPI_Datatype datatype, int *request);
+
+int ncmpi_iput_var_schar(int ncid, int varid, const signed char *op,
+                    int *request);
+
+int ncmpi_iput_var_text(int ncid, int varid, const char *op, int *request);
+
+int ncmpi_iput_var_short(int ncid, int varid, const short *op, int *request);
+
+int ncmpi_iput_var_int(int ncid, int varid, const int *op, int *request);
+
+int ncmpi_iput_var_uchar(int ncid, int varid, const unsigned char *op,
+                    int *request);
+
+int ncmpi_iput_var_long(int ncid, int varid, const long *op, int *request);
+
+int ncmpi_iput_var_float(int ncid, int varid, const float *op, int *request);
+
+int ncmpi_iput_var_double(int ncid, int varid, const double *op, int *request);
+\end{verbatim}
+
+
+{\bf ncmpi\_iget\_var\_TYPE()}: Post a Nonblocking Read for an Entire Variable
+
+\begin{verbatim}
+int ncmpi_iget_var(int ncid, int varid, void *buf, MPI_Offset bufcount,
+                    MPI_Datatype datatype, int *request);
+
+int ncmpi_iget_var_schar(int ncid, int varid, signed char *ip, int *request);
+
+int ncmpi_iget_var_text(int ncid, int varid, char *ip, int *request);
+
+int ncmpi_iget_var_short(int ncid, int varid, short *ip, int *request);
+
+int ncmpi_iget_var_int(int ncid, int varid, int *ip, int *request);
+
+int ncmpi_iget_var_uchar(int ncid, int varid, unsigned char *ip, int *request);
+
+int ncmpi_iget_var_long(int ncid, int varid, long *ip, int *request);
+
+int ncmpi_iget_var_float(int ncid, int varid, float *ip, int *request);
+
+int ncmpi_iget_var_double(int ncid, int varid, double *ip, int *request);
+\end{verbatim}
+
+
+{\bf ncmpi\_iput\_vara\_TYPE()}: Post a Nonblocking Write for Array of Values
+
+\begin{verbatim}
+int ncmpi_iput_vara(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const void *buf,
+                    MPI_Offset bufcount, MPI_Datatype datatype, int *request); 
+
+int ncmpi_iput_vara_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const signed char *op,
+                    int *request); 
+
+int ncmpi_iput_vara_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const char *op, int *request); 
+
+int ncmpi_iput_vara_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const short *op, int *request); 
+
+int ncmpi_iput_vara_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const int *op, int *request); 
+
+int ncmpi_iput_vara_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const unsigned char *op,
+                    int *request);
+
+int ncmpi_iput_vara_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const long *op, int *request);
+
+int ncmpi_iput_vara_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const float *op, int *request); 
+
+int ncmpi_iput_vara_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const double *op, int *request); 
+\end{verbatim}
+
+
+{\bf ncmpi\_iget\_vara\_TYPE()}: Post a Nonblocking Read for Array of Values
+
+\begin{verbatim}
+int ncmpi_iget_vara(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], void *buf, MPI_Offset bufcount,
+                    MPI_Datatype datatype, int *request); 
+
+int ncmpi_iget_vara_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], signed char *ip, int *request); 
+
+int ncmpi_iget_vara_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], char *ip, int *request); 
+
+int ncmpi_iget_vara_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], short *ip, int *request); 
+
+int ncmpi_iget_vara_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], int *ip, int *request); 
+
+int ncmpi_iget_vara_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], unsigned char *ip, int *request);
+
+int ncmpi_iget_vara_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], long *ip, int *request);
+
+int ncmpi_iget_vara_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], float *ip, int *request); 
+
+int ncmpi_iget_vara_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], double *ip, int *request);
+\end{verbatim}
+
+
+{\bf ncmpi\_iput\_vars\_TYPE()}: Post a Nonblocking Write for Subsampled Array of Values
+
+\begin{verbatim}
+int ncmpi_iput_vars(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const void *buf, MPI_Offset bufcount,
+                    MPI_Datatype datatype, int *request); 
+
+int ncmpi_iput_vars_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const signed char *op, int *request); 
+
+int ncmpi_iput_vars_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const char *op, int *request); 
+
+int ncmpi_iput_vars_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const short *op, int *request); 
+
+int ncmpi_iput_vars_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const int *op, int *request); 
+
+int ncmpi_iput_vars_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const unsigned char *op, int *request);
+
+int ncmpi_iput_vars_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const long *op, int *request);
+\end{verbatim}
+
+
+{\bf ncmpi\_iget\_vars\_TYPE()}: Post a Nonblocking Read for Subsampled Array of Values
+
+\begin{verbatim}
+int ncmpi_iget_vars(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    void *buf, MPI_Offset bufcount, MPI_Datatype datatype,
+                    int *request); 
+
+int ncmpi_iput_vars_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const float *op, int *request); 
+
+int ncmpi_iput_vars_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const double *op, int *request); 
+
+int ncmpi_iget_vars_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    signed char *ip, int *request); 
+
+int ncmpi_iget_vars_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    char *ip, int *request); 
+
+int ncmpi_iget_vars_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    short *ip, int *request); 
+
+int ncmpi_iget_vars_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    int *ip, int *request); 
+
+int ncmpi_iget_vars_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    unsigned char *ip, int *request);
+
+int ncmpi_iget_vars_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    long *ip, int *request); 
+
+int ncmpi_iget_vars_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    float *ip, int *request); 
+
+int ncmpi_iget_vars_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    double *ip, int *request); 
+\end{verbatim}
+
+
+{\bf ncmpi\_iput\_varm\_TYPE()}: Post a Nonblocking Write for Mapped Array of Values
+
+\begin{verbatim}
+int ncmpi_iput_varm(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const void *buf,
+                    MPI_Offset bufcount, MPI_Datatype datatype, int *request); 
+
+int ncmpi_iput_varm_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const signed char *op,
+                    int *request); 
+
+int ncmpi_iput_varm_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const char *op, int *request); 
+
+int ncmpi_iput_varm_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const short *op, int *request); 
+
+int ncmpi_iput_varm_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const int *op, int *request); 
+
+int ncmpi_iput_varm_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const unsigned char *op,
+                    int *request);
+
+int ncmpi_iput_varm_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const long *op, int *request);
+
+int ncmpi_iput_varm_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const float *op, int *request); 
+
+int ncmpi_iput_varm_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const double *op, int *request); 
+\end{verbatim}
+
+
+{\bf ncmpi\_iget\_varm\_TYPE()}: Post a Nonblocking Read for Mapped Array of Values
+
+\begin{verbatim}
+int ncmpi_iget_varm(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], void *buf, MPI_Offset bufcount,
+                    MPI_Datatype datatype, int *request); 
+
+int ncmpi_iget_varm_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], signed char *ip, int *request); 
+
+int ncmpi_iget_varm_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], char *ip, int *request); 
+
+int ncmpi_iget_varm_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], short *ip, int *request); 
+
+int ncmpi_iget_varm_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], int *ip, int *request); 
+
+int ncmpi_iget_varm_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], unsigned char *ip, int *request);
+
+int ncmpi_iget_varm_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], long *ip, int *request);
+
+int ncmpi_iget_varm_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], float *ip, int *request); 
+
+int ncmpi_iget_varm_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], double *ip, int *request);
+\end{verbatim}
diff --git a/doc/pnetcdf-api.bbl b/doc/pnetcdf-api.bbl
new file mode 100644
index 0000000..858537f
--- /dev/null
+++ b/doc/pnetcdf-api.bbl
@@ -0,0 +1,10 @@
+\begin{thebibliography}{1}
+
+\bibitem{thakur:romio}
+Rajeev Thakur, William Gropp, and Ewing Lusk.
+\newblock Data sieving and collective {I/O} in {ROMIO}.
+\newblock In {\em Proceedings of the Seventh Symposium on the Frontiers of
+  Massively Parallel Computation}, pages 182--189. IEEE Computer Society Press,
+  February 1999.
+
+\end{thebibliography}
diff --git a/doc/pnetcdf-api.tex b/doc/pnetcdf-api.tex
new file mode 100644
index 0000000..695ca71
--- /dev/null
+++ b/doc/pnetcdf-api.tex
@@ -0,0 +1,655 @@
+\documentclass[10pt]{article}
+% \usepackage{utopia}
+
+\pagestyle{plain}
+
+\addtolength{\hoffset}{-2cm}
+\addtolength{\textwidth}{4cm}
+
+\addtolength{\voffset}{-1.5cm}
+\addtolength{\textheight}{3cm}
+
+\setlength{\parindent}{0pt}
+\setlength{\parskip}{11pt}
+
+\title{A Parallel API for Creating and Reading NetCDF Files}
+
+\begin{document}
+
+\maketitle
+
+\begin{abstract}
+Scientists recognize the importance of portable and efficient mechanisms for
+storing datasets created and used by their applications.  NetCDF is one such
+mechanism and is popular in a number of applicaiton domains because of its
+availability on a wide variety of platforms and its easy to use API.  However,
+this API was originally designed for use in serial codes, and so the semantics
+of the interface are not designed to allow for high performance parallel
+access.
+
+In this work we present a new API for creating and reading NetCDF datasets,
+the \emph{Parallel NetCDF API}.  This interface builds on the original NetCDF
+interface and defines semantics for parallel access to NetCDF datasets.  The
+interface is built on top of MPI-IO, allowing for further performance gains
+through the use of collective I/O optimizations that already exist in MPI-IO
+implementations.
+
+\end{abstract}
+
+\section{Introduction}
+
+NetCDF is a popular package for storing data files in scientific applications.
+NetCDF consists of both an API and a portable file format.  The API provides a
+consistent interface for access NetCDF files across multiple platforms, while
+the NetCDF file format guarantees data portability.
+
+The NetCDF API provides a convenient mechanism for a single process to define
+and access variables and attributes in a NetCDF file.  However, it does not
+define a parallel access mechanism.  In particular there is no mechanism for
+concurrently writing to a NetCDF data file.  Because of this, parallel
+applications operating on NetCDF files must serialize access.  This is
+typically accomplished by shipping all data to and from a single process that
+performs NetCDF operations.  This mode of access is both cumbersome to the
+application programmer and considerably slower than parallel access to the
+NetCDF file.  This mode can be particularly inconvenient when data set sizes
+exceed the size of available memory on a single node; in this case the data
+must be split into pieces to be shipped and written.
+
+In this document we propose an alternative API for accessing NetCDF format
+files in a parallel application.  This API allows all processes in a parallel
+application to access the NetCDF file simultaneously, which is considerably
+more convenient than the serial API and allows for significantly higher
+performance.
+
+\emph{Note subset of interface that we are implementing, including both what
+types we support and any functions that we might be leaving out.}
+
+\section{Preliminaries}
+
+In MPI, communicators are typically used to describe collections of processes
+to MPI calls (e.g. the collective MPI-1 calls).  In our parallel NetCDF API we
+will similarly use a communicator to denote a collection of MPI processes that
+will access a NetCDF file.  By describing this collection of processes, we
+provide the underlying implementation (of our parallel NetCDF API) with
+information that it can use to ensure that the file is kept in a consistent
+state.  
+
+Further, by using the collective operations provided in our parallel NetCDF
+API (ones in which all processes in this collection participate), application
+programmers provide the underlying implementation with an opportunity to
+further optimize access to the NetCDF file.  These optimizations are performed
+without further intervention by the application programmer and have been
+proven to provide huge performance wins in multidimensional dataset access \cite{thakur:romio},
+exactly the kinds of accesses used in NetCDF.
+
+All this said, the original NetCDF interface is made available with a minimum
+of changes so that users migrating from the original NetCDF interface will
+have little trouble moving to this new, parallel NetCDF interface.
+
+The decision to slightly modify the API was not made lightly.  It is
+relatively trivial to port NetCDF to use MPI-IO through the use of the MPI-IO
+independent access calls.  However, it was only though adding this concept of
+a collection of processes simultaneously accessing the file and adding
+collective access semantics that we could hope to eliminate the serialization
+step necessary in the original API or gain the performance advantages
+available from the use of collective optimizations.  Thus our performance
+requirements mandated these small adjustments.
+
+% Finally, some of the calls in our API utilize MPI datatypes.  These datatypes
+% allow one to describe noncontiguous regions of data (in this case memory
+% regions) as an endpoint of a data transfer.
+
+\section{Parallel NetCDF API}
+
+The NetCDF interface breaks access into two \emph{modes}, ``define'' mode and
+``data'' mode.  The define mode is used to describe the data set to be stored,
+while the data mode is used for storing and retrieving data values.
+
+We maintain these modes and (for the most part) maintain the operations when
+in define mode.  We will discuss the API for opening and closing a dataset and
+for moving between modes first, next cover inquiry functions, then cover the
+define mode, attribute functions, and finally discuss the API for data mode.
+
+%
+% PREFIX
+%
+We will prefix our C interface calls with ``ncmpi'' and our Fortran interface
+calls with ``nfmpi''.  This ensures no naming clashes with existing NetCDF
+libraries and does not conflict with the desire to reserve the ``MPI'' prefix
+for functions that are part of the MPI standard.
+
+All of our functions return integer NetCDF status values, just as the original
+NetCDF interface does.
+
+We will only discuss points where our interface deviates from the original
+interface in the following sections. A complete function listing is included
+in Appendix A.
+
+\subsection{Variable and Parameter Types}
+
+%
+% MPI_Offset
+%
+Rather than using \texttt{size\_t} types for size parameters passed in to our
+functions, we choose to use \texttt{MPI\_Offset} type instead.  For many
+systems \texttt{size\_t} is a 32-bit unsigned value, which limits the maximum
+range of values to 4~GBytes.  The \texttt{MPI\_Offset} is typically a 64-bit
+value, so it does not have this limitation.  This gives us room to extend the
+file size capabilities of NetCDF at a later date.
+
+\emph{Add mapping of MPI types to NetCDF types.}
+
+\emph{Is NetCDF already exactly in external32 format?}
+
+\subsection{Dataset Functions}
+
+As mentioned before, we will define a collection of processes that are
+operating on the file by passing in a MPI communicator.  This communicator is
+passed in the call to \texttt{ncmpi\_create} or \texttt{ncmpi\_open}.  These
+calls are collective across all processes in the communicator.  The second
+additional parameter is an \texttt{MPI\_Info}.  This is used to pass hints in
+to the implementation (e.g. expected access pattern, aggregation
+information).  The value \texttt{MPI\_INFO\_NULL} may be passed in if the user
+does not want to take advantage of this feature.
+
+\begin{verbatim}
+int ncmpi_create(MPI_Comm comm, 
+                 const char *path, 
+                 int cmode,
+                 MPI_Info info,
+                 int *ncidp)
+
+int ncmpi_open(MPI_Comm comm, 
+               const char *path, 
+               int omode,
+               MPI_Info info,
+               int *ncidp)
+\end{verbatim}
+
+\subsection{Define Mode Functions}
+
+\emph{All define mode functions are collective} (see Appendix B for
+rationale).
+
+All processes in the communicator must call them with the same values.  At the
+end of the define mode the values passed in by all processes are checked to
+verify that they match, and if they do not then an error is returned from the
+\texttt{ncmpi\_enddef}.
+
+
+\subsection{Inquiry Functions}
+
+\emph{These calls are all collective operations} (see Appendix B for
+rationale).
+
+As in the original NetCDF interface, they may be called from either define or
+data mode.  \emph{ They return information stored prior to the last open,
+enddef, or sync.}
+
+% In the original NetCDF interface the inquiry functions could be called from
+% either data or define mode.  To aid in the implementation of these functions
+% in a parallel library, \emph{inquiry functions may only be called in data mode
+% in the parallel NetCDF API}.  They return information stored prior to the last
+% open, enddef, or sync.  This ensures that the NetCDF metadata need only be
+% kept up-to-date on all nodes when in data mode.
+%
+
+\subsection{Attribute Functions}
+
+\emph{These calls are all collective operations} (see Appendix B for
+rationale).
+
+Attributes in NetCDF are intended for storing scalar or vector values that
+describe a variable in some way.  As such the expectation is that these
+attributes will be small enough to fit into memory.  
+
+In the original interface, attribute operations can be performed in either
+define or data mode; however, it is possible for attribute operations that
+modify attributes (e.g. copy or create attributes) to fail if in data mode.
+This is possible because such operations can cause the amount of space needed
+to grow.  In this case the cost of the operation can be on the order of a copy
+of the entire dataset.  We will maintain these semantics.
+
+\subsection{Data Mode Functions}
+
+The most important change from the original NetCDF interface with respect to
+data mode functions is the split of data mode into two distinct modes:
+\emph{collective data mode} and \emph{independent data mode}.  \emph{By default when
+a user calls \texttt{ncmpi\_enddef} or \texttt{ncmpi\_open}, the user will be
+in collective data mode.}  The expectation is that most users will be using the
+collective operations; these users will never need to switch to independent
+data mode.  In collective data mode, all processes must call the same function
+on the same ncid at the same point in the code.  Different parameters for
+values such as start, count, and stride, are acceptable.  Knowledge that all
+processes will be calling the function allows for additional optimization
+under the API.  In independent mode processes do not need to coordinate calls
+to the API; however, this limits the optimizations that can be applied to I/O operations.
+
+A pair of new dataset operations \texttt{ncmpi\_begin\_indep\_data} and
+\texttt{ncmpi\_end\_indep\_data} switch into and out of independent data mode.
+These calls are collective.  Calling \texttt{ncmpi\_close} or
+\texttt{ncmpi\_redef} also leaves independent data mode.
+Note that it is illegal to enter independent data mode while in define mode.
+Users are reminded to call {\tt ncmpi\_enddef} to leave define mode and enter data mode.
+
+\begin{verbatim}
+int ncmpi_begin_indep_data(int ncid)
+
+int ncmpi_end_indep_data(int ncid)
+\end{verbatim}
+
+The separation of the data mode into two distinct data modes is necessary to
+provide consistent views of file data when moving between MPI-IO collective
+and independent operations.
+
+We have chosen to implement two collections of data mode functions.  The first
+collection closely mimics the original NetCDF access functions and is intended
+to serve as an easy path of migration from the original NetCDF interface to
+the parallel NetCDF interface.  We call this subset of our parallel NetCDF
+interface the \emph{high level data mode} interface.
+
+The second collection uses more MPI functionality in order to provide better
+handling of internal data representations and to more fully expose the
+capabilities of MPI-IO to the application programmer.  All of the first
+collection will be implemented in terms of these calls.  We will denote this
+the \emph{flexible data mode} interface.
+
+In both collections, both independent and collective operations are provided.
+Collective function names end with \texttt{\_all}.  They are collective across
+the communicator associated with the ncid, so all those processes must call
+the function at the same time.
+
+Remember that in all cases the input data type is converted into the
+appropriate type for the variable stored in the NetCDF file.
+
+\subsubsection{High Level Data Mode Interface}
+
+The independent calls in this interface closely resemble the NetCDF data mode
+interface.  The only major change is the use of \texttt{MPI\_Offset} types in
+place of \texttt{size\_t} types, as described previously.
+
+The collective calls have the same arguments as their independent
+counterparts, but they must be called by all processes in the communicator
+associated with the ncid.
+
+Here are the example prototypes for accessing a strided subarray of a variable
+in a NetCDF file; the remainder of the functions are listed in Appendix A.
+
+In our initial implementation the following data function types will be
+implemented for independent access: single data value read and write (var1),
+entire variable read and write (var), array of values read and write (vara),
+and subsampled array of values read and write (vars).  Collective versions of
+these types will also be provided, with the exception of a collective entire
+variable write; semantically this doesn't make sense.
+
+We could use the same function names for both independent and collective
+operations (relying instead on the mode associated with the ncid); however, we
+feel that the interface is cleaner, and it will be easier to detect bugs, with
+separate calls for independent and collective access.
+
+% \textbf{Strided Subarray Access}
+%
+Independent calls for writing or reading a strided subarray of values to/from
+a NetCDF variable (values are contiguous in memory):
+\begin{verbatim}
+int ncmpi_put_vars_uchar(int ncid, 
+                         int varid, 
+                         const MPI_Offset start[],
+                         const MPI_Offset count[], 
+                         const MPI_Offset stride[],
+                         const unsigned char *up)
+
+int ncmpi_get_vars_uchar(int ncid, 
+                         int varid, 
+                         const MPI_Offset start[],
+                         const MPI_Offset count[], 
+                         const MPI_Offset stride[],
+                         unsigned char *up)
+\end{verbatim}
+
+Collective calls for writing or reading a strided subarray of values to/from a
+NetCDF variable (values are contiguous in memory).
+\begin{verbatim}
+int ncmpi_put_vars_uchar_all(int ncid, 
+                             int varid, 
+                             const MPI_Offset start[],
+                             const MPI_Offset count[], 
+                             const MPI_Offset stride[],
+                             unsigned char *up)
+
+int ncmpi_get_vars_uchar_all(int ncid, 
+                             int varid, 
+                             const MPI_Offset start[],
+                             const MPI_Offset count[],
+                             const MPI_Offset stride[],
+                             unsigned char *up)
+\end{verbatim}
+
+\emph{Note what calls are and aren't implemented at this time.}
+
+\subsubsection{Flexible Data Mode Interface}
+
+This smaller set of functions is all that is needed to implement the data mode
+functions.  These are also made available to the application programmer.
+
+The advantage of these functions is that they allow the programmer to use MPI
+datatypes to describe the in-memory organization of the values.  The only
+mechanism provides in the original NetCDF interface for such a description is
+the mapped array calls.  Mapped arrays are a suboptimal method of describing
+any regular pattern in memory.
+
+In all these functions the varid, start, count, and stride values refer to the
+data in the file (just as in a NetCDF vars-type call).  The buf, count, and
+datatype fields refer to data in memory.
+
+Here are examples for subarray access:
+\begin{verbatim}
+int ncmpi_put_vars(int ncid,
+                   int varid,
+                   MPI_Offset start[],
+                   MPI_Offset count[],
+                   MPI_Offset stride[],
+                   const void *buf,
+                   int count,
+                   MPI_Datatype datatype)
+
+int ncmpi_get_vars(int ncid,
+                   int varid,
+                   MPI_Offset start[],
+                   MPI_Offset count[],
+                   MPI_Offset stride[],
+                   void *buf,
+                   int count,
+                   MPI_Datatype datatype)
+
+int ncmpi_put_vars_all(int ncid,
+                       int varid,
+                       MPI_Offset start[],
+                       MPI_Offset count[],
+                       MPI_Offset stride[],
+                       void *buf,
+                       int count,
+                       MPI_Datatype datatype)
+
+int ncmpi_get_vars_all(int ncid,
+                       int varid,
+                       MPI_Offset start[],
+                       MPI_Offset count[],
+                       MPI_Offset stride[],
+                       void *buf,
+                       int count,
+                       MPI_Datatype datatype)
+\end{verbatim}
+
+
+\subsubsection{Mapping Between NetCDF and MPI Types}
+
+It is assumed here that the datatypes passed to the flexible NetCDF interface
+use only one basic datatype.  For example, the datatype can be arbitrarily
+complex, but it cannot consist of both \texttt{MPI\_FLOAT} and
+\texttt{MPI\_INT} values, but only one of these basic types.
+
+\emph{Describe status of type support.}
+
+
+\subsection{Missing}
+
+Calls that were in John M.'s list but that we haven't mentioned here yet.
+
+Attribute functions, strerror, text functions, get\_vara\_text (?).
+
+\section{Examples}
+
+This section will hopefully soon hold some examples, perhaps based on writing
+out the 1D and 2D Jacobi examples in the Using MPI book using our interface?
+
+\section{Implementation Notes}
+
+Here we will keep any particular implementation details.  As the
+implementation matures, this section should discuss implementation decisions.
+
+One trend that will be seen throughout here is the use of collective I/O
+routines when it would be possible to use independent operations.  There are
+two reasons for this.  First, for some operations (such as reading the
+header), there are important optimizations that can be made to more
+efficiently read data from the I/O system, especially as the number of NetCDF
+application processes increases.  Second, the use of collective routines
+allows for the use of aggregation routines in the MPI-IO implementation.  This
+allows us to redirect I/O to nodes that have access to I/O resources in
+systems where not all processes have access.  This isn't currently possible
+using the independent I/O calls.
+
+See the ROMIO User's Guide for more information on the aggregation hints, in
+particular the \texttt{cb\_config\_list} hint.
+
+\subsection{Questions for Users on Implementation}
+\begin{itemize}
+\item Is this emphasis on collective operations appropriate or problematic?
+\item Is C or Fortran the primary language for NetCDF programs?
+\end{itemize}
+
+\subsection{I/O routines}
+
+All I/O within our implementation will be performed through MPI-IO.
+
+No temporary files will be created at any time.
+
+%
+% HEADER I/O
+%
+\subsection{Header I/O}
+
+\emph{It is assumed that headers are too small to benefit from parallel I/O.}
+
+All header updates will be performed with collective I/O, but only rank 0 will
+provide any input data.  This is important because only through the collective
+calls can our \texttt{cb\_config\_list} hint be used to control what hosts
+actually do writing.  Otherwise we could pick some arbitrary process to do
+I/O, but we have no way of knowing if that was a process that the user
+intended to do I/O in the first place (thus that process might not even be
+able to write to the file!)
+
+Headers are written all at once at \texttt{ncmpi\_enddef}.
+
+Likewise collective I/O will be used when reading the header, which should
+simply be used to read the entire header to everyone on open.
+
+\emph{First cut might not do this.}
+
+\subsection{Code Reuse}
+We will not reuse any NetCDF code.  This will give us an opportunity to leave
+out any code pertaining to optimizations on specific machines (e.g. Cray) that
+we will not need and, more importantly, cannot test.
+
+\subsection{Providing Independent and Collective I/O}
+In order to make use of \texttt{MPI\_File\_set\_view} for both independent and
+collective NetCDF operations, we will need to open the NetCDF file separately
+for both, with the input communicator for collective I/O and with
+MPI\_COMM\_SELF for independent I/O.  However, we can defer opening the file
+for independent access until an independent access call is made if we like.
+This can be an important optimization as we scale.
+
+Synchronization when switching between collective and independent access is
+mandatory to ensure correctness under the MPI I/O model.
+
+\subsection{Outline of I/O}
+
+Outline of steps to I/O:
+\begin{itemize}
+\item MPI\_File is extracted from ncid
+\item variable type is extracted from varid
+\item file view is created from:
+  \begin{itemize}
+  \item metadata associated with ncid
+  \item variable index info, array size, limited/unlimited, type from varid
+  \item start/count/stride info
+  \end{itemize}
+\item datatype/count must match number of elements specified by
+  start/count/stride
+\item status returns normal mpi status information, which is mapped to a
+  NetCDF error code.
+\end{itemize}
+
+
+\section{Future Work}
+
+More to add.
+
+%
+% BIBLIOGRAPHY
+%
+\bibliography{pnetcdf-api}
+\bibliographystyle{plain}
+
+%
+% APPENDIX A: FUNCTION LISTING
+%
+\section*{Appendix A: C API Listing}
+
+\input c_api
+
+%
+% APPENDIX B: RATIONALE
+%
+\section*{Appendix B: Rationale}
+
+This section covers the rationale behind our decisions on API specifics.
+
+%
+% define mode function semantics
+%
+\subsection*{B.1  Define Mode Function Semantics}
+
+There are two options to choose from here, either forcing a single process to
+make these calls (funnelled) or forcing all these calls to be collective with
+the same data.  Note that making them collective does \emph{not} imply any
+communication at the time the call is made.
+
+Both of these options allow for better error detection than what we
+previously described (functions independent, anyone could call, only node
+0's data was used).  Error detection could be performed at the end of the
+define mode to minimize costs.
+
+In fact, it is only fractionally more costly to implement collectives than
+funneled (including the error detection).  To do this one simply bcast's
+process 0's values out (which one would have to do anyway) and then
+allgathers a single char or int from everyone indicating if there was a
+problem.
+
+There has to be some synchronization at the end of the define mode in any
+case, so this extra error detection comes at an especially low cost.
+
+\subsection*{B.2  Attribute and Inquiry Function Semantics}
+
+There are similar options here to the ones for define mode functions.
+
+One option would be to make these functions independent.  This would be easy
+for read operations, but would be more difficult for write operations.  In
+particular we would need to gather up modifications at some point in order to
+distribute them out to all processes.  Ordering of modifications might also be
+an issue.  Finally, we would want to constrain use of these independent
+operations to the define mode so that we would have an obvious point at which
+to perform this collect and distribute operation (e.g. \texttt{ncmpi\_enddef}).
+
+Another option would be to make all of these functions collective.  This is an
+unnecessary constraint for the read operations, but it helps in implementing
+the write operations (we can distribute modifications right away) and allows
+us to maintain the use of these functions outside define mode if we wish.
+This is also more consistent with the SPMD model that (we think) our users are
+using.
+
+The final option would be to allow independent use of the read operations but
+force collective use of the write operations.  This would result in confusing
+semantics.
+
+For now we will implement the second option, all collective operation.  Based
+on feedback from users we will consider relaxing this constraint.
+
+\subsubsection*{Questions for Users Regarding Attribute and Inquiry Functions}
+\begin{itemize}
+\item Are attribute calls used in data mode?
+\item Is it inconvenient that the inquiry functions are collective?
+\end{itemize}
+
+\subsection*{B.3  Splitting Data Mode into Collective and Independent Data Modes}
+
+In both independent and collective MPI-IO operations, it is important to be
+able to set the file view to allow for noncontiguous file regions.  However,
+since the \texttt{MPI\_File\_set\_view} is a collective operation, it is
+impossible to use a single file handle to perform collective I/O and still be
+able to arbitrarily reset the file view before an independent operation
+(because all the processes would need to participate in the file set view).
+
+For this reason it is necessary to have two file handles in the case where
+both independent and collective I/O will be performed.  One file handle is
+opened with \texttt{MPI\_COMM\_SELF} and is used for independent operations,
+while the other is opened with the communicator containing all the processes
+for the collective operations.
+
+It is difficult if not impossible in the general case to ensure consistency of
+access when a collection of processes are using multiple MPI\_File handles to
+access the same file with mixed independent and collective operations.
+However, if explicit and collective synchronization points are introduced
+between phases where collective and independent I/O operations will be
+performed, then the correct set of operations to ensure a consistent view can
+be inserted at this point.
+
+\emph{Does this explanation make any sense?  I think we need to document this.}
+
+\subsection*{B.4  Even More MPI-Like Data Mode Functions}
+
+Recall that our flexible NetCDF interface has functions such as:
+\begin{verbatim}
+int ncmpi_put_vars(int ncid,
+                   int varid,
+                   MPI_Offset start[],
+                   MPI_Offset count[],
+                   MPI_Offset stride[],
+                   void *buf,
+                   int count,
+                   MPI_Datatype datatype)
+\end{verbatim}
+
+It is possible to move to an even more MPI-like interface by using an MPI
+datatype to describe the file region in addition to using datatypes for the
+memory region:
+\begin{verbatim}
+int ncmpi_put(int ncid,
+              int varid,
+              MPI_Datatype file_dtype,
+              void *buf,
+              int count,
+              MPI_Datatype mem_dtype)
+\end{verbatim}
+
+At first glance this looks rather elegant.  However, this isn't as clean as it
+seems.  The \texttt{file\_dtype} in this case has to describe the variable
+layout \emph{in terms of the variable array}, not in terms of the file,
+because the user doesn't know about the internal file layout.  So the
+underlying implementation would need to tear apart \texttt{file\_dtype} and
+rebuild a new datatype, on the fly, that corresponded to the data layout in
+the file as a whole.  This is complicated by the fact that
+\texttt{file\_dtype} could be arbitrarily complex.
+
+The flexible NetCDF interface parameters, \texttt{start}, \texttt{count}, and
+\texttt{stride} must also be used to build a file type, but the process is
+considerably simpler.
+
+\subsection*{B.5  MPI and NetCDF Types}
+
+\subsubsection*{Questions for Users Regarding MPI and NetCDF Types}
+
+\begin{itemize}
+\item How do users use text strings?
+\item What types are our users using?
+\end{itemize}
+
+\end{document}
+
+
+
+
+
+
+
+
diff --git a/doc/porting_notes.txt b/doc/porting_notes.txt
new file mode 100644
index 0000000..f091ec8
--- /dev/null
+++ b/doc/porting_notes.txt
@@ -0,0 +1,50 @@
+ 
+ these are some rough notes for porting code from the serial netcdf api to
+ the pnetcdf API.  Pnetcdf is very similar but there are some changes that
+ have to be made:
+
+
+. the nc_* functions are called ncmpi_*
+
+. the nf_* functions are called nfmpi_*
+
+. ncmpi_open takes a communicator and an info structure, in addition to the
+  parameters in the serial nc_open()
+
+For example:
+	status = nc_open(path, NC_NOWRITE, &ncid);
+becomes
+	status = ncmpi_open(MPI_COMM_WORLD, path, NC_NOWRITE, 
+		MPI_INFO_NULL, &ncid);
+
+. if you make any independent calls ( those not ending in _all), you must put
+  yourself into independent data mode with ncmpi_begin_indep_data(ncid) and
+  ncmpi_end_indep_data(ncid)
+
+. FILL_DOUBLE and FILL_FLOAT are called  NC_FILL_DOUBLE and NC_FILL_FLOAT
+  respectively.  We do not define these NetCDF-2.x era constants in pnetcdf.
+
+.  #include <mpi.h> .  If you want, define a communicator.  MPI_COMM_WORLD
+     should work ok for most things.
+
+. somewhere near main, call MPI_Init(): pnetcdf won't do that for you.
+
+. pnetcdf does not implement nc_advise
+
+. pnetcdf does not support all types that serial netcdf supports. see
+  src/lib/TODO for more specifics
+
+. If for some reason your code uses 'ptrdiff_t' types, consider using
+  MPI_Offset types
+
+. likewise, in many places where serial netcdf takes size_t types, we instead
+  take MPI_Offset types
+
+. Fortran users should use '#include <mpif.h>' and '#include "pnetcdf.inc"',
+  instead of using the Fortran INCLUDE directive.
+
+. Fortran 90 users can use 'use mpi' and 'use pnetcdf'.
+
+. Fortran  dimension sizes should be declared as type
+  INTEGER(KIND=MPI_OFFSET_KIND) 
+
diff --git a/doc/symbol_renaming.txt b/doc/symbol_renaming.txt
new file mode 100644
index 0000000..6179f94
--- /dev/null
+++ b/doc/symbol_renaming.txt
@@ -0,0 +1,23 @@
+#
+# We want apps to be able to link with both serial NetCDF and Parallel-NetCDF,
+# so we had to alter some symbols in the library.  The following list is a
+# start at documenting the changes.  I found such a list helpful when merging
+# netcdf-3.5 patches to pnetcdf
+#
+
+serial           parallel
+-------------------------
+ncx_len_NC       ncmpii_hdr_len_NC
+ncx_put_NC       ncmpii_hdr_put_NC
+nc_get_NC        ncmpii_hdr_get_NC
+ncx_get_size_t   ncmpix_get_size_t
+new_NC           ncmpii_new_NC
+v1h_get_NC_attarray  hdr_len_NC_attarray
+ncx_len_NC_var       hdr_len_NC_var
+ncx_len_NC_vararray  hdr_len_NC_vararray
+check_v1hs           hdr_check_buffer
+struct v1hs      struct bufferinfo
+NC_*		 ncmpii_NC_*
+nc__
+ncx_*            ncmpix_*
+
diff --git a/examples/C/Makefile.in b/examples/C/Makefile.in
new file mode 100644
index 0000000..6c02932
--- /dev/null
+++ b/examples/C/Makefile.in
@@ -0,0 +1,162 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2245 2015-12-20 18:39:52Z wkliao $
+#
+# @configure_input@
+
+srcdir  = @srcdir@
+VPATH   = @srcdir@
+
+include ../../macros.make
+
+# note the order of -L list matters
+INCLUDES  = -I../../src/lib
+LDFLAGS  := -L../../src/lib $(LDFLAGS)
+LIBS     := -lpnetcdf $(LIBS)
+
+C_SRCS  = collective_write.c \
+          nonblocking_write.c \
+          nonblocking_write_in_def.c \
+          column_wise.c \
+          block_cyclic.c \
+          flexible_api.c \
+          get_info.c \
+          hints.c \
+          mput.c \
+          put_varn_float.c \
+          put_varn_int.c \
+          create_open.c \
+          global_attributes.c \
+          put_vara.c \
+          get_vara.c \
+          transpose.c \
+          vard_int.c \
+          i_varn_int64.c \
+          bput_varn_uint.c \
+          fill_mode.c \
+          ghost_cell.c \
+          req_all.c
+
+# Note: put_vara must be run immediately before get_vara
+
+PROGS     = $(C_SRCS:.c=)
+OBJS      = $(C_SRCS:.c=.o)
+
+GARBAGE      = $(PROGS) *.nc
+
+PACKING_LIST = $(C_SRCS) depend Makefile.in
+
+all: $(PROGS)
+
+install:
+
+uninstall:
+
+collective_write: collective_write.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+nonblocking_write: nonblocking_write.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+nonblocking_write_in_def: nonblocking_write_in_def.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+get_info: get_info.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+column_wise: column_wise.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+block_cyclic: block_cyclic.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+put_vara: put_vara.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+mput: mput.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+hints: hints.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+flexible_api: flexible_api.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+put_varn_int: put_varn_int.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+put_varn_float: put_varn_float.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+create_open: create_open.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+global_attributes: global_attributes.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+get_vara: get_vara.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+transpose: transpose.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+vard_int: vard_int.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+i_varn_int64: i_varn_int64.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+bput_varn_uint: bput_varn_uint.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+fill_mode: fill_mode.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+ghost_cell: ghost_cell.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+req_all: req_all.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+TEST_MPIRUN_8  = $(subst NP,8,$(TEST_MPIRUN))
+TEST_MPIRUN_3  = $(subst NP,3,$(TEST_MPIRUN))
+
+ptest4: $(PROGS)
+	@for i in $(PROGS); do ( \
+        $(TEST_MPIRUN_4) ./$$i -q $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS:  C  parallel run on 4 processes --------------- $$i"; \
+        else \
+           echo "FAILED:  C  parallel run on 4 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest8: $(PROGS)
+	@for i in $(PROGS); do ( \
+        $(TEST_MPIRUN_8) ./$$i -q $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS:  C  parallel run on 8 processes --------------- $$i"; \
+        else \
+           echo "FAILED:  C  parallel run on 8 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest3: $(PROGS)
+	@for i in $(PROGS) ; do ( \
+        $(TEST_MPIRUN_3) ./$$i -q $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS:  C  parallel run on 3 processes --------------- $$i"; \
+        else \
+           echo "FAILED:  C  parallel run on 3 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest: ptest4
+ptests: ptest3 ptest4 ptest8
+ptest2 ptest6 ptest10:
+
+include $(srcdir)/depend
+include $(srcdir)/../../rules.make
+
+$(LIBRARY): ;
+
diff --git a/examples/C/block_cyclic.c b/examples/C/block_cyclic.c
new file mode 100644
index 0000000..c2d056f
--- /dev/null
+++ b/examples/C/block_cyclic.c
@@ -0,0 +1,301 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: block_cyclic.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example, generalized from column_wise.c, makes a number of nonblocking
+ * API calls, each writes a block of columns into a 2D integer array. In other
+ * words, the I/O pattern is a blocked cyclic along X dimension.
+ *
+ * Each process writes NX columns in total. The block length is controlled by
+ * block_len. In this example, block_len is set to 2. Blocks are layout in a
+ * cyclic fashion in the file. This example can test if PnetCDF can coalesce
+ * file offsets and lengths when constructing a merged filetype.
+ * 
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file. In this example, block_len = 2.
+ *
+ *    % mpicc -O2 -o block_cyclic block_cyclic.c -lpnetcdf
+ *    % mpiexec -l -n 4 ./block_cyclic /pvfs2/wkliao/testfile.nc
+ *    0:  0: NY=10 myNX=  4 myOff=  0
+ *    1:  1: NY=10 myNX=  4 myOff=  4
+ *    2:  2: NY=10 myNX=  4 myOff=  8
+ *    3:  3: NY=10 myNX=  4 myOff= 12
+ *    0: [i=0] iput() start=  0   0 count= 10   1
+ *    0: [i=1] iput() start=  0   1 count= 10   1
+ *    0: [i=2] iput() start=  0   8 count= 10   1
+ *    0: [i=3] iput() start=  0   9 count= 10   1
+ *    1: [i=0] iput() start=  0   2 count= 10   1
+ *    1: [i=1] iput() start=  0   3 count= 10   1
+ *    1: [i=2] iput() start=  0  10 count= 10   1
+ *    1: [i=3] iput() start=  0  11 count= 10   1
+ *    2: [i=0] iput() start=  0   4 count= 10   1
+ *    2: [i=1] iput() start=  0   5 count= 10   1
+ *    2: [i=2] iput() start=  0  12 count= 10   1
+ *    2: [i=3] iput() start=  0  13 count= 10   1
+ *    3: [i=0] iput() start=  0   6 count= 10   1
+ *    3: [i=1] iput() start=  0   7 count= 10   1
+ *    3: [i=2] iput() start=  0  14 count= 10   1
+ *    3: [i=3] iput() start=  0  15 count= 10   1
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            Y = 10 ;
+ *            X = 16 ;
+ *    variables:
+ *            int var(Y, X) ;
+ *    data:
+ *
+ *     var =
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NY 10
+#define NX 4
+
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+int main(int argc, char** argv) {
+    extern int optind;
+    char *filename="testfile.nc";
+    int i, j, verbose=1, rank, nprocs, err, num_reqs;
+    int ncid, cmode, varid, dimid[2], *reqs, *sts, **buf;
+    MPI_Offset myNX, G_NX, myOff, block_start, block_len;
+    MPI_Offset start[2], count[2];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* the global array is NY * (NX * nprocs) */
+    G_NX  = NX * nprocs;
+    myOff = NX * rank;
+    myNX  = NX;
+    if (verbose) printf("%2d: NY=%d myNX=%3lld myOff=%3lld\n",rank,NY,myNX,myOff);
+
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "X", G_NX, &dimid[1]);
+    ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimid, &varid);
+    ERR
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* First, fill the entire array with zeros, using a blocking I/O.
+       Every process writes a subarray of size NY * myNX */
+    buf    = (int**) malloc(myNX * sizeof(int*));
+    buf[0] = (int*)  calloc(NY * myNX, sizeof(int));
+    start[0] = 0;   start[1] = myOff;
+    count[0] = NY;  count[1] = myNX;
+    err = ncmpi_put_vara_int_all(ncid, varid, start, count, buf[0]);
+    free(buf[0]);
+
+    /* initialize the buffer with rank ID. Also make the case interesting,
+       by allocating buffers separately */
+    for (i=0; i<myNX; i++) {
+        buf[i] = (int*) malloc(NY * sizeof(int));
+        for (j=0; j<NY; j++) buf[i][j] = rank+10;
+    }
+
+    reqs = (int*) malloc(myNX * sizeof(int));
+    sts  = (int*) malloc(myNX * sizeof(int));
+
+    /* each proc writes myNX columns of the 2D array, block_len controls the
+       number of contiguous columns at a time */
+    block_start = 0;
+    block_len   = 2;  /* can be 1, 2, 3, ..., myNX */
+    if (block_len > myNX) block_len = myNX;
+
+    start[0] = 0;   start[1] = rank * block_len;
+    count[0] = NY;  count[1] = 1;
+    num_reqs = 0;
+    for (i=0; i<myNX; i++) {
+        err = ncmpi_iput_vara_int(ncid, varid, start, count, buf[i],
+                                  &reqs[num_reqs++]);
+        ERR
+
+        if (verbose)
+            printf("[i=%d] iput() start=%3lld %3lld count=%3lld %3lld\n",
+                   i, start[0],start[1], count[0],count[1]);
+
+        if (i % block_len == block_len-1)  {
+            int stride = MIN(myNX-1-i, block_len);
+            block_start += block_len * nprocs;
+            start[1] = block_start + stride * rank;
+        }
+        else
+            start[1]++;
+    }
+
+    err = ncmpi_wait_all(ncid, num_reqs, reqs, sts);
+    ERR
+
+    /* check status of all requests */
+    for (i=0; i<num_reqs; i++)
+        if (sts[i] != NC_NOERR)
+            printf("Error: nonblocking write fails on request %d (%s)\n",
+                   i, ncmpi_strerror(sts[i]));
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    free(sts);
+    free(reqs);
+    for (i=0; i<myNX; i++) free(buf[i]);
+    free(buf);
+
+    /* open an existing file created earlier for read -----------------------*/
+    cmode = NC_NOWRITE;
+    err = ncmpi_open(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* the global array is NY * (NX * nprocs) */
+    MPI_Offset global_ny, global_nx;
+    err = ncmpi_inq_dimid(ncid, "Y", &dimid[0]);
+    ERR
+    err = ncmpi_inq_dimlen(ncid, dimid[0], &global_ny);
+    ERR
+    assert(global_ny == NY);
+
+    err = ncmpi_inq_dimid(ncid, "X", &dimid[1]);
+    ERR
+    err = ncmpi_inq_dimlen(ncid, dimid[1], &global_nx);
+    ERR
+    assert(global_nx == G_NX);
+
+    myNX  = global_nx / nprocs;
+
+    err = ncmpi_inq_varid(ncid, "var", &varid);
+    ERR
+
+    /* initialize the buffer with -1, so a read error can be pinpointed */
+    buf    = (int**) malloc(myNX * sizeof(int*));
+    buf[0] = (int*)  malloc(global_ny * myNX * sizeof(int));
+    for (i=0; i<myNX; i++) {
+        if (i > 0) buf[i] = buf[i-1] + global_ny;
+        for (j=0; j<global_ny; j++) buf[i][j] = -1;
+    }
+
+    reqs = (int*) malloc(myNX * sizeof(int));
+    sts  = (int*) malloc(myNX * sizeof(int));
+
+    /* each proc reads myNX columns of the 2D array, block_len controls the
+       number of contiguous columns at a time */
+    block_start = 0;
+    block_len   = 2;  /* can be 1, 2, 3, ..., myNX */
+    if (block_len > myNX) block_len = myNX;
+
+    start[0] = 0;          start[1] = rank * block_len;
+    count[0] = global_ny;  count[1] = 1;
+    num_reqs = 0;
+    for (i=0; i<myNX; i++) {
+        err = ncmpi_iget_vara_int(ncid, varid, start, count, buf[i],
+                                  &reqs[num_reqs++]);
+        ERR
+
+        if (i % block_len == block_len-1)  {
+            int stride = MIN(myNX-1-i, block_len);
+            block_start += block_len * nprocs;
+            start[1] = block_start + stride * rank;
+        }
+        else
+            start[1]++;
+    }
+    err = ncmpi_wait_all(ncid, num_reqs, reqs, sts);
+    ERR
+
+    /* check status of all requests */
+    for (i=0; i<num_reqs; i++)
+        if (sts[i] != NC_NOERR)
+            printf("Error: nonblocking read fails on request %d (%s)\n",
+                   i, ncmpi_strerror(sts[i]));
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    /* check the read contents */
+    for (i=0; i<myNX; i++) {
+        for (j=0; j<global_ny; j++)
+            if (buf[i][j] != rank+10) {
+                printf("Read contents mismatch at buf[%d][%d] = %d (should be %d)\n", i,j,buf[i][j],rank+10);
+            }
+    }
+
+    free(sts);
+    free(reqs);
+    free(buf[0]);
+    free(buf);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/bput_varn_uint.c b/examples/C/bput_varn_uint.c
new file mode 100644
index 0000000..78e699e
--- /dev/null
+++ b/examples/C/bput_varn_uint.c
@@ -0,0 +1,347 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: bput_varn_uint.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example tests nonblocking buffered write varn APIs, including
+ * ncmpi_bput_varn_uint() and  ncmpi_bput_varn(),
+ * It first writes a sequence of requests with arbitrary array indices and
+ * lengths to four variables of type NC_UINT, and reads back.
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o i_varn_uint i_varn_uint.c -lpnetcdf
+ *    % mpiexec -n 4 ./i_varn_uint /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             Y = 4 ;
+ *             X = 10 ;
+ *    variables:
+ *            uint var0(Y, X) ;
+ *            uint var1(Y, X) ;
+ *            uint var2(Y, X) ;
+ *            uint var3(Y, X) ;
+ *    data:
+ *
+ *     var0 =
+ *      1, 1, 1, 3, 3, 0, 0, 2, 3, 3,
+ *      0, 2, 2, 2, 1, 3, 3, 2, 2, 2,
+ *      3, 3, 2, 1, 1, 1, 0, 0, 3, 3,
+ *      0, 0, 0, 2, 3, 3, 3, 1, 1, 1 ;
+ *
+ *     var1 =
+ *      2, 2, 2, 0, 0, 1, 1, 3, 0, 0,
+ *      1, 3, 3, 3, 2, 0, 0, 3, 3, 3,
+ *      0, 0, 3, 2, 2, 2, 1, 1, 0, 0,
+ *      1, 1, 1, 3, 0, 0, 0, 2, 2, 2 ;
+ *
+ *     var2 =
+ *      3, 3, 3, 1, 1, 2, 2, 0, 1, 1,
+ *      2, 0, 0, 0, 3, 1, 1, 0, 0, 0,
+ *      1, 1, 0, 3, 3, 3, 2, 2, 1, 1,
+ *      2, 2, 2, 0, 1, 1, 1, 3, 3, 3 ;
+ *
+ *     var3 =
+ *      0, 0, 0, 2, 2, 3, 3, 1, 2, 2,
+ *      3, 1, 1, 1, 0, 2, 2, 1, 1, 1,
+ *      2, 2, 1, 0, 0, 0, 3, 3, 2, 2,
+ *      3, 3, 3, 1, 2, 2, 2, 0, 0, 0 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h> /* getopt() */
+#include <string.h> /* strcpy() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+#define ERR \
+    if (err != NC_NOERR) { \
+        printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
+    }
+
+#define ERRS(n,a) { \
+    int _i; \
+    for (_i=0; _i<(n); _i++) { \
+        if ((a)[_i] != NC_NOERR) { \
+            printf("Error at line=%d: err[%d] %s\n", __LINE__, _i, \
+                   ncmpi_strerror((a)[_i])); \
+        } \
+    } \
+}
+
+static MPI_Offset *** calloc_3D(size_t z, size_t y, size_t x)
+{
+    int _j, _k;
+    MPI_Offset ***buf  = (MPI_Offset***) malloc(z     * sizeof(MPI_Offset**));
+    MPI_Offset  **bufy = (MPI_Offset**)  malloc(z*y   * sizeof(MPI_Offset*));
+    MPI_Offset   *bufx = (MPI_Offset*)   calloc(z*y*x,  sizeof(MPI_Offset));
+    for (_k=0; _k<z; _k++, bufy+=y) {
+        buf[_k] = bufy;
+        for (_j=0; _j<y; _j++, bufx+=x)
+            buf[_k][_j] = bufx;
+    }
+    return buf;
+}
+
+static void free_3D(MPI_Offset ***buf)
+{
+    free(buf[0][0]);
+    free(buf[0]);
+    free(buf);
+}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+static void check_contents(int ncid, int *varid)
+{
+    int i, j, err;
+    unsigned int expected[4][NY*NX] = {{1, 1, 1, 3, 3, 0, 0, 2, 3, 3,
+                                        0, 2, 2, 2, 1, 3, 3, 2, 2, 2,
+                                        3, 3, 2, 1, 1, 1, 0, 0, 3, 3,
+                                        0, 0, 0, 2, 3, 3, 3, 1, 1, 1},
+                                       {2, 2, 2, 0, 0, 1, 1, 3, 0, 0,
+                                        1, 3, 3, 3, 2, 0, 0, 3, 3, 3,
+                                        0, 0, 3, 2, 2, 2, 1, 1, 0, 0,
+                                        1, 1, 1, 3, 0, 0, 0, 2, 2, 2},
+                                       {3, 3, 3, 1, 1, 2, 2, 0, 1, 1,
+                                        2, 0, 0, 0, 3, 1, 1, 0, 0, 0,
+                                        1, 1, 0, 3, 3, 3, 2, 2, 1, 1,
+                                        2, 2, 2, 0, 1, 1, 1, 3, 3, 3},
+                                       {0, 0, 0, 2, 2, 3, 3, 1, 2, 2,
+                                        3, 1, 1, 1, 0, 2, 2, 1, 1, 1,
+                                        2, 2, 1, 0, 0, 0, 3, 3, 2, 2,
+                                        3, 3, 3, 1, 2, 2, 2, 0, 0, 0}};
+
+    unsigned int *r_buffer = (unsigned int*) malloc(NY*NX*sizeof(unsigned int));
+
+    for (i=0; i<4; i++) {
+        for (j=0; j<NY*NX; j++) r_buffer[j] = 99999;
+        err = ncmpi_get_var_uint_all(ncid, varid[i], r_buffer);
+        ERR
+
+        /* check if the contents of buf are expected */
+        for (j=0; j<NY*NX; j++)
+            if (r_buffer[j] != expected[i][j])
+                printf("Expected file contents [%d][%d]=%u, but got %u\n",
+                       i,j,expected[i][j],r_buffer[j]);
+    }
+    free(r_buffer);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char *filename="testfile.nc", exec[128];
+    int i, j, k, n, rank, nprocs, verbose=1, err;
+    int ncid, cmode, varid[4], dimid[2], nreqs, reqs[4], sts[4];
+    unsigned int *buffer[4];
+    int num_segs[4], req_lens[4];
+    MPI_Offset ***starts, ***counts;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    strcpy(exec, argv[0]);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    if (nprocs != 4 && rank == 0 && verbose)
+        printf("Warning: %s is intended to run on 4 processes\n",exec);
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_UINT, NDIMS, dimid, &varid[0]); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_UINT, NDIMS, dimid, &varid[1]); ERR
+    err = ncmpi_def_var(ncid, "var2", NC_UINT, NDIMS, dimid, &varid[2]); ERR
+    err = ncmpi_def_var(ncid, "var3", NC_UINT, NDIMS, dimid, &varid[3]); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* allocate space for starts and counts */
+    starts = calloc_3D(4, 6, NDIMS);
+    counts = calloc_3D(4, 6, NDIMS);
+
+    n = rank % 4;
+    num_segs[n] = 4; /* number of segments for this request */
+    starts[n][0][0]=0; starts[n][0][1]=5; counts[n][0][0]=1; counts[n][0][1]=2;
+    starts[n][1][0]=1; starts[n][1][1]=0; counts[n][1][0]=1; counts[n][1][1]=1;
+    starts[n][2][0]=2; starts[n][2][1]=6; counts[n][2][0]=1; counts[n][2][1]=2;
+    starts[n][3][0]=3; starts[n][3][1]=0; counts[n][3][0]=1; counts[n][3][1]=3;
+    /* starts[n][][] n_counts[n][][] indicate the following: ("-" means skip)
+              -  -  -  -  -  X  X  -  -  - 
+              X  -  -  -  -  -  -  -  -  - 
+              -  -  -  -  -  -  X  X  -  - 
+              X  X  X  -  -  -  -  -  -  - 
+     */
+    n = (rank+1) % 4;
+    num_segs[n] = 6; /* number of segments for this request */
+    starts[n][0][0]=0; starts[n][0][1]=3; counts[n][0][0]=1; counts[n][0][1]=2;
+    starts[n][1][0]=0; starts[n][1][1]=8; counts[n][1][0]=1; counts[n][1][1]=2;
+    starts[n][2][0]=1; starts[n][2][1]=5; counts[n][2][0]=1; counts[n][2][1]=2;
+    starts[n][3][0]=2; starts[n][3][1]=0; counts[n][3][0]=1; counts[n][3][1]=2;
+    starts[n][4][0]=2; starts[n][4][1]=8; counts[n][4][0]=1; counts[n][4][1]=2;
+    starts[n][5][0]=3; starts[n][5][1]=4; counts[n][5][0]=1; counts[n][5][1]=3;
+    /* starts[n][][] counts[n][][] indicate the following pattern.
+              -  -  -  X  X  -  -  -  X  X 
+              -  -  -  -  -  X  X  -  -  - 
+              X  X  -  -  -  -  -  -  X  X 
+              -  -  -  -  X  X  X  -  -  - 
+     */
+    n = (rank+2) % 4;
+    num_segs[n] = 5; /* number of segments for this request */
+    starts[n][0][0]=0; starts[n][0][1]=7; counts[n][0][0]=1; counts[n][0][1]=1;
+    starts[n][1][0]=1; starts[n][1][1]=1; counts[n][1][0]=1; counts[n][1][1]=3;
+    starts[n][2][0]=1; starts[n][2][1]=7; counts[n][2][0]=1; counts[n][2][1]=3;
+    starts[n][3][0]=2; starts[n][3][1]=2; counts[n][3][0]=1; counts[n][3][1]=1;
+    starts[n][4][0]=3; starts[n][4][1]=3; counts[n][4][0]=1; counts[n][4][1]=1;
+    /* starts[n][][] counts[n][][] indicate the following pattern.
+              -  -  -  -  -  -  -  X  -  - 
+              -  X  X  X  -  -  -  X  X  X 
+              -  -  X  -  -  -  -  -  -  - 
+              -  -  -  X  -  -  -  -  -  - 
+     */
+    n = (rank+3) % 4;
+    num_segs[n] = 4; /* number of segments for this request */
+    starts[n][0][0]=0; starts[n][0][1]=0; counts[n][0][0]=1; counts[n][0][1]=3;
+    starts[n][1][0]=1; starts[n][1][1]=4; counts[n][1][0]=1; counts[n][1][1]=1;
+    starts[n][2][0]=2; starts[n][2][1]=3; counts[n][2][0]=1; counts[n][2][1]=3;
+    starts[n][3][0]=3; starts[n][3][1]=7; counts[n][3][0]=1; counts[n][3][1]=3;
+     /*starts[n][][] counts[n][][] indicate the following pattern.
+              X  X  X  -  -  -  -  -  -  - 
+              -  -  -  -  X  -  -  -  -  - 
+              -  -  -  X  X  X  -  -  -  - 
+              -  -  -  -  -  -  -  X  X  X 
+     */
+
+    /* only rank 0, 1, 2, and 3 do I/O:
+     * each of ranks 0 to 3 write 4 nonblocking requests */
+    nreqs = 4;
+    if (rank >= 4) nreqs = 0;
+
+    /* bufsize must be max of data type converted before and after */
+    MPI_Offset bufsize = 0;
+
+    /* calculate length of each varn request, number of segments in each
+     * varn request, and allocate write buffer */
+    for (i=0; i<nreqs; i++) {
+        req_lens[i] = 0; /* total length this request */
+        for (j=0; j<num_segs[i]; j++) {
+            MPI_Offset req_len=1;
+            for (k=0; k<NDIMS; k++)
+                req_len *= counts[i][j][k];
+            req_lens[i] += req_len;
+        }
+        if (verbose) printf("req_lens[%d]=%d\n",i,req_lens[i]);
+
+        /* allocate I/O buffer and initialize its contents */
+        buffer[i] = (unsigned int*) malloc(req_lens[i] * sizeof(unsigned int));
+        for (j=0; j<req_lens[i]; j++) buffer[i][j] = rank;
+
+        bufsize += req_lens[i];
+    }
+    bufsize *= sizeof(unsigned int);
+    if (verbose) printf("%d: Attach buffer size %lld\n", rank, bufsize);
+
+    /* give PnetCDF a space to buffer the nonblocking requests */
+    if (bufsize > 0) {
+        err = ncmpi_buffer_attach(ncid, bufsize); ERR
+    }
+
+    /* write using varn API */
+    for (i=0; i<nreqs; i++) {
+        err = ncmpi_bput_varn_uint(ncid, varid[i], num_segs[i], starts[i],
+                                       counts[i], buffer[i], &reqs[i]);
+        ERR
+    }
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* check file contents */
+    if (nprocs >= 4) check_contents(ncid, varid);
+
+    for (i=0; i<nreqs; i++) free(buffer[i]);
+
+    /* test flexible put API, using a noncontiguous buftype */
+    for (i=0; i<nreqs; i++) {
+        MPI_Datatype buftype;
+        MPI_Type_vector(req_lens[i], 1, 2, MPI_UNSIGNED, &buftype);
+        MPI_Type_commit(&buftype);
+        buffer[i] = (unsigned int*) malloc(req_lens[i] * 2 * sizeof(unsigned int));
+        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank;
+
+        err = ncmpi_bput_varn(ncid, varid[i], num_segs[i], starts[i],
+                              counts[i], buffer[i], 1, buftype, &reqs[i]);
+        ERR
+        MPI_Type_free(&buftype);
+    }
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* check file contents */
+    if (nprocs >= 4) check_contents(ncid, varid);
+
+    /* free the buffer space for bput */
+    if (bufsize > 0) {
+        err = ncmpi_buffer_detach(ncid); ERR
+    }
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    for (i=0; i<nreqs; i++) free(buffer[i]);
+    free_3D(starts);
+    free_3D(counts);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/collective_write.c b/examples/C/collective_write.c
new file mode 100644
index 0000000..86b13df
--- /dev/null
+++ b/examples/C/collective_write.c
@@ -0,0 +1,231 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: collective_write.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/*
+ *    This example mimics the coll_perf.c from ROMIO.
+ *    It creates a netcdf file in CD-5 format and writes a number of
+ *    3D integer non-record variables. The measured write bandwidth is reported
+ *    at the end. Usage:
+ *    To compile:
+ *        mpicc -O2 collective_write.c -o collective_write -lpnetcdf
+ *    To run:
+ *        mpiexec -n num_processes ./collective_write [filename] [len]
+ *    where len decides the size of each local array, which is len x len x len.
+ *    So, each non-record variable is of size len*len*len * nprocs * sizeof(int)
+ *    All variables are partitioned among all processes in a 3D
+ *    block-block-block fashion. Below is an example standard output from
+ *    command:
+ *        mpiexec -n 32 ./collective_write /pvfs2/wkliao/testfile.nc 100
+ *
+ *    MPI hint: cb_nodes        = 2
+ *    MPI hint: cb_buffer_size  = 16777216
+ *    MPI hint: striping_factor = 32
+ *    MPI hint: striping_unit   = 1048576
+ *    Local array size 100 x 100 x 100 integers, size = 3.81 MB
+ *    Global array size 400 x 400 x 200 integers, write size = 0.30 GB
+ *     procs    Global array size  exec(sec)  write(MB/s)
+ *     -------  ------------------  ---------  -----------
+ *        32     400 x  400 x  200     6.67       45.72
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NDIMS    3
+#define NUM_VARS 10
+
+#define HANDLE_ERROR {                                \
+    if (err != NC_NOERR)                              \
+        printf("Error at line %d (%s)\n", __LINE__,   \
+               ncmpi_strerror(err));                  \
+}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name] [len]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    "       [len] size of each dimension of the local array\n";
+    fprintf(stderr, help, argv0);
+}
+
+/*----< print_info() >------------------------------------------------------*/
+static
+void print_info(MPI_Info *info_used)
+{
+    int     flag;
+    char    info_cb_nodes[64], info_cb_buffer_size[64];
+    char    info_striping_factor[64], info_striping_unit[64];
+
+    strcpy(info_cb_nodes,        "undefined");
+    strcpy(info_cb_buffer_size,  "undefined");
+    strcpy(info_striping_factor, "undefined");
+    strcpy(info_striping_unit,   "undefined");
+
+    MPI_Info_get(*info_used, "cb_nodes", 64, info_cb_nodes, &flag);
+    MPI_Info_get(*info_used, "cb_buffer_size", 64, info_cb_buffer_size, &flag);
+    MPI_Info_get(*info_used, "striping_factor", 64, info_striping_factor, &flag);
+    MPI_Info_get(*info_used, "striping_unit", 64, info_striping_unit, &flag);
+
+    printf("MPI hint: cb_nodes        = %s\n", info_cb_nodes);
+    printf("MPI hint: cb_buffer_size  = %s\n", info_cb_buffer_size);
+    printf("MPI hint: striping_factor = %s\n", info_striping_factor);
+    printf("MPI hint: striping_unit   = %s\n", info_striping_unit);
+}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    extern int optind;
+    char *filename="testfile.nc", str[512];
+    int i, j, rank, nprocs, len, ncid, bufsize, verbose=1, err;
+    int *buf[NUM_VARS], psizes[NDIMS], dimids[NDIMS], varids[NUM_VARS];
+    double write_timing, max_write_timing, write_bw;
+    MPI_Offset gsizes[NDIMS], starts[NDIMS], counts[NDIMS];
+    MPI_Offset write_size, sum_write_size;
+    MPI_Info info_used;
+
+    MPI_Init(&argc,&argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc >= 1) filename = argv[0];  /* optional argument */
+    len = 10; 
+    if (argc >= 2) len = atoi(argv[1]); /* optional argument */
+
+    for (i=0; i<NDIMS; i++)
+        psizes[i] = 0;
+
+    MPI_Dims_create(nprocs, NDIMS, psizes);
+    starts[0] = rank % psizes[0];
+    starts[1] = (rank / psizes[1]) % psizes[1];
+    starts[2] = (rank / (psizes[0] * psizes[1])) % psizes[2];
+
+    bufsize = 1;
+    for (i=0; i<NDIMS; i++) {
+        gsizes[i] = len * psizes[i];
+        starts[i] *= len;
+        counts[i]  = len;
+        bufsize   *= len;
+    }
+
+    /* allocate buffer and initialize with random numbers */
+    srand(rank);
+    for (i=0; i<NUM_VARS; i++) {
+        buf[i] = (int *) malloc(bufsize * sizeof(int));
+        for (j=0; j<bufsize; j++) buf[i][j] = rand();
+    }
+
+    MPI_Barrier(MPI_COMM_WORLD);
+    write_timing = MPI_Wtime();
+
+    /* create the file */
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER|NC_64BIT_DATA,
+                       MPI_INFO_NULL, &ncid);
+    if (err != NC_NOERR) {
+        printf("Error: ncmpi_create() file %s (%s)\n",filename,ncmpi_strerror(err));
+        MPI_Abort(MPI_COMM_WORLD, -1);
+        exit(1);
+    }
+
+    /* define dimensions */
+    for (i=0; i<NDIMS; i++) {
+        sprintf(str, "%c", 'x'+i);
+        err = ncmpi_def_dim(ncid, str, gsizes[i], &dimids[i]);
+        HANDLE_ERROR
+    }
+
+    /* define variables */
+    for (i=0; i<NUM_VARS; i++) {
+        sprintf(str, "var%d", i);
+        err = ncmpi_def_var(ncid, str, NC_INT, NDIMS, dimids, &varids[i]);
+        HANDLE_ERROR
+    }
+
+    /* exit the define mode */
+    err = ncmpi_enddef(ncid);
+    HANDLE_ERROR
+
+    /* get all the hints used */
+    err = ncmpi_inq_file_info(ncid, &info_used);
+    HANDLE_ERROR
+
+    /* write one variable at a time */
+    for (i=0; i<NUM_VARS; i++) {
+        err = ncmpi_put_vara_int_all(ncid, varids[i], starts, counts, buf[i]);
+        HANDLE_ERROR
+    }
+
+    /* close the file */
+    err = ncmpi_close(ncid);
+    HANDLE_ERROR
+
+    write_timing = MPI_Wtime() - write_timing;
+
+    write_size = bufsize * NUM_VARS * sizeof(int);
+    for (i=0; i<NUM_VARS; i++) free(buf[i]);
+
+    MPI_Reduce(&write_size, &sum_write_size, 1, MPI_LONG_LONG, MPI_SUM, 0, MPI_COMM_WORLD);
+    MPI_Reduce(&write_timing, &max_write_timing, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
+
+    if (rank == 0 && verbose) {
+        float subarray_size = (float)bufsize*sizeof(int)/1048576.0;
+        print_info(&info_used);
+        printf("Local array size %d x %d x %d integers, size = %.2f MB\n",len,len,len,subarray_size);
+        sum_write_size /= 1048576.0;
+        printf("Global array size %lld x %lld x %lld integers, write size = %.2f GB\n",
+               gsizes[0], gsizes[1], gsizes[2], sum_write_size/1024.0);
+
+        write_bw = sum_write_size/max_write_timing;
+        printf(" procs    Global array size  exec(sec)  write(MB/s)\n");
+        printf("-------  ------------------  ---------  -----------\n");
+        printf(" %4d    %4lld x %4lld x %4lld %8.2f  %10.2f\n", nprocs,
+               gsizes[0], gsizes[1], gsizes[2], max_write_timing, write_bw);
+    }
+    MPI_Info_free(&info_used);
+
+    /* print info about PnetCDF internal malloc usage */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_max_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && verbose)
+            printf("maximum heap memory allocted by PnetCDF internally is %lld bytes\n",
+                   sum_size);
+
+        /* check if there is any PnetCDF internal malloc residue */
+        err = ncmpi_inq_malloc_size(&malloc_size);
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/column_wise.c b/examples/C/column_wise.c
new file mode 100644
index 0000000..9deeb27
--- /dev/null
+++ b/examples/C/column_wise.c
@@ -0,0 +1,222 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: column_wise.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example makes a number of nonblocking API calls, each writes a single
+ * column of a 2D integer array. Each process writes NX columns and any two
+ * consecutive columns are of nprocs columns distance apart from each other. In
+ * this case, the fileview of each process interleaves with all other processes.
+ * If simply concatenating fileviews of all the nonblocking calls will result
+ * in a fileview that violates the MPI-IO requirement on the fileview of which
+ * flattened file offsets must be monotonically non-decreasing. PnetCDF handles
+ * this case by breaking down each nonblocking call into a list of offset-length
+ * pairs, merging the pairs across multiple nonblocking calls, and sorting
+ * them into an increasing order. The sorted pairs are used to construct a
+ * fileview that meets the monotonically non-decreasing offset requirement,
+ * and thus the nonblocking requests can be serviced by a single MPI-IO call. 
+ * 
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o column_wise column_wise.c -lpnetcdf
+ *    % mpiexec -l -n 4 ./column_wise /pvfs2/wkliao/testfile.nc
+ *    0:  0: myOff=  0 myNX=  4
+ *    1:  1: myOff=  4 myNX=  4
+ *    2:  2: myOff=  8 myNX=  4
+ *    3:  3: myOff= 12 myNX=  4
+ *    0:  0: start=  0   0 count= 10   1
+ *    1:  1: start=  0   1 count= 10   1
+ *    2:  2: start=  0   2 count= 10   1
+ *    3:  3: start=  0   3 count= 10   1
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            Y = 10 ;
+ *            X = 16 ;
+ *    variables:
+ *            int var(Y, X) ;
+ *    data:
+ *
+ *     var =
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NY 10
+#define NX 4
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char *filename = "testfile.nc";
+    int i, j, verbose=1, rank, nprocs, err, myNX, G_NX, myOff, num_reqs;
+    int ncid, cmode, varid, dimid[2], *reqs, *sts, **buf;
+    MPI_Offset start[2], count[2];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* the global array is NY * (NX * nprocs) */
+    G_NX  = NX * nprocs;
+    myOff = NX * rank;
+    myNX  = NX;
+    if (verbose) printf("%2d: myOff=%3d myNX=%3d\n",rank,myOff,myNX);
+
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "X", G_NX, &dimid[1]);
+    ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimid, &varid);
+    ERR
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* First, fill the entire array with zeros, using a blocking I/O.
+       Every process writes a subarray of size NY * myNX */
+    buf    = (int**) malloc(myNX * sizeof(int*));
+    buf[0] = (int*)  calloc(NY * myNX, sizeof(int));
+    start[0] = 0;   start[1] = myOff;
+    count[0] = NY;  count[1] = myNX;
+    err = ncmpi_put_vara_int_all(ncid, varid, start, count, buf[0]);
+    free(buf[0]);
+
+    /* initialize the buffer with rank ID. Also make the case interesting,
+       by allocating buffers separately */
+    for (i=0; i<myNX; i++) {
+        buf[i] = (int*) malloc(NY * sizeof(int));
+        for (j=0; j<NY; j++) buf[i][j] = rank;
+    }
+
+    reqs = (int*) malloc(myNX * sizeof(int));
+    sts  = (int*) malloc(myNX * sizeof(int));
+
+    /* each proc writes myNX single columns of the 2D array */
+    start[0]  = 0;   start[1] = rank;
+    count[0]  = NY;  count[1] = 1;
+    if (verbose)
+        printf("%2d: start=%3lld %3lld count=%3lld %3lld\n",
+               rank, start[0],start[1], count[0],count[1]);
+
+    num_reqs = 0;
+    for (i=0; i<myNX; i++) {
+        err = ncmpi_iput_vara_int(ncid, varid, start, count, buf[i],
+                                  &reqs[num_reqs++]);
+        ERR
+        start[1] += nprocs;
+    }
+    err = ncmpi_wait_all(ncid, num_reqs, reqs, sts);
+    ERR
+
+    /* check status of all requests */
+    for (i=0; i<num_reqs; i++)
+        if (sts[i] != NC_NOERR)
+            printf("Error: nonblocking write fails on request %d (%s)\n",
+                   i, ncmpi_strerror(sts[i]));
+
+    /* read back using the same access pattern */
+    for (i=0; i<myNX; i++)
+        for (j=0; j<NY; j++) buf[i][j] = -1;
+
+    /* each proc reads myNX single columns of the 2D array */
+    start[0]  = 0;   start[1] = rank;
+    count[0]  = NY;  count[1] = 1;
+
+    num_reqs = 0;
+    for (i=0; i<myNX; i++) {
+        err = ncmpi_iget_vara_int(ncid, varid, start, count, buf[i],
+                                  &reqs[num_reqs++]);
+        ERR
+        start[1] += nprocs;
+    }
+    err = ncmpi_wait_all(ncid, num_reqs, reqs, sts);
+    ERR
+
+    /* check status of all requests */
+    for (i=0; i<num_reqs; i++)
+        if (sts[i] != NC_NOERR)
+            printf("Error: nonblocking write fails on request %d (%s)\n",
+                   i, ncmpi_strerror(sts[i]));
+
+    for (i=0; i<myNX; i++) {
+        for (j=0; j<NY; j++)
+            if (buf[i][j] != rank)
+                printf("Error: expect buf[%d][%d]=%d but got %d\n",i,j,rank,buf[i][j]);
+    }
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    free(sts);
+    free(reqs);
+    for (i=0; i<myNX; i++) free(buf[i]);
+    free(buf);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/create_open.c b/examples/C/create_open.c
new file mode 100644
index 0000000..1a133fa
--- /dev/null
+++ b/examples/C/create_open.c
@@ -0,0 +1,105 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: create_open.c 2150 2015-10-10 05:52:57Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use ncmpi_create() to create a new file and
+ * ncmpi_open() to open the file for read only.
+ *
+ *    To compile:
+ *        mpicc -O2 create_open.c -o create_open -lpnetcdf
+ *
+ * Example commands for MPI run and outputs from running ncmpidump on the
+ * netCDF file produced by this example program:
+ *
+ *    % mpiexec -n 4 ./create_open /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-1
+ *    }
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char *filename="testfile.nc";
+    int i, rank, verbose=1, err;
+    int ncid, cmode, omode;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    if (verbose && rank == 0) printf("%s: example of file create and open\n",__FILE__);
+
+    /* create a new file using clobber mode ----------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* close file */
+    err = ncmpi_close(ncid);
+    ERR
+
+    /* open the newly created file for read only -----------------------------*/
+    omode = NC_NOWRITE;
+    err = ncmpi_open(MPI_COMM_WORLD, filename, omode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* close file */
+    err = ncmpi_close(ncid);
+    ERR
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/depend b/examples/C/depend
new file mode 100644
index 0000000..52b6997
--- /dev/null
+++ b/examples/C/depend
@@ -0,0 +1,22 @@
+block_cyclic.o: block_cyclic.c
+collective_write.o: collective_write.c
+column_wise.o: column_wise.c
+flexible_api.o: flexible_api.c
+get_info.o: get_info.c
+hints.o: hints.c
+nonblocking_write.o: nonblocking_write.c
+nonblocking_write_in_def.o: nonblocking_write_in_def.c
+put_vara.o: put_vara.c
+put_varn_float.o: put_varn_float.c
+put_varn_int.o: put_varn_int.c
+mput.o: mput.c
+create_open.o: create_open.c
+global_attributes.o: global_attributes.c
+get_vara.o: get_vara.c
+transpose.o: transpose.c
+vard_int.o: vard_int.c
+i_varn_int64.o: i_varn_int64.c
+bput_varn_uint.o: bput_varn_uint.c
+fill_mode.o: fill_mode.c
+ghost_cell.o: ghost_cell.c
+req_all.o: req_all.c
diff --git a/examples/C/fill_mode.c b/examples/C/fill_mode.c
new file mode 100644
index 0000000..fc48375
--- /dev/null
+++ b/examples/C/fill_mode.c
@@ -0,0 +1,206 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: fill_mode.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use 
+ * 1. ncmpi_set_fill() to enable fill mode
+ * 2. ncmpi_def_var_fill() to define the variable's fill value
+ * 3. ncmpi_inq_var_fill() to inquire the variable's fill mode information
+ * 4. ncmpi_put_vara_int_all() to write two 2D 4-byte integer array in parallel.
+ * It first defines a netCDF record variable of size NC_UNLIMITED * global_ny
+ * where
+ *    global_nx == (NX * number of MPI processes).
+ * It then defines a netCDF fixed-size variable of size global_nx * global_ny
+ * where
+ *    global_ny == NY and
+ *    global_nx == (NX * number of MPI processes).
+ * The data partitioning pattern for both variables are a column-wise
+ * partitioning across all processes. Each process writes a subarray of size
+ * ny * nx.
+ *
+ *    To compile:
+ *        mpicc -O2 fill_mode.c -o fill_mode -lpnetcdf
+ *
+ * Example commands for MPI run and outputs from running ncmpidump on the
+ * NC file produced by this example program:
+ *
+ *    % mpiexec -n 4 ./fill_mode -q /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-1
+ *    dimensions:
+ *            REC_DIM = UNLIMITED ; // (2 currently)
+ *            X = 16 ;
+ *            Y = 3 ;
+ *    variables:
+ *            int rec_var(REC_DIM, X) ;
+ *                rec_var:_FillValue = -1 ;
+ *            int fix_var(Y, X) ;
+ *    data:
+ *
+ *    rec_var =
+ *           0, 0, 0, _, 1, 1, 1, _, 2, 2, 2, _, 3, 3, 3, _,
+ *           0, 0, 0, _, 1, 1, 1, _, 2, 2, 2, _, 3, 3, 3, _ ;
+ *
+ *    fix_var =
+ *           0, 0, 0, _, 1, 1, 1, _, 2, 2, 2, _, 3, 3, 3, _,
+ *           0, 0, 0, _, 1, 1, 1, _, 2, 2, 2, _, 3, 3, 3, _,
+ *           0, 0, 0, _, 1, 1, 1, _, 2, 2, 2, _, 3, 3, 3, _ ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NY 3
+#define NX 4
+
+
+#define ERR {if(err!=NC_NOERR)printf("Error at %s line=%d: %s\n",__FILE__,__LINE__, ncmpi_strerror(err));}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[256];
+    int i, j, rank, nprocs, verbose=1, err, rec_varid, fix_varid;
+    int ncid, cmode, dimid[2], buf[NY][NX], no_fill, fill_value, old_mode;
+    MPI_Offset  global_ny, global_nx;
+    MPI_Offset start[2], count[2];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else strcpy(filename, "testfile.nc");
+
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* the global array is NY * (NX * nprocs) */
+    global_ny = NY;
+    global_nx = NX * nprocs;
+
+    /* define dimensions x and y */
+    err = ncmpi_def_dim(ncid, "REC_DIM", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", global_nx, &dimid[1]); ERR
+
+    /* define a 2D variable of integer type */
+    err = ncmpi_def_var(ncid, "rec_var", NC_INT, 2, dimid, &rec_varid); ERR
+
+    err = ncmpi_def_dim(ncid, "Y", global_ny, &dimid[0]); ERR
+    err = ncmpi_def_var(ncid, "fix_var", NC_INT, 2, dimid, &fix_varid); ERR
+
+    /* set the fill mode to NC_FILL for entire file */
+    err = ncmpi_set_fill(ncid, NC_FILL, &old_mode); ERR
+    if (verbose) {
+        if (old_mode == NC_FILL) printf("The old fill mode is NC_FILL\n");
+        else                     printf("The old fill mode is NC_NOFILL\n");
+    }
+
+    /* set the fill mode back to NC_NOFILL for entire file */
+    err = ncmpi_set_fill(ncid, NC_NOFILL, NULL); ERR
+
+    /* set the variable's fill mode to NC_FILL with default fill value */
+    err = ncmpi_def_var_fill(ncid, fix_varid, 0, NULL); ERR
+
+    /* set a customized fill value -1 */
+    fill_value = -1;
+    err = ncmpi_put_att_int(ncid, rec_varid, "_FillValue", NC_INT, 1, &fill_value);
+    ERR
+
+    /* do not forget to exit define mode */
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* now we are in data mode */
+    start[0] = 0;
+    start[1] = NX * rank;
+    count[0] = NY;
+    count[1] = NX;
+
+    /* initialize user buffer */
+    for (i=0; i<NY; i++)
+        for (j=0; j<NX; j++)
+             buf[i][j] = rank;
+
+    /* do not write the variable in full */
+    count[1]--;
+    err = ncmpi_put_vara_int_all(ncid, fix_varid, start, count, &buf[0][0]); ERR
+
+    err = ncmpi_inq_var_fill(ncid, fix_varid, &no_fill, &fill_value); ERR
+    if (no_fill != 0)
+        printf("Error: expecting no_fill to be 0\n");
+    if (fill_value != NC_FILL_INT)
+        printf("Error: expecting no_fill to be %ld but got %d\n",NC_FILL_INT,fill_value);
+
+    /* fill the 1st record of the record variable */
+    start[0] = 0;
+    err = ncmpi_fill_var_rec(ncid, rec_varid, start[0]); ERR
+
+    /* write to the 1st record */
+    count[0] = 1;
+    err = ncmpi_put_vara_int_all(ncid, rec_varid, start, count, &buf[0][0]); ERR
+
+    /* fill the 2nd record of the record variable */
+    start[0] = 1;
+    err = ncmpi_fill_var_rec(ncid, rec_varid, start[0]); ERR
+
+    /* write to the 2nd record */
+    err = ncmpi_put_vara_int_all(ncid, rec_varid, start, count, &buf[0][0]); ERR
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/flexible_api.c b/examples/C/flexible_api.c
new file mode 100644
index 0000000..f331dcf
--- /dev/null
+++ b/examples/C/flexible_api.c
@@ -0,0 +1,272 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: flexible_api.c 2150 2015-10-10 05:52:57Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This example shows how to use PnetCDF flexible APIs, ncmpi_put_vara_all()
+ * and ncmpi_iput_vara() to write two 2D array variables (one is of 4-byte
+ * integer byte and the other float type) in parallel. It first defines 2 netCDF
+ * variables of sizes
+ *    var_zy: NZ*nprocs x NY
+ *    var_yx: NY x NX*nprocs
+ *
+ * The data partitioning patterns on the 2 variables are row-wise and
+ * column-wise, respectively. Each process writes a subarray of size
+ * NZ x NY and NY x NX to var_zy and var_yx, respectively.
+ * Both local buffers have a ghost cell of length 3 surrounded along each
+ * dimension.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicc -O2 -o flexible_api flexible_api.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 4 ./flexible_api /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            Z = 20 ;
+ *            Y = 5 ;
+ *            X = 20 ;
+ *    variables:
+ *            int var_zy(Z, Y) ;
+ *            float var_yx(Y, X) ;
+ *    data:
+ *
+ *     var_zy =
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0,
+ *      1, 1, 1, 1, 1,
+ *      1, 1, 1, 1, 1,
+ *      1, 1, 1, 1, 1,
+ *      1, 1, 1, 1, 1,
+ *      1, 1, 1, 1, 1,
+ *      2, 2, 2, 2, 2,
+ *      2, 2, 2, 2, 2,
+ *      2, 2, 2, 2, 2,
+ *      2, 2, 2, 2, 2,
+ *      2, 2, 2, 2, 2,
+ *      3, 3, 3, 3, 3,
+ *      3, 3, 3, 3, 3,
+ *      3, 3, 3, 3, 3,
+ *      3, 3, 3, 3, 3,
+ *      3, 3, 3, 3, 3 ;
+ *
+ *     var_yx =
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 ;
+ *    }
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NZ 5
+#define NY 5
+#define NX 5
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char *filename="testfile.nc";
+    int i, j, rank, nprocs, verbose=1, err, req, status, ghost_len=3;
+    int ncid, cmode, varid0, varid1, dimid[3], *buf_zy;
+    int array_of_sizes[2], array_of_subsizes[2], array_of_starts[2];
+    double *buf_yx;
+    MPI_Offset start[2], count[2];
+    MPI_Datatype  subarray;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    if (verbose && rank == 0) printf("%s: example of using flexible APIs\n",__FILE__);
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* define 3 dimensions */
+    err = ncmpi_def_dim(ncid, "Z", NZ*nprocs, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "Y", NY,        &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX*nprocs, &dimid[2]); ERR
+
+    /* define a variable of size (NZ * nprocs) * NY */
+    err = ncmpi_def_var(ncid, "var_zy", NC_INT,   2, &dimid[0], &varid0); ERR
+    /* define a variable of size NY * (NX * nprocs) */
+    err = ncmpi_def_var(ncid, "var_yx", NC_FLOAT, 2, &dimid[1], &varid1); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* var_zy is partitioned along Z dimension */
+    array_of_sizes[0]    = NZ + 2*ghost_len;
+    array_of_sizes[1]    = NY + 2*ghost_len;
+    array_of_subsizes[0] = NZ;
+    array_of_subsizes[1] = NY;
+    array_of_starts[0]   = ghost_len;
+    array_of_starts[1]   = ghost_len;
+    MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                             array_of_starts, MPI_ORDER_C, MPI_INT, &subarray);
+    MPI_Type_commit(&subarray);
+
+    int buffer_len = (NZ+2*ghost_len) * (NY+2*ghost_len);
+    buf_zy = (int*) malloc(buffer_len * sizeof(int));
+    for (i=0; i<buffer_len; i++) buf_zy[i] = rank;
+
+    start[0] = NZ * rank; start[1] = 0;
+    count[0] = NZ;        count[1] = NY;
+    /* calling a blocking flexible API */
+    err = ncmpi_put_vara_all(ncid, varid0, start, count, buf_zy, 1, subarray);
+    ERR
+
+    /* check the contents of put buffer */
+    for (i=0; i<buffer_len; i++) {
+        if (buf_zy[i] != rank)
+            printf("Error put buffer[%d] is altered\n",i);
+    }
+
+    for (i=0; i<buffer_len; i++) buf_zy[i] = -1;
+    /* calling a blocking flexible API */
+    err = ncmpi_get_vara_all(ncid, varid0, start, count, buf_zy, 1, subarray);
+    ERR
+
+    /* check the contents of get buffer */
+    for (i=0; i<array_of_sizes[0]; i++) {
+        for (j=0; j<array_of_sizes[1]; j++) {
+            int index = i*array_of_sizes[1] + j;
+            if (i < ghost_len || ghost_len+array_of_subsizes[0] <= i ||
+                j < ghost_len || ghost_len+array_of_subsizes[1] <= j) {
+                if (buf_zy[index] != -1)
+                    printf("Unexpected get buffer[%d][%d]=%d\n",
+                           i,j,buf_zy[index]);
+            }
+            else {
+                if (buf_zy[index] != rank)
+                    printf("Unexpected get buffer[%d][%d]=%d\n",
+                           i,j,buf_zy[index]);
+            }
+        }
+    }
+    free(buf_zy);
+    MPI_Type_free(&subarray);
+
+    /* var_yx is partitioned along X dimension */
+    array_of_sizes[0]    = NY + 2*ghost_len;
+    array_of_sizes[1]    = NX + 2*ghost_len;
+    array_of_subsizes[0] = NY;
+    array_of_subsizes[1] = NX;
+    array_of_starts[0]   = ghost_len;
+    array_of_starts[1]   = ghost_len;
+    MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                             array_of_starts, MPI_ORDER_C, MPI_DOUBLE,
+                             &subarray);
+    MPI_Type_commit(&subarray);
+
+    buffer_len = (NY+2*ghost_len) * (NX+2*ghost_len);
+    buf_yx = (double*) malloc(buffer_len * sizeof(double));
+    for (i=0; i<buffer_len; i++) buf_yx[i] = rank;
+
+    start[0] = 0;  start[1] = NX * rank;
+    count[0] = NY; count[1] = NX;
+
+    /* calling a non-blocking flexible API */
+    err = ncmpi_iput_vara(ncid, varid1, start, count, buf_yx, 1, subarray,&req);
+    ERR
+    err = ncmpi_wait_all(ncid, 1, &req, &status); ERR
+    err = status; ERR
+
+    /* check the contents of put buffer */
+    for (i=0; i<buffer_len; i++) {
+        if (buf_yx[i] != rank)
+            printf("Error iput buffer[%d]=%f is altered\n",i,buf_yx[i]);
+    }
+
+    for (i=0; i<buffer_len; i++) buf_yx[i] = -1;
+
+    /* calling a non-blocking flexible API */
+    err = ncmpi_iget_vara(ncid, varid1, start, count, buf_yx, 1, subarray,&req);
+    ERR
+    err = ncmpi_wait_all(ncid, 1, &req, &status); ERR
+    err = status; ERR
+
+    /* check the contents of iget buffer */
+    for (i=0; i<array_of_sizes[0]; i++) {
+        for (j=0; j<array_of_sizes[1]; j++) {
+            int index = i*array_of_sizes[1] + j;
+            if (i < ghost_len || ghost_len+array_of_subsizes[0] <= i ||
+                j < ghost_len || ghost_len+array_of_subsizes[1] <= j) {
+                if (buf_yx[index] != -1)
+                    printf("Unexpected get buffer[%d][%d]=%f\n",
+                           i,j,buf_yx[index]);
+            }
+            else {
+                if (buf_yx[index] != rank)
+                    printf("Unexpected get buffer[%d][%d]=%f\n",
+                           i,j,buf_yx[index]);
+            }
+        }
+    }
+    free(buf_yx);
+    MPI_Type_free(&subarray);
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/get_info.c b/examples/C/get_info.c
new file mode 100644
index 0000000..1a655d3
--- /dev/null
+++ b/examples/C/get_info.c
@@ -0,0 +1,145 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: get_info.c 1669 2014-05-24 18:28:16Z wkliao $ */
+
+/*
+ *    prints all MPI-IO hints used
+ *    To compile:
+ *        mpicc -O2 get_info.c -o get_info -lpnetcdf
+ *    To run:
+ *        mpiexec -n 4 ./get_info [filename]
+ *
+ *    Example standard output:
+
+    MPI File Info: nkeys = 18
+    MPI File Info: [ 0] key =            cb_buffer_size, value = 16777216
+    MPI File Info: [ 1] key =             romio_cb_read, value = automatic
+    MPI File Info: [ 2] key =            romio_cb_write, value = automatic
+    MPI File Info: [ 3] key =                  cb_nodes, value = 1
+    MPI File Info: [ 4] key =         romio_no_indep_rw, value = false
+    MPI File Info: [ 5] key =              romio_cb_pfr, value = disable
+    MPI File Info: [ 6] key =         romio_cb_fr_types, value = aar
+    MPI File Info: [ 7] key =     romio_cb_fr_alignment, value = 1
+    MPI File Info: [ 8] key =     romio_cb_ds_threshold, value = 0
+    MPI File Info: [ 9] key =         romio_cb_alltoall, value = automatic
+    MPI File Info: [10] key =        ind_rd_buffer_size, value = 4194304
+    MPI File Info: [11] key =        ind_wr_buffer_size, value = 524288
+    MPI File Info: [12] key =             romio_ds_read, value = automatic
+    MPI File Info: [13] key =            romio_ds_write, value = automatic
+    MPI File Info: [14] key =            cb_config_list, value = *:1
+    MPI File Info: [15] key =      nc_header_align_size, value = 512
+    MPI File Info: [16] key =         nc_var_align_size, value = 512
+    MPI File Info: [17] key = nc_header_read_chunk_size, value = 0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+
+#define HANDLE_ERROR {                                \
+    if (err != NC_NOERR)                              \
+        printf("Error at line %d (%s)\n", __LINE__,   \
+               ncmpi_strerror(err));                  \
+}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+/*----< print_info() >------------------------------------------------------*/
+static
+void print_info(MPI_Info *info_used)
+{
+    int  i, nkeys;
+
+    MPI_Info_get_nkeys(*info_used, &nkeys);
+    printf("MPI File Info: nkeys = %d\n",nkeys);
+    for (i=0; i<nkeys; i++) {
+        char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
+        int  valuelen, flag;
+
+        MPI_Info_get_nthkey(*info_used, i, key);
+        MPI_Info_get_valuelen(*info_used, key, &valuelen, &flag);
+        MPI_Info_get(*info_used, key, valuelen+1, value, &flag);
+        printf("MPI File Info: [%2d] key = %25s, value = %s\n",i,key,value);
+    }
+}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    extern int optind;
+    char *filename="testfile.nc";
+    int i, rank, ncid, verbose=1, err;
+    MPI_Info info_used;
+
+    MPI_Init(&argc,&argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    /* create the file */
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER|NC_64BIT_DATA,
+                       MPI_INFO_NULL, &ncid);
+    if (err != NC_NOERR) {
+        printf("Error: ncmpi_create() file %s (%s)\n",filename,ncmpi_strerror(err));
+        MPI_Abort(MPI_COMM_WORLD, -1);
+        exit(1);
+    }
+
+    /* exit the define mode */
+    err = ncmpi_enddef(ncid);
+    HANDLE_ERROR
+
+    /* get all the hints used */
+    err = ncmpi_inq_file_info(ncid, &info_used);
+    HANDLE_ERROR
+
+    /* close the file */
+    err = ncmpi_close(ncid);
+    HANDLE_ERROR
+
+    if (rank == 0 && verbose) print_info(&info_used);
+    MPI_Info_free(&info_used);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/get_vara.c b/examples/C/get_vara.c
new file mode 100644
index 0000000..0260426
--- /dev/null
+++ b/examples/C/get_vara.c
@@ -0,0 +1,188 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: get_vara.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example is the read counterpart of example put_vara.c. It shows how to
+ * use ncmpi_get_vara_int_all() to read a 2D 4-byte integer array in parallel.
+ * It also reads a global attribute and two attribute of variable named "var".
+ * The data partitioning pattern is a column-wise partitioning across all
+ * processes. Each process reads a subarray of size local_ny * local_nx.
+ *
+ *    To compile:
+ *        mpicc -O2 get_vara.c -o get_vara -lpnetcdf
+ *
+ * Input file is the output file produced by put_vara.c. Here is the CDL dumped
+ * from running ncmpidump.
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-1
+ *    dimensions:
+ *            y = 10 ;
+ *            x = 16 ;
+ *    variables:
+ *            int var(y, x) ;
+ *                var:str_att_name = "example attribute of type text." ;
+ *                var:float_att_name = 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f ;
+ *    // global attributes:
+ *                :history = "Wed Apr 30 11:18:58 2014\n",
+ *       "" ;
+ *    data:
+ *
+ *     var =
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 ;
+ *    }
+ *
+ * Example command for MPI run:
+ *
+ *    % mpiexec -n 4 ./get_vara /pvfs2/wkliao/testfile.nc
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define CHECK_ERR { \
+    if (err!=NC_NOERR) { \
+        printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
+        goto fn_exit; \
+    } \
+}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] input netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char *filename="testfile.nc", str_att[NC_MAX_NAME];
+    int i, rank, nprocs, err, verbose=1, ncid, varid, dimid[2], *buf;
+    float *float_att;
+    MPI_Offset len, global_ny, global_nx, local_ny, local_nx;
+    MPI_Offset start[2], count[2];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    /* open an existing file for reading -------------------------------------*/
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid);
+    CHECK_ERR
+
+    /* get global attribute named "history" */
+    err = ncmpi_get_att_text(ncid, NC_GLOBAL, "history", str_att);
+    CHECK_ERR
+    err = ncmpi_inq_attlen(ncid, NC_GLOBAL, "history", &len);
+    CHECK_ERR
+    str_att[len] = '\0'; /* add a NULL char at the end */
+    if (rank == 0 && verbose)
+        printf("global attribute \"history\" of text: %s\n",str_att);
+
+    /* get dimension IDs for dimensions Y and X */
+    err = ncmpi_inq_dimid(ncid, "Y", &dimid[0]);
+    CHECK_ERR
+    err = ncmpi_inq_dimid(ncid, "X", &dimid[1]);
+    CHECK_ERR
+
+    /* get dimension lengths for dimensions Y and X */
+    err = ncmpi_inq_dimlen(ncid, dimid[0], &global_ny);
+    CHECK_ERR
+    err = ncmpi_inq_dimlen(ncid, dimid[1], &global_nx);
+    CHECK_ERR
+
+    /* get the variable ID of a 2D variable of integer type */
+    err = ncmpi_inq_varid(ncid, "var", &varid);
+    CHECK_ERR
+
+    /* get variable's attribute named "str_att_name" */
+    err = ncmpi_get_att_text(ncid, varid, "str_att_name", str_att);
+    CHECK_ERR
+    err = ncmpi_inq_attlen(ncid, varid, "str_att_name", &len);
+    CHECK_ERR
+    str_att[len] = '\0'; /* add a NULL char at the end */
+    if (rank == 0 && verbose)
+        printf("variable attribute \"str_att_name\" of type text = \"%s\"\n",
+               str_att);
+
+    /* get the length of variable's attribute named "float_att_name" */
+    err = ncmpi_inq_attlen(ncid, varid, "float_att_name", &len);
+    CHECK_ERR
+
+    /* get attribute contents */
+    float_att = (float*) malloc(len * sizeof(float));
+    err = ncmpi_get_att_float(ncid, varid, "float_att_name", float_att);
+    CHECK_ERR
+
+    /* the local array size */
+    local_ny = global_ny;
+    local_nx = global_nx / nprocs;
+    buf = (int*) malloc(local_nx * local_ny * sizeof(int));
+
+    /* prepare reading subarray */
+    start[0] = 0;
+    start[1] = local_nx * rank;
+    count[0] = local_ny;
+    count[1] = local_nx;
+
+    /* read a subarray in collective mode */
+    err = ncmpi_get_vara_int_all(ncid, varid, start, count, buf);
+    CHECK_ERR
+
+    err = ncmpi_close(ncid);
+    CHECK_ERR
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+fn_exit:
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/ghost_cell.c b/examples/C/ghost_cell.c
new file mode 100644
index 0000000..6c1116c
--- /dev/null
+++ b/examples/C/ghost_cell.c
@@ -0,0 +1,206 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: ghost_cell.c 2010 2015-02-14 19:45:48Z wkliao $ */
+
+/*
+ * This example shows how to use varm API to write a 2D array buffer with ghost
+ * cells to a variables. The size of ghost cells is nghosts and the ghost cells
+ * cells appear on both ends of each dimension. The contents of ghost cells are
+ * -8s and non-ghost cells are the process rank IDs.
+ *
+ * To compile:
+ *        mpicc -O2 ghost_cell.c -o ghost_cell -lpnetcdf
+ * To run:
+ *        mpiexec -n num_processes ./ghost_cell [filename] [len]
+ * where len decides the size of local array, which is len x len+1.
+ * So, the variable is of size len*(len+1) * nprocs * sizeof(int)
+ *
+ * The screen outputs from running ncmpidump on the output file produced by
+ * command:
+ * % mpiexec -n 4 ./ghost_cell -q /pvfs2/wkliao/testfile.nc 4
+ *
+ * % ncmpidump /pvfs2/wkliao/testfile.nc
+ *     netcdf testfile {
+ *     // file format: CDF-5 (big variables)
+ *     dimensions:
+ *         Y = 8 ;
+ *         X = 10 ;
+ *     variables:
+ *         int var(Y, X) ;
+ *         data:
+ *
+ *     var =
+ *         0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+ *         0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+ *         0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+ *         0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+ *         2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *         2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *         2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *         2, 2, 2, 2, 2, 3, 3, 3, 3, 3 ;
+ *     }
+ *
+ * In this case, the contents of local buffers are shown below.
+ *
+ * rank 0:                                rank 1:
+ *    -8, -8, -8, -8, -8, -8, -8, -8, -8     -8, -8, -8, -8, -8, -8, -8, -8, -8
+ *    -8, -8, -8, -8, -8, -8, -8, -8, -8     -8, -8, -8, -8, -8, -8, -8, -8, -8
+ *    -8, -8,  0,  0,  0,  0,  0, -8, -8     -8, -8,  1,  1,  1,  1,  1, -8, -8
+ *    -8, -8,  0,  0,  0,  0,  0, -8, -8     -8, -8,  1,  1,  1,  1,  1, -8, -8
+ *    -8, -8,  0,  0,  0,  0,  0, -8, -8     -8, -8,  1,  1,  1,  1,  1, -8, -8
+ *    -8, -8,  0,  0,  0,  0,  0, -8, -8     -8, -8,  1,  1,  1,  1,  1, -8, -8
+ *    -8, -8, -8, -8, -8, -8, -8, -8, -8     -8, -8, -8, -8, -8, -8, -8, -8, -8
+ *    -8, -8, -8, -8, -8, -8, -8, -8, -8     -8, -8, -8, -8, -8, -8, -8, -8, -8
+ *
+ * rank 2:                                rank 3:
+ *    -8, -8, -8, -8, -8, -8, -8, -8, -8     -8, -8, -8, -8, -8, -8, -8, -8, -8
+ *    -8, -8, -8, -8, -8, -8, -8, -8, -8     -8, -8, -8, -8, -8, -8, -8, -8, -8
+ *    -8, -8,  2,  2,  2,  2,  2, -8, -8     -8, -8,  3,  3,  3,  3,  3, -8, -8
+ *    -8, -8,  2,  2,  2,  2,  2, -8, -8     -8, -8,  3,  3,  3,  3,  3, -8, -8
+ *    -8, -8,  2,  2,  2,  2,  2, -8, -8     -8, -8,  3,  3,  3,  3,  3, -8, -8
+ *    -8, -8,  2,  2,  2,  2,  2, -8, -8     -8, -8,  3,  3,  3,  3,  3, -8, -8
+ *    -8, -8, -8, -8, -8, -8, -8, -8, -8     -8, -8, -8, -8, -8, -8, -8, -8, -8
+ *    -8, -8, -8, -8, -8, -8, -8, -8, -8     -8, -8, -8, -8, -8, -8, -8, -8, -8
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strlen() */
+#include <unistd.h> /* getopt() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define HANDLE_ERROR {                                         \
+    if (err != NC_NOERR)                                       \
+        printf("Error at %s line %d (%s)\n",__FILE__,__LINE__, \
+               ncmpi_strerror(err));                           \
+}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name] [len]\n"
+    "       [-h] Print this help\n"
+    "       [-q] quiet mode\n"
+    "       [filename] output netCDF file name\n"
+    "       [len] size of each dimension of the local array\n";
+    fprintf(stderr, help, argv0);
+}
+
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    extern int optind;
+    char *filename="testfile.nc";
+    int i, j, rank, nprocs, len, ncid, bufsize, verbose=1, err;
+    int psizes[2], local_rank[2], dimids[2], varid, nghosts;
+    int *buf, *buf_ptr;
+    MPI_Offset gsizes[2], starts[2], counts[2], imap[2];
+
+    MPI_Init(&argc,&argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc >= 1) filename = argv[0];  /* optional argument */
+    len = 4;
+    if (argc >= 2) len = atoi(argv[1]); /* optional argument */
+
+    /* calculate number of processes along each dimension */
+    psizes[0] = psizes[1] = 0;
+    MPI_Dims_create(nprocs, 2, psizes);
+    if (verbose && rank == 0)
+        printf("psizes=%d %d\n", psizes[0], psizes[1]);
+
+    gsizes[0] = len     * psizes[0]; /* global array size */
+    gsizes[1] = (len+1) * psizes[1];
+    if (verbose && rank == 0)
+        printf("global variable shape: %lld %lld\n", gsizes[0],gsizes[1]);
+
+    /* find its local rank IDs along each dimension */
+    local_rank[0] = rank / psizes[1];
+    local_rank[1] = rank % psizes[1];
+    if (verbose)
+        printf("rank %d: dim rank=%d %d\n", rank,local_rank[0],local_rank[1]);
+
+    counts[0] = len;
+    counts[1] = len+1;
+    starts[0] = local_rank[0] * counts[0];
+    starts[1] = local_rank[1] * counts[1];
+    if (verbose)
+        printf("starts=%lld %lld counts=%lld %lld\n",starts[0],starts[1],counts[0],counts[1]);
+
+    /* allocate and initialize buffer with ghost cells on both ends of each dim */
+    nghosts = 2;
+    bufsize = (counts[0] + 2 * nghosts) * (counts[1] + 2 * nghosts);
+    buf = (int *) malloc(bufsize * sizeof(int));
+    for (i=0; i<counts[0]+2*nghosts; i++)
+    for (j=0; j<counts[1]+2*nghosts; j++) {
+        if (nghosts <= i && i < counts[0]+nghosts &&
+            nghosts <= j && j < counts[1]+nghosts)
+            buf[i*(counts[1]+2*nghosts) + j] = rank;
+        else
+            buf[i*(counts[1]+2*nghosts) + j] = -8; /* all ghost cells have value -8 */
+    }
+
+    /* create the file */
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER|NC_64BIT_DATA,
+                       MPI_INFO_NULL, &ncid);
+    if (err != NC_NOERR) {
+        printf("Error: ncmpi_create() file %s (%s)\n",filename,ncmpi_strerror(err));
+        MPI_Abort(MPI_COMM_WORLD, -1);
+        exit(1);
+    }
+
+    /* define dimensions */
+    err = ncmpi_def_dim(ncid, "Y", gsizes[0], &dimids[0]);
+    HANDLE_ERROR
+    err = ncmpi_def_dim(ncid, "X", gsizes[1], &dimids[1]);
+    HANDLE_ERROR
+
+    /* define variable */
+    err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimids, &varid);
+    HANDLE_ERROR
+
+    /* exit the define mode */
+    err = ncmpi_enddef(ncid);
+    HANDLE_ERROR
+
+    /* set up imap[] for excluding ghost cells */
+    imap[1] = 1;
+    imap[0] = counts[1] + 2 * nghosts;
+
+    /* find the first non-ghost cell of the user buf */
+    buf_ptr = buf + nghosts * (counts[1]+2*nghosts + 1);
+
+    /* write the whole variable in file */
+    err = ncmpi_put_varm_int_all(ncid, varid, starts, counts, NULL, imap, buf_ptr);
+    HANDLE_ERROR
+
+    /* close the file */
+    err = ncmpi_close(ncid);
+    HANDLE_ERROR
+
+    free(buf);
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/global_attributes.c b/examples/C/global_attributes.c
new file mode 100644
index 0000000..180d6e5
--- /dev/null
+++ b/examples/C/global_attributes.c
@@ -0,0 +1,186 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: global_attributes.c 1713 2014-07-06 04:23:57Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example creates a new file and add 2 global attributes, one is of text
+ * type and the other 10 short integers. The file is closed and re-opened to
+ * read back the attributes.
+ *
+ *    To compile:
+ *        mpicc -O2 global_attributes.c -o global_attributes -lpnetcdf
+ *
+ * Example commands for MPI run and outputs from running ncmpidump on the
+ * netCDF file produced by this example program:
+ *
+ *    % mpiexec -n 4 ./global_attributes /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-1
+ *
+ *    // global attributes:
+ *                    :history = "Sun May  4 13:11:47 2014\n",
+ *        "" ;
+ *                    :digits = 0s, 1s, 2s, 3s, 4s, 5s, 6s, 7s, 8s, 9s ;
+ *    }
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strlen(), strcpy() */
+#include <unistd.h> /* getopt() */
+#include <time.h>   /* time() localtime(), asctime() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define ERR { \
+    if(err!=NC_NOERR) { \
+        printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
+        goto fn_exit; \
+    } \
+}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char *filename="testfile.nc";
+    char str_att[128], att_name[NC_MAX_NAME];
+    int i, rank, err, verbose=0, ncid, cmode, omode, ngatts;
+    short short_att[10], digit[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    time_t ltime;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* add a global attribute named "history": a time stamp at rank 0 */
+    ltime = time(NULL); /* get the current calendar time */
+    asctime_r(localtime(&ltime), str_att);
+
+    /* make sure the time string are consistent among all processes */
+    MPI_Bcast(str_att, strlen(str_att), MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    err = ncmpi_put_att_text(ncid, NC_GLOBAL, "history", strlen(str_att),
+                             &str_att[0]);
+    ERR
+    if (rank == 0 && verbose)
+        printf("writing global attribute \"history\" of text %s\n",
+               str_att);
+
+    /* add another global attribute named "digits": an array of short type */
+    err = ncmpi_put_att_short(ncid, NC_GLOBAL, "digits", NC_SHORT, 10,
+                             &digit[0]);
+    ERR
+    if (rank == 0 && verbose)
+        printf("writing global attribute \"digits\" of 10 short integers\n");
+
+    /* close file */
+    err = ncmpi_close(ncid);
+    ERR
+
+    /* open the newly created file for read only -----------------------------*/
+    omode = NC_NOWRITE;
+    err = ncmpi_open(MPI_COMM_WORLD, filename, omode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* find the number of global attributes */
+    err = ncmpi_inq_natts(ncid, &ngatts);
+    ERR
+
+    err = 0;
+    if (ngatts != 2) {
+        printf("Error: expected number of global attributes is 2, but got %d\n",
+               ngatts);
+        err = -1;
+    }
+    MPI_Allreduce(MPI_IN_PLACE, &err, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
+    if (err < 0) goto fn_exit;
+
+    /* find the name of first global attribute */
+    err = ncmpi_inq_attname(ncid, NC_GLOBAL, 0, att_name);
+    ERR
+
+    err = 0;
+    if (strncmp(att_name, "history", strlen("history"))) {
+        printf("Error: expected attribute name \"history\", but got %s\n",
+               att_name);
+        err = -1;
+    }
+    MPI_Allreduce(MPI_IN_PLACE, &err, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
+    if (err < 0) goto fn_exit;
+
+    /* read attribute value */
+    err = ncmpi_get_att_text(ncid, NC_GLOBAL, att_name, &str_att[0]);
+    ERR
+
+    /* find the name of second global attribute */
+    err = ncmpi_inq_attname(ncid, NC_GLOBAL, 1, att_name);
+    ERR
+
+    err = 0;
+    if (strncmp(att_name, "digits", strlen("digits"))) {
+        printf("Error: expected attribute name \"digits\", but got %s\n",
+               att_name);
+        err = -1;
+    }
+    MPI_Allreduce(MPI_IN_PLACE, &err, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
+    if (err < 0) goto fn_exit;
+
+    /* read attribute value */
+    err = ncmpi_get_att_short(ncid, NC_GLOBAL, att_name, &short_att[0]);
+    ERR
+
+    /* close file */
+    err = ncmpi_close(ncid);
+    ERR
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+fn_exit:
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/hints.c b/examples/C/hints.c
new file mode 100644
index 0000000..b6c1d29
--- /dev/null
+++ b/examples/C/hints.c
@@ -0,0 +1,196 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: hints.c 1669 2014-05-24 18:28:16Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example sets two PnetCDF hints:
+ *    nc_header_align_size and nc_var_align_size
+ * and prints the hint values as well as the header size, header extent, and
+ * two variables' starting file offsets.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicc -O2 -o hints hints.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 4 ./hints /pvfs2/wkliao/testfile.nc
+ *
+ *    nc_header_align_size      set to = 1024
+ *    nc_var_align_size         set to = 512
+ *    nc_header_read_chunk_size set to = 256
+ *    header size                      = 252
+ *    header extent                    = 1024
+ *    var_zy start file offset         = 1024
+ *    var_yx start file offset         = 3072
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NZ 5
+#define NY 5
+#define NX 5
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+static
+void print_hints(int ncid,
+                 int varid0,
+                 int varid1)
+{
+    char value[MPI_MAX_INFO_VAL];
+    int err, len, flag;
+    MPI_Offset header_size, header_extent, var_zy_start, var_yx_start;
+    MPI_Offset h_align=-1, v_align=-1, h_chunk=-1;
+    MPI_Info info_used;
+
+    err = ncmpi_inq_header_size  (ncid, &header_size);      ERR
+    err = ncmpi_inq_header_extent(ncid, &header_extent);    ERR
+    err = ncmpi_inq_varoffset(ncid, varid0, &var_zy_start); ERR
+    err = ncmpi_inq_varoffset(ncid, varid1, &var_yx_start); ERR
+
+    err = ncmpi_inq_file_info(ncid, &info_used); ERR
+    MPI_Info_get_valuelen(info_used, "nc_header_align_size", &len, &flag);
+    if (flag) {
+        MPI_Info_get(info_used, "nc_header_align_size", len+1, value, &flag);
+        h_align = atoll(value);
+    }
+        MPI_Info_get_valuelen(info_used, "nc_var_align_size", &len, &flag);
+    if (flag) {
+        MPI_Info_get(info_used, "nc_var_align_size", len+1, value, &flag);
+        v_align = atoll(value);
+    }
+    MPI_Info_get_valuelen(info_used, "nc_header_read_chunk_size", &len, &flag);
+    if (flag) {
+        MPI_Info_get(info_used, "nc_header_read_chunk_size", len+1, value,&flag);
+        h_chunk = atoll(value);
+    }
+    MPI_Info_free(&info_used);
+
+    if (h_align == -1)
+        printf("nc_header_align_size      is NOT set\n");
+    else
+        printf("nc_header_align_size      set to = %lld\n", h_align);
+
+    if (v_align == -1)
+        printf("nc_var_align_size         is NOT set\n");
+    else
+        printf("nc_var_align_size         set to = %lld\n", v_align);
+    if (h_chunk == -1)
+        printf("nc_header_read_chunk_size is NOT set\n");
+    else
+        printf("nc_header_read_chunk_size set to = %lld\n", h_chunk);
+
+    printf("header size                      = %lld\n", header_size);
+    printf("header extent                    = %lld\n", header_extent);
+    printf("var_zy start file offset         = %lld\n", var_zy_start);
+    printf("var_yx start file offset         = %lld\n", var_yx_start);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char *filename="testfile.nc";
+    int i, rank, nprocs, verbose=1, err;
+    int ncid, cmode, varid0, varid1, dimid[3], *buf_zy;
+    float *buf_yx;
+    MPI_Offset start[2], count[2];
+    MPI_Info info;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    MPI_Info_create(&info);
+    MPI_Info_set(info, "nc_header_align_size",      "1024"); /* size in bytes */
+    MPI_Info_set(info, "nc_var_align_size",         "512");  /* size in bytes */
+    MPI_Info_set(info, "nc_header_read_chunk_size", "256");  /* size in bytes */
+    /* note that set the above values to 1 to disable the alignment */
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, info, &ncid); ERR
+    MPI_Info_free(&info);
+
+    /* define 3 dimensions */
+    err = ncmpi_def_dim(ncid, "Z", NZ*nprocs, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "Y", NY*nprocs, &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX*nprocs, &dimid[2]); ERR
+
+    /* define a variable of size (NZ * nprocs) * (NY * nprocs) */
+    err = ncmpi_def_var(ncid, "var_zy", NC_INT,   2, &dimid[0], &varid0); ERR
+    /* define a variable of size (NY * nprocs) * (NX * nprocs) */
+    err = ncmpi_def_var(ncid, "var_yx", NC_FLOAT, 2, &dimid[1], &varid1); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* var_zy is partitioned along Z dimension */
+    buf_zy = (int*) malloc(NZ * (NY * nprocs) * sizeof(int));
+    for (i=0; i<NZ*(NY*nprocs); i++) buf_zy[i] = i;
+
+    start[0] = NZ * rank; start[1] = 0;
+    count[0] = NZ;        count[1] = NY * nprocs;
+    err = ncmpi_put_vara_int_all(ncid, varid0, start, count, buf_zy); ERR
+
+    /* var_yx is partitioned along X dimension */
+    buf_yx = (float*) malloc((NY * nprocs) * NX * sizeof(float));
+    for (i=0; i<(NY*nprocs)*NX; i++) buf_yx[i] = i;
+
+    start[0] = 0;           start[1] = NX * rank;
+    count[0] = NY * nprocs; count[1] = NX;
+    err = ncmpi_put_vara_float_all(ncid, varid1, start, count, buf_yx); ERR
+
+    if (rank == 0 && verbose) print_hints(ncid, varid0, varid1);
+
+    err = ncmpi_close(ncid); ERR
+
+    free(buf_zy);
+    free(buf_yx);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/i_varn_int64.c b/examples/C/i_varn_int64.c
new file mode 100644
index 0000000..1d7c1d8
--- /dev/null
+++ b/examples/C/i_varn_int64.c
@@ -0,0 +1,371 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: i_varn_int64.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example tests nonblocking varn APIs, including
+ * ncmpi_iput_varn_longlong(), ncmpi_iget_varn_longlong(), ncmpi_iput_varn(),
+ * and ncmpi_iget_varn().
+ * It first writes a sequence of requests with arbitrary array indices and
+ * lengths to four variables of type NC_INT64, and reads back.
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o i_varn_int64 i_varn_int64.c -lpnetcdf
+ *    % mpiexec -n 4 ./i_varn_int64 /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             Y = 4 ;
+ *             X = 10 ;
+ *    variables:
+ *            int64 var0(Y, X) ;
+ *            int64 var1(Y, X) ;
+ *            int64 var2(Y, X) ;
+ *            int64 var3(Y, X) ;
+ *    data:
+ *
+ *     var0 =
+ *      1, 1, 1, 3, 3, 0, 0, 2, 3, 3,
+ *      0, 2, 2, 2, 1, 3, 3, 2, 2, 2,
+ *      3, 3, 2, 1, 1, 1, 0, 0, 3, 3,
+ *      0, 0, 0, 2, 3, 3, 3, 1, 1, 1 ;
+ *
+ *     var1 =
+ *      2, 2, 2, 0, 0, 1, 1, 3, 0, 0,
+ *      1, 3, 3, 3, 2, 0, 0, 3, 3, 3,
+ *      0, 0, 3, 2, 2, 2, 1, 1, 0, 0,
+ *      1, 1, 1, 3, 0, 0, 0, 2, 2, 2 ;
+ *
+ *     var2 =
+ *      3, 3, 3, 1, 1, 2, 2, 0, 1, 1,
+ *      2, 0, 0, 0, 3, 1, 1, 0, 0, 0,
+ *      1, 1, 0, 3, 3, 3, 2, 2, 1, 1,
+ *      2, 2, 2, 0, 1, 1, 1, 3, 3, 3 ;
+ *
+ *     var3 =
+ *      0, 0, 0, 2, 2, 3, 3, 1, 2, 2,
+ *      3, 1, 1, 1, 0, 2, 2, 1, 1, 1,
+ *      2, 2, 1, 0, 0, 0, 3, 3, 2, 2,
+ *      3, 3, 3, 1, 2, 2, 2, 0, 0, 0 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h> /* getopt() */
+#include <string.h> /* strcpy() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+#define ERR \
+    if (err != NC_NOERR) { \
+        printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
+    }
+
+#define ERRS(n,a) { \
+    int _i; \
+    for (_i=0; _i<(n); _i++) { \
+        if ((a)[_i] != NC_NOERR) { \
+            printf("Error at line=%d: err[%d] %s\n", __LINE__, _i, \
+                   ncmpi_strerror((a)[_i])); \
+        } \
+    } \
+}
+
+static MPI_Offset *** calloc_3D(size_t z, size_t y, size_t x)
+{
+    int _j, _k;
+    MPI_Offset ***buf  = (MPI_Offset***) malloc(z     * sizeof(MPI_Offset**));
+    MPI_Offset  **bufy = (MPI_Offset**)  malloc(z*y   * sizeof(MPI_Offset*));
+    MPI_Offset   *bufx = (MPI_Offset*)   calloc(z*y*x,  sizeof(MPI_Offset));
+    for (_k=0; _k<z; _k++, bufy+=y) {
+        buf[_k] = bufy;
+        for (_j=0; _j<y; _j++, bufx+=x)
+            buf[_k][_j] = bufx;
+    }
+    return buf;
+}
+
+static void free_3D(MPI_Offset ***buf)
+{
+    free(buf[0][0]);
+    free(buf[0]);
+    free(buf);
+}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+static void check_contents(int ncid, int *varid)
+{
+    int i, j, err;
+    long long expected[4][NY*NX] = {{1, 1, 1, 3, 3, 0, 0, 2, 3, 3,
+                                     0, 2, 2, 2, 1, 3, 3, 2, 2, 2,
+                                     3, 3, 2, 1, 1, 1, 0, 0, 3, 3,
+                                     0, 0, 0, 2, 3, 3, 3, 1, 1, 1},
+                                    {2, 2, 2, 0, 0, 1, 1, 3, 0, 0,
+                                     1, 3, 3, 3, 2, 0, 0, 3, 3, 3,
+                                     0, 0, 3, 2, 2, 2, 1, 1, 0, 0,
+                                     1, 1, 1, 3, 0, 0, 0, 2, 2, 2},
+                                    {3, 3, 3, 1, 1, 2, 2, 0, 1, 1,
+                                     2, 0, 0, 0, 3, 1, 1, 0, 0, 0,
+                                     1, 1, 0, 3, 3, 3, 2, 2, 1, 1,
+                                     2, 2, 2, 0, 1, 1, 1, 3, 3, 3},
+                                    {0, 0, 0, 2, 2, 3, 3, 1, 2, 2,
+                                     3, 1, 1, 1, 0, 2, 2, 1, 1, 1,
+                                     2, 2, 1, 0, 0, 0, 3, 3, 2, 2,
+                                     3, 3, 3, 1, 2, 2, 2, 0, 0, 0}};
+
+    long long *r_buffer = (long long*) malloc(NY*NX * sizeof(long long));
+
+    for (i=0; i<4; i++) {
+        for (j=0; j<NY*NX; j++) r_buffer[j] = -1;
+        err = ncmpi_get_var_longlong_all(ncid, varid[i], r_buffer);
+        ERR
+
+        /* check if the contents of buf are expected */
+        for (j=0; j<NY*NX; j++)
+            if (r_buffer[j] != expected[i][j])
+                printf("Expected file contents [%d][%d]=%lld, but got %lld\n",
+                       i,j,expected[i][j],r_buffer[j]);
+    }
+    free(r_buffer);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char *filename="testfile.nc", exec[128];
+    int i, j, k, n, rank, nprocs, verbose=1, err;
+    int ncid, cmode, varid[4], dimid[2], nreqs, reqs[4], sts[4];
+    long long *buffer[4];
+    int num_segs[4], req_lens[4];
+    MPI_Offset ***starts, ***counts;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    strcpy(exec, argv[0]);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    if (nprocs != 4 && rank == 0 && verbose)
+        printf("Warning: %s is intended to run on 4 processes\n",exec);
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_INT64, NDIMS, dimid, &varid[0]); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT64, NDIMS, dimid, &varid[1]); ERR
+    err = ncmpi_def_var(ncid, "var2", NC_INT64, NDIMS, dimid, &varid[2]); ERR
+    err = ncmpi_def_var(ncid, "var3", NC_INT64, NDIMS, dimid, &varid[3]); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* allocate space for starts and counts */
+    starts = calloc_3D(4, 6, NDIMS);
+    counts = calloc_3D(4, 6, NDIMS);
+
+    n = rank % 4;
+    num_segs[n] = 4; /* number of segments for this request */
+    starts[n][0][0]=0; starts[n][0][1]=5; counts[n][0][0]=1; counts[n][0][1]=2;
+    starts[n][1][0]=1; starts[n][1][1]=0; counts[n][1][0]=1; counts[n][1][1]=1;
+    starts[n][2][0]=2; starts[n][2][1]=6; counts[n][2][0]=1; counts[n][2][1]=2;
+    starts[n][3][0]=3; starts[n][3][1]=0; counts[n][3][0]=1; counts[n][3][1]=3;
+    /* starts[n][][] n_counts[n][][] indicate the following: ("-" means skip)
+              -  -  -  -  -  X  X  -  -  - 
+              X  -  -  -  -  -  -  -  -  - 
+              -  -  -  -  -  -  X  X  -  - 
+              X  X  X  -  -  -  -  -  -  - 
+     */
+    n = (rank+1) % 4;
+    num_segs[n] = 6; /* number of segments for this request */
+    starts[n][0][0]=0; starts[n][0][1]=3; counts[n][0][0]=1; counts[n][0][1]=2;
+    starts[n][1][0]=0; starts[n][1][1]=8; counts[n][1][0]=1; counts[n][1][1]=2;
+    starts[n][2][0]=1; starts[n][2][1]=5; counts[n][2][0]=1; counts[n][2][1]=2;
+    starts[n][3][0]=2; starts[n][3][1]=0; counts[n][3][0]=1; counts[n][3][1]=2;
+    starts[n][4][0]=2; starts[n][4][1]=8; counts[n][4][0]=1; counts[n][4][1]=2;
+    starts[n][5][0]=3; starts[n][5][1]=4; counts[n][5][0]=1; counts[n][5][1]=3;
+    /* starts[n][][] counts[n][][] indicate the following pattern.
+              -  -  -  X  X  -  -  -  X  X 
+              -  -  -  -  -  X  X  -  -  - 
+              X  X  -  -  -  -  -  -  X  X 
+              -  -  -  -  X  X  X  -  -  - 
+     */
+    n = (rank+2) % 4;
+    num_segs[n] = 5; /* number of segments for this request */
+    starts[n][0][0]=0; starts[n][0][1]=7; counts[n][0][0]=1; counts[n][0][1]=1;
+    starts[n][1][0]=1; starts[n][1][1]=1; counts[n][1][0]=1; counts[n][1][1]=3;
+    starts[n][2][0]=1; starts[n][2][1]=7; counts[n][2][0]=1; counts[n][2][1]=3;
+    starts[n][3][0]=2; starts[n][3][1]=2; counts[n][3][0]=1; counts[n][3][1]=1;
+    starts[n][4][0]=3; starts[n][4][1]=3; counts[n][4][0]=1; counts[n][4][1]=1;
+    /* starts[n][][] counts[n][][] indicate the following pattern.
+              -  -  -  -  -  -  -  X  -  - 
+              -  X  X  X  -  -  -  X  X  X 
+              -  -  X  -  -  -  -  -  -  - 
+              -  -  -  X  -  -  -  -  -  - 
+     */
+    n = (rank+3) % 4;
+    num_segs[n] = 4; /* number of segments for this request */
+    starts[n][0][0]=0; starts[n][0][1]=0; counts[n][0][0]=1; counts[n][0][1]=3;
+    starts[n][1][0]=1; starts[n][1][1]=4; counts[n][1][0]=1; counts[n][1][1]=1;
+    starts[n][2][0]=2; starts[n][2][1]=3; counts[n][2][0]=1; counts[n][2][1]=3;
+    starts[n][3][0]=3; starts[n][3][1]=7; counts[n][3][0]=1; counts[n][3][1]=3;
+     /*starts[n][][] counts[n][][] indicate the following pattern.
+              X  X  X  -  -  -  -  -  -  - 
+              -  -  -  -  X  -  -  -  -  - 
+              -  -  -  X  X  X  -  -  -  - 
+              -  -  -  -  -  -  -  X  X  X 
+     */
+
+    /* only rank 0, 1, 2, and 3 do I/O:
+     * each of ranks 0 to 3 write 4 nonblocking requests */
+    nreqs = 4;
+    if (rank >= 4) nreqs = 0;
+
+    /* calculate length of each varn request, number of segments in each
+     * varn request, and allocate write buffer */
+    for (i=0; i<nreqs; i++) {
+        req_lens[i] = 0; /* total length this request */
+        for (j=0; j<num_segs[i]; j++) {
+            MPI_Offset req_len=1;
+            for (k=0; k<NDIMS; k++)
+                req_len *= counts[i][j][k];
+            req_lens[i] += req_len;
+        }
+        if (verbose) printf("req_lens[%d]=%d\n",i,req_lens[i]);
+
+        /* allocate I/O buffer and initialize its contents */
+        buffer[i] = (long long*) malloc(req_lens[i] * sizeof(long long));
+        for (j=0; j<req_lens[i]; j++) buffer[i][j] = rank;
+    }
+
+    /* write using varn API */
+    for (i=0; i<nreqs; i++) {
+        err = ncmpi_iput_varn_longlong(ncid, varid[i], num_segs[i], starts[i],
+                                       counts[i], buffer[i], &reqs[i]);
+        ERR
+    }
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* check file contents */
+    if (nprocs >= 4) check_contents(ncid, varid);
+
+    /* read using get_varn API and check contents */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) buffer[i][j] = -1;
+        err = ncmpi_iget_varn_longlong(ncid, varid[i], num_segs[i], starts[i],
+                                       counts[i], buffer[i], &reqs[i]);
+        ERR
+    }
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* check buffer contents */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++)
+            if (buffer[i][j] != rank)
+                printf("Expected read buf[%d][%d]=%d, but got %lld\n",
+                       i,j,rank,buffer[i][j]);
+    }                
+
+    for (i=0; i<nreqs; i++) free(buffer[i]);
+
+    /* test flexible put API, using a noncontiguous buftype */
+    for (i=0; i<nreqs; i++) {
+        MPI_Datatype buftype;
+        MPI_Type_vector(req_lens[i], 1, 2, MPI_LONG_LONG, &buftype);
+        MPI_Type_commit(&buftype);
+        buffer[i] = (long long*) malloc(req_lens[i] * 2 * sizeof(long long));
+        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank;
+
+        err = ncmpi_iput_varn(ncid, varid[i], num_segs[i], starts[i],
+                              counts[i], buffer[i], 1, buftype, &reqs[i]);
+        ERR
+        MPI_Type_free(&buftype);
+    }
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* check file contents */
+    if (nprocs >= 4) check_contents(ncid, varid);
+
+    /* test flexible get API, using a noncontiguous buftype */
+    for (i=0; i<nreqs; i++) {
+        MPI_Datatype buftype;
+        MPI_Type_vector(req_lens[i], 1, 2, MPI_LONG_LONG, &buftype);
+        MPI_Type_commit(&buftype);
+        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = -1;
+        err = ncmpi_iget_varn(ncid, varid[i], num_segs[i], starts[i],
+                              counts[i], buffer[i], 1, buftype, &reqs[i]);
+        ERR
+        MPI_Type_free(&buftype);
+    }
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* check buffer contents */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++)
+            if (buffer[i][j*2] != rank)
+                printf("Expected read buf[%d][%d]=%d, but got %lld\n",
+                       i,j*2,rank,buffer[i][j*2]);
+    }                
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    for (i=0; i<nreqs; i++) free(buffer[i]);
+    free_3D(starts);
+    free_3D(counts);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/mput.c b/examples/C/mput.c
new file mode 100644
index 0000000..fe0ad16
--- /dev/null
+++ b/examples/C/mput.c
@@ -0,0 +1,232 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: mput.c 1669 2014-05-24 18:28:16Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use a single call of ncmpi_mput_vara_all() to
+ * write a sequence of requests with arbitrary array indices and lengths.
+ * Using ncmpi_mput_vara_all() can achieve the same effect of HDF5 writing
+ * a sequence of selected file locations through the following 2 APIs.
+ *
+ *   H5Sselect_elements(fid, H5S_SELECT_SET, NUMP, (const hssize_t **)coord);
+ *   H5Dwrite(dataset, H5T_NATIVE_INT, mid, fid, H5P_DEFAULT, val); 
+ *
+ * Note that in ncmpi_mput_vara_all(), users can write more than one element
+ * starting at each selected location.
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o mput mput.c -lpnetcdf
+ *    % mpiexec -l -n 4 ./mput /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             Y = 4 ;
+ *             X = 10 ;
+ *    variables:
+ *             int var(Y, X) ;
+ *    data:
+ *
+ *     var =
+ *       3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+ *       0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+ *       1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+ *       0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char *filename="testfile.nc";
+    int i, rank, nprocs, verbose=1, err;
+    int ncid, cmode, varid, dimid[2], num_reqs, *buffer, **bufs, *nvarids;
+    MPI_Offset w_len, **starts, **counts, *bufcounts;
+    MPI_Datatype *datatypes;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    if (nprocs != 4 && rank == 0 && verbose)
+        printf("Warning: this program is intended to run on 4 processes\n");
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]);
+    ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT, NDIMS, dimid, &varid);
+    ERR
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* pick arbitrary numbers of requests for 4 processes */
+    num_reqs = 0;
+    if (rank == 0)      num_reqs = 4;
+    else if (rank == 1) num_reqs = 6;
+    else if (rank == 2) num_reqs = 5;
+    else if (rank == 3) num_reqs = 4;
+
+    starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+    counts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+    starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+    counts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+    for (i=1; i<num_reqs; i++) {
+        starts[i] = starts[i-1] + NDIMS;
+        counts[i] = counts[i-1] + NDIMS;
+    }
+
+    /* assign arbitrary starts and counts */
+    const int y=0, x=1;
+    if (rank == 0) {
+        starts[0][y] = 0; starts[0][x] = 5; counts[0][y] = 1; counts[0][x] = 2;
+        starts[1][y] = 1; starts[1][x] = 0; counts[1][y] = 1; counts[1][x] = 1;
+        starts[2][y] = 2; starts[2][x] = 6; counts[2][y] = 1; counts[2][x] = 2;
+        starts[3][y] = 3; starts[3][x] = 0; counts[3][y] = 1; counts[3][x] = 3;
+        /* rank 0 is writing the followings: ("-" means skip)
+                  -  -  -  -  -  0  0  -  -  - 
+                  0  -  -  -  -  -  -  -  -  - 
+                  -  -  -  -  -  -  0  0  -  - 
+                  0  0  0  -  -  -  -  -  -  - 
+         */
+    } else if (rank ==1) {
+        starts[0][y] = 0; starts[0][x] = 3; counts[0][y] = 1; counts[0][x] = 2;
+        starts[1][y] = 0; starts[1][x] = 8; counts[1][y] = 1; counts[1][x] = 2;
+        starts[2][y] = 1; starts[2][x] = 5; counts[2][y] = 1; counts[2][x] = 2;
+        starts[3][y] = 2; starts[3][x] = 0; counts[3][y] = 1; counts[3][x] = 2;
+        starts[4][y] = 2; starts[4][x] = 8; counts[4][y] = 1; counts[4][x] = 2;
+        starts[5][y] = 3; starts[5][x] = 4; counts[5][y] = 1; counts[5][x] = 3;
+        /* rank 1 is writing the followings: ("-" means skip)
+                  -  -  -  1  1  -  -  -  1  1 
+                  -  -  -  -  -  1  1  -  -  - 
+                  1  1  -  -  -  -  -  -  1  1 
+                  -  -  -  -  1  1  1  -  -  - 
+         */
+    } else if (rank ==2) {
+        starts[0][y] = 0; starts[0][x] = 7; counts[0][y] = 1; counts[0][x] = 1;
+        starts[1][y] = 1; starts[1][x] = 1; counts[1][y] = 1; counts[1][x] = 3;
+        starts[2][y] = 1; starts[2][x] = 7; counts[2][y] = 1; counts[2][x] = 3;
+        starts[3][y] = 2; starts[3][x] = 2; counts[3][y] = 1; counts[3][x] = 1;
+        starts[4][y] = 3; starts[4][x] = 3; counts[4][y] = 1; counts[4][x] = 1;
+        /* rank 2 is writing the followings: ("-" means skip)
+                  -  -  -  -  -  -  -  2  -  - 
+                  -  2  2  2  -  -  -  2  2  2 
+                  -  -  2  -  -  -  -  -  -  - 
+                  -  -  -  2  -  -  -  -  -  - 
+         */
+    } else if (rank ==3) {
+        starts[0][y] = 0; starts[0][x] = 0; counts[0][y] = 1; counts[0][x] = 3;
+        starts[1][y] = 1; starts[1][x] = 4; counts[1][y] = 1; counts[1][x] = 1;
+        starts[2][y] = 2; starts[2][x] = 3; counts[2][y] = 1; counts[2][x] = 3;
+        starts[3][y] = 3; starts[3][x] = 7; counts[3][y] = 1; counts[3][x] = 3;
+        /* rank 3 is writing the followings: ("-" means skip)
+                  3  3  3  -  -  -  -  -  -  - 
+                  -  -  -  -  3  -  -  -  -  - 
+                  -  -  -  3  3  3  -  -  -  - 
+                  -  -  -  -  -  -  -  3  3  3 
+         */
+    }
+
+    nvarids   = (int*)          malloc(num_reqs * sizeof(int));
+    bufcounts = (MPI_Offset*)   malloc(num_reqs * sizeof(MPI_Offset));
+    datatypes = (MPI_Datatype*) malloc(num_reqs * sizeof(MPI_Datatype));
+    w_len = 0;
+    for (i=0; i<num_reqs; i++) {
+        nvarids[i]    = varid;
+        bufcounts[i]  = counts[i][x];
+        datatypes[i]  = MPI_INT;
+        w_len        += bufcounts[i];
+    }
+
+    /* allocate I/O buffer and initialize its contents */
+    buffer = (int*)  malloc(w_len * sizeof(int));
+    for (i=0; i<w_len; i++) buffer[i] = rank;
+
+    /* set the buffer pointers to different offsets to the I/O buffer */
+    bufs    = (int**) malloc(num_reqs * sizeof(int*));
+    bufs[0] = buffer;
+    for (i=1; i<num_reqs; i++) bufs[i] = bufs[i-1] + bufcounts[i-1];
+
+    err = ncmpi_mput_vara_all(ncid, num_reqs, nvarids, starts, counts,
+                              (void**)bufs, bufcounts, datatypes);
+    ERR
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    free(buffer);
+    free(bufs);
+    free(nvarids);
+    free(bufcounts);
+    free(datatypes);
+    free(starts[0]);
+    free(counts[0]);
+    free(starts);
+    free(counts);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/nonblocking_write.c b/examples/C/nonblocking_write.c
new file mode 100644
index 0000000..cf7bda2
--- /dev/null
+++ b/examples/C/nonblocking_write.c
@@ -0,0 +1,276 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: nonblocking_write.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* wkliao:
+ *    This example is similar to collective_write.c but using nonblocking APIs.
+ *    It creates a netcdf file in CD-5 format and writes a number of
+ *    3D integer non-record variables. The measured write bandwidth is reported
+ *    at the end. Usage: (for example)
+ *    To compile:
+ *        mpicc -O2 nonblocking_write.c -o nonblocking_write -lpnetcdf
+ *    To run:
+ *        mpiexec -n num_processes ./nonblocking_write [filename] [len]
+ *    where len decides the size of each local array, which is len x len x len.
+ *    So, each non-record variable is of size len*len*len * nprocs * sizeof(int)
+ *    All variables are partitioned among all processes in a 3D
+ *    block-block-block fashion. Below is an example standard output from
+ *    command:
+ *        mpiexec -n 32 ./nonblocking_write /pvfs2/wkliao/testfile.nc 100
+ *
+ *    MPI hint: cb_nodes        = 2
+ *    MPI hint: cb_buffer_size  = 16777216
+ *    MPI hint: striping_factor = 32
+ *    MPI hint: striping_unit   = 1048576
+ *    Local array size 100 x 100 x 100 integers, size = 3.81 MB
+ *    Global array size 400 x 400 x 200 integers, write size = 0.30 GB
+ *     procs    Global array size  exec(sec)  write(MB/s)
+ *     -------  ------------------  ---------  -----------
+ *        32     400 x  400 x  200     6.67       45.72
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NDIMS    3
+#define NUM_VARS 10
+
+#define HANDLE_ERROR {                                \
+    if (err != NC_NOERR)                              \
+        printf("Error at line %d (%s)\n", __LINE__,   \
+               ncmpi_strerror(err));                  \
+}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name] [len]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    "       [len] size of each dimension of the local array\n";
+    fprintf(stderr, help, argv0);
+}
+
+/*----< print_info() >------------------------------------------------------*/
+static
+void print_info(MPI_Info *info_used)
+{
+    int     flag;
+    char    info_cb_nodes[64], info_cb_buffer_size[64];
+    char    info_striping_factor[64], info_striping_unit[64];
+
+    strcpy(info_cb_nodes,        "undefined");
+    strcpy(info_cb_buffer_size,  "undefined");
+    strcpy(info_striping_factor, "undefined");
+    strcpy(info_striping_unit,   "undefined");
+
+    MPI_Info_get(*info_used, "cb_nodes", 64, info_cb_nodes, &flag);
+    MPI_Info_get(*info_used, "cb_buffer_size", 64, info_cb_buffer_size, &flag);
+    MPI_Info_get(*info_used, "striping_factor", 64, info_striping_factor, &flag);
+    MPI_Info_get(*info_used, "striping_unit", 64, info_striping_unit, &flag);
+
+    printf("MPI hint: cb_nodes        = %s\n", info_cb_nodes);
+    printf("MPI hint: cb_buffer_size  = %s\n", info_cb_buffer_size);
+    printf("MPI hint: striping_factor = %s\n", info_striping_factor);
+    printf("MPI hint: striping_unit   = %s\n", info_striping_unit);
+}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    extern int optind;
+    int i, j, verbose=1, err;
+    int nprocs, len, *buf[NUM_VARS], bufsize, rank;
+    int gsizes[NDIMS], psizes[NDIMS];
+    double write_timing, max_write_timing, write_bw;
+    char *filename="testfile.nc", str[512];
+    int ncid, dimids[NDIMS], varids[NUM_VARS], req[NUM_VARS], st[NUM_VARS];
+    MPI_Offset starts[NDIMS], counts[NDIMS], write_size, sum_write_size;
+    MPI_Offset bbufsize;
+    MPI_Info info_used;
+
+    MPI_Init(&argc,&argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc >= 1) filename = argv[0];  /* optional argument */
+    len = 10; 
+    if (argc >= 2) len = atoi(argv[1]); /* optional argument */
+
+    for (i=0; i<NDIMS; i++) psizes[i] = 0;
+
+    MPI_Dims_create(nprocs, NDIMS, psizes);
+    starts[0] = rank % psizes[0];
+    starts[1] = (rank / psizes[1]) % psizes[1];
+    starts[2] = (rank / (psizes[0] * psizes[1])) % psizes[2];
+
+    bufsize = 1;
+    for (i=0; i<NDIMS; i++) {
+        gsizes[i] = len * psizes[i];
+        starts[i] *= len;
+        counts[i]  = len;
+        bufsize   *= len;
+    }
+
+    /* allocate buffer and initialize with random numbers */
+    srand(rank);
+    for (i=0; i<NUM_VARS; i++) {
+        buf[i] = (int *) malloc(bufsize * sizeof(int));
+        for (j=0; j<bufsize; j++) buf[i][j] = rand();
+    }
+
+    MPI_Barrier(MPI_COMM_WORLD);
+    write_timing = MPI_Wtime();
+
+    /* create the file */
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER|NC_64BIT_DATA,
+                       MPI_INFO_NULL, &ncid);
+    if (err != NC_NOERR) {
+        printf("Error: ncmpi_create() file %s (%s)\n",filename,ncmpi_strerror(err));
+        MPI_Abort(MPI_COMM_WORLD, -1);
+        exit(1);
+    }
+
+    /* define dimensions */
+    for (i=0; i<NDIMS; i++) {
+        sprintf(str, "%c", 'x'+i);
+        err = ncmpi_def_dim(ncid, str, gsizes[i], &dimids[i]);
+        HANDLE_ERROR
+    }
+
+    /* define variables */
+    for (i=0; i<NUM_VARS; i++) {
+        sprintf(str, "var%d", i);
+        err = ncmpi_def_var(ncid, str, NC_INT, NDIMS, dimids, &varids[i]);
+        HANDLE_ERROR
+    }
+
+    /* exit the define mode */
+    err = ncmpi_enddef(ncid);
+    HANDLE_ERROR
+
+    /* get all the hints used */
+    err = ncmpi_inq_file_info(ncid, &info_used);
+    HANDLE_ERROR
+
+    /* write one variable at a time using iput */
+    for (i=0; i<NUM_VARS; i++) {
+        err = ncmpi_iput_vara_int(ncid, varids[i], starts, counts, buf[i], &req[i]);
+        HANDLE_ERROR
+    }
+
+    /* wait for the nonblocking I/O to complete */
+    err = ncmpi_wait_all(ncid, NUM_VARS, req, st);
+    HANDLE_ERROR
+    for (i=0; i<NUM_VARS; i++) {
+        if (st[i] != NC_NOERR)
+            printf("Error: nonblocking write fails on request %d (%s)\n",
+                   i, ncmpi_strerror(st[i]));
+    }
+
+    /* write one variable at a time using bput */
+
+    /* bbufsize must be max of data type converted before and after */
+    bbufsize = bufsize * NUM_VARS * sizeof(int);
+    err = ncmpi_buffer_attach(ncid, bbufsize);
+    HANDLE_ERROR
+
+    for (i=0; i<NUM_VARS; i++) {
+        err = ncmpi_bput_vara_int(ncid, varids[i], starts, counts, buf[i], &req[i]);
+        HANDLE_ERROR
+        /* can safely change contents or free up the buf[i] here */
+    }
+
+    /* wait for the nonblocking I/O to complete */
+    err = ncmpi_wait_all(ncid, NUM_VARS, req, st);
+    HANDLE_ERROR
+    for (i=0; i<NUM_VARS; i++) {
+        if (st[i] != NC_NOERR)
+            printf("Error: nonblocking write fails on request %d (%s)\n",
+                   i, ncmpi_strerror(st[i]));
+    }
+
+    /* detach the temporary buffer */
+    err = ncmpi_buffer_detach(ncid);
+    HANDLE_ERROR
+
+    MPI_Offset put_size;
+    ncmpi_inq_put_size(ncid, &put_size);
+#ifdef MPI_OFFSET
+    MPI_Allreduce(MPI_IN_PLACE, &put_size, 1, MPI_OFFSET, MPI_SUM, MPI_COMM_WORLD);
+#else
+    MPI_Allreduce(MPI_IN_PLACE, &put_size, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD);
+#endif
+
+    /* close the file */
+    err = ncmpi_close(ncid);
+    HANDLE_ERROR
+
+    write_timing = MPI_Wtime() - write_timing;
+
+    write_size = bufsize * NUM_VARS * sizeof(int);
+    for (i=0; i<NUM_VARS; i++) free(buf[i]);
+
+#ifdef MPI_OFFSET
+    MPI_Reduce(&write_size,   &sum_write_size,   1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+#else
+    MPI_Reduce(&write_size,   &sum_write_size,   1, MPI_LONG_LONG, MPI_SUM, 0, MPI_COMM_WORLD);
+#endif
+    MPI_Reduce(&write_timing, &max_write_timing, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
+
+    if (rank == 0 && verbose) {
+        printf("\n");
+        printf("Total amount writes to variables only   (exclude header) = %lld bytes\n", sum_write_size);
+        printf("Total amount writes reported by pnetcdf (include header) = %lld bytes\n", put_size);
+        printf("\n");
+        float subarray_size = (float)bufsize*sizeof(int)/1048576.0;
+        print_info(&info_used);
+        printf("Local array size %d x %d x %d integers, size = %.2f MB\n",len,len,len,subarray_size);
+        sum_write_size /= 1048576.0;
+        printf("Global array size %d x %d x %d integers, write size = %.2f GB\n",
+               gsizes[0], gsizes[1], gsizes[2], sum_write_size/1024.0);
+
+        write_bw = sum_write_size/max_write_timing;
+        printf(" procs    Global array size  exec(sec)  write(MB/s)\n");
+        printf("-------  ------------------  ---------  -----------\n");
+        printf(" %4d    %4d x %4d x %4d %8.2f  %10.2f\n", nprocs,
+               gsizes[0], gsizes[1], gsizes[2], max_write_timing, write_bw);
+    }
+    MPI_Info_free(&info_used);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/nonblocking_write_in_def.c b/examples/C/nonblocking_write_in_def.c
new file mode 100644
index 0000000..6c66101
--- /dev/null
+++ b/examples/C/nonblocking_write_in_def.c
@@ -0,0 +1,268 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id$ */
+
+/* This example is the same as nonblocking_write.c expect all nonblocking
+ * write requests (calls to iput and bput) are posted in define mode.
+ * It creates a netcdf file in CD-5 format and writes a number of
+ * 3D integer non-record variables. The measured write bandwidth is reported
+ * at the end. Usage: (for example)
+ * To compile:
+ *   mpicc -O2 nonblocking_write_in_def.c -o nonblocking_write_in_def -lpnetcdf
+ * To run:
+ *   mpiexec -n num_processes ./nonblocking_write_in_def [filename] [len]
+ * where len decides the size of each local array, which is len x len x len.
+ * So, each non-record variable is of size len*len*len * nprocs * sizeof(int)
+ * All variables are partitioned among all processes in a 3D
+ * block-block-block fashion. Below is an example standard output from
+ * command:
+ *   mpiexec -n 32 ./nonblocking_write_in_def /pvfs2/wkliao/testfile.nc 100
+ *
+ *    MPI hint: cb_nodes        = 2
+ *    MPI hint: cb_buffer_size  = 16777216
+ *    MPI hint: striping_factor = 32
+ *    MPI hint: striping_unit   = 1048576
+ *    Local array size 100 x 100 x 100 integers, size = 3.81 MB
+ *    Global array size 400 x 400 x 200 integers, write size = 0.30 GB
+ *     procs    Global array size  exec(sec)  write(MB/s)
+ *     -------  ------------------  ---------  -----------
+ *        32     400 x  400 x  200     6.67       45.72
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NDIMS    3
+#define NUM_VARS 10
+
+#define HANDLE_ERROR {                                \
+    if (err != NC_NOERR)                              \
+        printf("Error at line %d (%s)\n", __LINE__,   \
+               ncmpi_strerror(err));                  \
+}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name] [len]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    "       [len] size of each dimension of the local array\n";
+    fprintf(stderr, help, argv0);
+}
+
+/*----< print_info() >------------------------------------------------------*/
+static
+void print_info(MPI_Info *info_used)
+{
+    int     flag;
+    char    info_cb_nodes[64], info_cb_buffer_size[64];
+    char    info_striping_factor[64], info_striping_unit[64];
+
+    strcpy(info_cb_nodes,        "undefined");
+    strcpy(info_cb_buffer_size,  "undefined");
+    strcpy(info_striping_factor, "undefined");
+    strcpy(info_striping_unit,   "undefined");
+
+    MPI_Info_get(*info_used, "cb_nodes", 64, info_cb_nodes, &flag);
+    MPI_Info_get(*info_used, "cb_buffer_size", 64, info_cb_buffer_size, &flag);
+    MPI_Info_get(*info_used, "striping_factor", 64, info_striping_factor, &flag);
+    MPI_Info_get(*info_used, "striping_unit", 64, info_striping_unit, &flag);
+
+    printf("MPI hint: cb_nodes        = %s\n", info_cb_nodes);
+    printf("MPI hint: cb_buffer_size  = %s\n", info_cb_buffer_size);
+    printf("MPI hint: striping_factor = %s\n", info_striping_factor);
+    printf("MPI hint: striping_unit   = %s\n", info_striping_unit);
+}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    extern int optind;
+    int i, j, verbose=1, err;
+    int nprocs, len, *buf[NUM_VARS], bufsize, rank;
+    int gsizes[NDIMS], psizes[NDIMS];
+    double write_timing, max_write_timing, write_bw;
+    char *filename="testfile.nc", str[512];
+    int ncid, dimids[NDIMS], varids[NUM_VARS];
+    MPI_Offset start[NDIMS], count[NDIMS], write_size, sum_write_size;
+    MPI_Offset bbufsize;
+    MPI_Info info_used;
+    MPI_Comm comm=MPI_COMM_WORLD;
+
+    MPI_Init(&argc,&argv);
+    MPI_Comm_rank(comm, &rank);
+    MPI_Comm_size(comm, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc >= 1) filename = argv[0];  /* optional argument */
+    len = 10; 
+    if (argc >= 2) len = atoi(argv[1]); /* optional argument */
+
+    for (i=0; i<NDIMS; i++) psizes[i] = 0;
+
+    MPI_Dims_create(nprocs, NDIMS, psizes);
+    start[0] = rank % psizes[0];
+    start[1] = (rank / psizes[1]) % psizes[1];
+    start[2] = (rank / (psizes[0] * psizes[1])) % psizes[2];
+
+    bufsize = 1;
+    for (i=0; i<NDIMS; i++) {
+        gsizes[i] = len * psizes[i];
+        start[i] *= len;
+        count[i]  = len;
+        bufsize  *= len;
+    }
+
+    /* allocate buffer and initialize with random numbers */
+    srand(rank);
+    for (i=0; i<NUM_VARS; i++) {
+        buf[i] = (int *) malloc(bufsize * sizeof(int));
+        for (j=0; j<bufsize; j++) buf[i][j] = rand();
+    }
+
+    MPI_Barrier(comm);
+    write_timing = MPI_Wtime();
+
+    /* create the file */
+    err = ncmpi_create(comm, filename, NC_CLOBBER|NC_64BIT_DATA, MPI_INFO_NULL,
+                       &ncid);
+    if (err != NC_NOERR) {
+        printf("Error: ncmpi_create() file %s (%s)\n",filename,ncmpi_strerror(err));
+        MPI_Abort(comm, -1);
+        exit(1);
+    }
+
+    /* define dimensions */
+    for (i=0; i<NDIMS; i++) {
+        sprintf(str, "%c", 'x'+i);
+        err = ncmpi_def_dim(ncid, str, gsizes[i], &dimids[i]);
+        HANDLE_ERROR
+    }
+
+    /* define variables */
+    for (i=0; i<NUM_VARS; i++) {
+        sprintf(str, "var%d", i);
+        err = ncmpi_def_var(ncid, str, NC_INT, NDIMS, dimids, &varids[i]);
+        HANDLE_ERROR
+    }
+
+    /* post a nonblocking request for writing one variable at a time using
+     * iput and ignore the request ID, as we will flush all pending request
+     * in one ncmpi_wait_all() call */
+    for (i=0; i<NUM_VARS; i++) {
+        err = ncmpi_iput_vara_int(ncid, varids[i], start, count, buf[i], NULL);
+        HANDLE_ERROR
+    }
+
+    /* write one variable at a time using bput */
+
+    /* bbufsize must be max of data type converted before and after */
+    bbufsize = bufsize * NUM_VARS * sizeof(int);
+    err = ncmpi_buffer_attach(ncid, bbufsize);
+    HANDLE_ERROR
+
+    /* post a nonblocking request for writing one variable at a time using
+     * bput and ignore the request ID, as we will flush all pending request
+     * in one ncmpi_wait_all() call */
+    for (i=0; i<NUM_VARS; i++) {
+        err = ncmpi_bput_vara_int(ncid, varids[i], start, count, buf[i], NULL);
+        HANDLE_ERROR
+        /* can safely change contents or free up the buf[i] here */
+    }
+
+    /* exit the define mode */
+    err = ncmpi_enddef(ncid);
+    HANDLE_ERROR
+
+    /* wait for all the nonblocking I/O to complete */
+    err = ncmpi_wait_all(ncid, NC_REQ_ALL, NULL, NULL);
+    HANDLE_ERROR
+
+    /* detach the temporary buffer */
+    err = ncmpi_buffer_detach(ncid);
+    HANDLE_ERROR
+
+    /* get all the hints used */
+    err = ncmpi_inq_file_info(ncid, &info_used);
+    HANDLE_ERROR
+
+    MPI_Offset put_size;
+    ncmpi_inq_put_size(ncid, &put_size);
+#ifdef MPI_OFFSET
+    MPI_Allreduce(MPI_IN_PLACE, &put_size, 1, MPI_OFFSET, MPI_SUM, comm);
+#else
+    MPI_Allreduce(MPI_IN_PLACE, &put_size, 1, MPI_LONG_LONG, MPI_SUM, comm);
+#endif
+
+    /* close the file */
+    err = ncmpi_close(ncid);
+    HANDLE_ERROR
+
+    write_timing = MPI_Wtime() - write_timing;
+
+    write_size = bufsize * NUM_VARS * sizeof(int);
+    for (i=0; i<NUM_VARS; i++) free(buf[i]);
+
+#ifdef MPI_OFFSET
+    MPI_Reduce(&write_size, &sum_write_size, 1, MPI_OFFSET, MPI_SUM, 0, comm);
+#else
+    MPI_Reduce(&write_size, &sum_write_size, 1, MPI_LONG_LONG, MPI_SUM, 0, comm);
+#endif
+    MPI_Reduce(&write_timing, &max_write_timing, 1, MPI_DOUBLE, MPI_MAX, 0, comm);
+
+    if (rank == 0 && verbose) {
+        printf("\n");
+        printf("Total amount writes to variables only   (exclude header) = %lld bytes\n", sum_write_size);
+        printf("Total amount writes reported by pnetcdf (include header) = %lld bytes\n", put_size);
+        printf("\n");
+        float subarray_size = (float)bufsize*sizeof(int)/1048576.0;
+        print_info(&info_used);
+        printf("Local array size %d x %d x %d integers, size = %.2f MB\n",len,len,len,subarray_size);
+        sum_write_size /= 1048576.0;
+        printf("Global array size %d x %d x %d integers, write size = %.2f GB\n",
+               gsizes[0], gsizes[1], gsizes[2], sum_write_size/1024.0);
+
+        write_bw = sum_write_size/max_write_timing;
+        printf(" procs    Global array size  exec(sec)  write(MB/s)\n");
+        printf("-------  ------------------  ---------  -----------\n");
+        printf(" %4d    %4d x %4d x %4d %8.2f  %10.2f\n", nprocs,
+               gsizes[0], gsizes[1], gsizes[2], max_write_timing, write_bw);
+    }
+    MPI_Info_free(&info_used);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, comm);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/put_vara.c b/examples/C/put_vara.c
new file mode 100644
index 0000000..baed78f
--- /dev/null
+++ b/examples/C/put_vara.c
@@ -0,0 +1,194 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: put_vara.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use ncmpi_put_vara_int_all() to write a 2D
+ * 4-byte integer array in parallel. It first defines a netCDF variable of
+ * size global_nx * global_ny where
+ *    global_ny == NY and
+ *    global_nx == (NX * number of MPI processes).
+ * The data partitioning pattern is a column-wise partitioning across all
+ * processes. Each process writes a subarray of size ny * nx.
+ *
+ *    To compile:
+ *        mpicc -O2 put_vara.c -o put_vara -lpnetcdf
+ *
+ * Example commands for MPI run and outputs from running ncmpidump on the
+ * NC file produced by this example program:
+ *
+ *    % mpiexec -n 4 ./put_vara /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            y = 10 ;
+ *            x = 16 ;
+ *    variables:
+ *            int var(y, x) ;
+ *                var:str_att_name = "example attribute of type text." ;
+ *                var:float_att_name = 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f ;
+ *                var:int64_att_name = 10000000000L ;
+ *    // global attributes:
+ *                :history = "Wed Apr 30 11:18:58 2014\n",
+ *       "" ;
+ *    data:
+ *
+ *     var =
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <time.h>   /* time() localtime(), asctime() */
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NY 10
+#define NX 4
+
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[256];
+    int i, j, rank, nprocs, verbose=1, err;
+    int ncid, cmode, varid, dimid[2], buf[NY][NX];
+    char str_att[128];
+    float float_att[100];
+    MPI_Offset  global_ny, global_nx;
+    MPI_Offset start[2], count[2];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else strcpy(filename, "testfile.nc");
+
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (verbose && rank == 0) printf("%s: example of using put_vara APIs\n",__FILE__);
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* the global array is NY * (NX * nprocs) */
+    global_ny = NY;
+    global_nx = NX * nprocs;
+
+    for (i=0; i<NY; i++)
+        for (j=0; j<NX; j++)
+             buf[i][j] = rank;
+
+    /* add a global attribute: a time stamp at rank 0 */
+    time_t ltime = time(NULL); /* get the current calendar time */
+    asctime_r(localtime(&ltime), str_att);
+
+    /* make sure the time string are consistent among all processes */
+    MPI_Bcast(str_att, strlen(str_att), MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    err = ncmpi_put_att_text(ncid, NC_GLOBAL, "history", strlen(str_att),
+                             &str_att[0]);
+    ERR
+
+    /* define dimensions x and y */
+    err = ncmpi_def_dim(ncid, "Y", global_ny, &dimid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "X", global_nx, &dimid[1]);
+    ERR
+
+    /* define a 2D variable of integer type */
+    err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimid, &varid);
+    ERR
+
+    /* add attributes to the variable */
+    strcpy(str_att, "example attribute of type text.");
+    err = ncmpi_put_att_text(ncid, varid, "str_att_name", strlen(str_att),
+                             &str_att[0]);
+    ERR
+
+    for (i=0; i<8; i++) float_att[i] = i;
+    err = ncmpi_put_att_float(ncid, varid, "float_att_name", NC_FLOAT, 8,
+                              &float_att[0]);
+    ERR
+    long long int64_att=10000000000LL;
+    err = ncmpi_put_att_longlong(ncid, varid, "int64_att_name", NC_INT64, 1,
+                              &int64_att);
+    ERR
+
+    /* do not forget to exit define mode */
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* now we are in data mode */
+    start[0] = 0;
+    start[1] = NX * rank;
+    count[0] = NY;
+    count[1] = NX;
+
+    err = ncmpi_put_vara_int_all(ncid, varid, start, count, &buf[0][0]);
+    ERR
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/put_varn_float.c b/examples/C/put_varn_float.c
new file mode 100644
index 0000000..d269373
--- /dev/null
+++ b/examples/C/put_varn_float.c
@@ -0,0 +1,218 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: put_varn_float.c 1669 2014-05-24 18:28:16Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use a single call of ncmpi_put_varn_float_all()
+ * to write a sequence of one-element requests with arbitrary array indices.
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o put_varn_float put_varn_float.c -lpnetcdf
+ *    % mpiexec -n 4 ./put_varn_float /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             Y = 4 ;
+ *             X = 10 ;
+ *    variables:
+ *             int var(Y, X) ;
+ *    data:
+ *
+ *     var =
+ *       3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+ *       0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+ *       1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+ *       0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char *filename="testfile.nc";
+    int i, rank, nprocs, verbose=1, err;
+    int ncid, cmode, varid, dimid[2], num_reqs;
+    float *buffer;
+    MPI_Offset **starts;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    if (nprocs != 4 && rank == 0 && verbose)
+        printf("Warning: this program is intended to run on 4 processes\n");
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]);
+    ERR
+    err = ncmpi_def_var(ncid, "var", NC_FLOAT, NDIMS, dimid, &varid);
+    ERR
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* pick arbitrary numbers of requests for 4 processes */
+    num_reqs = 0;
+    if (rank == 0)      num_reqs = 8;
+    else if (rank == 1) num_reqs = 13;
+    else if (rank == 2) num_reqs = 9;
+    else if (rank == 3) num_reqs = 10;
+
+    starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+    starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+    for (i=1; i<num_reqs; i++)
+        starts[i] = starts[i-1] + NDIMS;
+
+    /* assign arbitrary starts */
+    const int y=0, x=1;
+    if (rank == 0) {
+        starts[0][y] = 0; starts[0][x] = 5;
+        starts[1][y] = 1; starts[1][x] = 0;
+        starts[2][y] = 2; starts[2][x] = 6;
+        starts[3][y] = 3; starts[3][x] = 0;
+        starts[4][y] = 0; starts[4][x] = 6;
+        starts[5][y] = 2; starts[5][x] = 7;
+        starts[6][y] = 3; starts[6][x] = 1;
+        starts[7][y] = 3; starts[7][x] = 2;
+        /* rank 0 is writing the following locations: ("-" means skip)
+                  -  -  -  -  -  0  0  -  -  - 
+                  0  -  -  -  -  -  -  -  -  - 
+                  -  -  -  -  -  -  0  0  -  - 
+                  0  0  0  -  -  -  -  -  -  - 
+         */
+    } else if (rank ==1) {
+        starts[ 0][y] = 0; starts[ 0][x] = 3;
+        starts[ 1][y] = 0; starts[ 1][x] = 8;
+        starts[ 2][y] = 1; starts[ 2][x] = 5;
+        starts[ 3][y] = 2; starts[ 3][x] = 0;
+        starts[ 4][y] = 2; starts[ 4][x] = 8;
+        starts[ 5][y] = 3; starts[ 5][x] = 4;
+        starts[ 6][y] = 0; starts[ 6][x] = 4;
+        starts[ 7][y] = 0; starts[ 7][x] = 9;
+        starts[ 8][y] = 1; starts[ 8][x] = 6;
+        starts[ 9][y] = 2; starts[ 9][x] = 1;
+        starts[10][y] = 2; starts[10][x] = 9;
+        starts[11][y] = 3; starts[11][x] = 5;
+        starts[12][y] = 3; starts[12][x] = 6;
+        /* rank 1 is writing the following locations: ("-" means skip)
+                  -  -  -  1  1  -  -  -  1  1 
+                  -  -  -  -  -  1  1  -  -  - 
+                  1  1  -  -  -  -  -  -  1  1 
+                  -  -  -  -  1  1  1  -  -  - 
+         */
+    } else if (rank ==2) {
+        starts[0][y] = 0; starts[0][x] = 7;
+        starts[1][y] = 1; starts[1][x] = 1;
+        starts[2][y] = 1; starts[2][x] = 7;
+        starts[3][y] = 2; starts[3][x] = 2; 
+        starts[4][y] = 3; starts[4][x] = 3;
+        starts[5][y] = 1; starts[5][x] = 2;
+        starts[6][y] = 1; starts[6][x] = 8;
+        starts[7][y] = 1; starts[7][x] = 3;
+        starts[8][y] = 1; starts[8][x] = 9;
+        /* rank 2 is writing the following locations: ("-" means skip)
+                  -  -  -  -  -  -  -  2  -  - 
+                  -  2  2  2  -  -  -  2  2  2 
+                  -  -  2  -  -  -  -  -  -  - 
+                  -  -  -  2  -  -  -  -  -  - 
+         */
+    } else if (rank ==3) {
+        starts[0][y] = 0; starts[0][x] = 0;
+        starts[1][y] = 1; starts[1][x] = 4;
+        starts[2][y] = 2; starts[2][x] = 3;
+        starts[3][y] = 3; starts[3][x] = 7;
+        starts[4][y] = 0; starts[4][x] = 1;
+        starts[5][y] = 2; starts[5][x] = 4;
+        starts[6][y] = 3; starts[6][x] = 8;
+        starts[7][y] = 0; starts[7][x] = 2;
+        starts[8][y] = 2; starts[8][x] = 5;
+        starts[9][y] = 3; starts[9][x] = 9;
+        /* rank 3 is writing the following locations: ("-" means skip)
+                  3  3  3  -  -  -  -  -  -  - 
+                  -  -  -  -  3  -  -  -  -  - 
+                  -  -  -  3  3  3  -  -  -  - 
+                  -  -  -  -  -  -  -  3  3  3 
+         */
+    }
+
+    /* allocate I/O buffer and initialize its contents */
+    buffer = (float*) malloc(num_reqs * sizeof(float));
+    for (i=0; i<num_reqs; i++) buffer[i] =  (float)rank;
+
+    /* set the buffer pointers to different offsets to the I/O buffer */
+    err = ncmpi_put_varn_float_all(ncid, varid, num_reqs, starts, NULL, buffer);
+    ERR
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    free(buffer);
+    free(starts[0]);
+    free(starts);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/put_varn_int.c b/examples/C/put_varn_int.c
new file mode 100644
index 0000000..1159a11
--- /dev/null
+++ b/examples/C/put_varn_int.c
@@ -0,0 +1,219 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: put_varn_int.c 1669 2014-05-24 18:28:16Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use a single call of ncmpi_put_varn_int_all() to
+ * write a sequence of requests with arbitrary array indices and lengths.
+ * Using ncmpi_put_varn_int_all() can achieve the same effect of HDF5 writing
+ * a sequence of selected file locations through the following 2 APIs.
+ *
+ *   H5Sselect_elements(fid, H5S_SELECT_SET, NUMP, (const hssize_t **)coord);
+ *   H5Dwrite(dataset, H5T_NATIVE_INT, mid, fid, H5P_DEFAULT, val); 
+ *
+ * Note that in ncmpi_put_varn_int_all(), users can write more than one
+ * element starting at each selected location.
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o put_varn_int put_varn_int.c -lpnetcdf
+ *    % mpiexec -n 4 ./put_varn_int /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             Y = 4 ;
+ *             X = 10 ;
+ *    variables:
+ *             int var(Y, X) ;
+ *    data:
+ *
+ *     var =
+ *       3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+ *       0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+ *       1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+ *       0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char *filename="testfile.nc";
+    int i, j, rank, nprocs, verbose=1, err;
+    int ncid, cmode, varid, dimid[2], num_reqs, *buffer;
+    MPI_Offset w_len, **starts, **counts;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    if (nprocs != 4 && rank == 0 && verbose)
+        printf("Warning: this program is intended to run on 4 processes\n");
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]);
+    ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT, NDIMS, dimid, &varid);
+    ERR
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* pick arbitrary numbers of requests for 4 processes */
+    num_reqs = 0;
+    if (rank == 0)      num_reqs = 4;
+    else if (rank == 1) num_reqs = 6;
+    else if (rank == 2) num_reqs = 5;
+    else if (rank == 3) num_reqs = 4;
+
+    starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+    counts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+    starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+    counts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+    for (i=1; i<num_reqs; i++) {
+        starts[i] = starts[i-1] + NDIMS;
+        counts[i] = counts[i-1] + NDIMS;
+    }
+
+    /* assign arbitrary starts and counts */
+    const int y=0, x=1;
+    if (rank == 0) {
+        starts[0][y] = 0; starts[0][x] = 5; counts[0][y] = 1; counts[0][x] = 2;
+        starts[1][y] = 1; starts[1][x] = 0; counts[1][y] = 1; counts[1][x] = 1;
+        starts[2][y] = 2; starts[2][x] = 6; counts[2][y] = 1; counts[2][x] = 2;
+        starts[3][y] = 3; starts[3][x] = 0; counts[3][y] = 1; counts[3][x] = 3;
+        /* rank 0 is writing the followings: ("-" means skip)
+                  -  -  -  -  -  0  0  -  -  - 
+                  0  -  -  -  -  -  -  -  -  - 
+                  -  -  -  -  -  -  0  0  -  - 
+                  0  0  0  -  -  -  -  -  -  - 
+         */
+    } else if (rank ==1) {
+        starts[0][y] = 0; starts[0][x] = 3; counts[0][y] = 1; counts[0][x] = 2;
+        starts[1][y] = 0; starts[1][x] = 8; counts[1][y] = 1; counts[1][x] = 2;
+        starts[2][y] = 1; starts[2][x] = 5; counts[2][y] = 1; counts[2][x] = 2;
+        starts[3][y] = 2; starts[3][x] = 0; counts[3][y] = 1; counts[3][x] = 2;
+        starts[4][y] = 2; starts[4][x] = 8; counts[4][y] = 1; counts[4][x] = 2;
+        starts[5][y] = 3; starts[5][x] = 4; counts[5][y] = 1; counts[5][x] = 3;
+        /* rank 1 is writing the followings: ("-" means skip)
+                  -  -  -  1  1  -  -  -  1  1 
+                  -  -  -  -  -  1  1  -  -  - 
+                  1  1  -  -  -  -  -  -  1  1 
+                  -  -  -  -  1  1  1  -  -  - 
+         */
+    } else if (rank ==2) {
+        starts[0][y] = 0; starts[0][x] = 7; counts[0][y] = 1; counts[0][x] = 1;
+        starts[1][y] = 1; starts[1][x] = 1; counts[1][y] = 1; counts[1][x] = 3;
+        starts[2][y] = 1; starts[2][x] = 7; counts[2][y] = 1; counts[2][x] = 3;
+        starts[3][y] = 2; starts[3][x] = 2; counts[3][y] = 1; counts[3][x] = 1;
+        starts[4][y] = 3; starts[4][x] = 3; counts[4][y] = 1; counts[4][x] = 1;
+        /* rank 2 is writing the followings: ("-" means skip)
+                  -  -  -  -  -  -  -  2  -  - 
+                  -  2  2  2  -  -  -  2  2  2 
+                  -  -  2  -  -  -  -  -  -  - 
+                  -  -  -  2  -  -  -  -  -  - 
+         */
+    } else if (rank ==3) {
+        starts[0][y] = 0; starts[0][x] = 0; counts[0][y] = 1; counts[0][x] = 3;
+        starts[1][y] = 1; starts[1][x] = 4; counts[1][y] = 1; counts[1][x] = 1;
+        starts[2][y] = 2; starts[2][x] = 3; counts[2][y] = 1; counts[2][x] = 3;
+        starts[3][y] = 3; starts[3][x] = 7; counts[3][y] = 1; counts[3][x] = 3;
+        /* rank 3 is writing the followings: ("-" means skip)
+                  3  3  3  -  -  -  -  -  -  - 
+                  -  -  -  -  3  -  -  -  -  - 
+                  -  -  -  3  3  3  -  -  -  - 
+                  -  -  -  -  -  -  -  3  3  3 
+         */
+    }
+
+    w_len = 0; /* total write length for this process */
+    for (i=0; i<num_reqs; i++) {
+        MPI_Offset w_req_len=1;
+        for (j=0; j<NDIMS; j++)
+            w_req_len *= counts[i][j];
+        w_len += w_req_len;
+    }
+
+    /* allocate I/O buffer and initialize its contents */
+    buffer = (int*) malloc(w_len * sizeof(int));
+    for (i=0; i<w_len; i++) buffer[i] = rank;
+
+    /* set the buffer pointers to different offsets to the I/O buffer */
+    err = ncmpi_put_varn_int_all(ncid, varid, num_reqs, starts,
+                                 counts, buffer);
+    ERR
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    free(buffer);
+    free(starts[0]);
+    free(counts[0]);
+    free(starts);
+    free(counts);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/req_all.c b/examples/C/req_all.c
new file mode 100644
index 0000000..5704b0b
--- /dev/null
+++ b/examples/C/req_all.c
@@ -0,0 +1,185 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id$ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example is mostly the same as column_wise.c but shows how to use
+ * NC_REQ_ALL to commit all pending nonblocking I/O without checking the status
+ * of individual requests. In this case, the first encountered error will be
+ * returned in ncmpi_wait_all().
+ * 
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o req_all req_all.c -lpnetcdf
+ *    % mpiexec -l -n 4 ./column_wise /pvfs2/wkliao/testfile.nc
+ *    0:  0: myOff=  0 myNX=  4
+ *    1:  1: myOff=  4 myNX=  4
+ *    2:  2: myOff=  8 myNX=  4
+ *    3:  3: myOff= 12 myNX=  4
+ *    0:  0: start=  0   0 count= 10   1
+ *    1:  1: start=  0   1 count= 10   1
+ *    2:  2: start=  0   2 count= 10   1
+ *    3:  3: start=  0   3 count= 10   1
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-1
+ *    dimensions:
+ *            Y = 10 ;
+ *            X = 16 ;
+ *    variables:
+ *            int var(Y, X) ;
+ *    data:
+ *
+ *     var =
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NY 10
+#define NX 4
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char *filename = "testfile.nc";
+    int i, j, verbose=1, rank, nprocs, err, myNX, G_NX, myOff;
+    int ncid, cmode, varid, dimid[2], **buf;
+    MPI_Offset start[2], count[2];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) filename = argv[0]; /* optional argument */
+
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* the global array is NY * (NX * nprocs) */
+    G_NX  = NX * nprocs;
+    myOff = NX * rank;
+    myNX  = NX;
+    if (verbose) printf("%2d: myOff=%3d myNX=%3d\n",rank,myOff,myNX);
+
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "X", G_NX, &dimid[1]);
+    ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimid, &varid);
+    ERR
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* initialize the buffer with rank ID */
+    buf = (int**) malloc(myNX * sizeof(int*));
+    for (i=0; i<myNX; i++) {
+        buf[i] = (int*) malloc(NY * sizeof(int));
+        for (j=0; j<NY; j++) buf[i][j] = rank;
+    }
+
+    /* each proc writes myNX single columns of the 2D array */
+    start[0]  = 0;   start[1] = rank;
+    count[0]  = NY;  count[1] = 1;
+    if (verbose)
+        printf("%2d: start=%3lld %3lld count=%3lld %3lld\n",
+               rank, start[0],start[1], count[0],count[1]);
+
+    for (i=0; i<myNX; i++) {
+        err = ncmpi_iput_vara_int(ncid, varid, start, count, buf[i], NULL);
+        ERR
+        start[1] += nprocs;
+    }
+    err = ncmpi_wait_all(ncid, NC_REQ_ALL, NULL, NULL);
+    ERR
+
+    /* read back using the same access pattern */
+    for (i=0; i<myNX; i++)
+        for (j=0; j<NY; j++) buf[i][j] = -1;
+
+    /* each proc reads myNX single columns of the 2D array */
+    start[0]  = 0;   start[1] = rank;
+    count[0]  = NY;  count[1] = 1;
+
+    for (i=0; i<myNX; i++) {
+        err = ncmpi_iget_vara_int(ncid, varid, start, count, buf[i], NULL);
+        ERR
+        start[1] += nprocs;
+    }
+    err = ncmpi_wait_all(ncid, NC_REQ_ALL, NULL, NULL);
+    ERR
+
+    /* check contents of read data of all requests */
+    for (i=0; i<myNX; i++) {
+        for (j=0; j<NY; j++)
+            if (buf[i][j] != rank)
+                printf("Error: expect buf[%d][%d]=%d but got %d\n",i,j,rank,buf[i][j]);
+    }
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    for (i=0; i<myNX; i++) free(buf[i]);
+    free(buf);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/transpose.c b/examples/C/transpose.c
new file mode 100644
index 0000000..6228ca0
--- /dev/null
+++ b/examples/C/transpose.c
@@ -0,0 +1,235 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: transpose.c 1744 2014-08-23 19:19:58Z wkliao $ */
+
+/*
+ *    This example shows how to use varm API to write six 3D integer array
+ *    variables into a file. Each variable in the file is a dimensional
+ *    transposed array from the one stored in memory. In memory, a 3D array is
+ *    partitioned among all processes in a block-block-block fashion and in
+ *    ZYX (i.e. C) order. The dimension structures of the transposed six
+ *    arrays are
+ *       int ZYX_var(Z, Y, X) ;     ZYX -> ZYX
+ *       int ZXY_var(Z, X, Y) ;     ZYX -> ZXY
+ *       int YZX_var(Y, Z, X) ;     ZYX -> YZX
+ *       int YXZ_var(Y, X, Z) ;     ZYX -> YXZ
+ *       int XZY_var(X, Z, Y) ;     ZYX -> XZY
+ *       int XYZ_var(X, Y, Z) ;     ZYX -> XYZ
+ *
+ *    To compile:
+ *        mpicc -O2 transpose.c -o transpose -lpnetcdf
+ *    To run:
+ *        mpiexec -n num_processes ./transpose [filename] [len]
+ *    where len decides the size of local array, which is len x len+1 x len+2.
+ *    So, each variable is of size len*(len+1)*(len+2) * nprocs * sizeof(int)
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strlen() */
+#include <unistd.h> /* getopt() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NDIMS 3
+
+#define HANDLE_ERROR {                                \
+    if (err != NC_NOERR)                              \
+        printf("Error at line %d (%s)\n", __LINE__,   \
+               ncmpi_strerror(err));                  \
+}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name] [len]\n"
+    "       [-h] Print this help\n"
+    "       [-q] quiet mode\n"
+    "       [filename] output netCDF file name\n"
+    "       [len] size of each dimension of the local array\n";
+    fprintf(stderr, help, argv0);
+}
+
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    extern int optind;
+    char *filename="testfile.nc", str[512];
+    int i, j, k, rank, nprocs, len, ncid, bufsize, verbose=1, err;
+    int *buf, psizes[NDIMS], dimids[NDIMS], dimidsT[NDIMS];
+    int XYZ_id, XZY_id, YZX_id, YXZ_id, ZYX_id, ZXY_id;
+    MPI_Offset gsizes[NDIMS], starts[NDIMS], counts[NDIMS], imap[NDIMS];
+    MPI_Offset startsT[NDIMS], countsT[NDIMS];
+
+    MPI_Init(&argc,&argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc >= 1) filename = argv[0];  /* optional argument */
+    len = 2;
+    if (argc >= 2) len = atoi(argv[1]); /* optional argument */
+
+    for (i=0; i<NDIMS; i++)
+        psizes[i] = 0;
+
+    /* calculate number of processes along each dimension */
+    MPI_Dims_create(nprocs, NDIMS, psizes);
+    if (verbose && rank == 0) {
+        sprintf(str, "psizes= ");
+        for (i=0; i<NDIMS; i++) sprintf(str+strlen(str), "%d ",psizes[i]);
+        printf("%s\n",str);
+    }
+
+    /* for each MPI rank, find its local rank IDs along each dimension in
+     * starts[] */
+    int lower_dims=1;
+    for (i=NDIMS-1; i>=0; i--) {
+        starts[i] = rank / lower_dims % psizes[i];
+        lower_dims *= psizes[i];
+    }
+    if (verbose) {
+        sprintf(str, "proc %d: dim rank= ", rank);
+        for (i=0; i<NDIMS; i++) sprintf(str+strlen(str), "%lld ",starts[i]);
+        printf("%s\n",str);
+    }
+
+    bufsize = 1;
+    for (i=0; i<NDIMS; i++) {
+        gsizes[i]  = (len + i) * psizes[i]; /* global array size */
+        starts[i] *= (len + i);             /* start indices */
+        counts[i]  = (len + i);             /* array elements */
+        bufsize   *= (len + i);
+    }
+
+    /* allocate buffer and initialize with contiguous numbers */
+    buf = (int *) malloc(bufsize * sizeof(int));
+    for (k=0; k<counts[0]; k++)
+    for (j=0; j<counts[1]; j++)
+    for (i=0; i<counts[2]; i++)
+        buf[k*counts[1]*counts[2] +
+                      j*counts[2] + i] = (starts[0]+k)*gsizes[1]*gsizes[2]
+                                       + (starts[1]+j)*gsizes[2]
+                                       + (starts[2]+i);
+
+    /* create the file */
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER|NC_64BIT_DATA,
+                       MPI_INFO_NULL, &ncid);
+    if (err != NC_NOERR) {
+        printf("Error: ncmpi_create() file %s (%s)\n",filename,ncmpi_strerror(err));
+        MPI_Abort(MPI_COMM_WORLD, -1);
+        exit(1);
+    }
+
+    /* define dimensions */
+    for (i=0; i<NDIMS; i++) {
+        sprintf(str, "%c", 'Z'-i);
+        err = ncmpi_def_dim(ncid, str, gsizes[i], &dimids[i]);
+        HANDLE_ERROR
+    }
+
+    /* define variable with no transposed file layout: ZYX */
+    err = ncmpi_def_var(ncid, "ZYX_var", NC_INT, NDIMS, dimids, &ZYX_id);
+    HANDLE_ERROR
+
+    /* define variable with transposed file layout: ZYX -> ZXY */
+    dimidsT[0] = dimids[0]; dimidsT[1] = dimids[2]; dimidsT[2] = dimids[1];
+    err = ncmpi_def_var(ncid, "ZXY_var", NC_INT, NDIMS, dimidsT, &ZXY_id);
+    HANDLE_ERROR
+
+    /* define variable with transposed file layout: ZYX -> YZX */
+    dimidsT[0] = dimids[1]; dimidsT[1] = dimids[0]; dimidsT[2] = dimids[2];
+    err = ncmpi_def_var(ncid, "YZX_var", NC_INT, NDIMS, dimidsT, &YZX_id);
+    HANDLE_ERROR
+
+    /* define variable with transposed file layout: ZYX -> YXZ */
+    dimidsT[0] = dimids[1]; dimidsT[1] = dimids[2]; dimidsT[2] = dimids[0];
+    err = ncmpi_def_var(ncid, "YXZ_var", NC_INT, NDIMS, dimidsT, &YXZ_id);
+    HANDLE_ERROR
+
+    /* define variable with transposed file layout: ZYX -> XZY */
+    dimidsT[0] = dimids[2]; dimidsT[1] = dimids[0]; dimidsT[2] = dimids[1];
+    err = ncmpi_def_var(ncid, "XZY_var", NC_INT, NDIMS, dimidsT, &XZY_id);
+    HANDLE_ERROR
+
+    /* define variable with transposed file layout: ZYX -> XYZ */
+    dimidsT[0] = dimids[2]; dimidsT[1] = dimids[1]; dimidsT[2] = dimids[0];
+    err = ncmpi_def_var(ncid, "XYZ_var", NC_INT, NDIMS, dimidsT, &XYZ_id);
+    HANDLE_ERROR
+
+    /* exit the define mode */
+    err = ncmpi_enddef(ncid);
+    HANDLE_ERROR
+
+    /* write the whole variable in file: ZYX */
+    err = ncmpi_put_vara_int_all(ncid, ZYX_id, starts, counts, buf);
+    HANDLE_ERROR
+
+    /* ZYX -> ZXY: */
+    imap[1] = 1; imap[2] = counts[2]; imap[0] = counts[1]*counts[2];
+    startsT[0] = starts[0]; startsT[1] = starts[2]; startsT[2] = starts[1];
+    countsT[0] = counts[0]; countsT[1] = counts[2]; countsT[2] = counts[1];
+    /* write the transposed variable */
+    err = ncmpi_put_varm_int_all(ncid, ZXY_id, startsT, countsT, NULL, imap, buf);
+    HANDLE_ERROR
+
+    /* ZYX -> YZX: */
+    imap[2] = 1; imap[0] = counts[2]; imap[1] = counts[1]*counts[2];
+    startsT[0] = starts[1]; startsT[1] = starts[0]; startsT[2] = starts[2];
+    countsT[0] = counts[1]; countsT[1] = counts[0]; countsT[2] = counts[2];
+    /* write the transposed variable */
+    err = ncmpi_put_varm_int_all(ncid, YZX_id, startsT, countsT, NULL, imap, buf);
+    HANDLE_ERROR
+
+    /* ZYX -> YXZ: */
+    imap[1] = 1; imap[0] = counts[2]; imap[2] = counts[1]*counts[2];
+    startsT[0] = starts[1]; startsT[1] = starts[2]; startsT[2] = starts[0];
+    countsT[0] = counts[1]; countsT[1] = counts[2]; countsT[2] = counts[0];
+    /* write the transposed variable */
+    err = ncmpi_put_varm_int_all(ncid, YXZ_id, startsT, countsT, NULL, imap, buf);
+    HANDLE_ERROR
+
+    /* ZYX -> XZY: */
+    imap[0] = 1; imap[2] = counts[2]; imap[1] = counts[1]*counts[2];
+    startsT[0] = starts[2]; startsT[1] = starts[0]; startsT[2] = starts[1];
+    countsT[0] = counts[2]; countsT[1] = counts[0]; countsT[2] = counts[1];
+    /* write the transposed variable */
+    err = ncmpi_put_varm_int_all(ncid, XZY_id, startsT, countsT, NULL, imap, buf);
+    HANDLE_ERROR
+
+    /* ZYX -> XYZ: */
+    imap[0] = 1; imap[1] = counts[2]; imap[2] = counts[1]*counts[2];
+    startsT[0] = starts[2]; startsT[1] = starts[1]; startsT[2] = starts[0];
+    countsT[0] = counts[2]; countsT[1] = counts[1]; countsT[2] = counts[0];
+    /* write the transposed variable */
+    err = ncmpi_put_varm_int_all(ncid, XYZ_id, startsT, countsT, NULL, imap, buf);
+    HANDLE_ERROR
+
+    /* close the file */
+    err = ncmpi_close(ncid);
+    HANDLE_ERROR
+
+    free(buf);
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/C/vard_int.c b/examples/C/vard_int.c
new file mode 100644
index 0000000..486e58c
--- /dev/null
+++ b/examples/C/vard_int.c
@@ -0,0 +1,192 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: vard_int.c 2239 2015-12-18 18:21:09Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use the vard API ncmpi_put_vard() and
+ * ncmpi_get_vard() to write and read 2D record and fixed-size variables.
+ *
+ *    To compile:
+ *        mpicc -O2 vard_int.c -o vard_int -lpnetcdf
+ *
+ * Example commands for MPI run and outputs from running ncmpidump on the
+ * NC file produced by this example program:
+ *
+ *    % mpiexec -n 4 ./vard_int /pvfs2/wkliao/testfile.nc
+ *
+ * The expected results from the output file contents are:
+ *
+ *  % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-1
+ *    dimensions:
+ *           REC_DIM = UNLIMITED ; // (2 currently)
+ *           X = 12 ;
+ *           FIX_DIM = 2 ;
+ *    variables:
+ *           int rec_var(REC_DIM, X) ;
+ *           int fix_var(FIX_DIM, X) ;
+ *    data:
+ *
+ *     rec_var =
+ *       0, 1, 2, 100, 101, 102, 200, 201, 202, 300, 301, 302,
+ *       10, 11, 12, 110, 111, 112, 210, 211, 212, 310, 311, 312 ;
+ *
+ *     fix_var =
+ *       0, 1, 2, 100, 101, 102, 200, 201, 202, 300, 301, 302,
+ *       10, 11, 12, 110, 111, 112, 210, 211, 212, 310, 311, 312 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h> /* getopt() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define NY 2
+#define NX 3
+#define ERR if (err!=NC_NOERR) {printf("Error at line %d: %s\n", __LINE__,ncmpi_strerror(err));}
+
+static void
+usage(char *argv0)
+{
+    char *help =
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n";
+    fprintf(stderr, help, argv0);
+}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv) {
+
+    extern int optind;
+    char         filename[256];
+    int          i, j, err, ncid, verbose=1, varid0, varid1, dimids[2];
+    int          rank, nprocs, array_of_blocklengths[2], buf[NY][NX];
+    int          array_of_sizes[2], array_of_subsizes[2], array_of_starts[2];
+    MPI_Offset   start[2], count[2], recsize, bufcount, len;
+    MPI_Aint     array_of_displacements[2];
+    MPI_Datatype buftype, rec_filetype, fix_filetype;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else strcpy(filename, "testfile.nc");
+
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (verbose && rank == 0) printf("%s: example of using vard APIs\n",__FILE__);
+
+    start[0] = 0; start[1] = NX*rank;
+    count[0] = 2; count[1] = NX;
+
+    /* create a new file for write */
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, MPI_INFO_NULL,
+                       &ncid); ERR
+
+    /* define a 2D array */
+    err = ncmpi_def_dim(ncid, "REC_DIM", NC_UNLIMITED, &dimids[0]); ERR
+    err = ncmpi_def_dim(ncid, "X",       NX*nprocs,    &dimids[1]); ERR
+    err = ncmpi_def_var(ncid, "rec_var", NC_INT, 2, dimids, &varid0); ERR
+    err = ncmpi_def_dim(ncid, "FIX_DIM", 2, &dimids[0]); ERR
+    err = ncmpi_def_var(ncid, "fix_var", NC_INT, 2, dimids, &varid1); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* create a file type for the record variable */
+    err = ncmpi_inq_recsize(ncid, &recsize);
+    for (i=0; i<count[0]; i++) {
+        array_of_blocklengths[i] = count[1];
+        array_of_displacements[i] = start[1]*sizeof(int) + recsize * i;
+    }
+    MPI_Type_create_hindexed(2, array_of_blocklengths, array_of_displacements,
+                             MPI_INT, &rec_filetype);
+    MPI_Type_commit(&rec_filetype);
+
+    /* create a file type for the fixed-size variable */
+    array_of_sizes[0]    = 2;
+    array_of_sizes[1]    = NX*nprocs;
+    array_of_subsizes[0] = count[0];
+    array_of_subsizes[1] = count[1];
+    array_of_starts[0]   = start[0];
+    array_of_starts[1]   = start[1];
+    MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                             array_of_starts, MPI_ORDER_C,
+                             MPI_INT, &fix_filetype);
+    MPI_Type_commit(&fix_filetype);
+
+    buftype = MPI_INT;
+    bufcount = count[0] * count[1];
+
+    /* initialize the contents of the array */
+    for (j=0; j<NY; j++) for (i=0; i<NX; i++) buf[j][i] = rank*100 + j*10 + i;
+
+    /* write the record variable */
+    err = ncmpi_put_vard_all(ncid, varid0, rec_filetype, buf, bufcount,buftype);
+    ERR
+
+    /* check if the number of records changed to 2 */
+    err = ncmpi_inq_unlimdim(ncid, &dimids[0]); ERR
+    err = ncmpi_inq_dimlen(ncid, dimids[0], &len); ERR
+    if (len != 2)
+        printf("Error: number of records should be 2 but got %lld\n", len);
+
+    /* write the fixed-size variable */
+    err = ncmpi_put_vard_all(ncid, varid1, fix_filetype, buf, bufcount,buftype);
+    ERR
+
+    err = ncmpi_close(ncid); ERR
+
+    /* open the same file and read back for validate */
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL,
+                     &ncid); ERR
+
+    err = ncmpi_inq_varid(ncid, "rec_var", &varid0); ERR
+    err = ncmpi_inq_varid(ncid, "fix_var", &varid1); ERR
+
+    /* read back fixed-size variable */
+    err = ncmpi_get_vard_all(ncid, varid1, fix_filetype, buf, bufcount,buftype);
+    ERR
+
+    /* read back record variable */
+    err = ncmpi_get_vard_all(ncid, varid0, rec_filetype, buf, bufcount,buftype);
+    ERR
+
+    err = ncmpi_close(ncid); ERR
+    MPI_Type_free(&rec_filetype);
+    MPI_Type_free(&fix_filetype);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/examples/CXX/Makefile.in b/examples/CXX/Makefile.in
new file mode 100644
index 0000000..5f68a5d
--- /dev/null
+++ b/examples/CXX/Makefile.in
@@ -0,0 +1,130 @@
+#
+# Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2236 2015-12-18 03:49:41Z wkliao $
+#
+# @configure_input@
+
+srcdir  = @srcdir@
+VPATH   = @srcdir@
+
+include ../../macros.make
+
+# note the order of -L list matters
+INCLUDES  = -I../../src/lib -I../../src/libcxx
+LDFLAGS  := -L../../src/lib $(LDFLAGS)
+LIBS     := -lpnetcdf $(LIBS)
+
+C_SRCS  = collective_write.cpp \
+          nonblocking_write.cpp \
+          column_wise.cpp \
+          block_cyclic.cpp \
+          flexible_api.cpp \
+          get_info.cpp \
+          hints.cpp \
+          put_varn_float.cpp \
+          put_varn_int.cpp \
+          put_vara.cpp \
+          get_vara.cpp \
+          transpose.cpp \
+          vard_int.cpp \
+          fill_mode.cpp
+
+PROGS        = $(C_SRCS:.cpp=)
+OBJS         = $(C_SRCS:.cpp=.o)
+
+PAR_PROGS    = $(PROGS)
+
+GARBAGE      = $(PROGS) *.nc
+
+PACKING_LIST = $(C_SRCS) depend Makefile.in
+
+all: $(PROGS)
+
+install:
+
+uninstall:
+
+collective_write: collective_write.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+nonblocking_write: nonblocking_write.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+get_info: get_info.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+column_wise: column_wise.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+block_cyclic: block_cyclic.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+put_vara: put_vara.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+hints: hints.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+flexible_api: flexible_api.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+put_varn_int: put_varn_int.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+put_varn_float: put_varn_float.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+get_vara: get_vara.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+transpose: transpose.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+vard_int: vard_int.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+fill_mode: fill_mode.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+TEST_MPIRUN_8  = $(subst NP,8,$(TEST_MPIRUN))
+TEST_MPIRUN_3  = $(subst NP,3,$(TEST_MPIRUN))
+
+ptest4: $(PAR_PROGS)
+	@for i in $(PAR_PROGS); do ( \
+        $(TEST_MPIRUN_4) ./$$i -q $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS: C++ parallel run on 4 processes --------------- $$i"; \
+        else \
+           echo "FAILED: C++ parallel run on 4 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest8: $(PAR_PROGS)
+	@for i in $(PAR_PROGS) ; do ( \
+        $(TEST_MPIRUN_8) ./$$i -q $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS: C++ parallel run on 8 processes --------------- $$i"; \
+        else \
+           echo "FAILED: C++ parallel run on 8 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest3: $(PAR_PROGS)
+	@for i in $(PAR_PROGS) ; do ( \
+        $(TEST_MPIRUN_3) ./$$i -q $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS: C++ parallel run on 3 processes --------------- $$i"; \
+        else \
+           echo "FAILED: C++ parallel run on 3 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest: ptest4
+ptests: ptest3 ptest4 ptest8 
+ptest2 ptest6 ptest10:
+
+include $(srcdir)/depend
+include $(srcdir)/../../rules.make
+
+$(LIBRARY): ;
+
diff --git a/examples/CXX/block_cyclic.cpp b/examples/CXX/block_cyclic.cpp
new file mode 100644
index 0000000..be3dc56
--- /dev/null
+++ b/examples/CXX/block_cyclic.cpp
@@ -0,0 +1,301 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: block_cyclic.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example, generalized from column_wise.cpp, makes a number of nonblocking
+ * API calls, each writes a block of columns into a 2D integer array. In other
+ * words, the I/O pattern is a blocked cyclic along X dimension.
+ *
+ * Each process writes NX columns in total. The block length is controlled by
+ * block_len. In this example, block_len is set to 2. Blocks are layout in a
+ * cyclic fashion in the file. This example can test if PnetCDF can coalesce
+ * file offsets and lengths when constructing a merged filetype.
+ * 
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file. In this example, block_len = 2.
+ *
+ *    % mpicxx -O2 -o block_cyclic block_cyclic.cpp -lpnetcdf
+ *    % mpiexec -l -n 4 ./block_cyclic /pvfs2/wkliao/testfile.nc
+ *    0:  0: NY=10 myNX=  4 myOff=  0
+ *    1:  1: NY=10 myNX=  4 myOff=  4
+ *    2:  2: NY=10 myNX=  4 myOff=  8
+ *    3:  3: NY=10 myNX=  4 myOff= 12
+ *    0: [i=0] iput() start=  0   0 count= 10   1
+ *    0: [i=1] iput() start=  0   1 count= 10   1
+ *    0: [i=2] iput() start=  0   8 count= 10   1
+ *    0: [i=3] iput() start=  0   9 count= 10   1
+ *    1: [i=0] iput() start=  0   2 count= 10   1
+ *    1: [i=1] iput() start=  0   3 count= 10   1
+ *    1: [i=2] iput() start=  0  10 count= 10   1
+ *    1: [i=3] iput() start=  0  11 count= 10   1
+ *    2: [i=0] iput() start=  0   4 count= 10   1
+ *    2: [i=1] iput() start=  0   5 count= 10   1
+ *    2: [i=2] iput() start=  0  12 count= 10   1
+ *    2: [i=3] iput() start=  0  13 count= 10   1
+ *    3: [i=0] iput() start=  0   6 count= 10   1
+ *    3: [i=1] iput() start=  0   7 count= 10   1
+ *    3: [i=2] iput() start=  0  14 count= 10   1
+ *    3: [i=3] iput() start=  0  15 count= 10   1
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            Y = 10 ;
+ *            X = 16 ;
+ *    variables:
+ *            int var(Y, X) ;
+ *    data:
+ *
+ *     var =
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+ *      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+#define NY 10
+#define NX 4
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    << argv0;
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[128];
+    int i, j, verbose=1, rank, nprocs, num_reqs;
+    int *reqs, *sts, **buf;
+    MPI_Offset  myNX, G_NX, myOff, block_start, block_len;
+    vector<MPI_Offset> start(2), count(2);
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+
+    try {
+        /* create a new file for writing ------------------------------------*/
+        NcmpiFile nc(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                     NcmpiFile::classic5);
+
+        /* the global array is NY * (NX * nprocs) */
+        G_NX  = NX * nprocs;
+        myOff = NX * rank;
+        myNX  = NX;
+        if (verbose)
+            printf("%2d: NY=%d myNX=%3lld myOff=%3lld\n",rank,NY,myNX,myOff);
+
+        /* define dimensions x and y */
+        vector<NcmpiDim> dimid(2);
+
+        dimid[0] = nc.addDim("Y", NY);
+        dimid[1] = nc.addDim("X", G_NX);
+
+        /* define a 2D variable of integer type */
+        NcmpiVar var = nc.addVar("var", ncmpiInt, dimid);
+
+        /* First, fill the entire array with zeros, using a blocking I/O.
+           Every process writes a subarray of size NY * myNX */
+        buf    = (int**) malloc(myNX * sizeof(int*));
+        buf[0] = (int*)  calloc(NY * myNX, sizeof(int));
+        start[0] = 0;   start[1] = myOff;
+        count[0] = NY;  count[1] = myNX;
+
+        var.putVar_all(start, count, &buf[0][0]);
+
+        free(buf[0]);
+
+        /* initialize the buffer with rank ID. Also make the case interesting,
+           by allocating buffers separately */
+        for (i=0; i<myNX; i++) {
+            buf[i] = (int*) malloc(NY * sizeof(int));
+            for (j=0; j<NY; j++) buf[i][j] = rank+10;
+        }
+
+        reqs = (int*) malloc(myNX * sizeof(int));
+        sts  = (int*) malloc(myNX * sizeof(int));
+
+        /* each proc writes myNX columns of the 2D array, block_len controls the
+           the number of contiguous columns at a time */
+        block_start = 0;
+        block_len   = 2;  /* can be 1, 2, 3, ..., myNX */
+        if (block_len > myNX) block_len = myNX;
+
+        start[0] = 0;   start[1] = rank * block_len;
+        count[0] = NY;  count[1] = 1;
+        num_reqs = 0;
+        for (i=0; i<myNX; i++) {
+            var.iputVar(start, count, &buf[i][0], &reqs[num_reqs++]);
+
+            if (verbose)
+                printf("[i=%d] iput() start=%3lld %3lld count=%3lld %3lld\n",
+                       i, start[0],start[1], count[0],count[1]);
+
+            if (i % block_len == block_len-1)  {
+                int stride = MIN(myNX-1-i, block_len);
+                block_start += block_len * nprocs;
+                start[1] = block_start + stride * rank;
+            }
+            else
+                start[1]++;
+        }
+
+        nc.Wait_all(num_reqs, reqs, sts);
+
+        /* check status of all requests */
+        for (i=0; i<num_reqs; i++)
+            if (sts[i] != NC_NOERR)
+                printf("Error: nonblocking write fails on request %d (%s)\n",
+                       i, ncmpi_strerror(sts[i]));
+
+        free(sts);
+        free(reqs);
+        for (i=0; i<myNX; i++) free(buf[i]);
+        free(buf);
+
+        /* file is close implicitly */
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+       return 1;
+    }
+
+    try {
+        /* open an existing file created earlier for read -------------------*/
+        NcmpiFile nc(MPI_COMM_WORLD, filename, NcmpiFile::read);
+
+        /* the global array is NY * (NX * nprocs) */
+        NcmpiDim dimY = nc.getDim("Y");
+        if (dimY.isNull() || dimY.getSize() != NY || dimY.isUnlimited())
+            throw NcmpiException("read Error: dimension Y ",__FILE__,__LINE__);
+
+        NcmpiDim dimX = nc.getDim("X");
+        if (dimX.isNull() || dimX.getSize() != G_NX || dimX.isUnlimited())
+            throw NcmpiException("read Error: dimension X ",__FILE__,__LINE__);
+
+        myNX  = G_NX / nprocs;
+
+        NcmpiVar var = nc.getVar("var");
+
+        /* initialize the buffer with -1, so a read error can be pinpointed */
+        buf    = (int**) malloc(myNX * sizeof(int*));
+        buf[0] = (int*)  malloc(NY * myNX * sizeof(int));
+        for (i=0; i<myNX; i++) {
+            if (i > 0) buf[i] = buf[i-1] + NY;
+            for (j=0; j<NY; j++) buf[i][j] = -1;
+        }
+
+        reqs = (int*) malloc(myNX * sizeof(int));
+        sts  = (int*) malloc(myNX * sizeof(int));
+
+        /* each proc reads myNX columns of the 2D array, block_len controls the
+           the number of contiguous columns at a time */
+        block_start = 0;
+        block_len   = 2;  /* can be 1, 2, 3, ..., myNX */
+        if (block_len > myNX) block_len = myNX;
+
+        start[0] = 0;   start[1] = rank * block_len;
+        count[0] = NY;  count[1] = 1;
+        num_reqs = 0;
+        for (i=0; i<myNX; i++) {
+            var.igetVar(start, count, &buf[i][0], &reqs[num_reqs++]);
+
+            if (i % block_len == block_len-1)  {
+                int stride = MIN(myNX-1-i, block_len);
+                block_start += block_len * nprocs;
+                start[1] = block_start + stride * rank;
+            }
+            else
+                start[1]++;
+        }
+        nc.Wait_all(num_reqs, reqs, sts);
+
+        /* check status of all requests */
+        for (i=0; i<num_reqs; i++)
+            if (sts[i] != NC_NOERR)
+                printf("Error: nonblocking read fails on request %d (%s)\n",
+                       i, ncmpi_strerror(sts[i]));
+
+        /* check the read contents */
+        for (i=0; i<myNX; i++) {
+            for (j=0; j<NY; j++)
+                if (buf[i][j] != rank+10) {
+                    printf("Read contents mismatch at buf[%d][%d] = %d (should be %d)\n", i,j,buf[i][j],rank+10);
+                }
+        }
+
+        free(sts);
+        free(reqs);
+        free(buf[0]);
+        free(buf);
+
+        /* file is close implicitly */
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+    }
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/collective_write.cpp b/examples/CXX/collective_write.cpp
new file mode 100644
index 0000000..e2a7b9b
--- /dev/null
+++ b/examples/CXX/collective_write.cpp
@@ -0,0 +1,217 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: collective_write.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/*
+ *    This example mimics the coll_perf.c from ROMIO.
+ *    It creates a netcdf file in CD-5 format and writes a number of
+ *    3D integer non-record variables. The measured write bandwidth is reported
+ *    at the end. Usage:
+ *    To compile:
+ *        mpiccxx -O2 collective_write.cpp -o collective_write -lpnetcdf
+ *    To run:
+ *        mpiexec -n num_processes ./collective_write [filename] [len]
+ *    where len decides the size of each local array, which is len x len x len.
+ *    So, each non-record variable is of size len*len*len * nprocs * sizeof(int)
+ *    All variables are partitioned among all processes in a 3D
+ *    block-block-block fashion. Below is an example standard output from
+ *    command:
+ *        mpiexec -n 32 ./collective_write /pvfs2/wkliao/testfile.nc 100
+ *
+ *    MPI hint: cb_nodes        = 2
+ *    MPI hint: cb_buffer_size  = 16777216
+ *    MPI hint: striping_factor = 32
+ *    MPI hint: striping_unit   = 1048576
+ *    Local array size 100 x 100 x 100 integers, size = 3.81 MB
+ *    Global array size 400 x 400 x 200 integers, write size = 0.30 GB
+ *     procs    Global array size  exec(sec)  write(MB/s)
+ *     -------  ------------------  ---------  -----------
+ *        32     400 x  400 x  200     6.67       45.72
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+#define NDIMS    3
+#define NUM_VARS 10
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name] [len]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    "       [len] size of each dimension of the local array\n"
+    << argv0;
+}
+
+/*----< print_info() >------------------------------------------------------*/
+static
+void print_info(MPI_Info *info_used)
+{
+    int     flag;
+    char    info_cb_nodes[64], info_cb_buffer_size[64];
+    char    info_striping_factor[64], info_striping_unit[64];
+
+    strcpy(info_cb_nodes,        "undefined");
+    strcpy(info_cb_buffer_size,  "undefined");
+    strcpy(info_striping_factor, "undefined");
+    strcpy(info_striping_unit,   "undefined");
+
+    MPI_Info_get(*info_used, (char*)"cb_nodes", 64, info_cb_nodes, &flag);
+    MPI_Info_get(*info_used, (char*)"cb_buffer_size", 64, &info_cb_buffer_size[0], &flag);
+    MPI_Info_get(*info_used, (char*)"striping_factor", 64, &info_striping_factor[0], &flag);
+    MPI_Info_get(*info_used, (char*)"striping_unit", 64, info_striping_unit, &flag);
+
+    printf("MPI hint: cb_nodes        = %s\n", info_cb_nodes);
+    printf("MPI hint: cb_buffer_size  = %s\n", info_cb_buffer_size);
+    printf("MPI hint: striping_factor = %s\n", info_striping_factor);
+    printf("MPI hint: striping_unit   = %s\n", info_striping_unit);
+}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    extern int optind;
+    char filename[128], str[512];
+    int i, j, rank, nprocs, len, bufsize, verbose=1;
+    int *buf[NUM_VARS], psizes[NDIMS];
+    double write_timing, max_write_timing, write_bw;
+    vector<MPI_Offset> starts(NDIMS), counts(NDIMS);
+    MPI_Offset gsizes[NDIMS];
+    MPI_Offset write_size, sum_write_size;
+    MPI_Info info_used;
+
+    MPI_Init(&argc,&argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc >= 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+    len = 10; 
+    if (argc >= 2) len = atoi(argv[1]); /* optional argument */
+
+    for (i=0; i<NDIMS; i++)
+        psizes[i] = 0;
+
+    MPI_Dims_create(nprocs, NDIMS, psizes);
+    starts[0] = rank % psizes[0];
+    starts[1] = (rank / psizes[1]) % psizes[1];
+    starts[2] = (rank / (psizes[0] * psizes[1])) % psizes[2];
+
+    bufsize = 1;
+    for (i=0; i<NDIMS; i++) {
+        gsizes[i] = len * psizes[i];
+        starts[i] *= len;
+        counts[i]  = len;
+        bufsize   *= len;
+    }
+
+    /* allocate buffer and initialize with random numbers */
+    srand(rank);
+    for (i=0; i<NUM_VARS; i++) {
+        buf[i] = (int *) malloc(bufsize * sizeof(int));
+        for (j=0; j<bufsize; j++) buf[i][j] = rand();
+    }
+
+    MPI_Barrier(MPI_COMM_WORLD);
+    write_timing = MPI_Wtime();
+
+    try {
+        /* create the file */
+        NcmpiFile nc(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                     NcmpiFile::classic5);
+
+        /* define dimensions */
+        vector<NcmpiDim> dimids(NDIMS);
+        for (i=0; i<NDIMS; i++) {
+            sprintf(str, "%c", 'x'+i);
+            dimids[i] = nc.addDim(str, gsizes[i]);
+        }
+
+        /* define variables */
+        vector<NcmpiVar> vars(NUM_VARS);
+        for (i=0; i<NUM_VARS; i++) {
+            sprintf(str, "var%d", i);
+            vars[i] = nc.addVar(str, ncmpiInt, dimids);
+        }
+
+        /* get all the hints used */
+        nc.Inq_file_info(&info_used);
+
+        /* write one variable at a time */
+        for (i=0; i<NUM_VARS; i++)
+            vars[i].putVar_all(starts, counts, &buf[i][0]);
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+       return 1;
+    }
+
+    write_timing = MPI_Wtime() - write_timing;
+
+    write_size = bufsize * NUM_VARS * sizeof(int);
+    for (i=0; i<NUM_VARS; i++) free(buf[i]);
+
+    MPI_Reduce(&write_size, &sum_write_size, 1, MPI_LONG_LONG, MPI_SUM, 0, MPI_COMM_WORLD);
+    MPI_Reduce(&write_timing, &max_write_timing, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
+
+    if (rank == 0 && verbose) {
+        double write_amount = sum_write_size;
+        float subarray_size = (float)bufsize*sizeof(int)/1048576.0;
+        print_info(&info_used);
+        printf("Local array size %d x %d x %d integers, size = %.2f MB\n",len,len,len,subarray_size);
+        write_amount /= 1048576.0;
+        printf("Global array size %lld x %lld x %lld integers, write size = %.2f GB\n",
+               gsizes[0], gsizes[1], gsizes[2], write_amount/1024.0);
+
+        write_bw = write_amount/max_write_timing;
+        printf(" procs    Global array size  exec(sec)  write(MB/s)\n");
+        printf("-------  ------------------  ---------  -----------\n");
+        printf(" %4d    %4lld x %4lld x %4lld %8.2f  %10.2f\n", nprocs,
+               gsizes[0], gsizes[1], gsizes[2], max_write_timing, write_bw);
+    }
+    MPI_Info_free(&info_used);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/column_wise.cpp b/examples/CXX/column_wise.cpp
new file mode 100644
index 0000000..f0a05f5
--- /dev/null
+++ b/examples/CXX/column_wise.cpp
@@ -0,0 +1,200 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: column_wise.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example makes a number of nonblocking API calls, each writes a single
+ * column of a 2D integer array. Each process writes NX columns and any two
+ * consecutive columns are of nprocs columns distance apart from each other.
+ * In this case, the fileview of each process interleaves with all other
+ * processes.
+ * If simply concatenating fileviews of all the nonblocking calls will result
+ * in a fileview that violates the MPI-IO requirement on the fileview of which
+ * flattened file offsets must be monotonically non-decreasing. PnetCDF handles
+ * this case by breaking down each nonblocking call into a list of offset-length
+ * pairs, merging the pairs across multiple nonblocking calls, and sorting
+ * them into an increasing order. The sorted pairs are used to construct a
+ * fileview that meets the monotonically non-decreasing offset requirement,
+ * and thus the nonblocking requests can be serviced by a single MPI-IO call. 
+ * 
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicxx -O2 -o column_wise column_wise.cpp -lpnetcdf
+ *    % mpiexec -l -n 4 ./column_wise /pvfs2/wkliao/testfile.nc
+ *    0:  0: myOff=  0 myNX=  4
+ *    1:  1: myOff=  4 myNX=  4
+ *    2:  2: myOff=  8 myNX=  4
+ *    3:  3: myOff= 12 myNX=  4
+ *    0:  0: start=  0   0 count= 10   1
+ *    1:  1: start=  0   1 count= 10   1
+ *    2:  2: start=  0   2 count= 10   1
+ *    3:  3: start=  0   3 count= 10   1
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            Y = 10 ;
+ *            X = 16 ;
+ *    variables:
+ *            int var(Y, X) ;
+ *    data:
+ *
+ *     var =
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+#define NY 10
+#define NX 4
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    << argv0;
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[128];
+    int i, j, verbose=1, rank, nprocs, myNX, G_NX, myOff, num_reqs;
+    int *reqs, *sts, **buf;
+    vector<MPI_Offset> start(2), count(2);
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+
+    try {
+        NcmpiFile nc(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                     NcmpiFile::classic5);
+
+        /* the global array is NY * (NX * nprocs) */
+        G_NX  = NX * nprocs;
+        myOff = NX * rank;
+        myNX  = NX;
+        if (verbose) printf("%2d: myOff=%3d myNX=%3d\n",rank,myOff,myNX);
+
+        /* define dimensions Y and X */
+        vector<NcmpiDim> dimid(2);
+
+        dimid[0] = nc.addDim("Y", NY);
+        dimid[1] = nc.addDim("X", G_NX);
+
+        /* define a 2D variable of integer type */
+        NcmpiVar var = nc.addVar("var", ncmpiInt, dimid);
+
+        /* First, fill the entire array with zeros, using a blocking I/O.
+           Every process writes a subarray of size NY * myNX */
+        buf    = (int**) malloc(myNX * sizeof(int*));
+        buf[0] = (int*)  calloc(NY * myNX, sizeof(int));
+        start[0] = 0;   start[1] = myOff;
+        count[0] = NY;  count[1] = myNX;
+
+        var.putVar_all(start, count, &buf[0][0]);
+
+        free(buf[0]);
+
+        /* initialize the buffer with rank ID. Also make the case interesting,
+           by allocating buffers separately */
+        for (i=0; i<myNX; i++) {
+            buf[i] = (int*) malloc(NY * sizeof(int));
+            for (j=0; j<NY; j++) buf[i][j] = rank;
+        }
+
+        reqs = (int*) malloc(myNX * sizeof(int));
+        sts  = (int*) malloc(myNX * sizeof(int));
+
+        /* each proc writes myNX single columns of the 2D array */
+        start[0]  = 0;   start[1] = rank;
+        count[0]  = NY;  count[1] = 1;
+        if (verbose)
+            printf("%2d: start=%3lld %3lld count=%3lld %3lld\n",
+                   rank, start[0],start[1], count[0],count[1]);
+
+        num_reqs = 0;
+        for (i=0; i<myNX; i++) {
+            var.iputVar(start, count, &buf[0][0], &reqs[num_reqs++]);
+            start[1] += nprocs;
+        }
+        nc.Wait_all(num_reqs, reqs, sts);
+
+        /* check status of all requests */
+        for (i=0; i<num_reqs; i++)
+            if (sts[i] != NC_NOERR)
+                printf("Error: nonblocking write fails on request %d (%s)\n",
+                       i, ncmpi_strerror(sts[i]));
+
+        free(sts);
+        free(reqs);
+        for (i=0; i<myNX; i++) free(buf[i]);
+        free(buf);
+
+        /* file is close implicitly */
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+    }
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/depend b/examples/CXX/depend
new file mode 100644
index 0000000..cfd6d2b
--- /dev/null
+++ b/examples/CXX/depend
@@ -0,0 +1,14 @@
+collective_write.o: collective_write.cpp
+nonblocking_write.o: nonblocking_write.cpp
+column_wise.o: column_wise.cpp
+block_cyclic.o: block_cyclic.cpp
+flexible_api.o: flexible_api.cpp
+get_info.o: get_info.cpp
+hints.o: hints.cpp
+put_vara.o: put_vara.cpp
+get_vara.o: get_vara.cpp
+put_varn_float.o: put_varn_float.cpp
+put_varn_int.o: put_varn_int.cpp
+transpose.o: transpose.cpp
+vard_int.o: vard_int.cpp
+fill_mode.o: fill_mode.cpp
diff --git a/examples/CXX/fill_mode.cpp b/examples/CXX/fill_mode.cpp
new file mode 100644
index 0000000..24dd0cd
--- /dev/null
+++ b/examples/CXX/fill_mode.cpp
@@ -0,0 +1,213 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: fill_mode.cpp 2012 2015-02-16 05:52:44Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use 
+ * 1. NcmpiVar::setFill() to define the variable's fill value
+ * 2. NcmpiVar::getFillModeParameters() to inquire the variable's fill mode
+ *    information
+ * 3. NcmpiVar::fillVar() to write two 2D 4-byte integer array in parallel.
+ * It first defines a netCDF record variable of size NC_UNLIMITED * global_ny
+ * where
+ *    global_nx == (NX * number of MPI processes).
+ * It then defines a netCDF fixed-size variable of size global_nx * global_ny
+ * where
+ *    global_ny == NY and
+ *    global_nx == (NX * number of MPI processes).
+ *
+ *    To compile:
+ *        mpicxx -O2 fill_mode.cpp -o fill_mode -lpnetcdf
+ *
+ * Example commands for MPI run and outputs from running ncmpidump on the
+ * NC file produced by this example program:
+ *
+ *    % mpiexec -n 4 ./fill_mode /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            REC_DIM = UNLIMITED ; // (2 currently)
+ *            X = 16 ;
+ *            Y = 3 ;
+ *    variables:
+ *            int rec_var(REC_DIM, X) ;
+ *                    rec_var:_FillValue = -1 ;
+ *            int fix_var(Y, X) ;
+ *
+ *    // global attributes:
+ *                    :history = "Thu Feb 12 01:28:34 2015\n",
+ *       "" ;
+ *    data:
+ *
+ *    rec_var =
+ *           0, 0, 0, _, 1, 1, 1, _, 2, 2, 2, _, 3, 3, 3, _,
+ *           0, 0, 0, _, 1, 1, 1, _, 2, 2, 2, _, 3, 3, 3, _ ;
+ *
+ *    fix_var =
+ *           0, 0, 0, _, 1, 1, 1, _, 2, 2, 2, _, 3, 3, 3, _,
+ *           0, 0, 0, _, 1, 1, 1, _, 2, 2, 2, _, 3, 3, 3, _,
+ *           0, 0, 0, _, 1, 1, 1, _, 2, 2, 2, _, 3, 3, 3, _ ;
+ *    }
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <time.h>   /* time() localtime(), asctime() */
+
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+#define NY 3
+#define NX 4
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    << argv0;
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[128], str_att[128];
+    int i, j, verbose=1, rank, nprocs, buf[NY][NX];
+    MPI_Offset  global_ny, global_nx;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+
+    try {
+        /* create a new file for writing ------------------------------------*/
+        NcmpiFile ncFile(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                         NcmpiFile::classic5);
+
+        /* the global array is NY * (NX * nprocs) */
+        global_ny = NY;
+        global_nx = NX * nprocs;
+
+        for (i=0; i<NY; i++)
+            for (j=0; j<NX; j++)
+                 buf[i][j] = rank;
+
+        /* add a global attribute: a time stamp at rank 0 */
+        time_t ltime = time(NULL); /* get the current calendar time */
+        asctime_r(localtime(&ltime), str_att);
+
+        /* make sure the time string are consistent among all processes */
+        MPI_Bcast(str_att, 128, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+        ncFile.putAtt(string("history"), string(str_att));
+
+        /* define dimensions Y and X */
+        vector<NcmpiDim> dimid(2);
+
+        dimid[0] = ncFile.addDim("REC_DIM", NC_UNLIMITED);
+        dimid[1] = ncFile.addDim("X", global_nx);
+
+        /* define a 2D record variable of integer type */
+        NcmpiVar rec_var = ncFile.addVar("rec_var", ncmpiInt, dimid);
+
+        dimid[0] = ncFile.addDim("Y", global_ny);
+
+        /* define a 2D fixed-size variable of integer type */
+        NcmpiVar fix_var = ncFile.addVar("fix_var", ncmpiInt, dimid);
+
+        /* set the variable's fill mode to NC_FILL with default fill value */
+        fix_var.setFill(true);
+
+        /* set a customized fill value -1 */
+        int fill_value = -1;
+        rec_var.setFill(true, &fill_value);
+
+        /* now we are in data mode */
+        vector<MPI_Offset> start(2), count(2);
+        start[0] = 0;
+        start[1] = NX * rank;
+        count[0] = NY;
+        count[1] = NX;
+        if (verbose)
+            printf("%d: start=%lld %lld count=%lld %lld\n",rank,
+                   start[0],start[1],count[0],count[1]);
+
+        /* do not write the variable in full */
+        count[1]--;
+        fix_var.putVar_all(start, count, &buf[0][0]);
+
+        bool fillMode=true;
+        fix_var.getFillModeParameters(fillMode, &fill_value);
+        if (!fillMode)
+            printf("Error: expecting fillMode to be false\n");
+        if (fill_value != NC_FILL_INT)
+            printf("Error: expecting fillMode to be %ld but got %d\n",NC_FILL_INT,fill_value);
+
+        /* fill the 1st record of the record variable */
+        start[0] = 0;
+        rec_var.fillRec(start[0]);
+
+        /* write to the 1st record */
+        count[0] = 1;
+        rec_var.putVar_all(start, count, &buf[0][0]);
+
+        /* fill the 2nd record of the record variable */
+        start[0] = 1;
+        rec_var.fillRec(start[0]);
+
+        /* write to the 2nd record */
+        rec_var.putVar_all(start, count, &buf[0][0]);
+
+        /* file is close implicitly */
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+    }
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/flexible_api.cpp b/examples/CXX/flexible_api.cpp
new file mode 100644
index 0000000..12c4987
--- /dev/null
+++ b/examples/CXX/flexible_api.cpp
@@ -0,0 +1,228 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: flexible_api.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This example shows how to use PnetCDF flexible APIs, NcmpiVar::putVar_all()
+ * to write two 2D array variables (one is of 4-byte integer byte and the
+ * other float type) in parallel. It first defines 2 netCDF variables of sizes
+ *    var_zy: NZ*nprocs x NY
+ *    var_yx: NY x NX*nprocs
+ *
+ * The data partitioning patterns on the 2 variables are row-wise and
+ * column-wise, respectively. Each process writes a subarray of size
+ * NZ x NY and NY x NX to var_zy and var_yx, respectively.
+ * Both local buffers have a ghost cell of length 3 surrounded along each
+ * dimension.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicxx -O2 -o flexible_api flexible_api.cpp -lpnetcdf
+ *
+ *    % mpiexec -l -n 4 ./flexible_api /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            Z = 20 ;
+ *            Y = 5 ;
+ *            X = 20 ;
+ *    variables:
+ *            int var_zy(Z, Y) ;
+ *            float var_yx(Y, X) ;
+ *    data:
+ *
+ *     var_zy =
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0,
+ *      1, 1, 1, 1, 1,
+ *      1, 1, 1, 1, 1,
+ *      1, 1, 1, 1, 1,
+ *      1, 1, 1, 1, 1,
+ *      1, 1, 1, 1, 1,
+ *      2, 2, 2, 2, 2,
+ *      2, 2, 2, 2, 2,
+ *      2, 2, 2, 2, 2,
+ *      2, 2, 2, 2, 2,
+ *      2, 2, 2, 2, 2,
+ *      3, 3, 3, 3, 3,
+ *      3, 3, 3, 3, 3,
+ *      3, 3, 3, 3, 3,
+ *      3, 3, 3, 3, 3,
+ *      3, 3, 3, 3, 3 ;
+ *
+ *     var_yx =
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 ;
+ *    }
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+#define NZ 5
+#define NY 5
+#define NX 5
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    << argv0;
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[128];
+    int i, rank, nprocs, verbose=1, ghost_len=3;
+    int *buf_zy;
+    float *buf_yx;
+    MPI_Datatype  subarray;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+
+    try {
+        /* create a new file for writing ------------------------------------*/
+        NcmpiFile nc(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                     NcmpiFile::classic5);
+
+        /* define 3 dimensions */
+        vector<NcmpiDim> dimid(3);
+        dimid[0] = nc.addDim("Z", NZ*nprocs);
+        dimid[1] = nc.addDim("Y", NY);
+        dimid[2] = nc.addDim("X", NX*nprocs);
+
+        vector<NcmpiDim> dimid0(2), dimid1(2);
+        dimid0[0] =             dimid[0];
+        dimid0[1] = dimid1[0] = dimid[1];
+        dimid1[1] =             dimid[2];
+
+        /* define a variable of size (NZ * nprocs) * NY */
+        NcmpiVar var0 = nc.addVar("var_zy", ncmpiInt,   dimid0);
+
+        /* define a variable of size NY * (NX * nprocs) */
+        NcmpiVar var1 = nc.addVar("var_yx", ncmpiFloat, dimid1);
+
+        /* var_zy is partitioned along Z dimension */
+        int array_of_sizes[2], array_of_subsizes[2], array_of_starts[2];
+        array_of_sizes[0]    = NZ + 2*ghost_len;
+        array_of_sizes[1]    = NY + 2*ghost_len;
+        array_of_subsizes[0] = NZ;
+        array_of_subsizes[1] = NY;
+        array_of_starts[0]   = ghost_len;
+        array_of_starts[1]   = ghost_len;
+        MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                                 array_of_starts, MPI_ORDER_C, MPI_INT,
+                                 &subarray);
+        MPI_Type_commit(&subarray);
+
+        /* allocate buffer buf_zy and initialize its contents */
+        int buffer_len = (NZ+2*ghost_len) * (NY+2*ghost_len);
+        buf_zy = (int*) malloc(buffer_len * sizeof(int));
+        for (i=0; i<buffer_len; i++) buf_zy[i] = rank;
+
+        vector <MPI_Offset> start(2), count(2);
+        start[0] = NZ * rank; start[1] = 0;
+        count[0] = NZ;        count[1] = NY;
+        if (verbose)
+            printf("%d: start=%lld %lld count=%lld %lld\n",rank,
+                   start[0],start[1],count[0],count[1]);
+
+        /* calling a blocking flexible API */
+        var0.putVar_all(start, count, &buf_zy[0], 1, subarray);
+        free(buf_zy);
+        MPI_Type_free(&subarray);
+
+        /* var_yx is partitioned along X dimension */
+        array_of_sizes[0]    = NY + 2*ghost_len;
+        array_of_sizes[1]    = NX + 2*ghost_len;
+        array_of_subsizes[0] = NY;
+        array_of_subsizes[1] = NX;
+        array_of_starts[0]   = ghost_len;
+        array_of_starts[1]   = ghost_len;
+        MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                                 array_of_starts, MPI_ORDER_C, MPI_FLOAT,
+                                 &subarray);
+        MPI_Type_commit(&subarray);
+
+        /* allocate buffer buf_yx and initialize its contents */
+        buffer_len = (NY+2*ghost_len) * (NX+2*ghost_len);
+        buf_yx = (float*) malloc(buffer_len * sizeof(float));
+        for (i=0; i<buffer_len; i++) buf_yx[i] = rank;
+
+        start[0] = 0;  start[1] = NX * rank;
+        count[0] = NY; count[1] = NX;
+        if (verbose)
+            printf("%d: start=%lld %lld count=%lld %lld\n",rank,
+                   start[0],start[1],count[0],count[1]);
+
+        /* calling a non-blocking flexible API */
+        var1.putVar_all(start, count, buf_yx, 1, subarray);
+        free(buf_yx);
+        MPI_Type_free(&subarray);
+
+        /* file is close implicitly */
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+    }
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/get_info.cpp b/examples/CXX/get_info.cpp
new file mode 100644
index 0000000..4e96427
--- /dev/null
+++ b/examples/CXX/get_info.cpp
@@ -0,0 +1,137 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: get_info.cpp 1839 2014-10-30 20:22:37Z wkliao $ */
+
+/*
+ *    prints all MPI-IO hints used
+ *    To compile:
+ *        mpicxx -O2 get_info.c -o get_info -lpnetcdf
+ *    To run:
+ *        mpiexec -n 4 ./get_info [filename]
+ *
+ *    Example standard output:
+
+    MPI File Info: nkeys = 18
+    MPI File Info: [ 0] key =            cb_buffer_size, value = 16777216
+    MPI File Info: [ 1] key =             romio_cb_read, value = automatic
+    MPI File Info: [ 2] key =            romio_cb_write, value = automatic
+    MPI File Info: [ 3] key =                  cb_nodes, value = 1
+    MPI File Info: [ 4] key =         romio_no_indep_rw, value = false
+    MPI File Info: [ 5] key =              romio_cb_pfr, value = disable
+    MPI File Info: [ 6] key =         romio_cb_fr_types, value = aar
+    MPI File Info: [ 7] key =     romio_cb_fr_alignment, value = 1
+    MPI File Info: [ 8] key =     romio_cb_ds_threshold, value = 0
+    MPI File Info: [ 9] key =         romio_cb_alltoall, value = automatic
+    MPI File Info: [10] key =        ind_rd_buffer_size, value = 4194304
+    MPI File Info: [11] key =        ind_wr_buffer_size, value = 524288
+    MPI File Info: [12] key =             romio_ds_read, value = automatic
+    MPI File Info: [13] key =            romio_ds_write, value = automatic
+    MPI File Info: [14] key =            cb_config_list, value = *:1
+    MPI File Info: [15] key =      nc_header_align_size, value = 512
+    MPI File Info: [16] key =         nc_var_align_size, value = 512
+    MPI File Info: [17] key = nc_header_read_chunk_size, value = 0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    << argv0;
+}
+
+/*----< print_info() >------------------------------------------------------*/
+static
+void print_info(MPI_Info *info_used)
+{
+    int  i, nkeys;
+
+    MPI_Info_get_nkeys(*info_used, &nkeys);
+    printf("MPI File Info: nkeys = %d\n",nkeys);
+    for (i=0; i<nkeys; i++) {
+        char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
+        int  valuelen, flag;
+
+        MPI_Info_get_nthkey(*info_used, i, key);
+        MPI_Info_get_valuelen(*info_used, key, &valuelen, &flag);
+        MPI_Info_get(*info_used, key, valuelen+1, value, &flag);
+        printf("MPI File Info: [%2d] key = %25s, value = %s\n",i,key,value);
+    }
+}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    extern int optind;
+    char filename[128];
+    int i, rank, verbose=1;
+    MPI_Info info_used;
+
+    MPI_Init(&argc,&argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+
+    try {
+        /* create the file */
+        NcmpiFile ncFile(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                         NcmpiFile::classic5);
+
+        /* get all the default hints used */
+        ncFile.Inq_file_info(&info_used);
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+       return 1;
+    }
+
+    if (rank == 0 && verbose) print_info(&info_used);
+    MPI_Info_free(&info_used);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/get_vara.cpp b/examples/CXX/get_vara.cpp
new file mode 100644
index 0000000..0c1ec56
--- /dev/null
+++ b/examples/CXX/get_vara.cpp
@@ -0,0 +1,190 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: get_vara.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example is the read counterpart of example put_vara.cpp. It shows how to
+ * use NcmpiVar::getVar_all() to read a 2D 4-byte integer array in parallel.
+ * It also reads a global attribute and two attribute of variable named "var".
+ * The data partitioning pattern is a column-wise partitioning across all
+ * processes. Each process reads a subarray of size local_ny * local_nx.
+ *
+ *    To compile:
+ *        mpicxx -O2 get_vara.cpp -o get_vara -lpnetcdf
+ *
+ * Input file is the output file produced by put_vara.cpp. Here is the CDL
+ * dumped from running ncmpidump.
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-1
+ *    dimensions:
+ *            y = 10 ;
+ *            x = 16 ;
+ *    variables:
+ *            int var(y, x) ;
+ *                var:str_att_name = "example attribute of type text." ;
+ *                var:float_att_name = 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f ;
+ *    // global attributes:
+ *                :history = "Wed Apr 30 11:18:58 2014\n",
+ *       "" ;
+ *    data:
+ *
+ *     var =
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 ;
+ *    }
+ *
+ * Example command for MPI run:
+ *
+ *    % mpiexec -n 4 ./get_vara /pvfs2/wkliao/testfile.nc
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] input netCDF file name\n"
+    << argv0;
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[128], str_att[NC_MAX_NAME];
+    int i, rank, nprocs, err, verbose=1;
+    MPI_Offset len, global_ny, global_nx, local_ny, local_nx;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+
+    try {
+        /* open an existing file for reading --------------------------------*/
+        NcmpiFile ncFile(MPI_COMM_WORLD, filename, NcmpiFile::read);
+
+        // Check the format.
+        if (ncFile.getFormat() != NcmpiFile::classic5) {
+            cout << "unexpected file format"<<endl;
+            throw NcmpiException("read Error ",__FILE__,__LINE__);
+        }
+
+        /* get global attribute named "history" */
+        NcmpiGroupAtt att = ncFile.getAtt("history");
+        att.getValues(str_att);
+        len = att.getAttLength();
+        str_att[len] = '\0'; /* add a NULL char at the end */
+        if (rank == 0 && verbose)
+            printf("global attribute \"history\" of text: %s\n",str_att);
+
+        /* get dimension IDs for dimensions Y and X */
+        NcmpiDim yDim = ncFile.getDim("Y");
+        NcmpiDim xDim = ncFile.getDim("X");
+
+        /* get dimension lengths for dimensions Y and X */
+        global_ny = yDim.getSize();
+        global_nx = xDim.getSize();
+
+        /* get the variable ID of a 2D variable of integer type */
+        NcmpiVar var = ncFile.getVar("var");
+
+        /* get variable's attribute named "str_att_name" */
+        NcmpiVarAtt vatt = var.getAtt("str_att_name");
+        vatt.getValues(str_att);
+        len = vatt.getAttLength();
+        str_att[len] = '\0'; /* add a NULL char at the end */
+        if (rank == 0 && verbose)
+            printf("variable attribute \"str_att_name\" of type text = \"%s\"\n",
+                   str_att);
+
+        /* get the length of variable's attribute named "float_att_name" */
+        NcmpiVarAtt flt_vatt = var.getAtt("float_att_name");
+        len = flt_vatt.getAttLength();
+
+        /* get attribute contents */
+        float *float_att = (float*) malloc(len * sizeof(float));
+        flt_vatt.getValues(float_att);
+
+        /* the local array size */
+        local_ny = global_ny;
+        local_nx = global_nx / nprocs;
+        int *buf = (int*) malloc(local_nx * local_ny * sizeof(int));
+
+        /* prepare reading subarray */
+        vector<MPI_Offset> start(2), count(2);
+        start[0] = 0;
+        start[1] = local_nx * rank;
+        count[0] = local_ny;
+        count[1] = local_nx;
+
+        /* read a subarray in collective mode */
+
+        // var.getVar_all(start, count, &buf[0][0]);
+        var.getVar_all(start, count, buf);
+
+        free(buf);
+        free(float_att);
+        /* file is close implicitly */
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+    }
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/hints.cpp b/examples/CXX/hints.cpp
new file mode 100644
index 0000000..a9eb356
--- /dev/null
+++ b/examples/CXX/hints.cpp
@@ -0,0 +1,212 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: hints.cpp 1839 2014-10-30 20:22:37Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example sets two PnetCDF hints:
+ *    nc_header_align_size and nc_var_align_size
+ * and prints the hint values as well as the header size, header extent, and
+ * two variables' starting file offsets.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicxx -O2 -o hints hints.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 4 ./hints /pvfs2/wkliao/testfile.nc
+ *
+ *    nc_header_align_size      set to = 1024
+ *    nc_var_align_size         set to = 512
+ *    nc_header_read_chunk_size set to = 256
+ *    header size                      = 252
+ *    header extent                    = 1024
+ *    var_zy start file offset         = 1024
+ *    var_yx start file offset         = 3072
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+#define NZ 5
+#define NY 5
+#define NX 5
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    << argv0;
+}
+
+static
+void print_hints(NcmpiFile &ncFile,
+                 NcmpiVar  &var0,
+                 NcmpiVar  &var1)
+{
+    char value[MPI_MAX_INFO_VAL];
+    int len, flag;
+    MPI_Offset header_size, header_extent, var_zy_start, var_yx_start;
+    MPI_Offset h_align=-1, v_align=-1, h_chunk=-1;
+    MPI_Info info_used;
+
+    ncFile.Inq_header_size(&header_size);
+    ncFile.Inq_header_extent(&header_extent);
+
+    var0.Inq_file_offset(&var_zy_start);
+    var1.Inq_file_offset(&var_yx_start);
+    
+    /* get all the hints used */
+    ncFile.Inq_file_info(&info_used);
+
+    MPI_Info_get_valuelen(info_used, (char*)"nc_header_align_size", &len, &flag);
+    if (flag) {
+        MPI_Info_get(info_used, (char*)"nc_header_align_size", len+1, value, &flag);
+        h_align = atoll(value);
+    }
+        MPI_Info_get_valuelen(info_used, (char*)"nc_var_align_size", &len, &flag);
+    if (flag) {
+        MPI_Info_get(info_used, (char*)"nc_var_align_size", len+1, value, &flag);
+        v_align = atoll(value);
+    }
+    MPI_Info_get_valuelen(info_used, (char*)"nc_header_read_chunk_size", &len, &flag);
+    if (flag) {
+        MPI_Info_get(info_used, (char*)"nc_header_read_chunk_size", len+1, value,&flag);
+        h_chunk = atoll(value);
+    }
+    MPI_Info_free(&info_used);
+
+    if (h_align == -1)
+        printf("nc_header_align_size      is NOT set\n");
+    else
+        printf("nc_header_align_size      set to = %lld\n", h_align);
+
+    if (v_align == -1)
+        printf("nc_var_align_size         is NOT set\n");
+    else
+        printf("nc_var_align_size         set to = %lld\n", v_align);
+    if (h_chunk == -1)
+        printf("nc_header_read_chunk_size is NOT set\n");
+    else
+        printf("nc_header_read_chunk_size set to = %lld\n", h_chunk);
+
+    printf("header size                      = %lld\n", header_size);
+    printf("header extent                    = %lld\n", header_extent);
+    printf("var_zy start file offset         = %lld\n", var_zy_start);
+    printf("var_yx start file offset         = %lld\n", var_yx_start);
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[128];
+    int i, rank, nprocs, verbose=1, *buf_zy;
+    float *buf_yx;
+    vector<MPI_Offset> start(2), count(2);
+    MPI_Info info;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+
+    try {
+        MPI_Info_create(&info);
+        MPI_Info_set(info, (char*)"nc_header_align_size",      (char*)"1024");
+        MPI_Info_set(info, (char*)"nc_var_align_size",         (char*)"512");
+        MPI_Info_set(info, (char*)"nc_header_read_chunk_size", (char*)"256");
+        /* note that set the above values to 1 to disable the alignment */
+
+        /* create a new file for writing -------------------------------------*/
+        NcmpiFile ncFile(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                         NcmpiFile::classic5, info);
+        MPI_Info_free(&info);
+
+        /* define 3 dimensions */
+        vector<NcmpiDim> dimid(3);
+        dimid[0] = ncFile.addDim("Z", NZ*nprocs);
+        dimid[1] = ncFile.addDim("Y", NY*nprocs);
+        dimid[2] = ncFile.addDim("X", NX*nprocs);
+
+        /* define a variable of size (NZ * nprocs) * (NY * nprocs) */
+        vector<NcmpiDim> dimid_zy(2);
+        dimid_zy[0] = dimid[0];
+        dimid_zy[1] = dimid[1];
+        NcmpiVar var0 = ncFile.addVar("var_zy", ncmpiInt, dimid_zy);
+
+        /* define a variable of size (NY * nprocs) * (NX * nprocs) */
+        vector<NcmpiDim> dimid_yx(2);
+        dimid_yx[0] = dimid[1];
+        dimid_yx[1] = dimid[2];
+        NcmpiVar var1 = ncFile.addVar("var_yx", ncmpiFloat, dimid_yx);
+
+        /* var_zy is partitioned along Z dimension */
+        buf_zy = (int*) malloc(NZ * (NY * nprocs) * sizeof(int));
+        for (i=0; i<NZ*(NY*nprocs); i++) buf_zy[i] = i;
+
+        start[0] = NZ * rank; start[1] = 0;
+        count[0] = NZ;        count[1] = NY * nprocs;
+        var0.putVar_all(start, count, buf_zy);
+
+        /* var_yx is partitioned along X dimension */
+        buf_yx = (float*) malloc((NY * nprocs) * NX * sizeof(float));
+        for (i=0; i<(NY*nprocs)*NX; i++) buf_yx[i] = i;
+
+        start[0] = 0;           start[1] = NX * rank;
+        count[0] = NY * nprocs; count[1] = NX;
+        var1.putVar_all(start, count, buf_yx);
+
+        if (rank == 0 && verbose) print_hints(ncFile, var0, var1);
+
+        free(buf_zy);
+        free(buf_yx);
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+    }
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/nonblocking_write.cpp b/examples/CXX/nonblocking_write.cpp
new file mode 100644
index 0000000..fb92bd1
--- /dev/null
+++ b/examples/CXX/nonblocking_write.cpp
@@ -0,0 +1,262 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: nonblocking_write.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/*    This example is similar to collective_write.c but using nonblocking APIs.
+ *    It creates a netcdf file in CD-5 format and writes a number of
+ *    3D integer non-record variables. The measured write bandwidth is reported
+ *    at the end. Usage: (for example)
+ *    To compile:
+ *        mpicxx -O2 nonblocking_write.cpp -o nonblocking_write -lpnetcdf
+ *    To run:
+ *        mpiexec -n num_processes ./nonblocking_write [filename] [len]
+ *    where len decides the size of each local array, which is len x len x len.
+ *    So, each non-record variable is of size len*len*len * nprocs * sizeof(int)
+ *    All variables are partitioned among all processes in a 3D
+ *    block-block-block fashion. Below is an example standard output from
+ *    command:
+ *        mpiexec -n 32 ./nonblocking_write /pvfs2/wkliao/testfile.nc 100
+ *
+ *    MPI hint: cb_nodes        = 2
+ *    MPI hint: cb_buffer_size  = 16777216
+ *    MPI hint: striping_factor = 32
+ *    MPI hint: striping_unit   = 1048576
+ *    Local array size 100 x 100 x 100 integers, size = 3.81 MB
+ *    Global array size 400 x 400 x 200 integers, write size = 0.30 GB
+ *     procs    Global array size  exec(sec)  write(MB/s)
+ *     -------  ------------------  ---------  -----------
+ *        32     400 x  400 x  200     6.67       45.72
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+#define NDIMS    3
+#define NUM_VARS 10
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name] [len]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    "       [len] size of each dimension of the local array\n"
+    << argv0;
+}
+
+/*----< print_info() >------------------------------------------------------*/
+static
+void print_info(MPI_Info *info_used)
+{
+    int     flag;
+    char    info_cb_nodes[64], info_cb_buffer_size[64];
+    char    info_striping_factor[64], info_striping_unit[64];
+
+    strcpy(info_cb_nodes,        "undefined");
+    strcpy(info_cb_buffer_size,  "undefined");
+    strcpy(info_striping_factor, "undefined");
+    strcpy(info_striping_unit,   "undefined");
+
+    MPI_Info_get(*info_used, (char*)"cb_nodes", 64, info_cb_nodes, &flag);
+    MPI_Info_get(*info_used, (char*)"cb_buffer_size", 64, info_cb_buffer_size, &flag);
+    MPI_Info_get(*info_used, (char*)"striping_factor", 64, info_striping_factor, &flag);
+    MPI_Info_get(*info_used, (char*)"striping_unit", 64, info_striping_unit, &flag);
+
+    printf("MPI hint: cb_nodes        = %s\n", info_cb_nodes);
+    printf("MPI hint: cb_buffer_size  = %s\n", info_cb_buffer_size);
+    printf("MPI hint: striping_factor = %s\n", info_striping_factor);
+    printf("MPI hint: striping_unit   = %s\n", info_striping_unit);
+}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    extern int optind;
+    int i, j, verbose=1;
+    int nprocs, len, *buf[NUM_VARS], bufsize, rank;
+    int gsizes[NDIMS], psizes[NDIMS];
+    double write_timing, max_write_timing, write_bw;
+    char filename[128], str[512];
+    int req[NUM_VARS], st[NUM_VARS];
+    MPI_Offset write_size, sum_write_size;
+    vector<MPI_Offset> starts(NDIMS), counts(NDIMS);
+    MPI_Offset bbufsize, put_size;
+    MPI_Info info_used;
+
+    MPI_Init(&argc,&argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc >= 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+    len = 10; 
+    if (argc >= 2) len = atoi(argv[1]); /* optional argument */
+
+    for (i=0; i<NDIMS; i++) psizes[i] = 0;
+
+    MPI_Dims_create(nprocs, NDIMS, psizes);
+    starts[0] = rank % psizes[0];
+    starts[1] = (rank / psizes[1]) % psizes[1];
+    starts[2] = (rank / (psizes[0] * psizes[1])) % psizes[2];
+
+    bufsize = 1;
+    for (i=0; i<NDIMS; i++) {
+        gsizes[i] = len * psizes[i];
+        starts[i] *= len;
+        counts[i]  = len;
+        bufsize   *= len;
+    }
+
+    /* allocate buffer and initialize with random numbers */
+    srand(rank);
+    for (i=0; i<NUM_VARS; i++) {
+        buf[i] = (int *) malloc(bufsize * sizeof(int));
+        for (j=0; j<bufsize; j++) buf[i][j] = rand();
+    }
+
+    MPI_Barrier(MPI_COMM_WORLD);
+    write_timing = MPI_Wtime();
+
+    try {
+        /* create the file */
+        NcmpiFile nc(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                     NcmpiFile::classic5);
+
+        /* define dimensions */
+        vector<NcmpiDim> dimids(NDIMS);
+        for (i=0; i<NDIMS; i++) {
+            sprintf(str, "%c", 'x'+i);
+            dimids[i] = nc.addDim(str, gsizes[i]);
+        }
+
+        /* define variables */
+        vector<NcmpiVar> vars(NUM_VARS);
+        for (i=0; i<NUM_VARS; i++) {
+            sprintf(str, "var%d", i);
+            vars[i] = nc.addVar(str, ncmpiInt, dimids);
+        }
+
+        /* get all the hints used */
+        nc.Inq_file_info(&info_used);
+
+        /* write one variable at a time using iput */
+        for (i=0; i<NUM_VARS; i++)
+            vars[i].iputVar(starts, counts, &buf[i][0], &req[i]);
+
+        /* wait for the nonblocking I/O to complete */
+        nc.Wait_all(NUM_VARS, req, st);
+
+        for (i=0; i<NUM_VARS; i++) {
+            if (st[i] != NC_NOERR)
+                printf("Error: nonblocking write fails on request %d (%s)\n",
+                       i, ncmpi_strerror(st[i]));
+        }
+
+        /* write one variable at a time using bput */
+
+        /* bbufsize must be max of data type converted before and after */
+        bbufsize = bufsize * NUM_VARS * sizeof(int);
+        nc.Buffer_attach(bbufsize);
+
+        for (i=0; i<NUM_VARS; i++) {
+            vars[i].bputVar(starts, counts, buf[i], &req[i]);
+            /* can safely change contents or free up the buf[i] here */
+        }
+
+        /* wait for the nonblocking I/O to complete */
+        nc.Wait_all(NUM_VARS, req, st);
+        for (i=0; i<NUM_VARS; i++) {
+            if (st[i] != NC_NOERR)
+                printf("Error: nonblocking write fails on request %d (%s)\n",
+                       i, ncmpi_strerror(st[i]));
+        }
+
+        /* detach the temporary buffer */
+        nc.Buffer_detach();
+
+        nc.Inq_put_size(&put_size);
+#ifdef MPI_OFFSET
+        MPI_Allreduce(MPI_IN_PLACE, &put_size, 1, MPI_OFFSET, MPI_SUM, MPI_COMM_WORLD);
+#else
+        MPI_Allreduce(MPI_IN_PLACE, &put_size, 1, MPI_LONG_LONG, MPI_SUM, MPI_COMM_WORLD);
+#endif
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+       return 1;
+    }
+    write_timing = MPI_Wtime() - write_timing;
+
+    write_size = bufsize * NUM_VARS * sizeof(int);
+    for (i=0; i<NUM_VARS; i++) free(buf[i]);
+
+#ifdef MPI_OFFSET
+    MPI_Reduce(&write_size,   &sum_write_size,   1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+#else
+    MPI_Reduce(&write_size,   &sum_write_size,   1, MPI_LONG_LONG, MPI_SUM, 0, MPI_COMM_WORLD);
+#endif
+    MPI_Reduce(&write_timing, &max_write_timing, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
+
+    if (rank == 0 && verbose) {
+        double write_amount = sum_write_size;
+        float subarray_size = (float)bufsize*sizeof(int)/1048576.0;
+        printf("\n");
+        printf("Total amount writes to variables only   (exclude header) = %lld bytes\n", sum_write_size);
+        printf("Total amount writes reported by pnetcdf (include header) = %lld bytes\n", put_size);
+        printf("\n");
+        print_info(&info_used);
+        printf("Local array size %d x %d x %d integers, size = %.2f MB\n",len,len,len,subarray_size);
+        write_amount /= 1048576.0;
+        printf("Global array size %d x %d x %d integers, write size = %.2f GB\n",
+               gsizes[0], gsizes[1], gsizes[2], write_amount/1024.0);
+
+        write_bw = write_amount/max_write_timing;
+        printf(" procs    Global array size  exec(sec)  write(MB/s)\n");
+        printf("-------  ------------------  ---------  -----------\n");
+        printf(" %4d    %4d x %4d x %4d %8.2f  %10.2f\n", nprocs,
+               gsizes[0], gsizes[1], gsizes[2], max_write_timing, write_bw);
+    }
+    MPI_Info_free(&info_used);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/put_vara.cpp b/examples/CXX/put_vara.cpp
new file mode 100644
index 0000000..edb65d9
--- /dev/null
+++ b/examples/CXX/put_vara.cpp
@@ -0,0 +1,180 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: put_vara.cpp 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use NcmpiVar::putVar_all() to write a 2D
+ * 4-byte integer array in parallel. It first defines a netCDF variable of
+ * size global_nx * global_ny where
+ *    global_ny == NY and
+ *    global_nx == (NX * number of MPI processes).
+ * The data partitioning pattern is a column-wise partitioning across all
+ * processes. Each process writes a subarray of size ny * nx.
+ *
+ *    To compile:
+ *        mpicxx -O2 put_vara.cpp -o put_vara -lpnetcdf
+ *
+ * Example commands for MPI run and outputs from running ncmpidump on the
+ * NC file produced by this example program:
+ *
+ *    % mpiexec -n 4 ./put_vara /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            y = 10 ;
+ *            x = 16 ;
+ *    variables:
+ *            int var(y, x) ;
+ *                var:str_att_name = "example attribute of type text." ;
+ *                var:float_att_name = 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f ;
+ *    // global attributes:
+ *                :history = "Wed Apr 30 11:18:58 2014\n",
+ *       "" ;
+ *    data:
+ *
+ *     var =
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ *         0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 ;
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <time.h>   /* time() localtime(), asctime() */
+
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+#define NY 10
+#define NX 4
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    << argv0;
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[128], str_att[128];
+    int i, j, verbose=1, rank, nprocs, buf[NY][NX];
+    float float_att[100];
+    MPI_Offset  global_ny, global_nx;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+
+    try {
+        /* create a new file for writing ------------------------------------*/
+        NcmpiFile ncFile(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                         NcmpiFile::classic5);
+
+        /* the global array is NY * (NX * nprocs) */
+        global_ny = NY;
+        global_nx = NX * nprocs;
+
+        for (i=0; i<NY; i++)
+            for (j=0; j<NX; j++)
+                 buf[i][j] = rank;
+
+        /* add a global attribute: a time stamp at rank 0 */
+        time_t ltime = time(NULL); /* get the current calendar time */
+        asctime_r(localtime(&ltime), str_att);
+
+        /* make sure the time string are consistent among all processes */
+        MPI_Bcast(str_att, 128, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+        ncFile.putAtt(string("history"), string(str_att));
+
+        /* define dimensions Y and X */
+        vector<NcmpiDim> dimid(2);
+
+        dimid[0] = ncFile.addDim("Y", global_ny);
+        dimid[1] = ncFile.addDim("X", global_nx);
+
+        /* define a 2D variable of integer type */
+        NcmpiVar var = ncFile.addVar("var", ncmpiInt, dimid);
+
+        /* add attributes to the variable */
+        var.putAtt(string("str_att_name"),
+                   string("example attribute of type text."));
+
+        for (i=0; i<8; i++) float_att[i] = i;
+        var.putAtt(string("float_att_name"), ncmpiFloat, 8, float_att);
+
+        /* now we are in data mode */
+        vector<MPI_Offset> start(2), count(2);
+        start[0] = 0;
+        start[1] = NX * rank;
+        count[0] = NY;
+        count[1] = NX;
+        if (verbose)
+            printf("%d: start=%lld %lld count=%lld %lld\n",rank,
+                   start[0],start[1],count[0],count[1]);
+
+        var.putVar_all(start, count, &buf[0][0]);
+
+        /* file is close implicitly */
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+    }
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/put_varn_float.cpp b/examples/CXX/put_varn_float.cpp
new file mode 100644
index 0000000..5003878
--- /dev/null
+++ b/examples/CXX/put_varn_float.cpp
@@ -0,0 +1,222 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: put_varn_float.cpp 1669 2014-05-24 18:28:16Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use a single call of NcmpiVar::putVarn_all()
+ * to write a sequence of one-element requests with arbitrary array indices.
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicxx -O2 -o put_varn_float put_varn_float.cpp -lpnetcdf
+ *    % mpiexec -n 4 ./put_varn_float /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             Y = 4 ;
+ *             X = 10 ;
+ *    variables:
+ *             int var(Y, X) ;
+ *    data:
+ *
+ *     var =
+ *       3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+ *       0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+ *       1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+ *       0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    << argv0;
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[128];
+    int i, verbose=1, rank, nprocs, num_reqs;
+    float *buffer;
+    MPI_Offset **starts;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+
+    if (nprocs != 4 && rank == 0 && verbose)
+        printf("Warning: this program is intended to run on 4 processes\n");
+
+    try {
+        /* create a new file for writing -------------------------------------*/
+        NcmpiFile nc(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                     NcmpiFile::classic);
+
+        /* define dimensions Y and X */
+        vector<NcmpiDim> dimid(2);
+
+        dimid[0] = nc.addDim("Y", NY);
+        dimid[1] = nc.addDim("X", NX);
+
+        /* define a 2D variable of integer type */
+        NcmpiVar var = nc.addVar("var", ncmpiFloat, dimid);
+
+        /* pick arbitrary numbers of requests for 4 processes */
+        num_reqs = 0;
+        if (rank == 0)      num_reqs = 8;
+        else if (rank == 1) num_reqs = 13;
+        else if (rank == 2) num_reqs = 9;
+        else if (rank == 3) num_reqs = 10;
+
+        starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+        starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+        for (i=1; i<num_reqs; i++)
+            starts[i] = starts[i-1] + NDIMS;
+
+        /* assign arbitrary starts */
+        const int y=0, x=1;
+        if (rank == 0) {
+            starts[0][y] = 0; starts[0][x] = 5;
+            starts[1][y] = 1; starts[1][x] = 0;
+            starts[2][y] = 2; starts[2][x] = 6;
+            starts[3][y] = 3; starts[3][x] = 0;
+            starts[4][y] = 0; starts[4][x] = 6;
+            starts[5][y] = 2; starts[5][x] = 7;
+            starts[6][y] = 3; starts[6][x] = 1;
+            starts[7][y] = 3; starts[7][x] = 2;
+            /* rank 0 is writing the following locations: ("-" means skip)
+                      -  -  -  -  -  0  0  -  -  - 
+                      0  -  -  -  -  -  -  -  -  - 
+                      -  -  -  -  -  -  0  0  -  - 
+                      0  0  0  -  -  -  -  -  -  - 
+             */
+        } else if (rank ==1) {
+            starts[ 0][y] = 0; starts[ 0][x] = 3;
+            starts[ 1][y] = 0; starts[ 1][x] = 8;
+            starts[ 2][y] = 1; starts[ 2][x] = 5;
+            starts[ 3][y] = 2; starts[ 3][x] = 0;
+            starts[ 4][y] = 2; starts[ 4][x] = 8;
+            starts[ 5][y] = 3; starts[ 5][x] = 4;
+            starts[ 6][y] = 0; starts[ 6][x] = 4;
+            starts[ 7][y] = 0; starts[ 7][x] = 9;
+            starts[ 8][y] = 1; starts[ 8][x] = 6;
+            starts[ 9][y] = 2; starts[ 9][x] = 1;
+            starts[10][y] = 2; starts[10][x] = 9;
+            starts[11][y] = 3; starts[11][x] = 5;
+            starts[12][y] = 3; starts[12][x] = 6;
+            /* rank 1 is writing the following locations: ("-" means skip)
+                      -  -  -  1  1  -  -  -  1  1 
+                      -  -  -  -  -  1  1  -  -  - 
+                      1  1  -  -  -  -  -  -  1  1 
+                      -  -  -  -  1  1  1  -  -  - 
+             */
+        } else if (rank ==2) {
+            starts[0][y] = 0; starts[0][x] = 7;
+            starts[1][y] = 1; starts[1][x] = 1;
+            starts[2][y] = 1; starts[2][x] = 7;
+            starts[3][y] = 2; starts[3][x] = 2; 
+            starts[4][y] = 3; starts[4][x] = 3;
+            starts[5][y] = 1; starts[5][x] = 2;
+            starts[6][y] = 1; starts[6][x] = 8;
+            starts[7][y] = 1; starts[7][x] = 3;
+            starts[8][y] = 1; starts[8][x] = 9;
+            /* rank 2 is writing the following locations: ("-" means skip)
+                      -  -  -  -  -  -  -  2  -  - 
+                      -  2  2  2  -  -  -  2  2  2 
+                      -  -  2  -  -  -  -  -  -  - 
+                      -  -  -  2  -  -  -  -  -  - 
+             */
+        } else if (rank ==3) {
+            starts[0][y] = 0; starts[0][x] = 0;
+            starts[1][y] = 1; starts[1][x] = 4;
+            starts[2][y] = 2; starts[2][x] = 3;
+            starts[3][y] = 3; starts[3][x] = 7;
+            starts[4][y] = 0; starts[4][x] = 1;
+            starts[5][y] = 2; starts[5][x] = 4;
+            starts[6][y] = 3; starts[6][x] = 8;
+            starts[7][y] = 0; starts[7][x] = 2;
+            starts[8][y] = 2; starts[8][x] = 5;
+            starts[9][y] = 3; starts[9][x] = 9;
+            /* rank 3 is writing the following locations: ("-" means skip)
+                      3  3  3  -  -  -  -  -  -  - 
+                      -  -  -  -  3  -  -  -  -  - 
+                      -  -  -  3  3  3  -  -  -  - 
+                      -  -  -  -  -  -  -  3  3  3 
+             */
+        }
+
+        /* allocate I/O buffer and initialize its contents */
+        buffer = (float*) malloc(num_reqs * sizeof(float));
+        for (i=0; i<num_reqs; i++) buffer[i] =  (float)rank;
+
+        /* set the buffer pointers to different offsets to the I/O buffer */
+        var.putVarn_all(num_reqs, starts, NULL, buffer);
+
+        free(buffer);
+        free(starts[0]);
+        free(starts);
+
+        /* file is close implicitly */
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+    }
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/put_varn_int.cpp b/examples/CXX/put_varn_int.cpp
new file mode 100644
index 0000000..279e71a
--- /dev/null
+++ b/examples/CXX/put_varn_int.cpp
@@ -0,0 +1,223 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: put_varn_int.cpp 1839 2014-10-30 20:22:37Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use a single call of NcmpiVar::putVarn_all() to
+ * write a sequence of requests with arbitrary array indices and lengths.
+ * Using ncmpi_put_varn_int_all() can achieve the same effect of HDF5 writing
+ * a sequence of selected file locations through the following 2 APIs.
+ *
+ *   H5Sselect_elements(fid, H5S_SELECT_SET, NUMP, (const hssize_t **)coord);
+ *   H5Dwrite(dataset, H5T_NATIVE_INT, mid, fid, H5P_DEFAULT, val); 
+ *
+ * Note that in NcmpiVar::putVarn_all(), users can write more than one
+ * element starting at each selected location.
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o put_varn_int put_varn_int.cpp -lpnetcdf
+ *    % mpiexec -n 4 ./put_varn_int /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             Y = 4 ;
+ *             X = 10 ;
+ *    variables:
+ *             int var(Y, X) ;
+ *    data:
+ *
+ *     var =
+ *       3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+ *       0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+ *       1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+ *       0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    << argv0;
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[128];
+    int i, j, rank, nprocs, verbose=1;
+    int num_reqs, *buffer;
+    MPI_Offset w_len, **starts, **counts;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+
+    if (nprocs != 4 && rank == 0 && verbose)
+        printf("Warning: this program is intended to run on 4 processes\n");
+
+    try {
+        /* create a new file for writing ------------------------------------*/
+        NcmpiFile nc(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                     NcmpiFile::classic5);
+
+        /* define dimensions Y and X */
+        vector<NcmpiDim> dimid(2);
+
+        dimid[0] = nc.addDim("Y", NY);
+        dimid[1] = nc.addDim("X", NX);
+
+        /* define a 2D variable of integer type */
+        NcmpiVar var = nc.addVar("var", ncmpiInt, dimid);
+
+        /* pick arbitrary numbers of requests for 4 processes */
+        num_reqs = 0;
+        if (rank == 0)      num_reqs = 4;
+        else if (rank == 1) num_reqs = 6;
+        else if (rank == 2) num_reqs = 5;
+        else if (rank == 3) num_reqs = 4;
+
+        starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+        counts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+        starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+        counts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+        for (i=1; i<num_reqs; i++) {
+            starts[i] = starts[i-1] + NDIMS;
+            counts[i] = counts[i-1] + NDIMS;
+        }
+
+        /* assign arbitrary starts and counts */
+        const int y=0, x=1;
+        if (rank == 0) {
+            starts[0][y] = 0; starts[0][x] = 5; counts[0][y] = 1; counts[0][x] = 2;
+            starts[1][y] = 1; starts[1][x] = 0; counts[1][y] = 1; counts[1][x] = 1;
+            starts[2][y] = 2; starts[2][x] = 6; counts[2][y] = 1; counts[2][x] = 2;
+            starts[3][y] = 3; starts[3][x] = 0; counts[3][y] = 1; counts[3][x] = 3;
+            /* rank 0 is writing the followings: ("-" means skip)
+                      -  -  -  -  -  0  0  -  -  - 
+                      0  -  -  -  -  -  -  -  -  - 
+                      -  -  -  -  -  -  0  0  -  - 
+                      0  0  0  -  -  -  -  -  -  - 
+             */
+        } else if (rank ==1) {
+            starts[0][y] = 0; starts[0][x] = 3; counts[0][y] = 1; counts[0][x] = 2;
+            starts[1][y] = 0; starts[1][x] = 8; counts[1][y] = 1; counts[1][x] = 2;
+            starts[2][y] = 1; starts[2][x] = 5; counts[2][y] = 1; counts[2][x] = 2;
+            starts[3][y] = 2; starts[3][x] = 0; counts[3][y] = 1; counts[3][x] = 2;
+            starts[4][y] = 2; starts[4][x] = 8; counts[4][y] = 1; counts[4][x] = 2;
+            starts[5][y] = 3; starts[5][x] = 4; counts[5][y] = 1; counts[5][x] = 3;
+            /* rank 1 is writing the followings: ("-" means skip)
+                      -  -  -  1  1  -  -  -  1  1 
+                      -  -  -  -  -  1  1  -  -  - 
+                      1  1  -  -  -  -  -  -  1  1 
+                      -  -  -  -  1  1  1  -  -  - 
+             */
+        } else if (rank ==2) {
+            starts[0][y] = 0; starts[0][x] = 7; counts[0][y] = 1; counts[0][x] = 1;
+            starts[1][y] = 1; starts[1][x] = 1; counts[1][y] = 1; counts[1][x] = 3;
+            starts[2][y] = 1; starts[2][x] = 7; counts[2][y] = 1; counts[2][x] = 3;
+            starts[3][y] = 2; starts[3][x] = 2; counts[3][y] = 1; counts[3][x] = 1;
+            starts[4][y] = 3; starts[4][x] = 3; counts[4][y] = 1; counts[4][x] = 1;
+            /* rank 2 is writing the followings: ("-" means skip)
+                      -  -  -  -  -  -  -  2  -  - 
+                      -  2  2  2  -  -  -  2  2  2 
+                      -  -  2  -  -  -  -  -  -  - 
+                      -  -  -  2  -  -  -  -  -  - 
+             */
+        } else if (rank ==3) {
+            starts[0][y] = 0; starts[0][x] = 0; counts[0][y] = 1; counts[0][x] = 3;
+            starts[1][y] = 1; starts[1][x] = 4; counts[1][y] = 1; counts[1][x] = 1;
+            starts[2][y] = 2; starts[2][x] = 3; counts[2][y] = 1; counts[2][x] = 3;
+            starts[3][y] = 3; starts[3][x] = 7; counts[3][y] = 1; counts[3][x] = 3;
+            /* rank 3 is writing the followings: ("-" means skip)
+                      3  3  3  -  -  -  -  -  -  - 
+                      -  -  -  -  3  -  -  -  -  - 
+                      -  -  -  3  3  3  -  -  -  - 
+                      -  -  -  -  -  -  -  3  3  3 
+             */
+        }
+
+        w_len = 0; /* total write length for this process */
+        for (i=0; i<num_reqs; i++) {
+            MPI_Offset w_req_len=1;
+            for (j=0; j<NDIMS; j++)
+                w_req_len *= counts[i][j];
+            w_len += w_req_len;
+        }
+
+        /* allocate I/O buffer and initialize its contents */
+        buffer = (int*) malloc(w_len * sizeof(int));
+        for (i=0; i<w_len; i++) buffer[i] = rank;
+
+        /* set the buffer pointers to different offsets to the I/O buffer */
+        var.putVarn_all(num_reqs, starts, counts, buffer);
+
+        free(buffer);
+        free(starts[0]);
+        free(counts[0]);
+        free(starts);
+        free(counts);
+
+        /* file is close implicitly */
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+    }
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/transpose.cpp b/examples/CXX/transpose.cpp
new file mode 100644
index 0000000..0c6361f
--- /dev/null
+++ b/examples/CXX/transpose.cpp
@@ -0,0 +1,226 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: transpose.cpp 1839 2014-10-30 20:22:37Z wkliao $ */
+
+/*
+ *    This example shows how to use varm API to write six 3D integer array
+ *    variables into a file. Each variable in the file is a dimensional
+ *    transposed array from the one stored in memory. In memory, a 3D array is
+ *    partitioned among all processes in a block-block-block fashion and in
+ *    ZYX (i.e. C) order. The dimension structures of the transposed six
+ *    arrays are
+ *       int ZYX_var(Z, Y, X) ;     ZYX -> ZYX
+ *       int ZXY_var(Z, X, Y) ;     ZYX -> ZXY
+ *       int YZX_var(Y, Z, X) ;     ZYX -> YZX
+ *       int YXZ_var(Y, X, Z) ;     ZYX -> YXZ
+ *       int XZY_var(X, Z, Y) ;     ZYX -> XZY
+ *       int XYZ_var(X, Y, Z) ;     ZYX -> XYZ
+ *
+ *    To compile:
+ *        mpicxx -O2 transpose.cpp -o transpose -lpnetcdf
+ *    To run:
+ *        mpiexec -n num_processes ./transpose [filename] [len]
+ *    where len decides the size of local array, which is len x len+1 x len+2.
+ *    So, each variable is of size len*(len+1)*(len+2) * nprocs * sizeof(int)
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strlen() */
+#include <unistd.h> /* getopt() */
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+#define NDIMS 3
+
+#define HANDLE_ERROR {                                \
+    if (err != NC_NOERR)                              \
+        printf("Error at line %d (%s)\n", __LINE__,   \
+               ncmpi_strerror(err));                  \
+}
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name] [len]\n"
+    "       [-h] Print this help\n"
+    "       [-q] Quiet mode\n"
+    "       [filename] output netCDF file name\n"
+    "       [len] size of each dimension of the local array\n"
+    << argv0;
+}
+
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    extern int optind;
+    char filename[128], str[512];
+    int i, j, k, rank, nprocs, len, bufsize, verbose=1;
+    int *buf, psizes[NDIMS];
+    vector<MPI_Offset> gsizes(NDIMS), starts(NDIMS), counts(NDIMS), imap(NDIMS);
+    vector<MPI_Offset> startsT(NDIMS), countsT(NDIMS), strides(NDIMS);
+
+    MPI_Init(&argc,&argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc >= 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+    len = 2;
+    if (argc >= 2) len = atoi(argv[1]); /* optional argument */
+
+    for (i=0; i<NDIMS; i++)
+        psizes[i] = 0;
+
+    /* calculate number of processes along each dimension */
+    MPI_Dims_create(nprocs, NDIMS, psizes);
+    if (verbose && rank == 0) {
+        sprintf(str, "psizes= ");
+        for (i=0; i<NDIMS; i++) sprintf(str+strlen(str), "%d ",psizes[i]);
+        printf("%s\n",str);
+    }
+
+    /* for each MPI rank, find its local rank IDs along each dimension in
+     * starts[] */
+    int lower_dims=1;
+    for (i=NDIMS-1; i>=0; i--) {
+        starts[i] = rank / lower_dims % psizes[i];
+        lower_dims *= psizes[i];
+    }
+    if (verbose) {
+        sprintf(str, "proc %d: dim rank= ", rank);
+        for (i=0; i<NDIMS; i++) sprintf(str+strlen(str), "%lld ",starts[i]);
+        printf("%s\n",str);
+    }
+
+    bufsize = 1;
+    for (i=0; i<NDIMS; i++) {
+        gsizes[i]  = (len + i) * psizes[i]; /* global array size */
+        starts[i] *= (len + i);             /* start indices */
+        counts[i]  = (len + i);             /* array elements */
+        bufsize   *= (len + i);
+    }
+
+    /* allocate buffer and initialize with contiguous  numbers */
+    buf = (int *) malloc(bufsize * sizeof(int));
+    for (k=0; k<counts[0]; k++)
+    for (j=0; j<counts[1]; j++)
+    for (i=0; i<counts[2]; i++)
+        buf[k*counts[1]*counts[2] +
+                      j*counts[2] + i] = (starts[0]+k)*gsizes[1]*gsizes[2]
+                                       + (starts[1]+j)*gsizes[2]
+                                       + (starts[2]+i);
+
+    try {
+        /* create the file */
+        NcmpiFile nc(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                     NcmpiFile::classic5);
+
+        /* define dimensions */
+        vector<NcmpiDim> dimids(NDIMS);
+        for (i=0; i<NDIMS; i++) {
+            sprintf(str, "%c", 'Z'-i);
+            dimids[i] = nc.addDim(str, gsizes[i]);
+        }
+
+
+        /* define variable with no transposed file layout: ZYX */
+        NcmpiVar ZYX_id = nc.addVar("ZYX_var", ncmpiInt, dimids);
+
+        /* define variable with transposed file layout: ZYX -> ZXY */
+        vector<NcmpiDim> dimidsT(NDIMS);
+        dimidsT[0] = dimids[0]; dimidsT[1] = dimids[2]; dimidsT[2] = dimids[1];
+        NcmpiVar ZXY_id = nc.addVar("ZXY_var", ncmpiInt, dimidsT);
+
+        /* define variable with transposed file layout: ZYX -> YZX */
+        dimidsT[0] = dimids[1]; dimidsT[1] = dimids[0]; dimidsT[2] = dimids[2];
+        NcmpiVar YZX_id = nc.addVar("YZX_var", ncmpiInt, dimidsT);
+
+        /* define variable with transposed file layout: ZYX -> YXZ */
+        dimidsT[0] = dimids[1]; dimidsT[1] = dimids[2]; dimidsT[2] = dimids[0];
+        NcmpiVar YXZ_id = nc.addVar("YXZ_var", ncmpiInt, dimidsT);
+
+        /* define variable with transposed file layout: ZYX -> XZY */
+        dimidsT[0] = dimids[2]; dimidsT[1] = dimids[0]; dimidsT[2] = dimids[1];
+        NcmpiVar XZY_id = nc.addVar("XZY_var", ncmpiInt, dimidsT);
+
+        /* define variable with transposed file layout: ZYX -> XYZ */
+        dimidsT[0] = dimids[2]; dimidsT[1] = dimids[1]; dimidsT[2] = dimids[0];
+        NcmpiVar XYZ_id = nc.addVar("XYZ_var", ncmpiInt, dimidsT);
+
+        /* write the whole variable in file: ZYX */
+        ZYX_id.putVar_all(starts, counts, &buf[0]);
+
+        strides[0] = strides[1] = strides[2] = 1;
+        /* ZYX -> ZXY: */
+        imap[1] = 1; imap[2] = counts[2]; imap[0] = counts[1]*counts[2];
+        startsT[0] = starts[0]; startsT[1] = starts[2]; startsT[2] = starts[1];
+        countsT[0] = counts[0]; countsT[1] = counts[2]; countsT[2] = counts[1];
+        /* write the transposed variable */
+        ZXY_id.putVar_all(startsT, countsT, strides, imap, &buf[0]);
+
+        /* ZYX -> YZX: */
+        imap[2] = 1; imap[0] = counts[2]; imap[1] = counts[1]*counts[2];
+        startsT[0] = starts[1]; startsT[1] = starts[0]; startsT[2] = starts[2];
+        countsT[0] = counts[1]; countsT[1] = counts[0]; countsT[2] = counts[2];
+        /* write the transposed variable */
+        YZX_id.putVar_all(startsT, countsT, strides, imap, &buf[0]);
+
+        /* ZYX -> YXZ: */
+        imap[1] = 1; imap[0] = counts[2]; imap[2] = counts[1]*counts[2];
+        startsT[0] = starts[1]; startsT[1] = starts[2]; startsT[2] = starts[0];
+        countsT[0] = counts[1]; countsT[1] = counts[2]; countsT[2] = counts[0];
+        /* write the transposed variable */
+        YXZ_id.putVar_all(startsT, countsT, strides, imap, &buf[0]);
+
+        /* ZYX -> XZY: */
+        imap[0] = 1; imap[2] = counts[2]; imap[1] = counts[1]*counts[2];
+        startsT[0] = starts[2]; startsT[1] = starts[0]; startsT[2] = starts[1];
+        countsT[0] = counts[2]; countsT[1] = counts[0]; countsT[2] = counts[1];
+        /* write the transposed variable */
+        XZY_id.putVar_all(startsT, countsT, strides, imap, &buf[0]);
+
+        /* ZYX -> XYZ: */
+        imap[0] = 1; imap[1] = counts[2]; imap[2] = counts[1]*counts[2];
+        startsT[0] = starts[2]; startsT[1] = starts[1]; startsT[2] = starts[0];
+        countsT[0] = counts[2]; countsT[1] = counts[1]; countsT[2] = counts[0];
+        /* write the transposed variable */
+        XYZ_id.putVar_all(startsT, countsT, strides, imap, &buf[0]);
+
+        /* file is close implicitly */
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+    }
+
+    free(buf);
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/CXX/vard_int.cpp b/examples/CXX/vard_int.cpp
new file mode 100644
index 0000000..d685ee2
--- /dev/null
+++ b/examples/CXX/vard_int.cpp
@@ -0,0 +1,209 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: vard_int.cpp 2239 2015-12-18 18:21:09Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use the vard API ncmpi_put_vard() and
+ * ncmpi_get_vard() to write and read 2D record and fixed-size variables.
+ *
+ *    To compile:
+ *        mpicxx -O2 vard_int.cpp -o vard_int -lpnetcdf
+ *
+ * Example commands for MPI run and outputs from running ncmpidump on the
+ * NC file produced by this example program:
+ *
+ *    % mpiexec -n 4 ./vard_int /pvfs2/wkliao/testfile.nc
+ *
+ * The expected results from the output file contents are:
+ *
+ *  % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-1
+ *    dimensions:
+ *           REC_DIM = UNLIMITED ; // (2 currently)
+ *           X = 12 ;
+ *           FIX_DIM = 2 ;
+ *    variables:
+ *           int rec_var(REC_DIM, X) ;
+ *           int fix_var(FIX_DIM, X) ;
+ *    data:
+ *
+ *     rec_var =
+ *       0, 1, 2, 100, 101, 102, 200, 201, 202, 300, 301, 302,
+ *       10, 11, 12, 110, 111, 112, 210, 211, 212, 310, 311, 312 ;
+ *
+ *     fix_var =
+ *       0, 1, 2, 100, 101, 102, 200, 201, 202, 300, 301, 302,
+ *       10, 11, 12, 110, 111, 112, 210, 211, 212, 310, 311, 312 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <pnetcdf>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+#define NY 2
+#define NX 3
+
+static void
+usage(char *argv0)
+{
+    cerr <<
+    "Usage: %s [-h] | [-q] [file_name]\n"
+    "       [-h] Print help\n"
+    "       [-q] Quiet mode (reports when fail)\n"
+    "       [filename] output netCDF file name\n"
+    << argv0;
+}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[128];
+    int i, j, verbose=1;
+    int          rank, nprocs, array_of_blocklengths[2], buf[NY][NX];
+    int          array_of_sizes[2], array_of_subsizes[2], array_of_starts[2];
+    MPI_Offset   recsize, bufcount, len;
+    MPI_Aint     array_of_displacements[2];
+    MPI_Datatype buftype, rec_filetype, fix_filetype;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    while ((i = getopt(argc, argv, "hq")) != EOF)
+        switch(i) {
+            case 'q': verbose = 0;
+                      break;
+            case 'h':
+            default:  if (rank==0) usage(argv[0]);
+                      MPI_Finalize();
+                      return 0;
+        }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) strcpy(filename, argv[0]); /* optional argument */
+    else           strcpy(filename, "testfile.nc");
+
+    vector <MPI_Offset> start(2), count(2);
+    start[0] = 0; start[1] = NX*rank;
+    count[0] = 2; count[1] = NX;
+    if (verbose)
+        printf("%d: start=%lld %lld count=%lld %lld\n",rank,
+               start[0],start[1],count[0],count[1]);
+
+    /* create a file type for the fixed-size variable */
+    array_of_sizes[0]    = 2;
+    array_of_sizes[1]    = NX*nprocs;
+    array_of_subsizes[0] = count[0];
+    array_of_subsizes[1] = count[1];
+    array_of_starts[0]   = start[0];
+    array_of_starts[1]   = start[1];
+    MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                             array_of_starts, MPI_ORDER_C,
+                             MPI_INT, &fix_filetype);
+    MPI_Type_commit(&fix_filetype);
+
+    buftype = MPI_INT;
+    bufcount = count[0] * count[1];
+
+    try {
+        /* create a new file for writing ------------------------------------*/
+        NcmpiFile nc(MPI_COMM_WORLD, filename, NcmpiFile::replace);
+
+        /* define 3 dimensions */
+        vector<NcmpiDim> recdimid(2);
+        recdimid[0] = nc.addDim("REC_DIM", NC_UNLIMITED);
+        recdimid[1] = nc.addDim("X", NX*nprocs);
+
+        vector<NcmpiDim> fixdimid(2);
+        fixdimid[0] = nc.addDim("FIX_DIM", 2);
+        fixdimid[1] = recdimid[1];
+
+        /* define a variable of size (NZ * nprocs) * NY */
+        NcmpiVar var0 = nc.addVar("rec_var", ncmpiInt, recdimid);
+
+        /* define a variable of size NY * (NX * nprocs) */
+        NcmpiVar var1 = nc.addVar("fix_var", ncmpiInt, fixdimid);
+
+        nc.enddef();
+
+        /* create a file type for the record variable */
+        recsize = nc.getRecSize();
+        for (i=0; i<count[0]; i++) {
+            array_of_blocklengths[i] = count[1];
+            array_of_displacements[i] = start[1]*sizeof(int) + recsize * i;
+        }
+        MPI_Type_create_hindexed(2, array_of_blocklengths,
+                        array_of_displacements, MPI_INT, &rec_filetype);
+        MPI_Type_commit(&rec_filetype);
+
+        /* initialize the contents of the array */
+        for (j=0; j<NY; j++) for (i=0; i<NX; i++)
+            buf[j][i] = rank*100 + j*10 + i;
+
+        /* write the record variable */
+        var0.putVard_all(rec_filetype, buf, bufcount, buftype);
+
+        /* check if the number of records changed to 2 */
+        len = recdimid[0].getSize();
+        if (len != 2)
+            cout << "Error: number of records should be 2 but got " << len << "\n";
+
+        /* write the fixed-size variable */
+        var1.putVard_all(fix_filetype, buf, bufcount, buftype);
+
+        /* file is close implicitly */
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+    }
+
+    try {
+        /* open file for reading -----------------------------------------*/
+        NcmpiFile nc(MPI_COMM_WORLD, filename, NcmpiFile::read);
+
+        NcmpiVar var0 = nc.getVar("rec_var");
+        NcmpiVar var1 = nc.getVar("fix_var");
+
+        /* read the record variable */
+        var0.getVard_all(rec_filetype, buf, bufcount, buftype);
+
+        /* read the fixed-size variable */
+        var1.getVard_all(fix_filetype, buf, bufcount, buftype);
+    }
+    catch(NcmpiException& e) {
+       cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+    }
+
+    MPI_Type_free(&rec_filetype);
+    MPI_Type_free(&fix_filetype);
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/F77/Makefile.in b/examples/F77/Makefile.in
new file mode 100644
index 0000000..b033cab
--- /dev/null
+++ b/examples/F77/Makefile.in
@@ -0,0 +1,135 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2236 2015-12-18 03:49:41Z wkliao $
+#
+# @configure_input@
+
+srcdir  = @srcdir@
+VPATH   = @srcdir@
+
+include ../../macros.make
+
+# note the order of -L list matters
+INCLUDES  = -I../../src/lib -I../../src/libf
+ifeq (@SIZEOF_MPI_AINT_IS_4@, yes)
+FPPFLAGS += -DSIZEOF_MPI_AINT_IS_4
+endif
+FLDFLAGS := -L../../src/lib $(FLDFLAGS) $(LDFLAGS)
+LIBS     := -lpnetcdf $(LIBS)
+
+F77_SRCS  = nonblocking_write.f \
+            column_wise.f \
+            block_cyclic.f \
+            flexible_api.f \
+            get_info.f \
+            hints.f \
+            put_vara.f \
+            put_varn_real.f \
+            put_varn_int.f \
+            transpose.f \
+            i_varn_real.f \
+            bput_varn_int8.f \
+            fill_mode.f
+
+F77F_SRCS = vard_int.F
+
+PROGS     = $(F77_SRCS:.f=)   $(F77F_SRCS:.F=)
+OBJS      = $(F77_SRCS:.f=.o) $(F77F_SRCS:.F=.o)
+
+UTIL_SRCS  = utils.F90
+UTIL_OBJS  = $(UTIL_SRCS:.F90=.o)
+
+GARBAGE      = $(PROGS) *.nc
+
+PACKING_LIST = $(F77_SRCS) $(F77F_SRCS) $(UTIL_SRCS) depend Makefile.in
+
+all: $(PROGS)
+
+install:
+
+uninstall:
+
+nonblocking_write: nonblocking_write.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+get_info: get_info.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+column_wise: column_wise.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+block_cyclic: block_cyclic.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+put_vara: put_vara.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+hints: hints.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+flexible_api: flexible_api.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+put_varn_int: put_varn_int.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+put_varn_real: put_varn_real.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+transpose: transpose.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+vard_int: vard_int.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+i_varn_real: i_varn_real.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+bput_varn_int8: bput_varn_int8.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+fill_mode: fill_mode.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(FLDFLAGS) $(LIBS)
+
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+TEST_MPIRUN_8  = $(subst NP,8,$(TEST_MPIRUN))
+TEST_MPIRUN_3  = $(subst NP,3,$(TEST_MPIRUN))
+
+ptest4: $(PROGS)
+	@for i in $(PROGS); do ( \
+        $(TEST_MPIRUN_4) ./$$i -q $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS: F77 parallel run on 4 processes --------------- $$i"; \
+        else \
+           echo "FAILED: F77 parallel run on 4 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest8: $(PROGS)
+	@for i in $(PROGS); do ( \
+        $(TEST_MPIRUN_8) ./$$i -q $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS: F77 parallel run on 8 processes --------------- $$i"; \
+        else \
+           echo "FAILED: F77 parallel run on 8 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest3: $(PROGS)
+	@for i in $(PROGS); do ( \
+        $(TEST_MPIRUN_3) ./$$i -q $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS: F77 parallel run on 3 processes --------------- $$i"; \
+        else \
+           echo "FAILED: F77 parallel run on 3 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest: ptest4
+ptests: ptest3 ptest4 ptest8
+ptest2 ptest6 ptest10:
+
+include $(srcdir)/depend
+include $(srcdir)/../../rules.make
+
+$(LIBRARY): ;
+
diff --git a/examples/F77/block_cyclic.f b/examples/F77/block_cyclic.f
new file mode 100644
index 0000000..66d3843
--- /dev/null
+++ b/examples/F77/block_cyclic.f
@@ -0,0 +1,284 @@
+!
+!  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: block_cyclic.f 2245 2015-12-20 18:39:52Z wkliao $
+
+
+! This example, generalized from column_wise.f, makes a number of nonblocking
+! API calls, each writes a block of columns into a 2D integer array. In other
+! words, the I/O pattern is a blocked cyclic along X dimension.
+!
+! Each process writes NX rows in total. The block length is controlled by
+! block_len. In this example, block_len is set to 2. Blocks are layout in a
+! cyclic fashion in the file. This example can test if PnetCDF can coalesce
+! file offsets and lengths when constructing a merged filetype.
+! 
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file. In this example, block_len = 2.
+!
+!    % mpif77 -O2 -o block_cyclic block_cyclic.f -lpnetcdf
+!    % mpiexec -n 4 ./block_cyclic /pvfs2/wkliao/testfile.nc
+!
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!            Y = 10 ;
+!            X = 16 ;
+!    variables:
+!            int var(Y, X) ;
+!    data:
+!
+!     var =
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13 ;
+!    }
+!
+
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          endif
+      end ! subroutine check
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          integer NY, NX
+          PARAMETER(NX=10, NY=4)
+
+          character*128 filename, cmd
+          integer i, j, rank, nprocs, err, ierr, num_reqs, get_args
+          integer ncid, cmode, varid, dimid(2), stride, block_len
+          integer buf(NX, NY)
+          integer reqs(NY), sts(NY)
+          integer*8 G_NY, myOff, block_start,
+     +                                  global_nx, global_ny
+          integer*8 start(2), count(2)
+          integer*8 malloc_size, sum_size
+          logical verbose
+          integer dummy
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                   err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, err)
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                       MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! the global array is NX * (NY * nprocs) */
+          G_NY  = NY * nprocs
+          myOff = NY * rank
+
+          ! define dimensions
+          global_nx = NX
+          err = nfmpi_def_dim(ncid, 'Y', global_nx, dimid(2))
+          call check(err, 'In nfmpi_def_dim Y')
+
+          err = nfmpi_def_dim(ncid, 'X', G_NY, dimid(1))
+          call check(err, 'In nfmpi_def_dim X')
+
+          err = nfmpi_def_var(ncid, 'var', NF_INT, 2, dimid, varid)
+          call check(err, 'In nfmpi_def_var var')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! First, fill the entire array with zeros, using a blocking I/O.
+          ! Every process writes a subarray of size NX * NY
+          do i=1, NY 
+          do j=1, NX
+             buf(j,i) = 0
+          enddo
+          enddo
+          start(1) = myOff+1
+          start(2) = 1
+          count(1) = NY
+          count(2) = NX
+          err = nfmpi_put_vara_int_all(ncid, varid, start, count, buf)
+          call check(err, 'In nfmpi_put_vara_int_all: ')
+
+          ! initialize the buffer with rank ID
+          do i=1, NY 
+          do j=1, NX
+             buf(j,i) = rank+10
+          enddo
+          enddo
+
+          ! each proc writes NY columns of the 2D array, block_len controls the
+          ! the number of contiguous columns at a time
+          block_start = 0
+          block_len   = 2  ! can be 1, 2, 3, ..., NY
+          if (block_len .GT. NY) block_len = NY
+
+          start(1) = rank * block_len + 1
+          start(2) = 1
+          count(1) = 1
+          count(2) = NX
+          num_reqs = 0
+
+          do i=1, NY
+             num_reqs = num_reqs + 1
+             err = nfmpi_iput_vara_int(ncid, varid, start, count,
+     +                                 buf(1,i), reqs(num_reqs))
+             call check(err, 'In nfmpi_iput_vara_int: ')
+
+             if (MOD(i, block_len) .EQ. 0) then
+                 stride = NY-i
+                 if (stride .GT. block_len) stride = block_len
+                 block_start = block_start + block_len * nprocs
+                 start(1) = block_start + stride * rank + 1
+             else
+                 start(1) = start(1) + 1
+             endif
+          enddo
+
+          err = nfmpi_wait_all(ncid, num_reqs, reqs, sts)
+          call check(err, 'In nfmpi_wait_all: ')
+
+          ! check status of all requests
+          do i=1, num_reqs
+             if (sts(i) .NE. NF_NOERR) then
+                 print*, "Error: nonblocking write fails on request",
+     +                   i, ' ', nfmpi_strerror(sts(i))
+             endif
+          enddo
+
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! open an existing file created earlier for read
+          err = nfmpi_open(MPI_COMM_WORLD, filename, NF_NOWRITE,
+     +                     MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_open: ')
+
+          ! the global array is NX * (NY * nprocs) */
+          err = nfmpi_inq_dimid(ncid, "X", dimid(1))
+          call check(err, 'In nfmpi_inq_dimid X: ')
+          err = nfmpi_inq_dimlen(ncid, dimid(1), global_ny)
+          call check(err, 'In nfmpi_inq_dimlen: ')
+          ! G_NY must == NY * nprocs
+          ! myNY must == global_ny / nprocs
+
+          err = nfmpi_inq_dimid(ncid, "Y", dimid(2))
+          call check(err, 'In nfmpi_inq_dimid Y: ')
+          err = nfmpi_inq_dimlen(ncid, dimid(2), global_nx)
+          call check(err, 'In nfmpi_inq_dimlen: ')
+          ! global_nx must == NX
+
+          err = nfmpi_inq_varid(ncid, "var", varid)
+          call check(err, 'In nfmpi_inq_varid: ')
+
+          ! initialize the buffer with -1, so a read error can be pinpointed
+          do i=1, NY 
+          do j=1, NX
+             buf(j,i) = -1
+          enddo
+          enddo
+
+          ! each proc reads NY columns of the 2D array, block_len controls the
+          ! the number of contiguous columns at a time */
+          block_start = 0
+          block_len   = 2  ! can be 1, 2, 3, ..., NY
+          if (block_len .GT. NY) block_len = NY
+
+          start(1) = rank * block_len + 1
+          start(2) = 1
+          count(1) = 1
+          count(2) = global_nx
+          num_reqs = 0
+
+          do i=1, NY
+             num_reqs = num_reqs + 1
+             err = nfmpi_iget_vara_int(ncid, varid, start, count,
+     +                                 buf(1,i), reqs(num_reqs))
+             call check(err, 'In nfmpi_iget_vara_int: ')
+
+             if (MOD(i, block_len) .EQ. 0) then
+                 stride = NY-i
+                 if (stride .GT. block_len) stride = block_len
+                 block_start = block_start + block_len * nprocs
+                 start(1) = block_start + stride * rank + 1
+             else
+                 start(1) = start(1) + 1
+             endif
+          enddo
+
+          err = nfmpi_wait_all(ncid, num_reqs, reqs, sts)
+          call check(err, 'In nfmpi_wait_all: ')
+
+          ! check status of all requests
+          do i=1, num_reqs
+             if (sts(i) .NE. NF_NOERR) then
+                 print*, "Error: nonblocking write fails on request",
+     +                   i, ' ', nfmpi_strerror(sts(i))
+             endif
+          enddo
+
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! check the read contents */
+          do j=1, NY
+             do i=1, NX
+                  if (buf(i,j) .NE. rank+10) then
+                      print*, 'Read contents mismatch at buf i=', i,
+     +                        ' j=',j,' =', buf(i,j),' (should be ',
+     +                        rank+10, ')\n'
+                  endif
+             enddo
+          enddo
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+
+      end ! program main
diff --git a/examples/F77/bput_varn_int8.f b/examples/F77/bput_varn_int8.f
new file mode 100644
index 0000000..6cb2a42
--- /dev/null
+++ b/examples/F77/bput_varn_int8.f
@@ -0,0 +1,344 @@
+!
+!   Copyright (C) 2014, Northwestern University
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: bput_varn_int8.f 2224 2015-12-16 06:10:36Z wkliao $
+
+! This example tests nonblocking varn API: nfmpi_bput_varn_int8()
+! It writes a sequence of requests with arbitrary array indices and
+! lengths to four variables of type NF_INT64
+!
+! The compile and run commands are given below, together with an
+! ncmpidump of the output file.
+!
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file.
+!
+!    % mpif77 -O2 -o bput_varn_int8 bput_varn_int8.f -lpnetcdf
+!    % mpiexec -n 4 ./bput_varn_int8 /pvfs2/wkliao/testfile.nc
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!     dimensions:
+!              Y = 4 ;
+!              X = 10 ;
+!     variables:
+!             int64 var0(Y, X) ;
+!             int64 var1(Y, X) ;
+!             int64 var2(Y, X) ;
+!             int64 var3(Y, X) ;
+!     data:
+!
+!     var0 =
+!      1, 0, 3, 0,
+!      1, 2, 3, 0,
+!      1, 2, 2, 0,
+!      3, 2, 1, 2,
+!      3, 1, 1, 3,
+!      0, 3, 1, 3,
+!      0, 3, 0, 3,
+!      2, 2, 0, 1,
+!      3, 2, 3, 1,
+!      3, 2, 3, 1 ;
+!
+!     var1 =
+!      2, 1, 0, 1,
+!      2, 3, 0, 1,
+!      2, 3, 3, 1,
+!      0, 3, 2, 3,
+!      0, 2, 2, 0,
+!      1, 0, 2, 0,
+!      1, 0, 1, 0,
+!      3, 3, 1, 2,
+!      0, 3, 0, 2,
+!      0, 3, 0, 2 ;
+!
+!     var2 =
+!      3, 2, 1, 2,
+!      3, 0, 1, 2,
+!      3, 0, 0, 2,
+!      1, 0, 3, 0,
+!      1, 3, 3, 1,
+!      2, 1, 3, 1,
+!      2, 1, 2, 1,
+!      0, 0, 2, 3,
+!      1, 0, 1, 3,
+!      1, 0, 1, 3 ;
+!
+!     var3 =
+!      0, 3, 2, 3,
+!      0, 1, 2, 3,
+!      0, 1, 1, 3,
+!      2, 1, 0, 1,
+!      2, 0, 0, 2,
+!      3, 2, 0, 2,
+!      3, 2, 3, 2,
+!      1, 1, 3, 0,
+!      2, 1, 2, 0,
+!      2, 1, 2, 0 ;
+!     }
+!
+!    Note the above dump is in C order
+!
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          endif
+      end
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          integer NDIMS
+          integer*8 NX, NY
+          PARAMETER(NDIMS=2, NX=4, NY=10)
+
+          character*128 filename, cmd
+          integer i, j, k, n, err, ierr, nprocs, rank, get_args
+          integer cmode, ncid, varid(4), dimid(NDIMS), nreqs
+          integer reqs(4), sts(4), num_segs(4)
+
+          integer*8 start(NDIMS, 6, 4), count(NDIMS, 6, 4)
+          integer*8 malloc_size, sum_size, two
+          integer*8 req_len, bbufsize
+          integer*8 buffer(NX*NY,4)
+          logical verbose
+          integer dummy
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          two = 2
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                   err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, err)
+
+          if (nprocs .NE. 4 .AND. rank .EQ. 0 .AND. verbose)
+     +        print*,'Warning: ',cmd,' is intended to run on ',
+     +               '4 processes'
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                        MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define dimensions x and y
+          err = nfmpi_def_dim(ncid, "Y", NY, dimid(2))
+          call check(err, 'In nfmpi_def_dim Y: ')
+          err = nfmpi_def_dim(ncid, "X", NX, dimid(1))
+          call check(err, 'In nfmpi_def_dim X: ')
+
+          ! define 4 2D variables of int64 type
+          err = nfmpi_def_var(ncid, "var0", NF_INT64, two,
+     +                        dimid,varid(1))
+          call check(err, 'In nfmpi_def_var var0: ')
+          err = nfmpi_def_var(ncid, "var1", NF_INT64, two,
+     +                        dimid,varid(2))
+          call check(err, 'In nfmpi_def_var var1: ')
+          err = nfmpi_def_var(ncid, "var2", NF_INT64, two,
+     +                        dimid,varid(3))
+          call check(err, 'In nfmpi_def_var var2: ')
+          err = nfmpi_def_var(ncid, "var3", NF_INT64, two,
+     +                        dimid,varid(4))
+          call check(err, 'In nfmpi_def_var var3: ')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! now we are in data mode
+          n = mod(rank, 4) + 1
+          num_segs(n) = 4 ! number of segments for this request
+          start(1,1,n)=1
+          start(2,1,n)=6
+          count(1,1,n)=1
+          count(2,1,n)=2
+          start(1,2,n)=2
+          start(2,2,n)=1
+          count(1,2,n)=1
+          count(2,2,n)=1
+          start(1,3,n)=3
+          start(2,3,n)=7
+          count(1,3,n)=1
+          count(2,3,n)=2
+          start(1,4,n)=4
+          start(2,4,n)=1
+          count(1,4,n)=1
+          count(2,4,n)=3
+          ! start(:,:,n) n_count(:,:,n) indicate the following:
+          ! ("-" means skip)
+          !   -  -  -  -  -  X  X  -  -  -
+          !   X  -  -  -  -  -  -  -  -  -
+          !   -  -  -  -  -  -  X  X  -  -
+          !   X  X  X  -  -  -  -  -  -  -
+
+          n = mod(rank+1, 4) + 1
+          num_segs(n) = 6 ! number of segments for this request
+          start(1,1,n)=1
+          start(2,1,n)=4
+          count(1,1,n)=1
+          count(2,1,n)=2
+          start(1,2,n)=1
+          start(2,2,n)=9
+          count(1,2,n)=1
+          count(2,2,n)=2
+          start(1,3,n)=2
+          start(2,3,n)=6
+          count(1,3,n)=1
+          count(2,3,n)=2
+          start(1,4,n)=3
+          start(2,4,n)=1
+          count(1,4,n)=1
+          count(2,4,n)=2
+          start(1,5,n)=3
+          start(2,5,n)=9
+          count(1,5,n)=1
+          count(2,5,n)=2
+          start(1,6,n)=4
+          start(2,6,n)=5
+          count(1,6,n)=1
+          count(2,6,n)=3
+          ! start(:,:,n) n_count(:,:,n) indicate the following:
+          !   -  -  -  X  X  -  -  -  X  X
+          !   -  -  -  -  -  X  X  -  -  -
+          !   X  X  -  -  -  -  -  -  X  X
+          !   -  -  -  -  X  X  X  -  -  -
+
+          n = mod(rank+2, 4) + 1
+          num_segs(n) = 5 ! number of segments for this request
+          start(1,1,n)=1
+          start(2,1,n)=8
+          count(1,1,n)=1
+          count(2,1,n)=1
+          start(1,2,n)=2
+          start(2,2,n)=2
+          count(1,2,n)=1
+          count(2,2,n)=3
+          start(1,3,n)=2
+          start(2,3,n)=8
+          count(1,3,n)=1
+          count(2,3,n)=3
+          start(1,4,n)=3
+          start(2,4,n)=3
+          count(1,4,n)=1
+          count(2,4,n)=1
+          start(1,5,n)=4
+          start(2,5,n)=4
+          count(1,5,n)=1
+          count(2,5,n)=1
+          ! start(:,:,n) n_count(:,:,n) indicate the following:
+          !   -  -  -  -  -  -  -  X  -  -
+          !   -  X  X  X  -  -  -  X  X  X
+          !   -  -  X  -  -  -  -  -  -  -
+          !   -  -  -  X  -  -  -  -  -  -
+
+          n = mod(rank+3, 4) + 1
+          num_segs(n) = 4 ! number of segments for this request
+          start(1,1,n)=1
+          start(2,1,n)=1
+          count(1,1,n)=1
+          count(2,1,n)=3
+          start(1,2,n)=2
+          start(2,2,n)=5
+          count(1,2,n)=1
+          count(2,2,n)=1
+          start(1,3,n)=3
+          start(2,3,n)=4
+          count(1,3,n)=1
+          count(2,3,n)=3
+          start(1,4,n)=4
+          start(2,4,n)=8
+          count(1,4,n)=1
+          count(2,4,n)=3
+          ! start(:,:,n) n_count(:,:,n) indicate the following:
+          !   X  X  X  -  -  -  -  -  -  -
+          !   -  -  -  -  X  -  -  -  -  -
+          !   -  -  -  X  X  X  -  -  -  -
+          !   -  -  -  -  -  -  -  X  X  X
+
+          ! only rank 0, 1, 2, and 3 do I/O:
+          ! each of ranks 0 to 3 write 4 nonblocking requests
+          nreqs = 4
+          if (rank .GE. 4) nreqs = 0
+
+          ! initialize buffer contents
+          do i=1, 4
+          do j=1, NX*NY
+             buffer(j,i) = rank
+          enddo
+          enddo
+
+          ! bbufsize must be max of data type converted before and after
+          bbufsize = 0
+          do i=1, nreqs
+             do j=1, num_segs(i)
+                req_len = 1
+                do k=1, NDIMS
+                   req_len = req_len * count(k,j,i)
+                enddo
+                bbufsize = bbufsize + req_len
+             enddo
+          enddo
+          bbufsize = bbufsize * 8  ! 8 is size of integer(kind=8)
+          if (bbufsize .GT. 0) then
+              err = nfmpi_buffer_attach(ncid, bbufsize)
+              call check(err, 'In nfmpi_buffer_attach')
+          endif
+
+          do i=1, nreqs
+             err = nfmpi_bput_varn_int8(ncid, varid(i), num_segs(i),
+     +                                  start(1,1,i), count(1,1,i),
+     +                                  buffer(1,i), reqs(i))
+             call check(err, 'In nfmpi_bput_varn_int8: ')
+          enddo
+          err = nfmpi_wait_all(ncid, nreqs, reqs, sts)
+          call check(err, 'In nfmpi_wait_all: ')
+
+          ! detach the temporary buffer
+          if (bbufsize .GT. 0) then
+              err = nfmpi_buffer_detach(ncid)
+              call check(err, 'In nfmpi_buffer_detach: ')
+          endif
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size, ' B yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end
+
diff --git a/examples/F77/column_wise.f b/examples/F77/column_wise.f
new file mode 100644
index 0000000..613b5c7
--- /dev/null
+++ b/examples/F77/column_wise.f
@@ -0,0 +1,196 @@
+!
+!  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: column_wise.f 2245 2015-12-20 18:39:52Z wkliao $
+
+! This example makes a number of nonblocking API calls, each writes a single
+! row of a 2D integer array. Each process writes NY rows and any two
+! consecutive rows are of nprocs-row distance apart from each other.
+! In this case, the fileview of each process interleaves with all other processes.
+! If simply concatenating fileviews of all the nonblocking calls will result
+! in a fileview that violates the MPI-IO requirement on the fileview of which
+! flattened file offsets must be monotonically non-decreasing. PnetCDF handles
+! this case by breaking down each nonblocking call into a list of offset-length
+! pairs, merging the pairs across multiple nonblocking calls, and sorting
+! them into an increasing order. The sorted pairs are used to construct a
+! fileview that meets the monotonically non-decreasing offset requirement,
+! and thus the nonblocking requests can be serviced by a single MPI-IO call. 
+! 
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file. Note ncdump is in C order (row major).
+!
+!    % mpif77 -O2 -o column_wise column_wise.f -lpnetcdf
+!    % mpiexec -n 4 ./column_wise /pvfs2/wkliao/testfile.nc
+!
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!            Y = 10 ;
+!            X = 16 ;
+!    variables:
+!            int var(Y, X) ;
+!    data:
+!
+!     var =
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 ;
+!    }
+!
+
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          integer NY, NX
+          PARAMETER(NX=10, NY=4)
+
+          character*128 filename, cmd
+          integer i, j, rank, nprocs, err, ierr, num_reqs, get_args
+          integer ncid, cmode, varid, dimid(2)
+          integer buf(NX, NY)
+          integer reqs(NY), sts(NY)
+          integer*8 G_NY, myOff, block_start, block_len, global_nx
+          integer*8 start(2), count(2)
+          integer*8 malloc_size, sum_size
+          logical verbose
+          integer dummy
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                   err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, err)
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                       MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! the global array is NX * (NY * nprocs) */
+          G_NY  = NY * nprocs
+          myOff = NY * rank
+
+          ! define dimensions
+          global_nx = NX
+          err = nfmpi_def_dim(ncid, 'Y', global_nx, dimid(2))
+          call check(err, 'In nfmpi_def_dim Y')
+
+          err = nfmpi_def_dim(ncid, 'X', G_NY, dimid(1))
+          call check(err, 'In nfmpi_def_dim X')
+
+          err = nfmpi_def_var(ncid, 'var', NF_INT, 2, dimid, varid)
+          call check(err, 'In nfmpi_def_var var')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! First, fill the entire array with zeros, using a blocking I/O.
+          ! Every process writes a subarray of size NX * NY
+          do i=1, NY
+          do j=1, NX
+             buf(j,i) = 0
+          enddo
+          enddo
+          start(1) = myOff+1
+          start(2) = 1
+          count(1) = NY
+          count(2) = NX
+          err = nfmpi_put_vara_int_all(ncid, varid, start, count, buf)
+          call check(err, 'In nfmpi_put_vara_int_all: ')
+
+          ! initialize the buffer with rank ID
+          do i=1, NY
+          do j=1, NX
+             buf(j,i) = rank
+          enddo
+          enddo
+
+          ! each proc writes NY columns of the 2D array, block_len controls the
+          ! the number of contiguous columns at a time
+          block_start = 0
+          block_len   = 2  ! can be 1, 2, 3, ..., NY
+          if (block_len .GT. NY) block_len = NY
+
+          start(1) = rank + 1
+          start(2) = 1
+          count(1) = 1
+          count(2) = NX
+          num_reqs = 0
+
+          do i=1, NY
+             num_reqs = num_reqs + 1
+             err = nfmpi_iput_vara_int(ncid, varid, start, count,
+     +                                 buf(1,i), reqs(num_reqs))
+             call check(err, 'In nfmpi_iput_vara_int: ')
+
+             start(1) = start(1) + nprocs
+          enddo
+
+          err = nfmpi_wait_all(ncid, num_reqs, reqs, sts)
+          call check(err, 'In nfmpi_wait_all: ')
+
+          ! check status of all requests
+          do i=1, num_reqs
+             if (sts(i) .NE. NF_NOERR) then
+                 print*, "Error: nonblocking write fails on request",
+     +                   i, ' ', nfmpi_strerror(sts(i))
+             endif
+          enddo
+
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end ! program main
diff --git a/examples/F77/depend b/examples/F77/depend
new file mode 100644
index 0000000..63b2521
--- /dev/null
+++ b/examples/F77/depend
@@ -0,0 +1,14 @@
+block_cyclic.o: block_cyclic.f
+column_wise.o: column_wise.f
+flexible_api.o: flexible_api.f
+get_info.o: get_info.f
+hints.o: hints.f
+nonblocking_write.o: nonblocking_write.f
+put_vara.o: put_vara.f
+put_varn_real.o: put_varn_real.f
+put_varn_int.o: put_varn_int.f
+transpose.o: transpose.f
+vard_int.o: vard_int.F
+i_varn_real.o: i_varn_real.f
+bput_varn_int8.o: bput_varn_int8.f
+fill_mode.o: fill_mode.f
diff --git a/examples/F77/fill_mode.f b/examples/F77/fill_mode.f
new file mode 100644
index 0000000..3d20c8b
--- /dev/null
+++ b/examples/F77/fill_mode.f
@@ -0,0 +1,227 @@
+!
+!   Copyright (C) 2015, Northwestern University
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: fill_mode.f 2245 2015-12-20 18:39:52Z wkliao $
+
+!
+! This example shows how to use
+! 1. nfmpi_set_fill() to enable fill mode
+! 2. nfmpi_def_var_fill() to define the variable's fill value
+! 3. nfmpi_inq_var_fill() to inquire the variable's fill mode information
+! 4. nfmpi_put_vara_int_all() to write two 2D 4-byte integer array in parallel.
+! It first defines a netCDF record variable of size global_nx * NFMPI_UNLIMITED
+! where
+!    global_nx == (nx * number of MPI processes) and
+! It then defines a netCDF variable of size global_nx * global_ny where
+!    global_nx == (nx * number of MPI processes) and
+!    global_ny == ny
+! The data partitioning pattern for both variables are a column-wise
+! partitioning across all processes. Each process writes a subarray of size
+! nx * ny. Note the description above follows the Fortran array index order.
+!
+! Example commands for MPI run and outputs from running ncmpidump on the
+! NC file produced by this example program:
+!
+!    % mpif77 -O2 -o fill_mode fill_mode.f -lpnetcdf
+!    % mpiexec -n 4 ./fill_mode /pvfs2/wkliao/testfile.nc
+!
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!            REC_DIM = UNLIMITED ; // (2 currently)
+!            X = 20 ;
+!            Y = 3 ;
+!    variables:
+!            int rec_var(REC_DIM, X) ;
+!                    rec_var:_FillValue = -1 ;
+!            int fix_var(Y, X) ;
+!                    fix_var:_FillValue = -2147483647 ;
+!    data:
+!
+!     rec_var =
+!      0, 0, 0, 0, _, 1, 1, 1, 1, _, 2, 2, 2, 2, _, 3, 3, 3, 3, _,
+!      0, 0, 0, 0, _, 1, 1, 1, 1, _, 2, 2, 2, 2, _, 3, 3, 3, 3, _ ;
+!
+!     fix_var =
+!      0, 0, 0, 0, _, 1, 1, 1, 1, _, 2, 2, 2, 2, _, 3, 3, 3, 3, _,
+!      0, 0, 0, 0, _, 1, 1, 1, 1, _, 2, 2, 2, 2, _, 3, 3, 3, 3, _,
+!      0, 0, 0, 0, _, 1, 1, 1, 1, _, 2, 2, 2, 2, _, 3, 3, 3, 3, _ ;
+!    }
+!
+      subroutine check(err, message)
+          implicit none
+          include 'mpif.h'
+          include 'pnetcdf.inc'
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include 'mpif.h'
+          include 'pnetcdf.inc'
+
+          character*128 filename, cmd
+          integer i, j, err, ierr, nprocs, rank, get_args
+          integer cmode, ncid, rec_varid, fix_varid, dimid(2)
+          integer no_fill, fill_value, old_mode
+          integer*8 nx, ny, global_nx, global_ny, one
+          integer*8 starts(2), counts(2)
+          PARAMETER(nx=5, ny=3)
+          integer buf(nx,ny)
+          integer*8 malloc_size, sum_size
+          logical verbose
+          integer dummy
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          one = 1
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                   err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, err)
+
+          ! set parameters
+          global_nx = nx * nprocs
+          global_ny = ny
+
+          do i=1, ny
+          do j=1, nx
+             buf(j,i) = rank
+          enddo
+          enddo
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                       MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define dimensions x and y
+          err = nfmpi_def_dim(ncid, "REC_DIM", NFMPI_UNLIMITED,dimid(2))
+          call check(err, 'In nfmpi_def_dim REC_DIM: ')
+          err = nfmpi_def_dim(ncid, "X", global_nx, dimid(1))
+          call check(err, 'In nfmpi_def_dim X: ')
+
+          ! define a 2D record variable of integer type
+          err = nfmpi_def_var(ncid, "rec_var", NF_INT, 2, dimid,
+     +                        rec_varid)
+          call check(err, 'In nfmpi_def_var: ')
+
+          err = nfmpi_def_dim(ncid, "Y", global_ny, dimid(2))
+          call check(err, 'In nfmpi_def_dim Y: ')
+
+          ! define a 2D fixed-size variable of integer type
+          err = nfmpi_def_var(ncid, "fix_var", NF_INT, 2, dimid,
+     +                        fix_varid)
+          call check(err, 'In nfmpi_def_var: ')
+
+          ! set the fill mode to NF_FILL for entire file
+          err = nfmpi_set_fill(ncid, NF_FILL, old_mode)
+          call check(err, 'In nfmpi_set_fill: ')
+          if (verbose) then
+             if (old_mode .EQ. NF_FILL) then
+                 print*,"The old fill mode is NF_FILL"
+             else
+                 print*,"The old fill mode is NF_NOFILL"
+             endif
+          endif
+
+          ! set the fill mode back to NF_NOFILL for entire file
+          err = nfmpi_set_fill(ncid, NF_NOFILL, old_mode)
+          call check(err, 'In nfmpi_set_fill: ')
+
+          ! set the variable's fill mode to NF_FILL with default fill value
+          err = nfmpi_def_var_fill(ncid, fix_varid, 0, NF_FILL_INT)
+          call check(err, 'In nfmpi_def_var_fill: ')
+
+          ! set a customized fill value -1
+          fill_value = -1
+          err = nfmpi_put_att_int(ncid, rec_varid, "_FillValue", NF_INT,
+     +                            one, fill_value)
+          call check(err, 'In nfmpi_put_att_int: ')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! Note that in Fortran, array indices start with 1
+          starts(1) = nx * rank + 1
+          starts(2) = 1
+          counts(1) = nx
+          counts(2) = ny
+
+          ! do not write the variable in full
+          counts(1) = counts(1) - 1
+          err = nfmpi_put_vara_int_all(ncid, fix_varid, starts, counts,
+     +                                 buf)
+          call check(err, 'In nfmpi_put_vara_int_all: ')
+
+          err = nfmpi_inq_var_fill(ncid, fix_varid, no_fill, fill_value)
+          if (no_fill .NE. 0)
+     +        print*,"Error: expecting no_fill to be 0"
+          if (fill_value .NE. NF_FILL_INT)
+     +        print*,"Error: expecting no_fill to be ",NF_FILL_INT,
+     +               " but got ", fill_value
+
+          ! fill the 1st record of the record variable
+          starts(2) = 1
+          err = nfmpi_fill_var_rec(ncid, rec_varid, starts(2))
+          call check(err, 'In nfmpi_fill_var_rec: ')
+
+          ! write to the 1st record
+          counts(2) = 1
+          err = nfmpi_put_vara_int_all(ncid, rec_varid, starts, counts,
+     +                                 buf)
+          call check(err, 'In nfmpi_put_vara_int_all: ')
+
+          ! fill the 2nd record of the record variable
+          starts(2) = 2
+          err = nfmpi_fill_var_rec(ncid, rec_varid, starts(2))
+          call check(err, 'In nfmpi_fill_var_rec: ')
+
+          ! write to the 2nd record
+          err = nfmpi_put_vara_int_all(ncid, rec_varid, starts, counts,
+     +                                 buf)
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end ! program main
+
diff --git a/examples/F77/flexible_api.f b/examples/F77/flexible_api.f
new file mode 100644
index 0000000..b82c0e3
--- /dev/null
+++ b/examples/F77/flexible_api.f
@@ -0,0 +1,194 @@
+!
+!   Copyright (C) 2013, Northwestern University
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: flexible_api.f 2235 2015-12-18 03:38:49Z wkliao $
+
+!
+! This example shows how to use PnetCDF flexible API, nfmpi_put_vara_all()
+! to write a 2D 4-byte integer array in parallel.
+! It first defines a netCDF variable of size global_nx * global_ny where
+!    global_nx == 5 and
+!    global_ny == (4 * number of MPI processes).
+! The data partitioning pattern is a column-wise partitioning across all
+! proceses. Each process writes a subarray of size nx * ny.
+! The local buffer has a ghost cell of length 3 surrounding the 2D array
+!    integer buf(nx+2*ghost_len, ny+2*ghost_len)
+! Note the description above follows the Fortran array index order.
+!
+! Example commands for MPI run and outputs from running ncmpidump on the
+! NC file produced by this example program:
+!
+!    % mpif77 -O2 -o flexible_api flexible_api.f -lpnetcdf
+!    % mpiexec -n 4 ./flexible_api /pvfs2/wkliao/testfile.nc
+!
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!            x = 5 ;
+!            y = 16 ;
+!    variables:
+!            int var(y, x) ;
+!    data:
+!
+!     var =
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0,
+!      1, 1, 1, 1, 1,
+!      1, 1, 1, 1, 1,
+!      1, 1, 1, 1, 1,
+!      1, 1, 1, 1, 1,
+!      2, 2, 2, 2, 2,
+!      2, 2, 2, 2, 2,
+!      2, 2, 2, 2, 2,
+!      2, 2, 2, 2, 2,
+!      3, 3, 3, 3, 3,
+!      3, 3, 3, 3, 3,
+!      3, 3, 3, 3, 3,
+!      3, 3, 3, 3, 3 ;
+!    }
+!
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          character*128 filename, cmd
+          integer err, ierr, nprocs, rank, i, j, ghost_len, get_args
+          integer cmode, ncid, varid, dimid(2)
+          integer*8 nx, ny, global_nx, global_ny
+          integer*8 starts(2), counts(2), nTypes
+          PARAMETER(nx=5, ny=4, ghost_len=3)
+          integer buf(nx+2*ghost_len, ny+2*ghost_len)
+          integer subarray
+          integer array_of_sizes(2), array_of_subsizes(2)
+          integer array_of_starts(2)
+          integer*8 malloc_size, sum_size
+          logical verbose
+          integer dummy
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                   err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, err)
+
+          ! set parameters
+          global_nx = nx
+          global_ny = ny * nprocs
+
+          ! first initialize the entire buffer to -1
+          do i=1, ny+2*ghost_len 
+          do j=1, nx+2*ghost_len
+             buf(j,i) = -1
+          enddo
+          enddo
+          ! assign values for non-ghost cells
+          do j=ghost_len+1, ny+ghost_len
+             do i=ghost_len+1, nx+ghost_len
+                 buf(i, j) = rank
+             enddo
+          enddo
+
+          ! define an MPI datatype using MPI_Type_create_subarray()
+          array_of_sizes(1)    = nx + 2*ghost_len
+          array_of_sizes(2)    = ny + 2*ghost_len
+          array_of_subsizes(1) = nx
+          array_of_subsizes(2) = ny
+          array_of_starts(1)   = ghost_len  ! MPI start index starts with 0
+          array_of_starts(2)   = ghost_len
+          call MPI_Type_create_subarray(2, array_of_sizes,
+     +         array_of_subsizes, array_of_starts, MPI_ORDER_FORTRAN,
+     +         MPI_INTEGER, subarray, err)
+          call MPI_Type_commit(subarray, err)
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                        MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define dimensions x and y
+          err = nfmpi_def_dim(ncid, "y", global_ny, dimid(2))
+          call check(err, 'In nfmpi_def_dim y: ')
+          err = nfmpi_def_dim(ncid, "x", global_nx, dimid(1))
+          call check(err, 'In nfmpi_def_dim x: ')
+
+          ! define a 2D variable of integer type
+          err = nfmpi_def_var(ncid, "var", NF_INT, 2, dimid, varid)
+          call check(err, 'In nfmpi_def_var: ')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! Note that in Fortran, array indices start with 1
+          starts(1) = 1
+          starts(2) = ny * rank + 1
+          counts(1) = nx
+          counts(2) = ny
+          nTypes    = 1
+
+          ! In Fortran, subarray buffer type can also use array index ranges
+          ! for example in this case
+          !    buf(1+ghost_len:nx+ghost_len, 1+ghost_len:ny+ghost_len)
+          ! However, this does not work for nonblocking APIs because
+          ! wait/wait_all is called separately from the nonblocking calls
+          ! Fortran the subarray indexing is lost in the wait call
+          err = nfmpi_put_vara_all(ncid, varid, starts, counts, buf,
+     +                             nTypes, subarray)
+          call check(err, 'In nfmpi_put_vara_all: ')
+
+          call MPI_Type_free(subarray, err)
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end ! program main
+
diff --git a/examples/F77/get_info.f b/examples/F77/get_info.f
new file mode 100644
index 0000000..e14ed90
--- /dev/null
+++ b/examples/F77/get_info.f
@@ -0,0 +1,141 @@
+!
+!  Copyright (C) 2012, Northwestern University and Argonne National
+!  Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: get_info.f 2224 2015-12-16 06:10:36Z wkliao $
+
+!
+!    To compile:
+!        mpif77 -O2 get_info.f -o get_info -lpnetcdf
+!    To run:
+!        mpiexec -n 4 ./get_info /pvfs2/wkliao/testfile.nc
+!
+!    prints all MPI-IO hints used
+!
+!    Example standard output:
+!
+!   MPI File Info: nkeys =          18
+!   MPI File Info: [ 0] key =            cb_buffer_size, value =16777216
+!   MPI File Info: [ 1] key =             romio_cb_read, value =automatic
+!   MPI File Info: [ 2] key =            romio_cb_write, value =automatic
+!   MPI File Info: [ 3] key =                  cb_nodes, value =1
+!   MPI File Info: [ 4] key =         romio_no_indep_rw, value =false
+!   MPI File Info: [ 5] key =              romio_cb_pfr, value =disable
+!   MPI File Info: [ 6] key =         romio_cb_fr_types, value =aar
+!   MPI File Info: [ 7] key =     romio_cb_fr_alignment, value =1
+!   MPI File Info: [ 8] key =     romio_cb_ds_threshold, value =0
+!   MPI File Info: [ 9] key =         romio_cb_alltoall, value =automatic
+!   MPI File Info: [10] key =        ind_rd_buffer_size, value =4194304
+!   MPI File Info: [11] key =        ind_wr_buffer_size, value =524288
+!   MPI File Info: [12] key =             romio_ds_read, value =automatic
+!   MPI File Info: [13] key =            romio_ds_write, value =automatic
+!   MPI File Info: [14] key =            cb_config_list, value =*:1
+!   MPI File Info: [15] key =      nc_header_align_size, value =0
+!   MPI File Info: [16] key =         nc_var_align_size, value =0
+!   MPI File Info: [17] key = nc_header_read_chunk_size, value =0
+
+
+        program main
+        implicit none
+        include "mpif.h"
+        include "pnetcdf.inc"
+
+        character*256 filename, cmd
+        integer ncid, rank, info, omode, err, ierr, get_args
+        integer*8 malloc_size, sum_size
+        logical verbose
+        integer dummy
+
+        call MPI_Init(err)
+        call MPI_Comm_rank (MPI_COMM_WORLD, rank, err)
+
+        if (rank .EQ. 0) then
+            verbose = .TRUE.
+            filename = "testfile.nc"
+            ierr = get_args(2, cmd, filename, verbose, dummy)
+        endif
+        call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+        if (ierr .EQ. 0) goto 999
+
+        call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                 err)
+        call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                 MPI_COMM_WORLD, err)
+
+        omode = NF_NOWRITE + NF_64BIT_OFFSET
+        err = nfmpi_open(MPI_COMM_WORLD, filename, omode,
+     +                    MPI_INFO_NULL, ncid)
+        if (err .ne. NF_NOERR) call handle_err('nfmpi_open',err)
+
+
+        err = nfmpi_inq_file_info(ncid, info)
+        if (err .ne. NF_NOERR) call handle_err('nfmpi_inq_file_info',
+     +                                          err)
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) call handle_err('nfmpi_close',err)
+
+        if (rank .EQ. 0 .AND. verbose) call print_info(info)
+        call MPI_Info_free(info, err)
+
+        ! check if there is any PnetCDF internal malloc residue
+ 998    format(A,I13,A)
+        err = nfmpi_inq_malloc_size(malloc_size)
+        if (err .EQ. NF_NOERR) then
+            call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+     +                      MPI_SUM, 0, MPI_COMM_WORLD, err)
+            if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +          print 998,
+     +          'heap memory allocated by PnetCDF internally has ',
+     +          sum_size/1048576, ' MiB yet to be freed'
+        endif
+
+ 999    call MPI_Finalize(err)
+        ! call EXIT(0) ! EXIT() is a GNU extension
+
+        end ! program main
+
+        subroutine print_info(info_used)
+            implicit none
+            include "mpif.h"
+            include "pnetcdf.inc"
+
+            integer info_used
+
+            ! local variables
+            character*(MPI_MAX_INFO_VAL) key, value
+            integer nkeys, i, err
+            logical flag
+
+            call MPI_Info_get_nkeys(info_used, nkeys, err)
+            print *, 'MPI File Info: nkeys =', nkeys
+            do i=0, nkeys-1
+                call MPI_Info_get_nthkey(info_used, i, key, err)
+                call MPI_Info_get(info_used, key, MPI_MAX_INFO_VAL,
+     +                            value, flag, err)
+ 123            format('MPI File Info: [',I2,'] key = ',A25,
+     +                 ', value =',A)
+                print 123, i, key, value
+            enddo
+            print *
+
+            return
+        end ! subroutine print_info
+
+        subroutine handle_err(err_msg, errcode)
+            implicit none
+            include "mpif.h"
+            include "pnetcdf.inc"
+
+            character*(*) err_msg
+            integer       errcode
+
+            ! local variables
+            integer err 
+
+            print *, 'Error: ',err_msg//' '//nfmpi_strerror(errcode)
+            call MPI_Abort(MPI_COMM_WORLD, -1, err)
+            return
+        end ! subroutine handle_err
+
diff --git a/examples/F77/hints.f b/examples/F77/hints.f
new file mode 100644
index 0000000..2f068ef
--- /dev/null
+++ b/examples/F77/hints.f
@@ -0,0 +1,251 @@
+!
+!  Copyright (C) 2012, Northwestern University and Argonne National
+!  Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: hints.f 2224 2015-12-16 06:10:36Z wkliao $
+
+!
+! This example sets two PnetCDF hints:
+!    nc_header_align_size and nc_var_align_size
+! and prints the hint values as well as the header size, header extent, and
+! two variables' starting file offsets.
+!
+! The compile and run commands are given below.
+!
+!    % mpif77 -O2 -o hints hints.f -lpnetcdf
+!
+!    % mpiexec -n 4 ./hints /pvfs2/wkliao/testfile.nc
+!
+!    nc_header_align_size      set to = 1024
+!    nc_var_align_size         set to = 512
+!    nc_header_read_chunk_size set to = 256
+!    header size                      = 252
+!    header extent                    = 1024
+!    var_zy start file offset         = 1024
+!    var_yx start file offset         = 3072
+!
+
+
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      subroutine print_hints(ncid, varid0, varid1)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          integer ncid, varid0, varid1
+
+          ! local variables
+          character*(MPI_MAX_INFO_VAL) value
+          integer err, len, info_used
+          logical flag
+          integer*8 header_size, header_extent
+          integer*8 var_zy_start, var_yx_start
+          integer*8 h_align, v_align, h_chunk
+
+          h_align=-1
+          v_align=-1
+          h_chunk=-1
+
+          err = nfmpi_inq_header_size  (ncid, header_size)
+          call check(err, 'In nfmpi_inq_header_size: ')
+          err = nfmpi_inq_header_extent(ncid, header_extent)
+          call check(err, 'In nfmpi_inq_header_extent: ')
+          err = nfmpi_inq_varoffset(ncid, varid0, var_zy_start)
+          call check(err, 'In nfmpi_inq_varoffset varid0: ')
+          err = nfmpi_inq_varoffset(ncid, varid1, var_yx_start)
+          call check(err, 'In nfmpi_inq_varoffset varid1: ')
+
+          err = nfmpi_inq_file_info(ncid, info_used)
+          call check(err, 'In nfmpi_inq_file_info : ')
+
+          call MPI_Info_get_valuelen(info_used, "nc_header_align_size",
+     +                               len, flag, err)
+          if (flag) then
+              call MPI_Info_get(info_used, "nc_header_align_size",
+     +                          len+1, value, flag, err)
+              read(value, '(i16)') h_align
+          endif
+          call MPI_Info_get_valuelen(info_used, "nc_var_align_size",
+     +                               len, flag, err)
+          if (flag) then
+              call MPI_Info_get(info_used, "nc_var_align_size", len+1,
+     +                          value, flag, err)
+              read(value, '(i16)') v_align
+          endif
+          call MPI_Info_get_valuelen(info_used,
+     +                               "nc_header_read_chunk_size",
+     +                               len, flag, err)
+          if (flag) then
+              call MPI_Info_get(info_used, "nc_header_read_chunk_size",
+     +                          len+1, value, flag, err)
+              read(value, '(i16)') h_chunk
+          endif
+          call MPI_Info_free(info_used, err)
+
+          if (h_align .EQ. -1) then
+              print*,"nc_header_align_size      is NOT set"
+          else
+              print*,"nc_header_align_size      set to = ", h_align
+          endif
+          if (v_align .EQ. -1) then
+              print*,"nc_var_align_size         is NOT set"
+          else
+              print*,"nc_var_align_size         set to = ", v_align
+          endif
+          if (h_chunk .EQ. -1) then
+              print*,"nc_header_read_chunk_size is NOT set"
+          else
+              print*,"nc_header_read_chunk_size set to = ", h_chunk
+          endif
+
+          print*,"header size                      = ", header_size
+          print*,"header extent                    = ", header_extent
+          print*,"var_zy start file offset         = ", var_zy_start
+          print*,"var_yx start file offset         = ", var_yx_start
+      end ! subroutine print_hints
+
+      subroutine put_vara(ncid, varid, ny, nx, start, count)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          integer ncid, varid, ny, nx
+          integer*8 start(2), count(2)
+
+          integer i, j, rank, err
+          integer buf(nx, ny)
+
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+
+          do j=1, ny
+             do i=1, nx
+                buf(i,j) = rank ! j*nx + i
+             enddo
+          enddo
+
+          err = nfmpi_put_vara_int_all(ncid, varid, start, count, buf)
+          call check(err, 'In nfmpi_put_vara_int_all : ')
+
+      end ! subroutine put_vara
+
+      program main
+      implicit none
+      include "mpif.h"
+      include "pnetcdf.inc"
+
+      character*256 filename, cmd
+      integer NZ, NY, NX
+      integer ncid, rank, nprocs, info, cmode, err, ierr, get_args
+      integer varid0, varid1, dimid(3), dimid2(2)
+      integer*8 start(2), count(2), llen
+      integer*8 malloc_size, sum_size
+      logical verbose
+      integer dummy
+
+      call MPI_Init(err)
+      call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+      call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+      NZ = 5
+      NY = 5
+      NX = 5
+
+      if (rank .EQ. 0) then
+          verbose = .TRUE.
+          filename = "testfile.nc"
+          ierr = get_args(2, cmd, filename, verbose, dummy)
+      endif
+      call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+      if (ierr .EQ. 0) goto 999
+
+      call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +               err)
+      call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +               MPI_COMM_WORLD, err)
+
+      call MPI_Info_create(info, err)
+      call MPI_Info_set(info, "nc_header_align_size",      "1024", err)
+      call MPI_Info_set(info, "nc_var_align_size",         "512",  err)
+      call MPI_Info_set(info, "nc_header_read_chunk_size", "256",  err)
+      ! note that set the above values to 1 to disable the alignment
+
+      ! create a new file for writing
+      cmode = NF_CLOBBER + NF_64BIT_DATA
+      err = nfmpi_create(MPI_COMM_WORLD, filename, cmode, info, ncid)
+      call check(err, 'In nfmpi_create : ')
+      call MPI_Info_free(info, err)
+
+      ! define 3 dimensions
+      llen = NZ*nprocs
+      err = nfmpi_def_dim(ncid, "Z", llen, dimid(1))
+      call check(err, 'In nfmpi_def_dim Z : ')
+      llen = NY*nprocs
+      err = nfmpi_def_dim(ncid, "Y", llen, dimid(2))
+      call check(err, 'In nfmpi_def_dim Y : ')
+      llen = NX*nprocs
+      err = nfmpi_def_dim(ncid, "X", llen, dimid(3))
+      call check(err, 'In nfmpi_def_dim X : ')
+
+      ! define a variable of size (NZ * nprocs) * (NY * nprocs)
+      dimid2(1) = dimid(1)
+      dimid2(2) = dimid(2)
+      err = nfmpi_def_var(ncid, "var_zy", NF_INT,   2, dimid2, varid0)
+      call check(err, 'In nfmpi_def_var var_zy : ')
+      ! define a variable of size (NY * nprocs) * (NX * nprocs)
+      dimid2(1) = dimid(2)
+      dimid2(2) = dimid(3)
+      err = nfmpi_def_var(ncid, "var_yx", NF_FLOAT, 2, dimid2, varid1)
+      call check(err, 'In nfmpi_def_var var_yx : ')
+
+      err = nfmpi_enddef(ncid)
+      call check(err, 'In nfmpi_enddef : ')
+
+      ! var_zy is partitioned along Z dimension
+      start(1) = NZ * rank + 1
+      start(2) = 1
+      count(1) = NZ
+      count(2) = NY * nprocs
+      call put_vara(ncid, varid0, NZ, NY * nprocs, start, count)
+
+      ! var_yx is partitioned along X dimension
+      start(1) = 1
+      start(2) = NX * rank + 1
+      count(1) = NY * nprocs
+      count(2) = NX
+      call put_vara(ncid, varid1, NY * nprocs, NX, start, count)
+
+      if (rank .EQ. 0 .AND. verbose)
+     +    call print_hints(ncid, varid0, varid1)
+
+      err = nfmpi_close(ncid)
+
+      ! check if there is any PnetCDF internal malloc residue
+ 998  format(A,I13,A)
+      err = nfmpi_inq_malloc_size(malloc_size)
+      if (err .EQ. NF_NOERR) then
+          call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+      if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +        print 998,
+     +        'heap memory allocated by PnetCDF internally has ',
+     +        sum_size/1048576, ' MiB yet to be freed'
+      endif
+
+ 999  call MPI_Finalize(err)
+      ! call EXIT(0) ! EXIT() is a GNU extension
+      end ! program
+
diff --git a/examples/F77/i_varn_real.f b/examples/F77/i_varn_real.f
new file mode 100644
index 0000000..bea1f0d
--- /dev/null
+++ b/examples/F77/i_varn_real.f
@@ -0,0 +1,323 @@
+!
+!   Copyright (C) 2014, Northwestern University
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: i_varn_real.f 2224 2015-12-16 06:10:36Z wkliao $
+
+! This example tests nonblocking varn API, nfmpi_iput_varn_real()
+! It writes a sequence of requests with arbitrary array indices and
+! lengths to four variables of type NF_REAL
+!
+! The compile and run commands are given below, together with an
+! ncmpidump of the output file.
+!
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file.
+!
+!    % mpif77 -O2 -o i_varn_real i_varn_real.f -lpnetcdf
+!    % mpiexec -n 4 ./i_varn_real /pvfs2/wkliao/testfile.nc
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!     dimensions:
+!              Y = 4 ;
+!              X = 10 ;
+!     variables:
+!             float var0(Y, X) ;
+!             float var1(Y, X) ;
+!             float var2(Y, X) ;
+!             float var3(Y, X) ;
+!     data:
+!
+!     var0 =
+!      1, 0, 3, 0,
+!      1, 2, 3, 0,
+!      1, 2, 2, 0,
+!      3, 2, 1, 2,
+!      3, 1, 1, 3,
+!      0, 3, 1, 3,
+!      0, 3, 0, 3,
+!      2, 2, 0, 1,
+!      3, 2, 3, 1,
+!      3, 2, 3, 1 ;
+!
+!     var1 =
+!      2, 1, 0, 1,
+!      2, 3, 0, 1,
+!      2, 3, 3, 1,
+!      0, 3, 2, 3,
+!      0, 2, 2, 0,
+!      1, 0, 2, 0,
+!      1, 0, 1, 0,
+!      3, 3, 1, 2,
+!      0, 3, 0, 2,
+!      0, 3, 0, 2 ;
+!
+!     var2 =
+!      3, 2, 1, 2,
+!      3, 0, 1, 2,
+!      3, 0, 0, 2,
+!      1, 0, 3, 0,
+!      1, 3, 3, 1,
+!      2, 1, 3, 1,
+!      2, 1, 2, 1,
+!      0, 0, 2, 3,
+!      1, 0, 1, 3,
+!      1, 0, 1, 3 ;
+!
+!     var3 =
+!      0, 3, 2, 3,
+!      0, 1, 2, 3,
+!      0, 1, 1, 3,
+!      2, 1, 0, 1,
+!      2, 0, 0, 2,
+!      3, 2, 0, 2,
+!      3, 2, 3, 2,
+!      1, 1, 3, 0,
+!      2, 1, 2, 0,
+!      2, 1, 2, 0 ;
+!     }
+!
+!    Note the above dump is in C order
+!
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          integer NDIMS
+          integer*8 NX, NY
+          PARAMETER(NDIMS=2, NX=4, NY=10)
+
+          character*128 filename, cmd
+          integer i, j, n, err, ierr, nprocs, rank, get_args
+          integer cmode, ncid, varid(4), dimid(NDIMS), nreqs
+          integer reqs(4), sts(4), num_segs(4)
+
+          integer*8 start(NDIMS, 6, 4)
+          integer*8 count(NDIMS, 6, 4)
+          integer*8 malloc_size, sum_size, two
+          real buffer(NX*NY,4)
+          logical verbose
+          integer dummy
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          two = 2
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                   err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, err)
+
+          if (nprocs .NE. 4 .AND. rank .EQ. 0 .AND. verbose)
+     +        print*,'Warning: ',cmd,' is intended to run on ',
+     +               '4 processes'
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                        MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define dimensions x and y
+          err = nfmpi_def_dim(ncid, "Y", NY, dimid(2))
+          call check(err, 'In nfmpi_def_dim Y: ')
+          err = nfmpi_def_dim(ncid, "X", NX, dimid(1))
+          call check(err, 'In nfmpi_def_dim X: ')
+
+          ! define 4 2D variables of real type
+          err = nfmpi_def_var(ncid, "var0", NF_REAL, two,
+     +                        dimid,varid(1))
+          call check(err, 'In nfmpi_def_var var0: ')
+          err = nfmpi_def_var(ncid, "var1", NF_REAL, two,
+     +                        dimid,varid(2))
+          call check(err, 'In nfmpi_def_var var1: ')
+          err = nfmpi_def_var(ncid, "var2", NF_REAL, two,
+     +                        dimid,varid(3))
+          call check(err, 'In nfmpi_def_var var2: ')
+          err = nfmpi_def_var(ncid, "var3", NF_REAL, two,
+     +                        dimid,varid(4))
+          call check(err, 'In nfmpi_def_var var3: ')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          if (rank .GE. 4) goto 123
+
+          ! now we are in data mode
+          n = rank+1
+          num_segs(n) = 4 ! number of segments for this request
+          start(1,1,n)=1
+          start(2,1,n)=6
+          count(1,1,n)=1
+          count(2,1,n)=2
+          start(1,2,n)=2
+          start(2,2,n)=1
+          count(1,2,n)=1
+          count(2,2,n)=1
+          start(1,3,n)=3
+          start(2,3,n)=7
+          count(1,3,n)=1
+          count(2,3,n)=2
+          start(1,4,n)=4
+          start(2,4,n)=1
+          count(1,4,n)=1
+          count(2,4,n)=3
+          ! start(:,:,n) n_count(:,:,n) indicate the following:
+          ! ("-" means skip)
+          !   -  -  -  -  -  X  X  -  -  -
+          !   X  -  -  -  -  -  -  -  -  -
+          !   -  -  -  -  -  -  X  X  -  -
+          !   X  X  X  -  -  -  -  -  -  -
+
+          n = mod(rank+1, 4) + 1
+          num_segs(n) = 6 ! number of segments for this request
+          start(1,1,n)=1
+          start(2,1,n)=4
+          count(1,1,n)=1
+          count(2,1,n)=2
+          start(1,2,n)=1
+          start(2,2,n)=9
+          count(1,2,n)=1
+          count(2,2,n)=2
+          start(1,3,n)=2
+          start(2,3,n)=6
+          count(1,3,n)=1
+          count(2,3,n)=2
+          start(1,4,n)=3
+          start(2,4,n)=1
+          count(1,4,n)=1
+          count(2,4,n)=2
+          start(1,5,n)=3
+          start(2,5,n)=9
+          count(1,5,n)=1
+          count(2,5,n)=2
+          start(1,6,n)=4
+          start(2,6,n)=5
+          count(1,6,n)=1
+          count(2,6,n)=3
+          ! start(:,:,n) n_count(:,:,n) indicate the following:
+          !   -  -  -  X  X  -  -  -  X  X
+          !   -  -  -  -  -  X  X  -  -  -
+          !   X  X  -  -  -  -  -  -  X  X
+          !   -  -  -  -  X  X  X  -  -  -
+
+          n = mod(rank+2, 4) + 1
+          num_segs(n) = 5 ! number of segments for this request
+          start(1,1,n)=1
+          start(2,1,n)=8
+          count(1,1,n)=1
+          count(2,1,n)=1
+          start(1,2,n)=2
+          start(2,2,n)=2
+          count(1,2,n)=1
+          count(2,2,n)=3
+          start(1,3,n)=2
+          start(2,3,n)=8
+          count(1,3,n)=1
+          count(2,3,n)=3
+          start(1,4,n)=3
+          start(2,4,n)=3
+          count(1,4,n)=1
+          count(2,4,n)=1
+          start(1,5,n)=4
+          start(2,5,n)=4
+          count(1,5,n)=1
+          count(2,5,n)=1
+          ! start(:,:,n) n_count(:,:,n) indicate the following:
+          !   -  -  -  -  -  -  -  X  -  -
+          !   -  X  X  X  -  -  -  X  X  X
+          !   -  -  X  -  -  -  -  -  -  -
+          !   -  -  -  X  -  -  -  -  -  -
+
+          n = mod(rank+3, 4) + 1
+          num_segs(n) = 4 ! number of segments for this request
+          start(1,1,n)=1
+          start(2,1,n)=1
+          count(1,1,n)=1
+          count(2,1,n)=3
+          start(1,2,n)=2
+          start(2,2,n)=5
+          count(1,2,n)=1
+          count(2,2,n)=1
+          start(1,3,n)=3
+          start(2,3,n)=4
+          count(1,3,n)=1
+          count(2,3,n)=3
+          start(1,4,n)=4
+          start(2,4,n)=8
+          count(1,4,n)=1
+          count(2,4,n)=3
+          ! start(:,:,n) n_count(:,:,n) indicate the following:
+          !   X  X  X  -  -  -  -  -  -  -
+          !   -  -  -  -  X  -  -  -  -  -
+          !   -  -  -  X  X  X  -  -  -  -
+          !   -  -  -  -  -  -  -  X  X  X
+
+          ! only rank 0, 1, 2, and 3 do I/O:
+          ! each of ranks 0 to 3 write 4 nonblocking requests
+ 123      nreqs = 4
+          if (rank .GE. 4) nreqs = 0
+
+          ! initialize buffer contents
+          do i=1, 4
+          do j=1, NX*NY
+             buffer(j,i) = rank
+          enddo
+          enddo
+
+          do i=1, nreqs
+             err = nfmpi_iput_varn_real(ncid, varid(i), num_segs(i),
+     +                                  start(1,1,i), count(1,1,i),
+     +                                  buffer(1,i), reqs(i))
+             call check(err, 'In nfmpi_iput_varn_real: ')
+          enddo
+          err = nfmpi_wait_all(ncid, nreqs, reqs, sts)
+          call check(err, 'In nfmpi_wait_all: ')
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size, ' B yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end ! program main
+
diff --git a/examples/F77/nonblocking_write.f b/examples/F77/nonblocking_write.f
new file mode 100644
index 0000000..0a1923e
--- /dev/null
+++ b/examples/F77/nonblocking_write.f
@@ -0,0 +1,204 @@
+!
+!  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: nonblocking_write.f 2245 2015-12-20 18:39:52Z wkliao $
+
+!    This example is the Fortran 77 version of nonblocking_write.c
+!    It creates a netcdf file in CD-5 format and writes a number of
+!    3D integer non-record variables.
+!    Usage: (for example)
+!    To compile:
+!        mpif77 -O2 nonblocking_write.f -o nonblocking_write -lpnetcdf
+!    To run (for example):
+!        mpiexec -n 32 ./nonblocking_write /pvfs2/wkliao/testfile.nc 10
+!    The size of each local array is len x len x len. Each non-record
+!    variable is of size len*len*len * nprocs * sizeof(int)
+!    All variables are partitioned among all processes in a 3D
+!    block-block-block fashion.
+!
+
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          integer NDIMS, NUM_VARS, BUFSIZE
+          PARAMETER(NDIMS=3, NUM_VARS=10, BUFSIZE=1000)
+
+          character*128 filename, cmd, str
+          integer i, j, cmode, err, ierr, get_args
+          integer rank, nprocs, ncid, len
+          integer buf(BUFSIZE, NUM_VARS), buf1d(BUFSIZE)
+          integer psizes(NDIMS), dimids(NDIMS), varids(NUM_VARS)
+          integer req(NUM_VARS), st(NUM_VARS)
+          integer*8 gsizes(NDIMS)
+          integer*8 starts(NDIMS), counts(NDIMS)
+          integer*8 bbufsize
+          integer*8 malloc_size, sum_size
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              len = 10
+              ierr = get_args(3, cmd, filename, verbose, len)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                   err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, err)
+          call MPI_Bcast(len, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+
+          if (len .GT. BUFSIZE) then
+             print*,'Maximum len is 10, change it to 10'
+             len = BUFSIZE
+          endif
+
+          do i=1,NDIMS
+             psizes(i) = 0
+          enddo
+
+          ! create a block-block-block data partitioning
+          call MPI_Dims_create(nprocs, NDIMS, psizes, err)
+          starts(1) = mod(rank, psizes(1))
+          starts(2) = mod((rank / psizes(2)), psizes(2))
+          starts(3) = mod((rank / (psizes(1) * psizes(2))), psizes(3))
+
+          bbufsize = 1
+          do i=1,NDIMS
+              gsizes(i) = len * psizes(i)
+              starts(i) = starts(i) * len + 1
+              counts(i) = len
+              bbufsize  = bbufsize * len
+          enddo
+
+          do i=1,NUM_VARS
+             do j=1,BUFSIZE
+                buf(j,i) = rank
+             enddo
+          enddo
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                       MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define dimensions
+          do i=1, NDIMS
+             write(str,'(I1)') i-1
+             err = nfmpi_def_dim(ncid, "x"//str,
+     +                           gsizes(i), dimids(i))
+             call check(err, 'In nfmpi_def_dim x'//str)
+          enddo
+
+          !define variables
+          do i=1, NUM_VARS
+             write(str,'(I1)') i-1
+             err = nfmpi_def_var(ncid, "var"//str,
+     +                           NF_INT, NDIMS, dimids, varids(i))
+             call check(err, 'In nfmpi_def_var var'//str)
+          enddo
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! write one variable at a time using iput
+          do i=1, NUM_VARS
+             do j=1,BUFSIZE
+                buf1d(j) = buf(j,i)
+             enddo
+             write(str,'(I1)') i-1
+             err = nfmpi_iput_vara_int(ncid, varids(i), starts,
+     +                                 counts, buf1d, req(i))
+             call check(err, 'In nfmpi_iput_vara_int '//str)
+          enddo
+
+          ! wait for the nonblocking I/O to complete
+          err = nfmpi_wait_all(ncid, NUM_VARS, req, st)
+          call check(err, 'In nfmpi_wait_all')
+
+          ! check the status of each nonblocking request
+          do i=1, NUM_VARS
+             write(str,'(I1)') i-1
+             call check(st(i), 'In nfmpi_wait_all req '//str)
+          enddo
+
+          ! write one variable at a time using bput
+
+          ! bbufsize must be max of data type converted before and after
+          bbufsize = bbufsize * NUM_VARS * 4  ! 4 is size of integer
+          err = nfmpi_buffer_attach(ncid, bbufsize)
+          call check(err, 'In nfmpi_buffer_attach')
+
+           do i=1, NUM_VARS
+             do j=1,BUFSIZE
+                buf1d(j) = buf(j,i)
+             enddo
+             write(str,'(I1)') i-1
+             err = nfmpi_bput_vara_int(ncid, varids(i), starts,
+     +                                 counts, buf1d, req(i))
+             call check(err, 'In nfmpi_bput_vara_int '//str)
+
+             ! can safely change the contents of buf(:,i) now
+           enddo
+
+          ! wait for the nonblocking I/O to complete
+          err = nfmpi_wait_all(ncid, NUM_VARS, req, st)
+          call check(err, 'In nfmpi_wait_all')
+
+          ! check the status of each nonblocking request
+          do i=1, NUM_VARS
+             write(str,'(I1)') i-1
+             call check(st(i), 'In nfmpi_wait_all req '//str)
+          enddo
+
+          ! detach the temporary buffer
+          err = nfmpi_buffer_detach(ncid)
+          call check(err, 'In nfmpi_buffer_detach')
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ', 
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+
+      end
+
diff --git a/examples/F77/put_vara.f b/examples/F77/put_vara.f
new file mode 100644
index 0000000..0225e49
--- /dev/null
+++ b/examples/F77/put_vara.f
@@ -0,0 +1,159 @@
+!
+!   Copyright (C) 2013, Northwestern University
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: put_vara.f 2245 2015-12-20 18:39:52Z wkliao $
+
+!
+! This example shows how to use nfmpi_put_vara_int_all() to write a 2D
+! 4-byte integer array in parallel. It first defines a netCDF variable of
+! size global_nx * global_ny where
+!    global_nx == 5 and
+!    global_ny == (4 * number of MPI processes).
+! The data partitioning pattern is a column-wise partitioning across all
+! processes. Each process writes a subarray of size nx * ny.
+! Note the description above follows the Fortran array index order.
+!
+! Example commands for MPI run and outputs from running ncmpidump on the
+! NC file produced by this example program:
+!
+!    % mpif77 -O2 -o put_vara put_vara.f -lpnetcdf
+!    % mpiexec -n 4 ./put_vara /pvfs2/wkliao/testfile.nc
+!
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!            x = 5 ;
+!            y = 16 ;
+!    variables:
+!            int var(y, x) ;
+!    data:
+!
+!     var =
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0,
+!      1, 1, 1, 1, 1,
+!      1, 1, 1, 1, 1,
+!      1, 1, 1, 1, 1,
+!      1, 1, 1, 1, 1,
+!      2, 2, 2, 2, 2,
+!      2, 2, 2, 2, 2,
+!      2, 2, 2, 2, 2,
+!      2, 2, 2, 2, 2,
+!      3, 3, 3, 3, 3,
+!      3, 3, 3, 3, 3,
+!      3, 3, 3, 3, 3,
+!      3, 3, 3, 3, 3 ;
+!    }
+!
+      subroutine check(err, message)
+          implicit none
+          include 'mpif.h'
+          include 'pnetcdf.inc'
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include 'mpif.h'
+          include 'pnetcdf.inc'
+
+          character*128 filename, cmd
+          integer i, j, err, ierr, nprocs, rank, get_args, dummy
+          integer cmode, ncid, varid, dimid(2)
+          integer*8 nx, ny, global_nx, global_ny
+          integer*8 starts(2), counts(2)
+          PARAMETER(nx=5, ny=4)
+          integer buf(nx,ny)
+          integer*8 malloc_size, sum_size
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                   err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, err)
+
+          ! set parameters
+          global_nx = nx
+          global_ny = ny * nprocs
+
+          do i=1, ny
+          do j=1, nx
+             buf(j,i) = rank
+          enddo
+          enddo
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                       MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define dimensions x and y
+          err = nfmpi_def_dim(ncid, "x", global_nx, dimid(1))
+          call check(err, 'In nfmpi_def_dim x: ')
+          err = nfmpi_def_dim(ncid, "y", global_ny, dimid(2))
+          call check(err, 'In nfmpi_def_dim y: ')
+
+          ! define a 2D variable of integer type
+          err = nfmpi_def_var(ncid, "var", NF_INT, 2, dimid, varid)
+          call check(err, 'In nfmpi_def_var: ')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! Note that in Fortran, array indices start with 1
+          starts(1) = 1
+          starts(2) = ny * rank + 1
+          counts(1) = nx
+          counts(2) = ny
+
+          err = nfmpi_put_vara_int_all(ncid, varid, starts, counts, buf)
+          call check(err, 'In nfmpi_put_vara_int_all: ')
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end ! program main
+
diff --git a/examples/F77/put_varn_int.f b/examples/F77/put_varn_int.f
new file mode 100644
index 0000000..a9af29d
--- /dev/null
+++ b/examples/F77/put_varn_int.f
@@ -0,0 +1,257 @@
+!
+!   Copyright (C) 2013, Northwestern University
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: put_varn_int.f 2224 2015-12-16 06:10:36Z wkliao $
+
+! This example shows how to use a single call of nfmpi_put_varn_int_all() to
+! write a sequence of requests with arbitrary array indices and lengths.
+! Using nfmpi_put_varn_int_all() can achieve the same effect of HDF5 writing
+! a sequence of selected file locations through the following 2 APIs.
+!
+!   H5Sselect_elements(fid, H5S_SELECT_SET, NUMP, (const hssize_t **)coord);
+!   H5Dwrite(dataset, H5T_NATIVE_INT, mid, fid, H5P_DEFAULT, val);
+!
+! Note that in nfmpi_put_varn_int_all(), users can write more than one element
+! starting at each selected location.
+!
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file.
+!
+!    % mpif77 -O2 -o put_varn_int put_varn_int.f -lpnetcdf
+!    % mpiexec -n 4 ./put_varn_int /pvfs2/wkliao/testfile.nc
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!             X = 4 ;
+!             Y = 10 ;
+!    variables:
+!             int var(Y, X) ;
+!    data:
+!
+!     var =
+!      2, 2, 1, 1,
+!      2, 2, 0, 0,
+!      1, 1, 0, 0,
+!      1, 1, 3, 3,
+!      3, 3, 2, 2,
+!      0, 0, 1, 1,
+!      0, 0, 1, 1,
+!      2, 2, 0, 0,
+!      3, 3, 3, 3,
+!      3, 3, 3, 3 ;
+!    }
+!
+!    Note the above dump is in C order
+!
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          integer NDIMS
+          integer*8 NX, NY
+          PARAMETER(NDIMS=2, NX=4, NY=10)
+
+          character*128 filename, cmd
+          integer i, j, err, ierr, nprocs, rank, get_args, dummy
+          integer cmode, ncid, varid, dimid(NDIMS), num_reqs
+
+          integer*8 w_len, w_req_len
+          integer*8 starts(NDIMS,5)
+          integer*8 counts(NDIMS,5)
+          integer*8 malloc_size, sum_size
+          integer buffer(1024)
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                   err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, err)
+
+          if (nprocs .NE. 4 .AND. rank .EQ. 0 .AND. verbose)
+     +        print*,'Warning: ',cmd,' is intended to run on ',
+     +               '4 processes'
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                        MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define dimensions x and y
+          err = nfmpi_def_dim(ncid, "X", NX, dimid(1))
+          call check(err, 'In nfmpi_def_dim X: ')
+          err = nfmpi_def_dim(ncid, "Y", NY, dimid(2))
+          call check(err, 'In nfmpi_def_dim Y: ')
+
+          ! define a 2D variable of integer type
+          err = nfmpi_def_var(ncid, "var", NF_INT, NDIMS, dimid, varid)
+          call check(err, 'In nfmpi_def_var: ')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! pick arbitrary numbers of requests for 4 processes
+          num_reqs = 0
+          if (rank .EQ. 0) then
+              num_reqs = 3
+          elseif (rank .EQ. 1) then
+              num_reqs = 3
+          elseif (rank .EQ. 2) then
+              num_reqs = 3
+          elseif (rank .EQ. 3) then
+              num_reqs = 3
+          endif
+
+          ! Note that in Fortran, array indices start with 1
+
+          ! assign arbitrary starts and counts
+          if (rank .EQ. 0) then
+              ! rank 0 is writing the followings: ("-" means skip)
+              !        -  -  -  -  -  0  0  -  -  - 
+              !        -  -  -  -  -  0  0  -  -  - 
+              !        -  0  0  -  -  -  -  0  -  - 
+              !        -  0  0  -  -  -  -  0  -  - 
+              ! Note this is in Fortran order
+              starts(1, 1) = 1
+              starts(2, 1) = 6
+              counts(1, 1) = 2
+              counts(2, 1) = 2
+              starts(1, 2) = 3
+              starts(2, 2) = 2
+              counts(1, 2) = 2
+              counts(2, 2) = 2
+              starts(1, 3) = 3
+              starts(2, 3) = 8
+              counts(1, 3) = 2
+              counts(2, 3) = 1
+          elseif (rank .EQ. 1) then
+              ! rank 1 is writing the followings: ("-" means skip)
+              !        -  -  1  1  -  -  -  -  -  - 
+              !        -  -  1  1  -  -  -  -  -  - 
+              !        1  -  -  -  -  1  1  -  -  - 
+              !        1  -  -  -  -  1  1  -  -  - 
+              ! Note this is in Fortran order
+              starts(1, 1) = 1
+              starts(2, 1) = 3
+              counts(1, 1) = 2
+              counts(2, 1) = 2
+              starts(1, 2) = 3
+              starts(2, 2) = 1
+              counts(1, 2) = 2
+              counts(2, 2) = 1
+              starts(1, 3) = 3
+              starts(2, 3) = 6
+              counts(1, 3) = 2
+              counts(2, 3) = 2
+          elseif (rank .EQ. 2) then
+              ! rank 2 is writing the followings: ("-" means skip)
+              !        2  2  -  -  -  -  -  2  -  - 
+              !        2  2  -  -  -  -  -  2  -  - 
+              !        -  -  -  -  2  -  -  -  -  - 
+              !        -  -  -  -  2  -  -  -  -  - 
+              ! Note this is in Fortran order
+              starts(1, 1) = 1
+              starts(2, 1) = 1
+              counts(1, 1) = 2
+              counts(2, 1) = 2
+              starts(1, 2) = 1
+              starts(2, 2) = 8
+              counts(1, 2) = 2
+              counts(2, 2) = 1
+              starts(1, 3) = 3
+              starts(2, 3) = 5
+              counts(1, 3) = 2
+              counts(2, 3) = 1
+          elseif (rank .EQ. 3) then
+              ! rank 3 is writing the followings: ("-" means skip)
+              !        -  -  -  -  3  -  -  -  3  3 
+              !        -  -  -  -  3  -  -  -  3  3 
+              !        -  -  -  3  -  -  -  -  3  3 
+              !        -  -  -  3  -  -  -  -  3  3 
+              ! Note this is in Fortran order
+              starts(1, 1) = 1
+              starts(2, 1) = 5
+              counts(1, 1) = 2
+              counts(2, 1) = 1
+              starts(1, 2) = 1
+              starts(2, 2) = 9
+              counts(1, 2) = 4
+              counts(2, 2) = 2
+              starts(1, 3) = 3
+              starts(2, 3) = 4
+              counts(1, 3) = 2
+              counts(2, 3) = 1
+          endif
+ 
+          ! w_len is total write length for this process
+          w_len = 0
+          do i=1, num_reqs
+             w_req_len = 1
+             do j=1, NDIMS
+                w_req_len = w_req_len * counts(j, i)
+             enddo
+             w_len = w_len + w_req_len
+          enddo
+
+          ! initialize buffer contents
+          do i=1, 1024
+             buffer(i) = rank
+          enddo
+
+          err = nfmpi_put_varn_int_all(ncid, varid, num_reqs, starts,
+     +                                 counts, buffer)
+          call check(err, 'In nfmpi_put_varn_int_all: ')
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end ! program main
+
diff --git a/examples/F77/put_varn_real.f b/examples/F77/put_varn_real.f
new file mode 100644
index 0000000..d2dd79f
--- /dev/null
+++ b/examples/F77/put_varn_real.f
@@ -0,0 +1,261 @@
+!
+!  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: put_varn_real.f 2224 2015-12-16 06:10:36Z wkliao $
+
+!
+! This example shows how to use a single call of nfmpi_put_varn_real_all()
+! to write a sequence of one-element requests with arbitrary array indices.
+!
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file.
+!
+!    % mpif77 -O2 -o put_varn_real put_varn_real.f -lpnetcdf
+!    % mpiexec -n 4 ./put_varn_real /pvfs2/wkliao/testfile.nc
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!             Y = 4 ;
+!             X = 10 ;
+!    variables:
+!             int var(Y, X) ;
+!    data:
+!
+!     var =
+!       3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+!       0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+!       1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+!       0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+!    }
+!
+
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          integer NDIMS
+          PARAMETER(NDIMS=2)
+
+          character*128 filename, cmd
+          integer rank, nprocs, err, num_reqs, ierr, get_args, dummy
+          integer i, j, ncid, cmode, varid, dimid(2), y, x
+          real buffer(13)
+          integer*8 NY, NX
+          integer*8 starts(NDIMS, 13)
+          integer*8 counts(NDIMS, 13)
+          integer*8 malloc_size, sum_size
+          logical verbose
+
+          NY = 4
+          NX = 10
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                   err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, err)
+
+          if (nprocs .NE. 4 .AND. rank .EQ. 0 .AND. verbose)
+     +        print*,'Warning: ',cmd,' is intended to run on ',
+     +               '4 processes'
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                       MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! create a global array of size NY * NX */
+          err = nfmpi_def_dim(ncid, "Y", NY, dimid(2))
+          call check(err, 'In nfmpi_def_dim Y: ')
+          err = nfmpi_def_dim(ncid, "X", NX, dimid(1))
+          call check(err, 'In nfmpi_def_dim X: ')
+          err = nfmpi_def_var(ncid, "var", NF_FLOAT, NDIMS, dimid,
+     +                        varid)
+          call check(err, 'In nfmpi_def_var var: ')
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! pick arbitrary numbers of requests for 4 processes
+          num_reqs = 0
+          if (rank .EQ.  0) then
+              num_reqs = 8
+          elseif (rank .EQ. 1) then
+              num_reqs = 13
+          elseif (rank .EQ. 2) then
+              num_reqs = 9
+          elseif (rank .EQ. 3) then
+              num_reqs = 10
+          endif
+
+          ! assign arbitrary starts
+          y=2
+          x=1
+          if (rank .EQ. 0) then
+              starts(y, 1) = 1
+              starts(x, 1) = 6
+              starts(y, 2) = 2
+              starts(x, 2) = 1
+              starts(y, 3) = 3
+              starts(x, 3) = 7
+              starts(y, 4) = 4
+              starts(x, 4) = 1
+              starts(y, 5) = 1
+              starts(x, 5) = 7
+              starts(y, 6) = 3
+              starts(x, 6) = 8
+              starts(y, 7) = 4
+              starts(x, 7) = 2
+              starts(y, 8) = 4
+              starts(x, 8) = 3
+              ! rank 0 is writing the following locations: ("-" means skip)
+              !   -  -  -  -  -  0  0  -  -  - 
+              !   0  -  -  -  -  -  -  -  -  - 
+              !   -  -  -  -  -  -  0  0  -  - 
+              !   0  0  0  -  -  -  -  -  -  - 
+          elseif (rank .EQ. 1) then
+              starts(y,  1) = 1
+              starts(x,  1) = 4
+              starts(y,  2) = 1
+              starts(x,  2) = 9
+              starts(y,  3) = 2
+              starts(x,  3) = 6
+              starts(y,  4) = 3
+              starts(x,  4) = 1
+              starts(y,  5) = 3
+              starts(x,  5) = 9
+              starts(y,  6) = 4
+              starts(x,  6) = 5
+              starts(y,  7) = 1
+              starts(x,  7) = 5
+              starts(y,  8) = 1
+              starts(x,  8) = 10
+              starts(y,  9) = 2
+              starts(x,  9) = 7
+              starts(y, 10) = 3
+              starts(x, 10) = 2
+              starts(y, 11) = 3
+              starts(x, 11) = 10
+              starts(y, 12) = 4
+              starts(x, 12) = 6
+              starts(y, 13) = 4
+              starts(x, 13) = 7
+              ! rank 1 is writing the following locations: ("-" means skip)
+              !   -  -  -  1  1  -  -  -  1  1 
+              !   -  -  -  -  -  1  1  -  -  - 
+              !   1  1  -  -  -  -  -  -  1  1 
+              !   -  -  -  -  1  1  1  -  -  - 
+          elseif (rank .EQ. 2) then
+              starts(y, 1) = 1
+              starts(x, 1) = 8
+              starts(y, 2) = 2
+              starts(x, 2) = 2
+              starts(y, 3) = 2
+              starts(x, 3) = 8
+              starts(y, 4) = 3
+              starts(x, 4) = 3
+              starts(y, 5) = 4
+              starts(x, 5) = 4
+              starts(y, 6) = 2
+              starts(x, 6) = 3
+              starts(y, 7) = 2
+              starts(x, 7) = 9
+              starts(y, 8) = 2
+              starts(x, 8) = 4
+              starts(y, 9) = 2
+              starts(x, 9) = 10
+              ! rank 2 is writing the following locations: ("-" means skip)
+              !   -  -  -  -  -  -  -  2  -  - 
+              !   -  2  2  2  -  -  -  2  2  2 
+              !   -  -  2  -  -  -  -  -  -  - 
+              !   -  -  -  2  -  -  -  -  -  - 
+          elseif (rank .EQ. 3) then
+              starts(y,  1) = 1
+              starts(x,  1) = 1
+              starts(y,  2) = 2
+              starts(x,  2) = 5
+              starts(y,  3) = 3
+              starts(x,  3) = 4
+              starts(y,  4) = 4
+              starts(x,  4) = 8
+              starts(y,  5) = 1
+              starts(x,  5) = 2
+              starts(y,  6) = 3
+              starts(x,  6) = 5
+              starts(y,  7) = 4
+              starts(x,  7) = 9
+              starts(y,  8) = 1
+              starts(x,  8) = 3
+              starts(y,  9) = 3
+              starts(x,  9) = 6
+              starts(y, 10) = 4
+              starts(x, 10) = 10
+              ! rank 3 is writing the following locations: ("-" means skip)
+              !   3  3  3  -  -  -  -  -  -  - 
+              !   -  -  -  -  3  -  -  -  -  - 
+              !   -  -  -  3  3  3  -  -  -  - 
+              !   -  -  -  -  -  -  -  3  3  3 
+          endif
+
+          ! allocate I/O buffer and initialize its contents
+          do i=1, 13
+             buffer(i) = rank
+             do j=1, NDIMS
+                counts(j,i) = 1
+             enddo
+          enddo
+
+          ! set the buffer pointers to different offsets to the I/O buffer
+          err = nfmpi_put_varn_real_all(ncid, varid, num_reqs, starts,
+     +                                  counts, buffer)
+          call check(err, 'In nfmpi_put_varn_real_all: ')
+
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+
+      end ! program
+
diff --git a/examples/F77/transpose.f b/examples/F77/transpose.f
new file mode 100644
index 0000000..73bd1b8
--- /dev/null
+++ b/examples/F77/transpose.f
@@ -0,0 +1,290 @@
+!
+!   Copyright (C) 2014, Northwestern University
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: transpose.f 2224 2015-12-16 06:10:36Z wkliao $
+
+!
+!    This example shows how to use varm API to write six 3D integer
+!    array variables into a file. Each variable in the file is a
+!    dimensional transposed array from the one stored in memory. In
+!    memory, a 3D array is partitioned among all processes in a
+!    block-block-block fashion and in XYZ (i.e. Fortran) order. Note
+!    the variable and dimension naming below is in Fortran order. The
+!    dimension structures of the transposed six arrays are
+!       integer XYZ_var(X, Y, Z)      XYZ -> XYZ (no transpose)
+!       integer XZY_var(X, Z, Y)      XYZ -> XZY
+!       integer YXZ_var(Y, X, Z)      XYZ -> YXZ
+!       integer YZX_var(Y, Z, X)      XYZ -> YZX
+!       integer ZXY_var(Z, X, Y)      XYZ -> ZXY
+!       integer ZYX_var(Z, Y, X)      XYZ -> ZYX
+!
+!    To compile:
+!        mpif77 -O2 transpose.f -o transpose -lpnetcdf
+!    To run:
+!        mpiexec -n num_processes ./transpose [filename] [len]
+!    where len decides the size of local array, which is
+!    (len+2) x (len+1) x len. So, each variable is of size
+!    (len+2)*(len+1)*len * nprocs * sizeof(int)
+!
+      subroutine check(err, message)
+          implicit none
+          include 'mpif.h'
+          include 'pnetcdf.inc'
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include 'mpif.h'
+          include 'pnetcdf.inc'
+
+          character*128 filename, cmd
+          integer err, ierr, nprocs, rank, lower_dims, get_args, dummy
+          integer cmode, ncid, psizes(3), dimids(3), dimidsT(3)
+          integer XYZ_id, XZY_id, YZX_id, YXZ_id, ZYX_id, ZXY_id
+          integer*8 gsizes(3), starts(3)
+          integer*8 counts(3), strides(3), imap(3)
+          integer*8 startsT(3), countsT(3)
+          integer*8 malloc_size, sum_size, one
+          integer i, j, k, nx, ny, nz
+          PARAMETER(nx=4, ny=3, nz=2)
+          integer buf(nx,ny,nz)
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          one = 1
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                   err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, err)
+
+          ! calculate number of processes along each dimension
+          psizes(1) = 0
+          psizes(2) = 0
+          psizes(3) = 0
+          call MPI_Dims_create(nprocs, 3, psizes, err)
+          if (verbose .AND. rank .EQ. 0) print*, "psizes= ",psizes(1),
+     +                                   psizes(2),psizes(3)
+
+          ! for each MPI rank, find its local rank IDs along each dimension in
+          ! starts()
+          lower_dims = 1
+          do i=1, 3
+              starts(i) = MOD(rank / lower_dims, psizes(i))
+              lower_dims = lower_dims * psizes(i)
+          enddo
+          if (verbose)
+     +        print*, "proc ",rank,": dim rank= ",starts(1),starts(2),
+     +                starts(3)
+
+          strides(1) = 1
+          strides(2) = 1
+          strides(3) = 1
+          gsizes(1)  = nx
+          gsizes(2)  = ny
+          gsizes(3)  = nz
+          do i=1, 3
+             starts(i) = starts(i) * gsizes(i) + 1 ! start indices
+             counts(i) = gsizes(i)                 ! array elements
+             gsizes(i) = gsizes(i) * psizes(i)     ! global array size
+          enddo
+
+          if (verbose) then
+              print*, "proc ",rank,": starts= ",starts(1),starts(2),
+     +                starts(3)
+              print*, "proc ",rank,": counts= ",counts(1),counts(2),
+     +                counts(3)
+          endif
+
+          ! initialize buffer with contiguous numbers
+          do k=1, nz
+          do j=1, ny
+          do i=1, nx
+              buf(i, j, k) = INT((starts(3)+k-2)*gsizes(2)*gsizes(1) +
+     +                           (starts(2)+j-2)*gsizes(1) +
+     +                           (starts(1)+i-2))
+          enddo
+          enddo
+          enddo
+          if (verbose .AND. rank .EQ. 0) print*, "buf= ",buf
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+          cmode = NF_CLOBBER
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                       MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define dimensions X, Y, Z
+          err = nfmpi_def_dim(ncid, "X", gsizes(1), dimids(1))
+          call check(err, 'In nfmpi_def_dim X: ')
+          err = nfmpi_def_dim(ncid, "Y", gsizes(2), dimids(2))
+          call check(err, 'In nfmpi_def_dim Y: ')
+          err = nfmpi_def_dim(ncid, "Z", gsizes(3), dimids(3))
+          call check(err, 'In nfmpi_def_dim Z: ')
+
+          ! define variable with no transposed file layout: XYZ
+          err = nfmpi_def_var(ncid, "XYZ_var", NF_INT, 3, dimids,
+     +                        XYZ_id)
+          call check(err, 'In nfmpi_def_var XYZ_var: ')
+
+          ! define variable with transposed file layout: XYZ -> XZY
+          dimidsT(1) = dimids(1)
+          dimidsT(2) = dimids(3)
+          dimidsT(3) = dimids(2)
+          err = nfmpi_def_var(ncid, "XZY_var", NF_INT, 3, dimidsT,
+     +                        XZY_id)
+          call check(err, 'In nfmpi_def_var XZY_var: ')
+
+          ! define variable with transposed file layout: XYZ -> YXZ
+          dimidsT(1) = dimids(2)
+          dimidsT(2) = dimids(1)
+          dimidsT(3) = dimids(3)
+          err = nfmpi_def_var(ncid, "YXZ_var", NF_INT, 3, dimidsT,
+     +                        YXZ_id)
+          call check(err, 'In nfmpi_def_var YXZ_var: ')
+
+          ! define variable with transposed file layout: XYZ -> YZX
+          dimidsT(1) = dimids(2)
+          dimidsT(2) = dimids(3)
+          dimidsT(3) = dimids(1)
+          err = nfmpi_def_var(ncid, "YZX_var", NF_INT, 3, dimidsT,
+     +                        YZX_id)
+          call check(err, 'In nfmpi_def_var YZX_var: ')
+
+          ! define variable with transposed file layout: XYZ -> ZXY
+          dimidsT(1) = dimids(3)
+          dimidsT(2) = dimids(1)
+          dimidsT(3) = dimids(2)
+          err = nfmpi_def_var(ncid, "ZXY_var", NF_INT, 3, dimidsT,
+     +                        ZXY_id)
+          call check(err, 'In nfmpi_def_var ZXY_var: ')
+
+          ! define variable with transposed file layout: XYZ -> ZYX
+          dimidsT(1) = dimids(3)
+          dimidsT(2) = dimids(2)
+          dimidsT(3) = dimids(1)
+          err = nfmpi_def_var(ncid, "ZYX_var", NF_INT, 3, dimidsT,
+     +                        ZYX_id)
+          call check(err, 'In nfmpi_def_var ZYX_var: ')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! write the whole variable in file: XYZ
+          err = nfmpi_put_vara_int_all(ncid, XYZ_id, starts, counts,buf)
+          call check(err, 'In nfmpi_put_vara_int_all XYZ: ')
+
+          ! write the transposed variable:  XYZ -> XZY
+          imap(1) = one
+          imap(2) = counts(1)*counts(2)
+          imap(3) = counts(1)
+          startsT(1) = starts(1)
+          startsT(2) = starts(3)
+          startsT(3) = starts(2)
+          countsT(1) = counts(1)
+          countsT(2) = counts(3)
+          countsT(3) = counts(2)
+          err = nfmpi_put_varm_int_all(ncid, XZY_id, startsT, countsT,
+     +                                 strides, imap, buf)
+          call check(err, 'In nfmpi_put_varm_int_all XZY: ')
+
+          ! write the transposed variable:  XYZ -> YXZ
+          imap(1) = counts(1)
+          imap(2) = one
+          imap(3) = counts(1)*counts(2)
+          startsT(1) = starts(2)
+          startsT(2) = starts(1)
+          startsT(3) = starts(3)
+          countsT(1) = counts(2)
+          countsT(2) = counts(1)
+          countsT(3) = counts(3)
+          err = nfmpi_put_varm_int_all(ncid, YXZ_id, startsT, countsT,
+     +                                 strides, imap, buf)
+          call check(err, 'In nfmpi_put_varm_int_all YZX: ')
+
+          ! write the transposed variable:  XYZ -> YZX
+          imap(1) = counts(1)
+          imap(2) = counts(1)*counts(2)
+          imap(3) = one
+          startsT(1) = starts(2)
+          startsT(2) = starts(3)
+          startsT(3) = starts(1)
+          countsT(1) = counts(2)
+          countsT(2) = counts(3)
+          countsT(3) = counts(1)
+          err = nfmpi_put_varm_int_all(ncid, YZX_id, startsT, countsT,
+     +                                 strides, imap, buf)
+          call check(err, 'In nfmpi_put_varm_int_all YZX: ')
+
+          ! write the transposed variable:  XYZ -> ZXY
+          imap(1) = counts(1)*counts(2)
+          imap(2) = one
+          imap(3) = counts(1)
+          startsT(1) = starts(3)
+          startsT(2) = starts(1)
+          startsT(3) = starts(2)
+          countsT(1) = counts(3)
+          countsT(2) = counts(1)
+          countsT(3) = counts(2)
+          err = nfmpi_put_varm_int_all(ncid, ZXY_id, startsT, countsT,
+     +                                 strides, imap, buf)
+          call check(err, 'In nfmpi_put_varm_int_all ZXY: ')
+
+          ! write the transposed variable:  XYZ -> ZYX
+          imap(1) = counts(1)*counts(2)
+          imap(2) = counts(1)
+          imap(3) = one
+          startsT(1) = starts(3)
+          startsT(2) = starts(2)
+          startsT(3) = starts(1)
+          countsT(1) = counts(3)
+          countsT(2) = counts(2)
+          countsT(3) = counts(1)
+          err = nfmpi_put_varm_int_all(ncid, ZYX_id, startsT, countsT,
+     +                                 strides, imap, buf)
+          call check(err, 'In nfmpi_put_varm_int_all ZYX: ')
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, 
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end ! program main
+
diff --git a/examples/F77/utils.F90 b/examples/F77/utils.F90
new file mode 100644
index 0000000..d83aeca
--- /dev/null
+++ b/examples/F77/utils.F90
@@ -0,0 +1,53 @@
+!
+!  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: utils.F90 2120 2015-09-22 07:11:58Z wkliao $
+
+    ! This function gets the executable name and output file name from the
+    ! command line.
+    integer function get_args(max_argc, cmd, filename, verbose, len)
+#ifdef NAGf90Fortran
+        USE F90_UNIX_ENV, only : iargc, getarg
+        implicit none
+#else
+        implicit none
+        integer iargc
+#endif
+        integer max_argc, len
+        character(len=*) cmd, filename
+        logical verbose
+
+        ! local variables
+        integer argc
+        character(len=16) quiet_mode, str
+
+
+        call getarg(0, cmd)
+        argc = IARGC()
+        if (argc .GT. max_argc) then
+            if (max_argc .EQ. 3) &
+                print*,'Usage: ',trim(cmd),' [-q] [filename] [len]'
+            if (max_argc .EQ. 2) &
+                print*,'Usage: ',trim(cmd),' [-q] [filename]'
+            get_args = 0
+            return
+        endif
+        call getarg(1, quiet_mode)
+        if (quiet_mode(1:2) .EQ. '-q') then
+            verbose = .FALSE.
+            if (argc .GE. 2) call getarg(2, filename)
+            if (argc .EQ. 3) then
+                call getarg(3, str)
+                read (str,'(I10)') len
+            endif
+        else
+            if (argc .GE. 1) call getarg(1, filename)
+            if (argc .EQ. 2) then
+                call getarg(2, str)
+                read (str,'(I10)') len
+            endif
+        endif
+    end function get_args
diff --git a/examples/F77/vard_int.F b/examples/F77/vard_int.F
new file mode 100644
index 0000000..814f8f9
--- /dev/null
+++ b/examples/F77/vard_int.F
@@ -0,0 +1,233 @@
+!
+!   Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: vard_int.F 2239 2015-12-18 18:21:09Z wkliao $
+
+!
+! This example shows how to use the vard API nfmpi_put_vard() and
+! nfmpi_get_vard() to write and read 2D record and fixed-size
+! variables.
+!
+!    To compile:
+!        mpif77 -O2 vard_int.f -o vard_int -lpnetcdf
+!
+! Example commands for MPI run and outputs from running ncmpidump on
+! the NC file produced by this example program:
+!
+!    % mpiexec -n 4 ./vard_int /pvfs2/wkliao/testfile.nc
+!
+! The expected results from the output file contents are:
+!
+!  % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-1
+!    dimensions:
+!           REC_DIM = UNLIMITED ; // (2 currently)
+!           X = 12 ;
+!           FIX_DIM = 2 ;
+!    variables:
+!           int rec_var(REC_DIM, X) ;
+!           int fix_var(FIX_DIM, X) ;
+!    data:
+!
+!     rec_var =
+!       0, 1, 2, 100, 101, 102, 200, 201, 202, 300, 301, 302,
+!       10, 11, 12, 110, 111, 112, 210, 211, 212, 310, 311, 312 ;
+!
+!     fix_var =
+!       0, 1, 2, 100, 101, 102, 200, 201, 202, 300, 301, 302,
+!       10, 11, 12, 110, 111, 112, 210, 211, 212, 310, 311, 312 ;
+!    }
+!
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err
+          character message*(*)
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message//' '//nfmpi_strerror(err)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          character*128 filename, cmd
+          integer err, ierr, nprocs, rank, i, j, get_args, dummy
+          integer cmode, ncid, varid0, varid1, dimid(2)
+          integer*8 NX, NY, len, bufcount
+          integer*8 start(2), count(2)
+          PARAMETER(NX=3, NY=2)
+          integer buf(NX, NY)
+          integer buftype, rec_filetype, fix_filetype
+          integer array_of_sizes(2), array_of_subsizes(2)
+          integer array_of_starts(2), blocklengths(2)
+          integer*8 malloc_size, sum_size, recsize, two
+#ifdef SIZEOF_MPI_AINT_IS_4
+          integer disps(2)
+#else
+          integer*8 disps(2)
+#endif
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          two = 2
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD,
+     +                   err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, err)
+
+          start(1) = NX * rank
+          start(2) = 0
+          count(1) = NX
+          count(2) = 2
+
+          ! initialized buffer contents
+          do j=1, INT(count(2))
+             do i=1, INT(count(1))
+                 buf(i, j) = rank*100 + j*10 + i
+             enddo
+          enddo
+
+          ! create file, truncate it if exists
+          cmode = NF_CLOBBER
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                       MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define 2 dimensions
+          err = nfmpi_def_dim(ncid, "REC_DIM", NFMPI_UNLIMITED,dimid(2))
+          call check(err, 'In nfmpi_def_dim REC_DIM: ')
+          len = NX * nprocs
+          err = nfmpi_def_dim(ncid, "X", len, dimid(1))
+          call check(err, 'In nfmpi_def_dim X: ')
+
+          ! define 2D record variables of integer type
+          err = nfmpi_def_var(ncid, "rec_var", NF_INT, 2, dimid, varid0)
+          call check(err, 'In nfmpi_def_var: rec_var ')
+
+          ! define 2D fixed-size variable of integer type
+          err = nfmpi_def_dim(ncid, "FIX_DIM", two, dimid(2))
+          call check(err, 'In nfmpi_def_dim RECV_DIM: ')
+          err = nfmpi_def_var(ncid, "fix_var", NF_INT, 2, dimid, varid1)
+          call check(err, 'In nfmpi_def_var: fix_var ')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! create a file type for the record variable */
+          err = nfmpi_inq_recsize(ncid, recsize)
+          call check(err, 'In nfmpi_inq_recsize: ')
+          blocklengths(1) = INT(count(1))
+          blocklengths(2) = INT(count(1))
+          disps(1) = start(1)*4
+          disps(2) = recsize + start(1)*4
+          call MPI_Type_create_hindexed(2, blocklengths, disps,
+     +                                  MPI_INTEGER, rec_filetype, err)
+          call MPI_Type_commit(rec_filetype, err)
+
+          ! create a file type for the fixed-size variable
+          array_of_sizes(1) = INT(NX*nprocs)
+          array_of_sizes(2) = 2
+          array_of_subsizes(1) = INT(count(1))
+          array_of_subsizes(2) = INT(count(2))
+          array_of_starts(1) = INT(start(1))
+          array_of_starts(2) = INT(start(2))
+          call MPI_Type_create_subarray(2, array_of_sizes,
+     +         array_of_subsizes, array_of_starts, MPI_ORDER_FORTRAN,
+     +         MPI_INTEGER, fix_filetype, err)
+          call MPI_Type_commit(fix_filetype, err)
+
+          bufcount = count(1) * count(2)
+          buftype = MPI_INTEGER
+
+          ! write the record variable */
+          err = nfmpi_put_vard_all(ncid, varid0, rec_filetype, buf,
+     +                             bufcount, buftype)
+          call check(err, 'In nfmpi_put_vard_all: ')
+
+          ! check if the number of records changed to 2
+          err = nfmpi_inq_unlimdim(ncid, dimid(2))
+          call check(err, 'In nfmpi_inq_unlimdim: ')
+          err = nfmpi_inq_dimlen(ncid, dimid(2), len)
+          call check(err, 'In nfmpi_inq_dimlen: ')
+          if (len .NE. 2) then
+              print*, 'Error: number of records should be 2 but got ',
+     +                 len
+          endif
+
+          ! write the fixed-size variable
+          err = nfmpi_put_vard_all(ncid, varid1, fix_filetype, buf,
+     +                             bufcount, buftype)
+          call check(err, 'In nfmpi_put_vard_all: ')
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! open the same file and read back for validate */
+          err = nfmpi_open(MPI_COMM_WORLD, filename, NF_NOWRITE,
+     +                     MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_open: ')
+
+          err = nfmpi_inq_varid(ncid, "rec_var", varid0)
+          call check(err, 'In nfmpi_inq_varid rec_var: ')
+          err = nfmpi_inq_varid(ncid, "fix_var", varid1)
+          call check(err, 'In nfmpi_inq_varid fix_var: ')
+
+          ! PnetCDF start() argument starts with 1
+          start(1) = start(1) + 1
+          start(2) = start(2) + 1
+
+          ! read back record variable
+          err = nfmpi_get_vard_all(ncid, varid0, rec_filetype, buf,
+     +                             bufcount, buftype)
+          call check(err, 'In nfmpi_get_vard_all: ')
+
+          ! read back fixed-size variable
+          err = nfmpi_get_vard_all(ncid, varid1, fix_filetype, buf,
+     +                             bufcount, buftype)
+          call check(err, 'In nfmpi_get_vard_all: ')
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          call MPI_Type_free(rec_filetype, err)
+          call MPI_Type_free(fix_filetype, err)
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end ! program main
+
diff --git a/examples/F90/Makefile.in b/examples/F90/Makefile.in
new file mode 100644
index 0000000..e5736fc
--- /dev/null
+++ b/examples/F90/Makefile.in
@@ -0,0 +1,123 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2236 2015-12-18 03:49:41Z wkliao $
+#
+# @configure_input@
+
+srcdir  = @srcdir@
+VPATH   = @srcdir@
+
+include ../../macros.make
+
+# note the order of -L list matters
+INCLUDES    = @FC_MODINC at ../../src/libf90
+F90LDFLAGS := -L../../src/lib $(F90LDFLAGS) $(LDFLAGS)
+LIBS       := -lpnetcdf $(LIBS)
+
+F90_SRCS  = nonblocking_write.f90 \
+            column_wise.f90 \
+            block_cyclic.f90 \
+            flexible_api.f90 \
+            get_info.f90 \
+            hints.f90 \
+            put_var.f90 \
+            put_varn_real.f90 \
+            put_varn_int.f90 \
+            transpose.f90 \
+            vard_int.f90 \
+            fill_mode.f90
+
+PROGS     = $(F90_SRCS:.f90=)
+OBJS      = $(F90_SRCS:.f90=.o)
+
+UTIL_SRCS  = utils.F90
+UTIL_OBJS  = $(UTIL_SRCS:.F90=.o)
+
+GARBAGE      = $(PROGS) *.nc
+
+PACKING_LIST = $(F90_SRCS) $(UTIL_SRCS) depend Makefile.in
+
+all: $(PROGS)
+
+install:
+
+uninstall:
+
+nonblocking_write: nonblocking_write.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(F90LDFLAGS) $(LIBS)
+
+get_info: get_info.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(F90LDFLAGS) $(LIBS)
+
+column_wise: column_wise.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(F90LDFLAGS) $(LIBS)
+
+block_cyclic: block_cyclic.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(F90LDFLAGS) $(LIBS)
+
+put_var: put_var.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(F90LDFLAGS) $(LIBS)
+
+hints: hints.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(F90LDFLAGS) $(LIBS)
+
+flexible_api: flexible_api.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(F90LDFLAGS) $(LIBS)
+
+put_varn_int: put_varn_int.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(F90LDFLAGS) $(LIBS)
+
+put_varn_real: put_varn_real.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(F90LDFLAGS) $(LIBS)
+
+transpose: transpose.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(F90LDFLAGS) $(LIBS)
+
+vard_int: vard_int.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(F90LDFLAGS) $(LIBS)
+
+fill_mode: fill_mode.o $(UTIL_OBJS) $(LIBRARY)
+	$(LINK.F90) $< $(UTIL_OBJS) $(F90LDFLAGS) $(LIBS)
+
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+TEST_MPIRUN_8  = $(subst NP,8,$(TEST_MPIRUN))
+TEST_MPIRUN_3  = $(subst NP,3,$(TEST_MPIRUN))
+
+ptest4: $(PROGS)
+	@for i in $(PROGS); do ( \
+        $(TEST_MPIRUN_4) ./$$i -q $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS: F90 parallel run on 4 processes --------------- $$i"; \
+        else \
+           echo "FAILED: F90 parallel run on 4 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest8: $(PROGS)
+	@for i in $(PROGS); do ( \
+        $(TEST_MPIRUN_8) ./$$i -q $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS: F90 parallel run on 8 processes --------------- $$i"; \
+        else \
+           echo "FAILED: F90 parallel run on 8 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest3: $(PROGS)
+	@for i in $(PROGS); do ( \
+        $(TEST_MPIRUN_3) ./$$i -q $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS: F90 parallel run on 3 processes --------------- $$i"; \
+        else \
+           echo "FAILED: F90 parallel run on 3 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest: ptest4
+ptests: ptest3 ptest4 ptest8
+ptest2 ptest6 ptest10:
+
+include $(srcdir)/depend
+include $(srcdir)/../../rules.make
+
+$(LIBRARY): ;
+
diff --git a/examples/F90/block_cyclic.f90 b/examples/F90/block_cyclic.f90
new file mode 100644
index 0000000..6ef74f5
--- /dev/null
+++ b/examples/F90/block_cyclic.f90
@@ -0,0 +1,278 @@
+!
+!  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: block_cyclic.f90 2245 2015-12-20 18:39:52Z wkliao $
+
+
+! This example, generalized from column_wise.f, makes a number of nonblocking
+! API calls, each writes a block of columns into a 2D integer array. In other
+! words, the I/O pattern is a blocked cyclic along X dimension.
+!
+! Each process writes NX rows in total. The block length is controlled by
+! block_len. In this example, block_len is set to 2. Blocks are layout in a
+! cyclic fashion in the file. This example can test if PnetCDF can coalesce
+! file offsets and lengths when constructing a merged filetype.
+! 
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file. In this example, block_len = 2.
+!
+!    % mpif90 -O2 -o block_cyclic block_cyclic.f90 -lpnetcdf
+!    % mpiexec -n 4 ./block_cyclic /pvfs2/wkliao/testfile.nc
+!
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!            Y = 10 ;
+!            X = 16 ;
+!    variables:
+!            int var(Y, X) ;
+!    data:
+!
+!     var =
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13,
+!      10, 10, 11, 11, 12, 12, 13, 13, 10, 10, 11, 11, 12, 12, 13, 13 ;
+!    }
+!
+
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          integer NY, NX
+          PARAMETER(NX=10, NY=4)
+
+          character(LEN=128) filename, cmd
+          integer i, j, rank, nprocs, err, num_reqs, ierr, get_args, dummy
+          integer ncid, cmode, varid, dimid(2), stride, block_len
+          integer, dimension(:,:), allocatable :: buf
+          integer, dimension(:), allocatable :: reqs, sts
+          integer(kind=MPI_OFFSET_KIND) G_NY, myOff, block_start, &
+                                        global_nx, global_ny
+          integer(kind=MPI_OFFSET_KIND) start(2), count(2)
+          integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD, err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! the global array is NX * (NY * nprocs) */
+          G_NY  = NY * nprocs
+          myOff = NY * rank
+
+          ! define dimensions
+          global_nx = NX
+          err = nf90mpi_def_dim(ncid, 'Y', global_nx, dimid(2))
+          call check(err, 'In nf90mpi_def_dim Y')
+
+          err = nf90mpi_def_dim(ncid, 'X', G_NY, dimid(1))
+          call check(err, 'In nf90mpi_def_dim X')
+
+          err = nf90mpi_def_var(ncid, 'var', NF90_INT, dimid, varid)
+          call check(err, 'In nf90mpi_def_var var')
+
+          ! do not forget to exit define mode
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! First, fill the entire array with zeros, using a blocking I/O.
+          ! Every process writes a subarray of size NX * NY
+          allocate(buf(NX, NY))
+          buf = 0
+
+          allocate(reqs(NY))
+          allocate(sts(NY))
+
+          start(1) = myOff+1
+          start(2) = 1
+          count(1) = NY
+          count(2) = NX
+          err = nf90mpi_put_var_all(ncid, varid, buf, start, count)
+          call check(err, 'In nf90mpi_put_vara_int_all: ')
+
+          ! initialize the buffer with rank ID
+          buf = rank+10
+
+          ! each proc writes NY columns of the 2D array, block_len controls the
+          ! the number of contiguous columns at a time
+          block_start = 0
+          block_len   = 2  ! can be 1, 2, 3, ..., NY
+          if (block_len > NY) block_len = NY
+
+          start(1) = rank * block_len + 1
+          start(2) = 1
+          count(1) = 1
+          count(2) = NX
+          num_reqs = 0
+
+          do i=1, NY
+             num_reqs = num_reqs + 1
+             err = nf90mpi_iput_var(ncid, varid, buf(:,i), &
+                                    reqs(num_reqs), start, &
+                                    count)
+             call check(err, 'In nf90mpi_iput_vara_int: ')
+
+             if (MOD(i, block_len) .EQ. 0) then
+                 stride = NY-i
+                 if (stride .GT. block_len) stride = block_len
+                 block_start = block_start + block_len * nprocs
+                 start(1) = block_start + stride * rank + 1;
+             else
+                 start(1) = start(1) + 1
+             endif
+          enddo
+
+          err = nf90mpi_wait_all(ncid, num_reqs, reqs, sts)
+          call check(err, 'In nf90mpi_wait_all: ')
+
+          ! check status of all requests
+          do i=1, num_reqs
+             if (sts(i) .NE. NF90_NOERR) then
+                 print*, "Error: nonblocking write fails on request", &
+                         i, ' ', nf90mpi_strerror(sts(i))
+             endif
+          enddo
+
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          ! open an existing file created earlier for read
+          err = nf90mpi_open(MPI_COMM_WORLD, filename, NF90_NOWRITE, &
+                           MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_open: ')
+
+          ! the global array is NX * (NY * nprocs) */
+          err = nf90mpi_inq_dimid(ncid, "X", dimid(1))
+          call check(err, 'In nf90mpi_inq_dimid X: ')
+          err = nf90mpi_inquire_dimension(ncid, dimid(1), len=global_ny)
+          call check(err, 'In nf90mpi_inq_dimlen: ')
+          ! G_NY must == NY * nprocs
+          ! myNY must == global_ny / nprocs
+
+          err = nf90mpi_inq_dimid(ncid, "Y", dimid(2))
+          call check(err, 'In nf90mpi_inq_dimid Y: ')
+          err = nf90mpi_inquire_dimension(ncid, dimid(2), len=global_nx)
+          call check(err, 'In nf90mpi_inq_dimlen: ')
+          ! global_nx must == NX
+
+          err = nf90mpi_inq_varid(ncid, "var", varid)
+          call check(err, 'In nf90mpi_inq_varid: ')
+
+          ! initialize the buffer with -1, so a read error can be pinpointed
+          buf = -1
+
+          ! each proc reads NY columns of the 2D array, block_len controls the
+          ! the number of contiguous columns at a time */
+          block_start = 0
+          block_len   = 2  ! can be 1, 2, 3, ..., NY
+          if (block_len .GT. NY) block_len = NY
+
+          start(1) = rank * block_len + 1
+          start(2) = 1
+          count(1) = 1
+          count(2) = global_nx
+          num_reqs = 0
+
+          do i=1, NY
+             num_reqs = num_reqs + 1
+             err = nf90mpi_iget_var(ncid, varid, buf(:,i), &
+                                    reqs(num_reqs), start, count)
+             call check(err, 'In nf90mpi_iget_vara_int: ')
+
+             if (MOD(i, block_len) .EQ. 0) then
+                 stride = NY-i
+                 if (stride .GT. block_len) stride = block_len
+                 block_start = block_start + block_len * nprocs
+                 start(1) = block_start + stride * rank + 1;
+             else
+                 start(1) = start(1) + 1
+             endif
+          enddo
+
+          err = nf90mpi_wait_all(ncid, num_reqs, reqs, sts)
+          call check(err, 'In nf90mpi_wait_all: ')
+
+          ! check status of all requests
+          do i=1, num_reqs
+             if (sts(i) .NE. NF90_NOERR) then
+                 print*, "Error: nonblocking write fails on request", &
+                         i, ' ', nf90mpi_strerror(sts(i))
+             endif
+          enddo
+
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          ! check the read contents */
+          do j=1, NY
+             do i=1, NX
+                  if (buf(i,j) .NE. rank+10) then
+                      print*, 'Read contents mismatch at buf i=', i, &
+                              ' j=',j,' =', buf(i,j),' (should be ', &
+                              rank+10, ')\n'
+                  endif
+             enddo
+          enddo
+
+          deallocate(buf)
+          deallocate(reqs)
+          deallocate(sts)
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nf90mpi_inq_malloc_size(malloc_size)
+          if (err == NF90_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+
+      end program main
diff --git a/examples/F90/column_wise.f90 b/examples/F90/column_wise.f90
new file mode 100644
index 0000000..2ce5a13
--- /dev/null
+++ b/examples/F90/column_wise.f90
@@ -0,0 +1,186 @@
+!
+!  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: column_wise.f90 2245 2015-12-20 18:39:52Z wkliao $
+
+! This example makes a number of nonblocking API calls, each writes a single
+! row of a 2D integer array. Each process writes NY rows and any two
+! consecutive rows are of nprocs-row distance apart from each other.
+! In this case, the fileview of each process interleaves with all other processes.
+! If simply concatenating fileviews of all the nonblocking calls will result
+! in a fileview that violates the MPI-IO requirement on the fileview of which
+! flattened file offsets must be monotonically non-decreasing. PnetCDF handles
+! this case by breaking down each nonblocking call into a list of offset-length
+! pairs, merging the pairs across multiple nonblocking calls, and sorting
+! them into an increasing order. The sorted pairs are used to construct a
+! fileview that meets the monotonically non-decreasing offset requirement,
+! and thus the nonblocking requests can be serviced by a single MPI-IO call. 
+! 
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file. Note ncdump is in C order (row major).
+!
+!    % mpif90 -O2 -o column_wise column_wise.f90 -lpnetcdf
+!    % mpiexec -n 4 ./column_wise /pvfs2/wkliao/testfile.nc
+!
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!            Y = 10 ;
+!            X = 16 ;
+!    variables:
+!            int var(Y, X) ;
+!    data:
+!
+!     var =
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+!      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 ;
+!    }
+!
+
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          integer NY, NX
+          PARAMETER(NX=10, NY=4)
+
+          character(LEN=128) filename, cmd
+          integer i, rank, nprocs, err, num_reqs, ierr, get_args, dummy
+          integer ncid, cmode, varid, dimid(2)
+          integer buf(NX, NY)
+          integer reqs(NY), sts(NY)
+          integer(kind=MPI_OFFSET_KIND) G_NY, myOff, block_start, &
+                                        block_len, global_nx
+          integer(kind=MPI_OFFSET_KIND) start(2), count(2)
+          integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD, err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! the global array is NX * (NY * nprocs) */
+          G_NY  = NY * nprocs
+          myOff = NY * rank
+
+          ! define dimensions
+          global_nx = NX
+          err = nf90mpi_def_dim(ncid, 'Y', global_nx, dimid(2))
+          call check(err, 'In nf90mpi_def_dim Y')
+
+          err = nf90mpi_def_dim(ncid, 'X', G_NY, dimid(1))
+          call check(err, 'In nf90mpi_def_dim X')
+
+          err = nf90mpi_def_var(ncid, 'var', NF90_INT, dimid, varid)
+          call check(err, 'In nf90mpi_def_var var')
+
+          ! do not forget to exit define mode
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! First, fill the entire array with zeros, using a blocking I/O.
+          ! Every process writes a subarray of size NX * NY
+          buf = 0
+          start(1) = myOff+1
+          start(2) = 1
+          count(1) = NY
+          count(2) = NX
+          err = nf90mpi_put_var_all(ncid, varid, buf, start, count)
+          call check(err, 'In nf90mpi_put_var_all: ')
+
+          ! initialize the buffer with rank ID
+          buf = rank
+
+          ! each proc writes NY columns of the 2D array, block_len controls the
+          ! the number of contiguous columns at a time
+          block_start = 0
+          block_len   = 2  ! can be 1, 2, 3, ..., NY
+          if (block_len > NY) block_len = NY
+
+          start(1) = rank + 1
+          start(2) = 1
+          count(1) = 1
+          count(2) = NX
+          num_reqs = 0
+
+          do i=1, NY
+             num_reqs = num_reqs + 1
+             err = nf90mpi_iput_var(ncid, varid, buf(:,i), &
+                                     reqs(num_reqs), start, count)
+             call check(err, 'In nf90mpi_iput_var: ')
+
+             start(1) = start(1) + nprocs
+          enddo
+
+          err = nf90mpi_wait_all(ncid, num_reqs, reqs, sts)
+          call check(err, 'In nf90mpi_wait_all: ')
+
+          ! check status of all requests
+          do i=1, num_reqs
+             if (sts(i) .NE. NF90_NOERR) then
+                 print*, "Error: nonblocking write fails on request", &
+                         i, ' ', nf90mpi_strerror(sts(i))
+             endif
+          enddo
+
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nf90mpi_inq_malloc_size(malloc_size)
+          if (err == NF90_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+
+      end program main
diff --git a/examples/F90/depend b/examples/F90/depend
new file mode 100644
index 0000000..3954e90
--- /dev/null
+++ b/examples/F90/depend
@@ -0,0 +1,12 @@
+block_cyclic.o: block_cyclic.f90
+column_wise.o: column_wise.f90
+flexible_api.o: flexible_api.f90
+get_info.o: get_info.f90
+hints.o: hints.f90
+nonblocking_write.o: nonblocking_write.f90
+put_var.o: put_var.f90
+put_varn_real.o: put_varn_real.f90
+put_varn_int.o: put_varn_int.f90
+transpose.o: transpose.f90
+vard_int.o: vard_int.f90
+fill_mode.o: fill_mode.f90
diff --git a/examples/F90/fill_mode.f90 b/examples/F90/fill_mode.f90
new file mode 100644
index 0000000..f3e2a79
--- /dev/null
+++ b/examples/F90/fill_mode.f90
@@ -0,0 +1,218 @@
+!
+!   Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: fill_mode.f90 2245 2015-12-20 18:39:52Z wkliao $
+
+! This example shows how to use
+! 1. nf90mpi_set_fill() to enable fill mode
+! 2. nf90mpi_def_var_fill() to define the variable's fill value
+! 3. nf90mpi_inq_var_fill() to inquire the variable's fill mode
+! information
+! 4. nf90mpi_put_vara_int_all() to write two 2D 4-byte integer array in
+! parallel.
+! It first defines a netCDF record variable of size global_nx *
+! NFMPI_UNLIMITED
+! where
+!    global_nx == (nx * number of MPI processes) and
+! It then defines a netCDF variable of size global_nx * global_ny where
+!    global_nx == (nx * number of MPI processes) and
+!    global_ny == ny
+! The data partitioning pattern for both variables are a column-wise
+! partitioning across all processes. Each process writes a subarray of
+! size
+! nx * ny. Note the description above follows the Fortran array index
+! order.
+
+! Example commands for MPI run and outputs from running ncmpidump on the
+! NC file produced by this example program:
+!
+!    % mpif90 -O2 -o fill_mode fill_mode.f90 -lpnetcdf
+!    % mpiexec -n 4 ./fill_mode /pvfs2/wkliao/testfile.nc
+!
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!            REC_DIM = UNLIMITED ; // (2 currently)
+!            X = 20 ;
+!            Y = 3 ;
+!    variables:
+!            int rec_var(REC_DIM, X) ;
+!                    rec_var:_FillValue = -1 ;
+!            int fix_var(Y, X) ;
+!                    fix_var:_FillValue = -2147483647 ;
+!    data:
+!
+!     rec_var =
+!      0, 0, 0, 0, _, 1, 1, 1, 1, _, 2, 2, 2, 2, _, 3, 3, 3, 3, _,
+!      0, 0, 0, 0, _, 1, 1, 1, 1, _, 2, 2, 2, 2, _, 3, 3, 3, 3, _ ;
+!
+!     fix_var =
+!      0, 0, 0, 0, _, 1, 1, 1, 1, _, 2, 2, 2, 2, _, 3, 3, 3, 3, _,
+!      0, 0, 0, 0, _, 1, 1, 1, 1, _, 2, 2, 2, 2, _, 3, 3, 3, 3, _,
+!      0, 0, 0, 0, _, 1, 1, 1, 1, _, 2, 2, 2, 2, _, 3, 3, 3, 3, _ ;
+!    }
+!
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          character(LEN=128) filename, cmd
+          integer err, nprocs, rank, ierr, get_args, dummy
+          integer cmode, ncid, rec_varid, fix_varid, dimid(2)
+          integer no_fill, fill_value, old_mode
+          integer(kind=MPI_OFFSET_KIND) nx, ny, global_nx, global_ny
+          integer(kind=MPI_OFFSET_KIND) starts(2), counts(2)
+          integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+          PARAMETER(nx=5, ny=4)
+          integer buf(nx,ny)
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD, err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
+
+          ! set parameters
+          global_nx = nx * nprocs
+          global_ny = ny
+
+          buf = rank;
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! define dimensions x and y
+          err = nf90mpi_def_dim(ncid, "REC_DIM", NFMPI_UNLIMITED, dimid(2))
+          call check(err, 'In nf90mpi_def_dim REC_DIM: ')
+          err = nf90mpi_def_dim(ncid, "X", global_nx, dimid(1))
+          call check(err, 'In nf90mpi_def_dim X: ')
+
+          ! define a 2D variable of integer type
+          err = nf90mpi_def_var(ncid, "rec_var", NF90_INT, dimid, rec_varid)
+          call check(err, 'In nf90mpi_def_var rec_var: ')
+
+          err = nf90mpi_def_dim(ncid, "Y", global_ny, dimid(2))
+          call check(err, 'In nf90mpi_def_dim Y: ')
+
+          ! define a 2D variable of integer type
+          err = nf90mpi_def_var(ncid, "fix_var", NF90_INT, dimid, fix_varid)
+          call check(err, 'In nf90mpi_def_var fix_var: ')
+
+          ! set the fill mode to NF90_FILL for entire file
+          err = nf90mpi_set_fill(ncid, NF90_FILL, old_mode)
+          call check(err, 'In nf90mpi_set_fill: ')
+          if (verbose) then
+             if (old_mode .EQ. NF90_FILL) then
+                 print*,"The old fill mode is NF90_FILL"
+             else
+                 print*,"The old fill mode is NF90_NOFILL"
+             endif
+          endif
+
+          ! set the fill mode back to NF90_NOFILL for entire file
+          err = nf90mpi_set_fill(ncid, NF90_NOFILL, old_mode)
+          call check(err, 'In nf90mpi_set_fill: ')
+
+          ! set the variable's fill mode to NF90_FILL with default fill
+          ! value
+          err = nf90mpi_def_var_fill(ncid, fix_varid, 0, NF90_FILL_INT)
+          call check(err, 'In nf90mpi_def_var_fill: ')
+
+          ! set a customized fill value -1
+          fill_value = -1
+          err = nf90mpi_put_att(ncid, rec_varid, "_FillValue", fill_value)
+          call check(err, 'In nf90mpi_put_att: ')
+
+          ! do not forget to exit define mode
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! Note that in Fortran, array indices start with 1
+          starts(1) = nx * rank + 1
+          starts(2) = 1
+          counts(1) = nx
+          counts(2) = ny
+
+          ! do not write the variable in full
+          counts(1) = counts(1) - 1
+          err = nf90mpi_put_var_all(ncid, fix_varid, buf, starts, counts)
+          call check(err, 'In nf90mpi_put_var_all: ')
+
+          err = nf90mpi_inq_var_fill(ncid, fix_varid, no_fill, fill_value)
+          if (no_fill .NE. 0) &
+              print*,"Error: expecting no_fill to be 0"
+          if (fill_value .NE. NF90_FILL_INT) &
+              print*,"Error: expecting no_fill to be ",NF90_FILL_INT, &
+                     " but got ", fill_value
+
+          ! fill the 1st record of the record variable
+          starts(2) = 1
+          err = nf90mpi_fill_var_rec(ncid, rec_varid, starts(2))
+          call check(err, 'In nf90mpi_fill_var_rec: ')
+
+          ! write to the 1st record
+          counts(2) = 1;
+          err = nf90mpi_put_var_all(ncid, rec_varid, buf, starts, counts)
+          call check(err, 'In nf90mpi_put_var_all: ')
+
+          ! fill the 2nd record of the record variable
+          starts(2) = 2
+          err = nf90mpi_fill_var_rec(ncid, rec_varid, starts(2))
+          call check(err, 'In nf90mpi_fill_var_rec: ')
+
+          ! write to the 2nd record
+          err = nf90mpi_put_var_all(ncid, rec_varid, buf, starts, counts)
+          call check(err, 'In nf90mpi_put_var_all: ')
+
+          ! close the file
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nf90mpi_inq_malloc_size(malloc_size)
+          if (err == NF90_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end program main
+
diff --git a/examples/F90/flexible_api.f90 b/examples/F90/flexible_api.f90
new file mode 100644
index 0000000..aa779c3
--- /dev/null
+++ b/examples/F90/flexible_api.f90
@@ -0,0 +1,182 @@
+!
+!   Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: flexible_api.f90 2245 2015-12-20 18:39:52Z wkliao $
+
+!
+! This example shows how to use PnetCDF flexible API, nf90mpi_put_var_all()
+! to write a 2D 4-byte integer array in parallel. It first defines a netCDF
+! variable of size global_nx * global_ny where
+!    global_nx == 5 and
+!    global_ny == (4 * number of MPI processes).
+! The data partitioning pattern is a column-wise partitioning across all
+! processes. Each process writes a subarray of size nx * ny.
+! The local buffer has a ghost cell of length 3 surrounding the 2D array
+!    integer buf(nx+2*ghost_len, ny+2*ghost_len)
+! Note the description above follows the Fortran array index order.
+!
+! Example commands for MPI run and outputs from running ncmpidump on the
+! NC file produced by this example program:
+!
+!    % mpif90 -O2 -o flexible_api flexible_api.f90 -lpnetcdf
+!    % mpiexec -n 4 ./flexible_api /pvfs2/wkliao/testfile.nc
+!
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!            x = 5 ;
+!            y = 16 ;
+!    variables:
+!            int var(y, x) ;
+!    data:
+!
+!     var =
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0,
+!      1, 1, 1, 1, 1,
+!      1, 1, 1, 1, 1,
+!      1, 1, 1, 1, 1,
+!      1, 1, 1, 1, 1,
+!      2, 2, 2, 2, 2,
+!      2, 2, 2, 2, 2,
+!      2, 2, 2, 2, 2,
+!      2, 2, 2, 2, 2,
+!      3, 3, 3, 3, 3,
+!      3, 3, 3, 3, 3,
+!      3, 3, 3, 3, 3,
+!      3, 3, 3, 3, 3 ;
+!    }
+!
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          character(LEN=128) filename, cmd
+          integer err, nprocs, rank, i, j, ghost_len, ierr, get_args, dummy
+          integer cmode, ncid, varid, dimid(2)
+          integer(kind=MPI_OFFSET_KIND) nx, ny, global_nx, global_ny
+          integer(kind=MPI_OFFSET_KIND) starts(2), counts(2), nTypes
+          PARAMETER(nx=5, ny=4, ghost_len=3)
+          integer buf(nx+2*ghost_len, ny+2*ghost_len)
+          integer subarray
+          integer array_of_sizes(2), array_of_subsizes(2)
+          integer array_of_starts(2)
+          integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD, err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
+
+          ! set parameters
+          global_nx = nx
+          global_ny = ny * nprocs
+
+          ! first initialize the entire buffer to -1
+          buf = -1;
+          ! assign values for non-ghost cells
+          do j=ghost_len+1, ny+ghost_len
+             do i=ghost_len+1, nx+ghost_len
+                 buf(i, j) = rank
+             enddo
+          enddo
+
+          ! define an MPI datatype using MPI_Type_create_subarray()
+          array_of_sizes(1)    = nx + 2*ghost_len
+          array_of_sizes(2)    = ny + 2*ghost_len
+          array_of_subsizes(1) = nx
+          array_of_subsizes(2) = ny
+          array_of_starts(1)   = ghost_len  ! MPI start index starts with 0
+          array_of_starts(2)   = ghost_len
+          call MPI_Type_create_subarray(2, array_of_sizes, &
+               array_of_subsizes, array_of_starts, MPI_ORDER_FORTRAN, &
+               MPI_INTEGER, subarray, err)
+          call MPI_Type_commit(subarray, err)
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! define dimensions x and y
+          err = nf90mpi_def_dim(ncid, "y", global_ny, dimid(2))
+          call check(err, 'In nf90mpi_def_dim y: ')
+          err = nf90mpi_def_dim(ncid, "x", global_nx, dimid(1))
+          call check(err, 'In nf90mpi_def_dim x: ')
+
+          ! define a 2D variable of integer type
+          err = nf90mpi_def_var(ncid, "var", NF90_INT, dimid, varid)
+          call check(err, 'In nf90mpi_def_var: ')
+
+          ! do not forget to exit define mode
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! Note that in Fortran, array indices start with 1
+          starts(1) = 1
+          starts(2) = ny * rank + 1
+          counts(1) = nx
+          counts(2) = ny
+          nTypes    = 1
+
+          ! must explicitly use the argument keywords for the buffer type and
+          ! number of buffer types, if any previous argument is skipped
+          err = nf90mpi_put_var_all(ncid, varid, buf, starts, counts, &
+                                    BUFCOUNT=nTypes, BUFTYPE=subarray)
+          call check(err, 'In nf90mpi_put_var_all: ')
+
+          call MPI_Type_free(subarray, err)
+
+          ! close the file
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nf90mpi_inq_malloc_size(malloc_size)
+          if (err == NF90_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end program main
+
diff --git a/examples/F90/get_info.f90 b/examples/F90/get_info.f90
new file mode 100644
index 0000000..86c8e9c
--- /dev/null
+++ b/examples/F90/get_info.f90
@@ -0,0 +1,139 @@
+!*********************************************************************
+!*
+!*  Copyright (C) 2012, Northwestern University and Argonne National
+!*  Laboratory
+!*  See COPYRIGHT notice in top-level directory.
+!*
+!*********************************************************************/
+! $Id: get_info.f90 2139 2015-10-08 01:59:10Z wkliao $
+
+!    To compile:
+!        mpif90 -O2 get_info.f90 -o get_info -lpnetcdf
+!    To run:
+!        mpiexec -n 4 ./get_info /pvfs2/wkliao/filename
+!
+!    prints all MPI-IO hints used
+!
+!    Example standard output:
+!
+!   MPI File Info: nkeys =          18
+!   MPI File Info: [ 0] key =            cb_buffer_size, value =16777216
+!   MPI File Info: [ 1] key =             romio_cb_read, value =automatic
+!   MPI File Info: [ 2] key =            romio_cb_write, value =automatic
+!   MPI File Info: [ 3] key =                  cb_nodes, value =1
+!   MPI File Info: [ 4] key =         romio_no_indep_rw, value =false
+!   MPI File Info: [ 5] key =              romio_cb_pfr, value =disable
+!   MPI File Info: [ 6] key =         romio_cb_fr_types, value =aar
+!   MPI File Info: [ 7] key =     romio_cb_fr_alignment, value =1
+!   MPI File Info: [ 8] key =     romio_cb_ds_threshold, value =0
+!   MPI File Info: [ 9] key =         romio_cb_alltoall, value =automatic
+!   MPI File Info: [10] key =        ind_rd_buffer_size, value =4194304
+!   MPI File Info: [11] key =        ind_wr_buffer_size, value =524288
+!   MPI File Info: [12] key =             romio_ds_read, value =automatic
+!   MPI File Info: [13] key =            romio_ds_write, value =automatic
+!   MPI File Info: [14] key =            cb_config_list, value =*:1
+!   MPI File Info: [15] key =      nc_header_align_size, value =0
+!   MPI File Info: [16] key =         nc_var_align_size, value =0
+!   MPI File Info: [17] key = nc_header_read_chunk_size, value =0
+
+
+        program main
+        use mpi
+        use pnetcdf
+        implicit none
+
+        character(len = 256) :: filename, cmd
+        integer ncid, rank, info, omode, err, ierr, get_args, dummy
+        integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+        logical verbose
+
+        call MPI_Init(err)
+        call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+
+        if (rank .EQ. 0) then
+            verbose = .TRUE.
+            filename = "testfile.nc"
+            ierr = get_args(2, cmd, filename, verbose, dummy)
+        endif
+        call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+        if (ierr .EQ. 0) goto 999
+
+        call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD, err)
+        call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
+
+        omode = NF90_NOWRITE + NF90_64BIT_OFFSET
+        err = nf90mpi_open(MPI_COMM_WORLD, trim(filename), omode, &
+                            MPI_INFO_NULL, ncid)
+        if (err .ne. NF90_NOERR) call handle_err('nf90mpi_open',err)
+
+
+        err = nf90mpi_inq_file_info(ncid, info)
+        if (err .ne. NF90_NOERR) then
+            call handle_err('nf90mpi_inq_file_info', err)
+        endif
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) call handle_err('nf90mpi_close',err)
+
+        if (rank .EQ. 0 .AND. verbose) call print_info(info)
+        call MPI_Info_free(info, err)
+
+        ! check if there is any PnetCDF internal malloc residue
+ 998    format(A,I13,A)
+        err = nf90mpi_inq_malloc_size(malloc_size)
+        if (err == NF90_NOERR) then
+            call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                            MPI_SUM, 0, MPI_COMM_WORLD, err)
+            if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                'heap memory allocated by PnetCDF internally has ',  &
+                sum_size/1048576, ' MiB yet to be freed'
+        endif
+
+ 999    call MPI_Finalize(err)
+        ! call EXIT(0) ! EXIT() is a GNU extension
+
+        end program main
+
+        subroutine print_info(info_used)
+            use mpi
+            use pnetcdf
+            implicit none
+
+            integer, intent(in) :: info_used
+
+            ! local variables
+            character*(MPI_MAX_INFO_VAL) key, value
+            integer nkeys, i, err
+            logical flag
+
+            call MPI_Info_get_nkeys(info_used, nkeys, err)
+            print *, 'MPI File Info: nkeys =', nkeys
+            do i=0, nkeys-1
+                call MPI_Info_get_nthkey(info_used, i, key, err)
+                call MPI_Info_get(info_used, key, MPI_MAX_INFO_VAL, &
+                                  value, flag, err)
+ 123            format('MPI File Info: [',I2,'] key = ',A25, &
+                       ', value =',A)
+                print 123, i, trim(key), trim(value)
+            enddo
+            print *, ''
+
+            return
+        end subroutine print_info
+
+        subroutine handle_err(err_msg, errcode)
+            use mpi
+            use pnetcdf
+            implicit none
+
+            character*(*), intent(in) :: err_msg
+            integer,       intent(in) :: errcode
+
+            ! local variables
+            integer err 
+
+            print *, 'Error: ',trim(err_msg),' ',nf90mpi_strerror(errcode)
+            call MPI_Abort(MPI_COMM_WORLD, -1, err)
+            return
+        end subroutine handle_err
+
diff --git a/examples/F90/hints.f90 b/examples/F90/hints.f90
new file mode 100644
index 0000000..05198f4
--- /dev/null
+++ b/examples/F90/hints.f90
@@ -0,0 +1,248 @@
+!
+!
+!  Copyright (C) 2012, Northwestern University and Argonne National
+!  Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: hints.f90 2139 2015-10-08 01:59:10Z wkliao $
+
+!
+! This example sets two PnetCDF hints:
+!    nc_header_align_size and nc_var_align_size
+! and prints the hint values as well as the header size, header extent, and
+! two variables' starting file offsets.
+!
+! The compile and run commands are given below.
+!
+!    % mpif90 -O2 -o hints hints.f90 -lpnetcdf
+!
+!    % mpiexec -n 4 ./hints /pvfs2/wkliao/testfile.nc
+!
+!    nc_header_align_size      set to = 1024
+!    nc_var_align_size         set to = 512
+!    nc_header_read_chunk_size set to = 256
+!    header size                      = 252
+!    header extent                    = 1024
+!    var_zy start file offset         = 1024
+!    var_yx start file offset         = 3072
+!
+
+
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      subroutine print_hints(ncid, varid0, varid1)
+          use mpi
+          use pnetcdf
+          implicit none
+
+          integer ncid, varid0, varid1
+
+          ! local variables
+          character*(MPI_MAX_INFO_VAL) value
+          integer err, len, info_used
+          logical flag
+          integer(kind=MPI_OFFSET_KIND) header_size, header_extent
+          integer(kind=MPI_OFFSET_KIND) var_zy_start, var_yx_start
+          integer(kind=MPI_OFFSET_KIND) h_align, v_align, h_chunk
+
+          h_align=-1
+          v_align=-1
+          h_chunk=-1
+
+          err = nf90mpi_inq_header_size  (ncid, header_size)
+          call check(err, 'In nf90mpi_inq_header_size: ')
+          err = nf90mpi_inq_header_extent(ncid, header_extent)
+          call check(err, 'In nf90mpi_inq_header_extent: ')
+          err = nf90mpi_inq_varoffset(ncid, varid0, var_zy_start)
+          call check(err, 'In nf90mpi_inq_varoffset varid0: ')
+          err = nf90mpi_inq_varoffset(ncid, varid1, var_yx_start)
+          call check(err, 'In nf90mpi_inq_varoffset varid1: ')
+
+          err = nf90mpi_inq_file_info(ncid, info_used)
+          call check(err, 'In nf90mpi_inq_file_info : ')
+
+          call MPI_Info_get_valuelen(info_used, "nc_header_align_size", &
+                                     len, flag, err)
+          if (flag) then
+              call MPI_Info_get(info_used, "nc_header_align_size", &
+                                len+1, value, flag, err)
+              read(value, '(i16)') h_align
+          endif
+          call MPI_Info_get_valuelen(info_used, "nc_var_align_size", &
+                                     len, flag, err)
+          if (flag) then
+              call MPI_Info_get(info_used, "nc_var_align_size", len+1, &
+                                value, flag, err)
+              read(value, '(i16)') v_align
+          endif
+          call MPI_Info_get_valuelen(info_used, &
+                                     "nc_header_read_chunk_size", &
+                                     len, flag, err)
+          if (flag) then
+              call MPI_Info_get(info_used, "nc_header_read_chunk_size", &
+                                len+1, value, flag, err)
+              read(value, '(i16)') h_chunk
+          endif
+          call MPI_Info_free(info_used, err)
+
+          if (h_align .EQ. -1) then
+              print*,"nc_header_align_size      is NOT set"
+          else
+              print*,"nc_header_align_size      set to = ", h_align
+          endif
+          if (v_align .EQ. -1) then
+              print*,"nc_var_align_size         is NOT set"
+          else
+              print*,"nc_var_align_size         set to = ", v_align
+          endif
+          if (h_chunk .EQ. -1) then
+              print*,"nc_header_read_chunk_size is NOT set"
+          else
+              print*,"nc_header_read_chunk_size set to = ", h_chunk
+          endif
+
+          print*,"header size                      = ", header_size
+          print*,"header extent                    = ", header_extent
+          print*,"var_zy start file offset         = ", var_zy_start
+          print*,"var_yx start file offset         = ", var_yx_start
+      end subroutine print_hints
+
+      subroutine put_vara(ncid, varid, ny, nx, start, count)
+          use mpi
+          use pnetcdf
+          implicit none
+
+          integer ncid, varid, ny, nx
+          integer(KIND=MPI_OFFSET_KIND) start(2), count(2)
+
+          integer i, j, rank, err
+          integer buf(nx, ny)
+
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+
+          do j=1, ny
+             do i=1, nx
+                buf(i,j) = rank ! j*nx + i
+             enddo
+          enddo
+
+          err = nf90mpi_put_var_all(ncid, varid, buf, start, count)
+          call check(err, 'In nf90mpi_put_var_all : ')
+
+      end subroutine put_vara
+
+      program main
+      use mpi
+      use pnetcdf
+      implicit none
+
+      character(len = 256) :: filename, cmd
+      integer NZ, NY, NX
+      integer ncid, rank, nprocs, info, cmode, err, ierr, get_args, dummy
+      integer varid0, varid1, dimid(3), dimid2(2)
+      integer(KIND=MPI_OFFSET_KIND) start(2), count(2), llen
+      integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+      logical verbose
+
+      call MPI_Init(err)
+      call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+      call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+      NZ = 5
+      NY = 5
+      NX = 5
+
+      if (rank .EQ. 0) then
+          verbose = .TRUE.
+          filename = "testfile.nc"
+          ierr = get_args(2, cmd, filename, verbose, dummy)
+      endif
+      call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+      if (ierr .EQ. 0) goto 999
+
+      call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD, err)
+      call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
+
+      call MPI_Info_create(info, err)
+      call MPI_Info_set(info, "nc_header_align_size",      "1024", err)
+      call MPI_Info_set(info, "nc_var_align_size",         "512",  err)
+      call MPI_Info_set(info, "nc_header_read_chunk_size", "256",  err)
+      ! note that set the above values to 1 to disable the alignment
+
+      ! create a new file for writing
+      cmode = NF90_CLOBBER + NF90_64BIT_DATA
+      err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, info, ncid)
+      call check(err, 'In nf90mpi_create : ')
+      call MPI_Info_free(info, err)
+
+      ! define 3 dimensions
+      llen = NZ*nprocs
+      err = nf90mpi_def_dim(ncid, "Z", llen, dimid(1))
+      call check(err, 'In nf90mpi_def_dim Z : ')
+      llen = NY*nprocs
+      err = nf90mpi_def_dim(ncid, "Y", llen, dimid(2))
+      call check(err, 'In nf90mpi_def_dim Y : ')
+      llen = NX*nprocs
+      err = nf90mpi_def_dim(ncid, "X", llen, dimid(3))
+      call check(err, 'In nf90mpi_def_dim X : ')
+
+      ! define a variable of size (NZ * nprocs) * (NY * nprocs)
+      dimid2(1) = dimid(1)
+      dimid2(2) = dimid(2)
+      err = nf90mpi_def_var(ncid, "var_zy", NF90_INT,   dimid2, varid0)
+      call check(err, 'In nf90mpi_def_var var_zy : ')
+      ! define a variable of size (NY * nprocs) * (NX * nprocs)
+      dimid2(1) = dimid(2)
+      dimid2(2) = dimid(3)
+      err = nf90mpi_def_var(ncid, "var_yx", NF90_FLOAT, dimid2, varid1)
+      call check(err, 'In nf90mpi_def_var var_yx : ')
+
+      err = nf90mpi_enddef(ncid)
+      call check(err, 'In nf90mpi_enddef : ')
+
+      ! var_zy is partitioned along Z dimension
+      start(1) = NZ * rank + 1
+      start(2) = 1
+      count(1) = NZ
+      count(2) = NY * nprocs
+      call put_vara(ncid, varid0, NZ, NY * nprocs, start, count)
+
+      ! var_yx is partitioned along X dimension
+      start(1) = 1
+      start(2) = NX * rank + 1
+      count(1) = NY * nprocs
+      count(2) = NX
+      call put_vara(ncid, varid1, NY * nprocs, NX, start, count)
+
+      if (rank .EQ. 0 .AND. verbose) call print_hints(ncid, varid0, varid1)
+
+      err = nf90mpi_close(ncid)
+
+      ! check if there is any PnetCDF internal malloc residue
+ 998  format(A,I13,A)
+      err = nf90mpi_inq_malloc_size(malloc_size)
+      if (err == NF90_NOERR) then
+          call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                          MPI_SUM, 0, MPI_COMM_WORLD, err)
+          if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+              'heap memory allocated by PnetCDF internally has ',  &
+              sum_size/1048576, ' MiB yet to be freed'
+      endif
+
+ 999  call MPI_Finalize(err)
+      ! call EXIT(0) ! EXIT() is a GNU extension
+
+      end program
+
diff --git a/examples/F90/nonblocking_write.f90 b/examples/F90/nonblocking_write.f90
new file mode 100644
index 0000000..bd28db3
--- /dev/null
+++ b/examples/F90/nonblocking_write.f90
@@ -0,0 +1,197 @@
+!
+!  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: nonblocking_write.f90 2245 2015-12-20 18:39:52Z wkliao $
+
+!    This example is the Fortran 90 version of nonblocking_write.c
+!    It creates a netcdf file in CD-5 format and writes a number of
+!    3D integer non-record variables.
+!    Usage: (for example)
+!    To compile:
+!        mpif90 -O2 nonblocking_write.f90 -o nonblocking_write -lpnetcdf
+!    To run:
+!        mpiexec -n num_processes ./nonblocking_write [filename] [len]
+!    where len decides the size of each local array, which is
+!    len x len x len. Each non-record variable is of size
+!          len*len*len * nprocs * sizeof(int)
+!    All variables are partitioned among all processes in a 3D
+!    block-block-block fashion.
+!
+
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          integer NDIMS, NUM_VARS
+          PARAMETER(NDIMS=3, NUM_VARS=10)
+
+          character(LEN=256) filename, cmd, str
+          integer i, cmode, err, ierr, get_args
+          integer rank, nprocs, len, bufsize, ncid
+          integer psizes(NDIMS), dimids(NDIMS), varids(NUM_VARS)
+          integer req(NUM_VARS), st(NUM_VARS)
+          integer(kind=MPI_OFFSET_KIND) gsizes(NDIMS)
+          integer(kind=MPI_OFFSET_KIND) starts(NDIMS), counts(NDIMS)
+          integer(kind=MPI_OFFSET_KIND) bbufsize
+          integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+          logical verbose
+
+          ! define an array of pointers
+          type intp
+              integer, dimension(:), pointer :: p
+          end type intp
+          type(intp) buf(NUM_VARS)
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              len = 10
+              ierr = get_args(3, cmd, filename, verbose, len)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD, err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
+          call MPI_Bcast(len, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+
+          do i=1,NDIMS
+             psizes(i) = 0
+          enddo
+
+          ! create a block-block-block data partitioning
+          call MPI_Dims_create(nprocs, NDIMS, psizes, err);
+          starts(1) = mod(rank, psizes(1))
+          starts(2) = mod((rank / psizes(2)), psizes(2))
+          starts(3) = mod((rank / (psizes(1) * psizes(2))), psizes(3))
+
+          bufsize = 1
+          do i=1,NDIMS
+              gsizes(i) = len * psizes(i)
+              starts(i) = starts(i) * len + 1;
+              counts(i) = len;
+              bufsize   = bufsize * len;
+          enddo
+
+          ! allocate buffer and initialize with rank IDs
+          do i=1, NUM_VARS
+             allocate(buf(i)%p(bufsize))
+             buf(i)%p(:) = rank
+          enddo
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! define dimensions
+          do i=1, NDIMS
+             write(str,'(I2)') i
+             err = nf90mpi_def_dim(ncid, "x"//trim(ADJUSTL(str)), &
+                                   gsizes(i), dimids(i))
+             call check(err, 'In nf90mpi_def_dim x'//trim(str))
+          enddo
+
+          !define variables
+          do i=1, NUM_VARS
+             write(str,'(I2)') i
+             err = nf90mpi_def_var(ncid, "var"//trim(ADJUSTL(str)), &
+                                   NF90_INT, dimids, varids(i))
+             call check(err, 'In nf90mpi_def_var var'//trim(str))
+          enddo
+
+          ! do not forget to exit define mode
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! write one variable at a time using iput
+          do i=1, NUM_VARS
+             write(str,'(I2)') i
+             err = nf90mpi_iput_var(ncid, varids(i), buf(i)%p, req(i), &
+                                    starts, counts)
+             call check(err, 'In nf90mpi_iput_var '//trim(str))
+          enddo
+
+          ! wait for the nonblocking I/O to complete
+          err = nf90mpi_wait_all(ncid, NUM_VARS, req, st)
+          call check(err, 'In nf90mpi_wait_all')
+
+          ! check the status of each nonblocking request
+          do i=1, NUM_VARS
+             write(str,'(I2)') i
+             call check(st(i), 'In nf90mpi_wait_all req '//trim(str))
+          enddo
+
+          ! write one variable at a time using bput
+
+          ! bbufsize must be max of data type converted before and after
+          bbufsize = bufsize * NUM_VARS * 4  ! 4 is size of integer
+          err = nf90mpi_buffer_attach(ncid, bbufsize)
+          call check(err, 'In nf90mpi_buffer_attach')
+
+          do i=1, NUM_VARS
+             write(str,'(I2)') i
+             err = nf90mpi_bput_var(ncid, varids(i), buf(i)%p, req(i), &
+                                    starts, counts)
+             call check(err, 'In nf90mpi_bput_var '//trim(str))
+
+             ! can safely free up the buffer here
+             deallocate(buf(i)%p)
+          enddo
+
+          ! wait for the nonblocking I/O to complete
+          err = nf90mpi_wait_all(ncid, NUM_VARS, req, st)
+          call check(err, 'In nf90mpi_wait_all')
+
+          ! check the status of each nonblocking request
+          do i=1, NUM_VARS
+             write(str,'(I2)') i
+             call check(st(i), 'In nf90mpi_wait_all req '//trim(str))
+          enddo
+
+          ! detach the temporary buffer
+          err = nf90mpi_buffer_detach(ncid)
+          call check(err, 'In nf90mpi_buffer_detach')
+
+          ! close the file
+          err = nf90mpi_close(ncid);
+          call check(err, 'In nf90mpi_close')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nf90mpi_inq_malloc_size(malloc_size)
+          if (err == NF90_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+
+      end program main
+
diff --git a/examples/F90/put_var.f90 b/examples/F90/put_var.f90
new file mode 100644
index 0000000..957cbd9
--- /dev/null
+++ b/examples/F90/put_var.f90
@@ -0,0 +1,152 @@
+!
+!   Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: put_var.f90 2245 2015-12-20 18:39:52Z wkliao $
+
+!
+! This example shows how to use nf90mpi_put_var_all() to write a 2D
+! 4-byte integer array in parallel. It first defines a netCDF variable of
+! size global_nx * global_ny where
+!    global_nx == 5 and
+!    global_ny == (4 * number of MPI processes).
+! The data partitioning pattern is a column-wise partitioning across all
+! processes. Each process writes a subarray of size nx * ny.
+! Note the description above follows the Fortran array index order.
+!
+! Example commands for MPI run and outputs from running ncmpidump on the
+! NC file produced by this example program:
+!
+!    % mpif90 -O2 -o put_var put_var.f90 -lpnetcdf
+!    % mpiexec -n 4 ./put_var /pvfs2/wkliao/testfile.nc
+!
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!            x = 5 ;
+!            y = 16 ;
+!    variables:
+!            int var(y, x) ;
+!    data:
+!
+!     var =
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0,
+!      1, 1, 1, 1, 1,
+!      1, 1, 1, 1, 1,
+!      1, 1, 1, 1, 1,
+!      1, 1, 1, 1, 1,
+!      2, 2, 2, 2, 2,
+!      2, 2, 2, 2, 2,
+!      2, 2, 2, 2, 2,
+!      2, 2, 2, 2, 2,
+!      3, 3, 3, 3, 3,
+!      3, 3, 3, 3, 3,
+!      3, 3, 3, 3, 3,
+!      3, 3, 3, 3, 3 ;
+!    }
+!
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          character(LEN=128) filename, cmd
+          integer err, nprocs, rank, ierr, get_args, dummy
+          integer cmode, ncid, varid, dimid(2)
+          integer(kind=MPI_OFFSET_KIND) nx, ny, global_nx, global_ny
+          integer(kind=MPI_OFFSET_KIND) starts(2), counts(2)
+          integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+          PARAMETER(nx=5, ny=4)
+          integer buf(nx,ny)
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD, err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
+
+          ! set parameters
+          global_nx = nx
+          global_ny = ny * nprocs
+
+          buf = rank;
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! define dimensions x and y
+          err = nf90mpi_def_dim(ncid, "x", global_nx, dimid(1))
+          call check(err, 'In nf90mpi_def_dim x: ')
+          err = nf90mpi_def_dim(ncid, "y", global_ny, dimid(2))
+          call check(err, 'In nf90mpi_def_dim y: ')
+
+          ! define a 2D variable of integer type
+          err = nf90mpi_def_var(ncid, "var", NF90_INT, dimid, varid)
+          call check(err, 'In nf90mpi_def_var: ')
+
+          ! do not forget to exit define mode
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! Note that in Fortran, array indices start with 1
+          starts(1) = 1
+          starts(2) = ny * rank + 1
+          counts(1) = nx
+          counts(2) = ny
+
+          err = nf90mpi_put_var_all(ncid, varid, buf, starts, counts)
+          call check(err, 'In nf90mpi_put_var_all: ')
+
+          ! close the file
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nf90mpi_inq_malloc_size(malloc_size)
+          if (err == NF90_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end program main
+
diff --git a/examples/F90/put_varn_int.f90 b/examples/F90/put_varn_int.f90
new file mode 100644
index 0000000..0c15021
--- /dev/null
+++ b/examples/F90/put_varn_int.f90
@@ -0,0 +1,259 @@
+!
+!   Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: put_varn_int.f90 2139 2015-10-08 01:59:10Z wkliao $
+
+! This example shows how to use a single call of nf90mpi_put_varn_all() to
+! write a sequence of requests with arbitrary array indices and lengths.
+! Using nf90mpi_put_varn_all() can achieve the same effect of HDF5 writing
+! a sequence of selected file locations through the following 2 APIs.
+!
+!   H5Sselect_elements(fid, H5S_SELECT_SET, NUMP, (const hssize_t **)coord);
+!   H5Dwrite(dataset, H5T_NATIVE_INT, mid, fid, H5P_DEFAULT, val); 
+!
+! Note that in nf90mpi_put_varn_all(), users can write more than one element
+! starting at each selected location.
+!
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file.
+!
+!    % mpif90 -O2 -o put_varn_int put_varn_int.f90 -lpnetcdf
+!    % mpiexec -n 4 ./put_varn_int /pvfs2/wkliao/testfile.nc
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!             X = 4 ;
+!             Y = 10 ;
+!    variables:
+!             int var(Y, X) ;
+!    data:
+!
+!     var =
+!      2, 2, 1, 1,
+!      2, 2, 0, 0,
+!      1, 1, 0, 0,
+!      1, 1, 3, 3,
+!      3, 3, 2, 2,
+!      0, 0, 1, 1,
+!      0, 0, 1, 1,
+!      2, 2, 0, 0,
+!      3, 3, 3, 3,
+!      3, 3, 3, 3 ;
+!    }
+!
+!    Note the above dump is in C order
+!
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          integer NDIMS
+          integer(kind=MPI_OFFSET_KIND) NX, NY
+          PARAMETER(NDIMS=2, NX=4, NY=10)
+
+          character(LEN=128) filename, cmd
+          integer i, j, err, nprocs, rank, ierr, get_args, dummy
+          integer cmode, ncid, varid, dimid(NDIMS), num_reqs
+
+          integer(kind=MPI_OFFSET_KIND) w_len, w_req_len
+          integer(kind=MPI_OFFSET_KIND), allocatable :: starts(:,:)
+          integer(kind=MPI_OFFSET_KIND), allocatable :: counts(:,:)
+          integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+          integer, allocatable :: buffer(:)
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD, err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
+
+          if (nprocs .NE. 4 .AND. rank .EQ. 0 .AND. verbose) &
+              print*,'Warning: ',trim(cmd),' is intended to run on ', &
+                     '4 processes'
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! define dimensions x and y
+          err = nf90mpi_def_dim(ncid, "X", NX, dimid(1))
+          call check(err, 'In nf90mpi_def_dim X: ')
+          err = nf90mpi_def_dim(ncid, "Y", NY, dimid(2))
+          call check(err, 'In nf90mpi_def_dim Y: ')
+
+          ! define a 2D variable of integer type
+          err = nf90mpi_def_var(ncid, "var", NF90_INT, dimid, varid)
+          call check(err, 'In nf90mpi_def_var: ')
+
+          ! do not forget to exit define mode
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! pick arbitrary numbers of requests for 4 processes
+          num_reqs = 0
+          if (rank .EQ. 0) then
+              num_reqs = 3
+          elseif (rank .EQ. 1) then
+              num_reqs = 3
+          elseif (rank .EQ. 2) then
+              num_reqs = 3
+          elseif (rank .EQ. 3) then
+              num_reqs = 3
+          endif
+
+          ! Note that in Fortran, array indices start with 1
+          ALLOCATE(starts(NDIMS, num_reqs))
+          ALLOCATE(counts(NDIMS, num_reqs))
+
+          ! assign arbitrary starts and counts
+          if (rank .EQ. 0) then
+              ! rank 0 is writing the followings: ("-" means skip)
+              !        -  -  -  -  -  0  0  -  -  - 
+              !        -  -  -  -  -  0  0  -  -  - 
+              !        -  0  0  -  -  -  -  0  -  - 
+              !        -  0  0  -  -  -  -  0  -  - 
+              ! Note this is in Fortran order
+              starts(1, 1) = 1
+              starts(2, 1) = 6
+              counts(1, 1) = 2
+              counts(2, 1) = 2
+              starts(1, 2) = 3
+              starts(2, 2) = 2
+              counts(1, 2) = 2
+              counts(2, 2) = 2
+              starts(1, 3) = 3
+              starts(2, 3) = 8
+              counts(1, 3) = 2
+              counts(2, 3) = 1
+          elseif (rank .EQ. 1) then
+              ! rank 1 is writing the followings: ("-" means skip)
+              !        -  -  1  1  -  -  -  -  -  - 
+              !        -  -  1  1  -  -  -  -  -  - 
+              !        1  -  -  -  -  1  1  -  -  - 
+              !        1  -  -  -  -  1  1  -  -  - 
+              ! Note this is in Fortran order
+              starts(1, 1) = 1
+              starts(2, 1) = 3
+              counts(1, 1) = 2
+              counts(2, 1) = 2
+              starts(1, 2) = 3
+              starts(2, 2) = 1
+              counts(1, 2) = 2
+              counts(2, 2) = 1
+              starts(1, 3) = 3
+              starts(2, 3) = 6
+              counts(1, 3) = 2
+              counts(2, 3) = 2
+          elseif (rank .EQ. 2) then
+              ! rank 2 is writing the followings: ("-" means skip)
+              !        2  2  -  -  -  -  -  2  -  - 
+              !        2  2  -  -  -  -  -  2  -  - 
+              !        -  -  -  -  2  -  -  -  -  - 
+              !        -  -  -  -  2  -  -  -  -  - 
+              ! Note this is in Fortran order
+              starts(1, 1) = 1
+              starts(2, 1) = 1
+              counts(1, 1) = 2
+              counts(2, 1) = 2
+              starts(1, 2) = 1
+              starts(2, 2) = 8
+              counts(1, 2) = 2
+              counts(2, 2) = 1
+              starts(1, 3) = 3
+              starts(2, 3) = 5
+              counts(1, 3) = 2
+              counts(2, 3) = 1
+          elseif (rank .EQ. 3) then
+              ! rank 3 is writing the followings: ("-" means skip)
+              !        -  -  -  -  3  -  -  -  3  3 
+              !        -  -  -  -  3  -  -  -  3  3 
+              !        -  -  -  3  -  -  -  -  3  3 
+              !        -  -  -  3  -  -  -  -  3  3 
+              ! Note this is in Fortran order
+              starts(1, 1) = 1
+              starts(2, 1) = 5
+              counts(1, 1) = 2
+              counts(2, 1) = 1
+              starts(1, 2) = 1
+              starts(2, 2) = 9
+              counts(1, 2) = 4
+              counts(2, 2) = 2
+              starts(1, 3) = 3
+              starts(2, 3) = 4
+              counts(1, 3) = 2
+              counts(2, 3) = 1
+          endif
+ 
+          ! w_len is total write length for this process
+          w_len = 0
+          do i=1, num_reqs
+             w_req_len = 1
+             do j=1, NDIMS
+                w_req_len = w_req_len * counts(j, i)
+             enddo
+             w_len = w_len + w_req_len;
+          enddo
+          ALLOCATE(buffer(w_len))
+
+          ! initialize buffer contents
+          buffer = rank;
+
+          err = nf90mpi_put_varn_all(ncid, varid, buffer, num_reqs, &
+                                     starts, counts)
+          call check(err, 'In nf90mpi_put_varn_int_all: ')
+
+          ! close the file
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          DEALLOCATE(buffer);
+          DEALLOCATE(starts);
+          DEALLOCATE(counts);
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nf90mpi_inq_malloc_size(malloc_size)
+          if (err == NF90_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end program main
+
diff --git a/examples/F90/put_varn_real.f90 b/examples/F90/put_varn_real.f90
new file mode 100644
index 0000000..8f0c293
--- /dev/null
+++ b/examples/F90/put_varn_real.f90
@@ -0,0 +1,253 @@
+!
+!  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: put_varn_real.f90 2139 2015-10-08 01:59:10Z wkliao $
+
+!
+! This example shows how to use a single call of nf90mpi_put_varn_all()
+! to write a sequence of one-element requests with arbitrary array indices.
+!
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file.
+!
+!    % mpif90 -O2 -o put_varn_real put_varn_real.f90 -lpnetcdf
+!    % mpiexec -n 4 ./put_varn_real /pvfs2/wkliao/testfile.nc
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!             Y = 4 ;
+!             X = 10 ;
+!    variables:
+!             int var(Y, X) ;
+!    data:
+!
+!     var =
+!       3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+!       0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+!       1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+!       0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+!    }
+!
+
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          integer NDIMS
+          PARAMETER(NDIMS=2)
+
+          character(LEN=128) filename, cmd
+          integer rank, nprocs, err, num_reqs, ierr, get_args, dummy
+          integer ncid, cmode, varid, dimid(2), y, x
+          real buffer(13)
+          integer(kind=MPI_OFFSET_KIND) NY, NX
+          integer(kind=MPI_OFFSET_KIND) starts(NDIMS, 13)
+          integer(kind=MPI_OFFSET_KIND) counts(NDIMS, 13)
+          integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+          logical verbose
+
+          NY = 4
+          NX = 10
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD, err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
+
+          if (nprocs .NE. 4 .AND. rank .EQ. 0 .AND. verbose) &
+              print*,'Warning: ',trim(cmd),' is intended to run on ', &
+                     '4 processes'
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                             MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! create a global array of size NY * NX */
+          err = nf90mpi_def_dim(ncid, "Y", NY, dimid(2))
+          call check(err, 'In nf90mpi_def_dim Y: ')
+          err = nf90mpi_def_dim(ncid, "X", NX, dimid(1))
+          call check(err, 'In nf90mpi_def_dim X: ')
+          err = nf90mpi_def_var(ncid, "var", NF90_FLOAT, dimid, varid)
+          call check(err, 'In nf90mpi_def_var var: ')
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! pick arbitrary numbers of requests for 4 processes
+          num_reqs = 0
+          if (rank .EQ.  0) then
+              num_reqs = 8
+          elseif (rank .EQ. 1) then
+              num_reqs = 13
+          elseif (rank .EQ. 2) then
+              num_reqs = 9
+          elseif (rank .EQ. 3) then
+              num_reqs = 10
+          endif
+
+          ! assign arbitrary starts
+          y=2
+          x=1
+          if (rank .EQ. 0) then
+              starts(y, 1) = 1
+              starts(x, 1) = 6
+              starts(y, 2) = 2
+              starts(x, 2) = 1
+              starts(y, 3) = 3
+              starts(x, 3) = 7
+              starts(y, 4) = 4
+              starts(x, 4) = 1
+              starts(y, 5) = 1
+              starts(x, 5) = 7
+              starts(y, 6) = 3
+              starts(x, 6) = 8
+              starts(y, 7) = 4
+              starts(x, 7) = 2
+              starts(y, 8) = 4
+              starts(x, 8) = 3
+              ! rank 0 is writing the following locations: ("-" means skip)
+              !   -  -  -  -  -  0  0  -  -  - 
+              !   0  -  -  -  -  -  -  -  -  - 
+              !   -  -  -  -  -  -  0  0  -  - 
+              !   0  0  0  -  -  -  -  -  -  - 
+          elseif (rank .EQ. 1) then
+              starts(y,  1) = 1
+              starts(x,  1) = 4
+              starts(y,  2) = 1
+              starts(x,  2) = 9
+              starts(y,  3) = 2
+              starts(x,  3) = 6
+              starts(y,  4) = 3
+              starts(x,  4) = 1
+              starts(y,  5) = 3
+              starts(x,  5) = 9
+              starts(y,  6) = 4
+              starts(x,  6) = 5
+              starts(y,  7) = 1
+              starts(x,  7) = 5
+              starts(y,  8) = 1
+              starts(x,  8) = 10
+              starts(y,  9) = 2
+              starts(x,  9) = 7
+              starts(y, 10) = 3
+              starts(x, 10) = 2
+              starts(y, 11) = 3
+              starts(x, 11) = 10
+              starts(y, 12) = 4
+              starts(x, 12) = 6
+              starts(y, 13) = 4
+              starts(x, 13) = 7
+              ! rank 1 is writing the following locations: ("-" means skip)
+              !   -  -  -  1  1  -  -  -  1  1 
+              !   -  -  -  -  -  1  1  -  -  - 
+              !   1  1  -  -  -  -  -  -  1  1 
+              !   -  -  -  -  1  1  1  -  -  - 
+          elseif (rank .EQ. 2) then
+              starts(y, 1) = 1
+              starts(x, 1) = 8
+              starts(y, 2) = 2
+              starts(x, 2) = 2
+              starts(y, 3) = 2
+              starts(x, 3) = 8
+              starts(y, 4) = 3
+              starts(x, 4) = 3
+              starts(y, 5) = 4
+              starts(x, 5) = 4
+              starts(y, 6) = 2
+              starts(x, 6) = 3
+              starts(y, 7) = 2
+              starts(x, 7) = 9
+              starts(y, 8) = 2
+              starts(x, 8) = 4
+              starts(y, 9) = 2
+              starts(x, 9) = 10
+              ! rank 2 is writing the following locations: ("-" means skip)
+              !   -  -  -  -  -  -  -  2  -  - 
+              !   -  2  2  2  -  -  -  2  2  2 
+              !   -  -  2  -  -  -  -  -  -  - 
+              !   -  -  -  2  -  -  -  -  -  - 
+          elseif (rank .EQ. 3) then
+              starts(y,  1) = 1
+              starts(x,  1) = 1
+              starts(y,  2) = 2
+              starts(x,  2) = 5
+              starts(y,  3) = 3
+              starts(x,  3) = 4
+              starts(y,  4) = 4
+              starts(x,  4) = 8
+              starts(y,  5) = 1
+              starts(x,  5) = 2
+              starts(y,  6) = 3
+              starts(x,  6) = 5
+              starts(y,  7) = 4
+              starts(x,  7) = 9
+              starts(y,  8) = 1
+              starts(x,  8) = 3
+              starts(y,  9) = 3
+              starts(x,  9) = 6
+              starts(y, 10) = 4
+              starts(x, 10) = 10
+              ! rank 3 is writing the following locations: ("-" means skip)
+              !   3  3  3  -  -  -  -  -  -  - 
+              !   -  -  -  -  3  -  -  -  -  - 
+              !   -  -  -  3  3  3  -  -  -  - 
+              !   -  -  -  -  -  -  -  3  3  3 
+          endif
+          counts = 1
+
+          ! allocate I/O buffer and initialize its contents
+          buffer = rank
+
+          ! set the buffer pointers to different offsets to the I/O buffer
+          err = nf90mpi_put_varn_all(ncid, varid, buffer, num_reqs, &
+                                     starts, counts)
+          call check(err, 'In nf90mpi_put_varn_all: ')
+
+          err = nf90mpi_close(ncid);
+          call check(err, 'In nf90mpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nf90mpi_inq_malloc_size(malloc_size)
+          if (err == NF90_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+
+      end program
+
diff --git a/examples/F90/transpose.f90 b/examples/F90/transpose.f90
new file mode 100644
index 0000000..44b4331
--- /dev/null
+++ b/examples/F90/transpose.f90
@@ -0,0 +1,235 @@
+!
+!   Copyright (C) 2014, Northwestern University
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: transpose.f90 2139 2015-10-08 01:59:10Z wkliao $
+
+!
+!    This example shows how to use varm API to write six 3D integer
+!    array variables into a file. Each variable in the file is a
+!    dimensional transposed array from the one stored in memory. In
+!    memory, a 3D array is partitioned among all processes in a
+!    block-block-block fashion and in XYZ (i.e. Fortran) order. Note
+!    the variable and dimension naming below is in Fortran order. The
+!    dimension structures of the transposed six arrays are
+!       integer XYZ_var(X, Y, Z)      XYZ -> XYZ (no transpose)
+!       integer XZY_var(X, Z, Y)      XYZ -> XZY
+!       integer YXZ_var(Y, X, Z)      XYZ -> YXZ
+!       integer YZX_var(Y, Z, X)      XYZ -> YZX
+!       integer ZXY_var(Z, X, Y)      XYZ -> ZXY
+!       integer ZYX_var(Z, Y, X)      XYZ -> ZYX
+!
+!    To compile:
+!        mpif90 -O2 transpose.f90 -o transpose -lpnetcdf
+!    To run:
+!        mpiexec -n num_processes ./transpose [filename] [len]
+!    where len decides the size of local array, which is
+!    (len+2) x (len+1) x len. So, each variable is of size
+!    (len+2)*(len+1)*len * nprocs * sizeof(int)
+!
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          character(LEN=128) filename, cmd
+          integer err, nprocs, rank, lower_dims, ierr, get_args, dummy
+          integer cmode, ncid, psizes(3), dimids(3), dimidsT(3)
+          integer XYZ_id, XZY_id, YZX_id, YXZ_id, ZYX_id, ZXY_id
+          integer(kind=MPI_OFFSET_KIND) gsizes(3), starts(3)
+          integer(kind=MPI_OFFSET_KIND) counts(3), strides(3), imap(3)
+          integer(kind=MPI_OFFSET_KIND) startsT(3), countsT(3)
+          integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+          integer i, j, k, nx, ny, nz
+          PARAMETER(nx=4, ny=3, nz=2)
+          integer buf(nx,ny,nz)
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD, err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
+
+          ! calculate number of processes along each dimension
+          psizes = 0
+          call MPI_Dims_create(nprocs, 3, psizes, err)
+          if (verbose .AND. rank .EQ. 0) print*, "psizes= ",psizes(1:3)
+
+          ! for each MPI rank, find its local rank IDs along each dimension in
+          ! starts()
+          lower_dims = 1
+          do i=1, 3
+              starts(i) = MOD(rank / lower_dims, psizes(i))
+              lower_dims = lower_dims * psizes(i)
+          enddo
+          if (verbose) print*, "proc ",rank,": dim rank= ",starts(1:3)
+
+          strides = 1
+          gsizes  = (/ nx, ny, nz /)
+          do i=1, 3
+             starts(i) = starts(i) * gsizes(i) + 1 ! start indices
+             counts(i) = gsizes(i)                 ! array elements
+             gsizes(i) = gsizes(i) * psizes(i)     ! global array size
+          enddo
+
+          if (verbose) then
+              print*, "proc ",rank,": starts= ",starts(1:3)
+              print*, "proc ",rank,": counts= ",counts(1:3)
+          endif
+
+          ! initialize buffer with contiguous numbers
+          do k=1, nz
+          do j=1, ny
+          do i=1, nx
+              buf(i, j, k) = INT((starts(3)+k-2)*gsizes(2)*gsizes(1) + &
+                                 (starts(2)+j-2)*gsizes(1) + &
+                                 (starts(1)+i-2))
+          enddo
+          enddo
+          enddo
+          if (verbose .AND. rank .EQ. 0) print*, "buf= ",buf
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+          cmode = NF90_CLOBBER
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! define dimensions X, Y, Z
+          err = nf90mpi_def_dim(ncid, "X", gsizes(1), dimids(1))
+          call check(err, 'In nf90mpi_def_dim X: ')
+          err = nf90mpi_def_dim(ncid, "Y", gsizes(2), dimids(2))
+          call check(err, 'In nf90mpi_def_dim Y: ')
+          err = nf90mpi_def_dim(ncid, "Z", gsizes(3), dimids(3))
+          call check(err, 'In nf90mpi_def_dim Z: ')
+
+          ! define variable with no transposed file layout: XYZ
+          err = nf90mpi_def_var(ncid, "XYZ_var", NF90_INT, dimids, &
+                                XYZ_id)
+          call check(err, 'In nf90mpi_def_var XYZ_var: ')
+
+          ! define variable with transposed file layout: XYZ -> XZY
+          dimidsT = (/ dimids(1), dimids(3), dimids(2) /)
+          err = nf90mpi_def_var(ncid, "XZY_var", NF90_INT, dimidsT, &
+                                XZY_id)
+          call check(err, 'In nf90mpi_def_var XZY_var: ')
+
+          ! define variable with transposed file layout: XYZ -> YXZ
+          dimidsT = (/ dimids(2), dimids(1), dimids(3) /)
+          err = nf90mpi_def_var(ncid, "YXZ_var", NF90_INT, dimidsT, &
+                                YXZ_id)
+          call check(err, 'In nf90mpi_def_var YXZ_var: ')
+
+          ! define variable with transposed file layout: XYZ -> YZX
+          dimidsT = (/ dimids(2), dimids(3), dimids(1) /)
+          err = nf90mpi_def_var(ncid, "YZX_var", NF90_INT, dimidsT, &
+                                YZX_id)
+          call check(err, 'In nf90mpi_def_var YZX_var: ')
+
+          ! define variable with transposed file layout: XYZ -> ZXY
+          dimidsT = (/ dimids(3), dimids(1), dimids(2) /)
+          err = nf90mpi_def_var(ncid, "ZXY_var", NF90_INT, dimidsT, &
+                                ZXY_id)
+          call check(err, 'In nf90mpi_def_var ZXY_var: ')
+
+          ! define variable with transposed file layout: XYZ -> ZYX
+          dimidsT = (/ dimids(3), dimids(2), dimids(1) /)
+          err = nf90mpi_def_var(ncid, "ZYX_var", NF90_INT, dimidsT, &
+                                ZYX_id)
+          call check(err, 'In nf90mpi_def_var ZYX_var: ')
+
+          ! do not forget to exit define mode
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! write the whole variable in file: XYZ
+          err = nf90mpi_put_var_all(ncid, XYZ_id, buf, starts, counts)
+          call check(err, 'In nf90mpi_put_vara_int_all XYZ: ')
+
+          ! write the transposed variable:  XYZ -> XZY
+          imap    = (/ 1_MPI_OFFSET_KIND, counts(1)*counts(2), counts(1) /)
+          startsT = (/ starts(1), starts(3), starts(2) /)
+          countsT = (/ counts(1), counts(3), counts(2) /)
+          err = nf90mpi_put_var_all(ncid, XZY_id, buf, startsT, &
+                                    countsT, strides, imap)
+          call check(err, 'In nf90mpi_put_var_all XZY: ')
+
+          ! write the transposed variable:  XYZ -> YXZ
+          imap    = (/ counts(1), 1_MPI_OFFSET_KIND, counts(1)*counts(2) /)
+          startsT = (/ starts(2), starts(1), starts(3) /)
+          countsT = (/ counts(2), counts(1), counts(3) /)
+          err = nf90mpi_put_var_all(ncid, YXZ_id, buf, startsT, &
+                                    countsT, strides, imap)
+          call check(err, 'In nf90mpi_put_var_all YZX: ')
+
+          ! write the transposed variable:  XYZ -> YZX
+          imap    = (/ counts(1), counts(1)*counts(2), 1_MPI_OFFSET_KIND /)
+          startsT = (/ starts(2), starts(3), starts(1) /)
+          countsT = (/ counts(2), counts(3), counts(1) /)
+          err = nf90mpi_put_var_all(ncid, YZX_id, buf, startsT, &
+                                    countsT, strides, imap)
+          call check(err, 'In nf90mpi_put_var_all YZX: ')
+
+          ! write the transposed variable:  XYZ -> ZXY
+          imap    = (/ counts(1)*counts(2), 1_MPI_OFFSET_KIND, counts(1) /)
+          startsT = (/ starts(3), starts(1), starts(2) /)
+          countsT = (/ counts(3), counts(1), counts(2) /)
+          err = nf90mpi_put_var_all(ncid, ZXY_id, buf, startsT, &
+                                    countsT, strides, imap)
+          call check(err, 'In nf90mpi_put_var_all ZXY: ')
+
+          ! write the transposed variable:  XYZ -> ZYX
+          imap    = (/ counts(1)*counts(2), counts(1), 1_MPI_OFFSET_KIND /)
+          startsT = (/ starts(3), starts(2), starts(1) /)
+          countsT = (/ counts(3), counts(2), counts(1) /)
+          err = nf90mpi_put_var_all(ncid, ZYX_id, buf, startsT, &
+                                    countsT, strides, imap)
+          call check(err, 'In nf90mpi_put_var_all ZYX: ')
+
+          ! close the file
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nf90mpi_inq_malloc_size(malloc_size)
+          if (err == NF90_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ', &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end program main
+
diff --git a/examples/F90/utils.F90 b/examples/F90/utils.F90
new file mode 100644
index 0000000..d83aeca
--- /dev/null
+++ b/examples/F90/utils.F90
@@ -0,0 +1,53 @@
+!
+!  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: utils.F90 2120 2015-09-22 07:11:58Z wkliao $
+
+    ! This function gets the executable name and output file name from the
+    ! command line.
+    integer function get_args(max_argc, cmd, filename, verbose, len)
+#ifdef NAGf90Fortran
+        USE F90_UNIX_ENV, only : iargc, getarg
+        implicit none
+#else
+        implicit none
+        integer iargc
+#endif
+        integer max_argc, len
+        character(len=*) cmd, filename
+        logical verbose
+
+        ! local variables
+        integer argc
+        character(len=16) quiet_mode, str
+
+
+        call getarg(0, cmd)
+        argc = IARGC()
+        if (argc .GT. max_argc) then
+            if (max_argc .EQ. 3) &
+                print*,'Usage: ',trim(cmd),' [-q] [filename] [len]'
+            if (max_argc .EQ. 2) &
+                print*,'Usage: ',trim(cmd),' [-q] [filename]'
+            get_args = 0
+            return
+        endif
+        call getarg(1, quiet_mode)
+        if (quiet_mode(1:2) .EQ. '-q') then
+            verbose = .FALSE.
+            if (argc .GE. 2) call getarg(2, filename)
+            if (argc .EQ. 3) then
+                call getarg(3, str)
+                read (str,'(I10)') len
+            endif
+        else
+            if (argc .GE. 1) call getarg(1, filename)
+            if (argc .EQ. 2) then
+                call getarg(2, str)
+                read (str,'(I10)') len
+            endif
+        endif
+    end function get_args
diff --git a/examples/F90/vard_int.f90 b/examples/F90/vard_int.f90
new file mode 100644
index 0000000..4644d63
--- /dev/null
+++ b/examples/F90/vard_int.f90
@@ -0,0 +1,225 @@
+!
+!   Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: vard_int.f90 2239 2015-12-18 18:21:09Z wkliao $
+
+!
+! This example shows how to use the vard API nf90mpi_put_vard() and
+! nf90mpi_get_vard() to write and read 2D record and fixed-size
+! variables.
+!
+!    To compile:
+!        mpif90 -O2 vard_int.f90 -o vard_int -lpnetcdf
+!
+! Example commands for MPI run and outputs from running ncmpidump on
+! the NC file produced by this example program:
+!
+!    % mpiexec -n 4 ./vard_int /pvfs2/wkliao/testfile.nc
+!
+! The expected results from the output file contents are:
+!
+!  % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-1
+!    dimensions:
+!           REC_DIM = UNLIMITED ; // (2 currently)
+!           X = 12 ;
+!           FIX_DIM = 2 ;
+!    variables:
+!           int rec_var(REC_DIM, X) ;
+!           int fix_var(FIX_DIM, X) ;
+!    data:
+!
+!     rec_var =
+!       0, 1, 2, 100, 101, 102, 200, 201, 202, 300, 301, 302,
+!       10, 11, 12, 110, 111, 112, 210, 211, 212, 310, 311, 312 ;
+!
+!     fix_var =
+!       0, 1, 2, 100, 101, 102, 200, 201, 202, 300, 301, 302,
+!       10, 11, 12, 110, 111, 112, 210, 211, 212, 310, 311, 312 ;
+!    }
+!
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          character(LEN=128) filename, cmd
+          integer err, nprocs, rank, i, j, ierr, get_args, dummy
+          integer cmode, ncid, varid0, varid1, dimid(2)
+          integer(kind=MPI_OFFSET_KIND) NX, NY
+          integer(kind=MPI_OFFSET_KIND) start(2), count(2), bufcount
+          PARAMETER(NX=5, NY=2)
+          integer buf(NX, NY)
+          integer buftype, rec_filetype, fix_filetype
+          integer array_of_sizes(2), array_of_subsizes(2)
+          integer array_of_starts(2), blocklengths(2)
+          integer(kind=MPI_OFFSET_KIND) len, malloc_size, sum_size, recsize
+          integer(kind=MPI_ADDRESS_KIND) disps(2)
+          logical verbose
+
+          call MPI_Init(err)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, err)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              verbose = .TRUE.
+              filename = "testfile.nc"
+              ierr = get_args(2, cmd, filename, verbose, dummy)
+          endif
+          call MPI_Bcast(ierr, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
+          if (ierr .EQ. 0) goto 999
+
+          call MPI_Bcast(verbose, 1, MPI_LOGICAL, 0, MPI_COMM_WORLD, err)
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err)
+
+          start(1) = NX * rank
+          start(2) = 0
+          count(1) = NX
+          count(2) = 2
+
+          ! initialized buffer contents
+          do j=1, INT(count(2))
+             do i=1, INT(count(1))
+                 buf(i, j) = rank*100 + j*10 + i
+             enddo
+          enddo
+
+          ! create file, truncate it if exists
+          cmode = NF90_CLOBBER
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! define 2 dimensions
+          err = nf90mpi_def_dim(ncid, "RECV_DIM", NF90MPI_UNLIMITED, dimid(2))
+          call check(err, 'In nf90mpi_def_dim RECV_DIM: ')
+          len = NX * nprocs
+          err = nf90mpi_def_dim(ncid, "X", len, dimid(1))
+          call check(err, 'In nf90mpi_def_dim X: ')
+
+          ! define 2D record variables of integer type
+          err = nf90mpi_def_var(ncid, "rec_var", NF90_INT, dimid, varid0)
+          call check(err, 'In nf90mpi_def_var: rec_var ')
+
+          ! define 2D fixed-size variable of integer type
+          err = nf90mpi_def_dim(ncid, "FIX_DIM", 2_MPI_OFFSET_KIND, dimid(2))
+          call check(err, 'In nf90mpi_def_dim RECV_DIM: ')
+          err = nf90mpi_def_var(ncid, "fix_var", NF90_INT, dimid, varid1)
+          call check(err, 'In nf90mpi_def_var: fix_var ')
+
+          ! do not forget to exit define mode
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! create a file type for the record variable */
+          err = nf90mpi_inq_recsize(ncid, recsize)
+          call check(err, 'In nf90mpi_inq_recsize: ')
+          blocklengths(1) = INT(count(1))
+          blocklengths(2) = INT(count(1))
+          disps(1) = start(1)*4
+          disps(2) = recsize + start(1)*4
+          call MPI_Type_create_hindexed(2, blocklengths, disps, &
+                                        MPI_INTEGER, rec_filetype, err)
+          call MPI_Type_commit(rec_filetype, err)
+
+          ! create a file type for the fixed-size variable
+          array_of_sizes(1) = INT(NX*nprocs)
+          array_of_sizes(2) = 2
+          array_of_subsizes(1) = INT(count(1))
+          array_of_subsizes(2) = INT(count(2))
+          array_of_starts(1) = INT(start(1))
+          array_of_starts(2) = INT(start(2))
+          call MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes, &
+               array_of_starts, MPI_ORDER_FORTRAN, MPI_INTEGER, fix_filetype,&
+               err)
+          call MPI_Type_commit(fix_filetype, err)
+
+          bufcount = count(1) * count(2)
+          buftype = MPI_INTEGER
+
+          ! write the record variable */
+          err = nf90mpi_put_vard_all(ncid, varid0, rec_filetype, buf, &
+                                     bufcount, buftype)
+          call check(err, 'In nf90mpi_put_vard_all: ')
+
+          ! check if the number of records changed to 2
+          err = nf90mpi_inquire(ncid, unlimitedDimId=dimid(2))
+          call check(err, 'In nf90mpi_inquire: ')
+          err = nf90mpi_inquire_dimension(ncid, dimid(2), len=len)
+          call check(err, 'In nf90mpi_inquire_dimension: ')
+          if (len .NE. 2) then
+              print*, 'Error: number of records should be 2 but got ', &
+                       len
+          endif
+
+          ! write the fixed-size variable
+          err = nf90mpi_put_vard_all(ncid, varid1, fix_filetype, buf, &
+                                     bufcount, buftype)
+          call check(err, 'In nf90mpi_put_vard_all: ')
+
+          ! close the file
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          ! open the same file and read back for validate */
+          err = nf90mpi_open(MPI_COMM_WORLD, filename, NF90_NOWRITE, &
+                             MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_open: ')
+
+          err = nf90mpi_inq_varid(ncid, "rec_var", varid0)
+          call check(err, 'In nf90mpi_inq_varid rec_var: ')
+          err = nf90mpi_inq_varid(ncid, "fix_var", varid1)
+          call check(err, 'In nf90mpi_inq_varid fix_var: ')
+
+          ! PnetCDF start() argument starts with 1
+          start = start + 1
+
+          ! read back record variable
+          err = nf90mpi_get_vard_all(ncid, varid0, rec_filetype, buf, &
+                                     bufcount, buftype)
+          call check(err, 'In nf90mpi_get_vard_all: ')
+
+          ! read back fixed-size variable
+          err = nf90mpi_get_vard_all(ncid, varid1, fix_filetype, buf, &
+                                     bufcount, buftype)
+          call check(err, 'In nf90mpi_get_vard_all: ')
+
+          ! close the file
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          call MPI_Type_free(rec_filetype, err)
+          call MPI_Type_free(fix_filetype, err)
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nf90mpi_inq_malloc_size(malloc_size)
+          if (err == NF90_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+ 999      call MPI_Finalize(err)
+          ! call EXIT(0) ! EXIT() is a GNU extension
+      end program main
+
diff --git a/examples/Makefile.in b/examples/Makefile.in
new file mode 100644
index 0000000..3a82558
--- /dev/null
+++ b/examples/Makefile.in
@@ -0,0 +1,72 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2219 2015-12-11 22:30:03Z wkliao $
+#
+# @configure_input@
+
+srcdir  = @srcdir@
+VPATH   = @srcdir@
+
+include ../macros.make
+
+GARBAGE =
+
+SUBDIRS = C tutorial
+
+ifeq (@has_mpicxx@, yes)
+SUBDIRS += CXX
+endif
+
+ifeq (@has_fortran@, yes)
+SUBDIRS += F77
+SUBDIRS += F90
+endif
+
+PACKING_LIST = Makefile.in README
+
+PACKING_SUBDIRS = C tutorial F77 F90 CXX
+
+all: $(SUBDIRS)
+$(SUBDIRS):
+	$(MAKE) $(MFLAGS) -C $@
+
+ptest: all
+ifeq (@enable_coverage@, yes)
+	echo "Parallel test is disabled because coverage analysis was enabled"
+else
+	(echo "=============================================")  && \
+	(echo "    Parallel testing on 4 MPI processes")  && \
+	(echo "=============================================")  && \
+	( for d in $(SUBDIRS) ; do \
+		$(MAKE) $(MFLAGS) -C $$d ptest4 ; \
+	done ) ;
+endif
+
+ptests: all
+ifeq (@enable_coverage@, yes)
+	echo "Parallel test is disabled because coverage analysis was enabled"
+else
+	for i in 3 4 8 ; do \
+	(echo "=============================================")  && \
+	(echo "    Parallel testing on $$i MPI processes")  && \
+	(echo "=============================================")  && \
+	( for d in $(SUBDIRS) ; do \
+	$(MAKE) $(MFLAGS) -C $$d ptest$$i ; \
+	done ) ; \
+	done ;
+endif
+
+INSTALLDIRS = $(SUBDIRS:%=install-%)
+install: all $(INSTALLDIRS)
+$(INSTALLDIRS): 
+	$(MAKE) $(MFLAGS) -C $(@:install-%=%) install
+
+UNINSTALLDIRS = $(SUBDIRS:%=uninstall-%)
+uninstall: $(UNINSTALLDIRS)
+$(UNINSTALLDIRS): 
+	$(MAKE) $(MFLAGS) -C $(@:uninstall-%=%) uninstall
+
+include $(srcdir)/../rules.make
+
diff --git a/examples/README b/examples/README
new file mode 100644
index 0000000..eba19f5
--- /dev/null
+++ b/examples/README
@@ -0,0 +1,322 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: README 2245 2015-12-20 18:39:52Z wkliao $
+#
+
+This directory contains several example programs. Detailed descriptions of
+each program, compile and run instructions, and sample outputs are provided
+at the beginning of each file. Most of the example programs are developed
+with C, C++, F77, and F90 versions.
+
+
+./tutorial
+    A directory contains example programs that use different parallel I/O
+    strategies, including:
+        Parallel I/O from the master process
+        Concurrent I/O on separate files
+        Real parallel I/O on shared files
+        Using "flexible" APIs
+        Using non-blocking APIs
+        Using non-blocking buffered write APIs
+
+   Detailed descriptions for these programs can be found in
+   http://trac.mcs.anl.gov/projects/parallel-netcdf/wiki/QuickTutorial
+
+
+  ./C/block_cyclic.c
+./CXX/block_cyclic.cpp
+./F77/block_cyclic.f
+./F90/block_cyclic.f90
+
+    This example makes a number of nonblocking API calls, each to write a
+    block of columns into a 2D integer variable in a file. In other words,
+    data partitioning pattern is a block-cyclic along X dimension.
+    The pattern is described by the rank IDs if run with 4 processes.
+
+        0,  0,  1,  1,  2,  2,  3,  3,  0,  0,  1,  1,  2,  2,  3,  3,
+        0,  0,  1,  1,  2,  2,  3,  3,  0,  0,  1,  1,  2,  2,  3,  3,
+        0,  0,  1,  1,  2,  2,  3,  3,  0,  0,  1,  1,  2,  2,  3,  3,
+        0,  0,  1,  1,  2,  2,  3,  3,  0,  0,  1,  1,  2,  2,  3,  3,
+        0,  0,  1,  1,  2,  2,  3,  3,  0,  0,  1,  1,  2,  2,  3,  3,
+        0,  0,  1,  1,  2,  2,  3,  3,  0,  0,  1,  1,  2,  2,  3,  3,
+        0,  0,  1,  1,  2,  2,  3,  3,  0,  0,  1,  1,  2,  2,  3,  3,
+        0,  0,  1,  1,  2,  2,  3,  3,  0,  0,  1,  1,  2,  2,  3,  3,
+        0,  0,  1,  1,  2,  2,  3,  3,  0,  0,  1,  1,  2,  2,  3,  3,
+        0,  0,  1,  1,  2,  2,  3,  3,  0,  0,  1,  1,  2,  2,  3,  3 ;
+
+
+./C/collective_write.c
+./CXX/collective_write.cpp
+    This example defined NUM_VARS 3D integer non-record variables in a file.
+    All variables are partitioned among processes in a 3D block-block-block
+    fashion. The I/O is carried out by making NUM_VARS calls to 
+    ncmpi_put_vara_int_all(), one for each variable. Performance measurements
+    are reported in the standard output.
+
+
+  ./C/column_wise.c
+./CXX/column_wise.cpp
+./F77/column_wise.f
+./F90/column_wise.f90
+    This example makes a number of nonblocking API calls, each writes a single
+    column of a 2D integer variable defined in a file. The data partitioning
+    pattern among processes is a cyclic along dimension X, illustrated below
+    by the process rank IDs if run with 4 processes
+
+       0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+       0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+       0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+       0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+       0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+       0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+       0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+       0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+       0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+       0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 ;
+
+
+  ./C/flexible_api.c
+./CXX/flexible_api.cpp
+./F77/flexible_api.f
+./F90/flexible_api.f90
+    This example shows how to use PnetCDF flexible APIs, ncmpi_put_vara_all()
+    and ncmpi_iput_vara() to write two 2D array variables (one is of 4-byte
+    integer byte and the other float type) in parallel.
+    Local buffers have a ghost cell of length 3 surrounded along each
+    dimension.
+
+
+  ./C/get_info.c
+./CXX/get_info.cpp
+./F77/get_info.f
+./F90/get_info.f90
+    These two example programs print the PnetCDF and MPI-IO hints to the
+    standard output.
+
+
+  ./C/hints.c
+./CXX/hints.cpp
+./F77/hints.f
+./F90/hints.f90
+    This example sets two PnetCDF hints:
+        nc_header_align_size and
+        nc_var_align_size
+    and prints the hint values, the header size, header extent, and
+    variables' starting file offsets.
+
+
+./C/mput.c
+    This example shows how to use a single call of ncmpi_mput_vara_all() to
+    write a sequence of requests with arbitrary array indices and lengths.
+    It is intended to run on 4 processes. If more processes were allocated,
+    the extra processes write zero-length requests. The offsets and lengths
+    are just some random numbers to make the output look like:
+
+        3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+        0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+        1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+        0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+
+
+
+  ./C/nonblocking_write.c
+./CXX/nonblocking_write.cpp
+./F77/nonblocking_write.f
+./F90/nonblocking_write.f90
+    This example is almost the same as to collective_write.c but using
+    nonblocking APIs instead.
+
+
+  ./C/put_vara.c
+./CXX/put_vara.cpp
+./F77/put_vara.f
+./F90/put_var.f90
+    This example shows how to use nfmpi_put_vara_int_all() to write a 2D
+    4-byte integer array in parallel. The data partitioning pattern among
+    processes is a *-block in Fortran order. It is described by the process
+    rank IDs as below if run on 4 processes.
+
+         0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0,
+         1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1,
+         2, 2, 2, 2, 2,
+         2, 2, 2, 2, 2,
+         2, 2, 2, 2, 2,
+         2, 2, 2, 2, 2,
+         3, 3, 3, 3, 3,
+         3, 3, 3, 3, 3,
+         3, 3, 3, 3, 3,
+         3, 3, 3, 3, 3 ;
+
+
+  ./C/put_varn_float.c
+./CXX/put_varn_float.cpp
+./F77/put_varn_real.f
+./F90/put_varn_real.f90
+    This example makes a single call of ncmpi_put_varn_float_all() to write a
+    sequence of one-element requests with arbitrary array indices. All
+    subrequest indices, starts[], are within the boundaries of a single
+    variable.  See comments at the beginning of the source file for compile,
+    run instructions, and example output.
+
+
+  ./C/put_varn_int.c
+./CXX/put_varn_int.cpp
+./F77/put_varn_int.f
+./F90/put_varn_int.f90
+    This example makes a single call of ncmpi_put_varn_int_all() to write a
+    sequence of requests with arbitrary array indices and lengths. All
+    subrequests (starts[] and counts[]) are within the boundaries of a single
+    variable.  See comments at the beginning of the source file for compile,
+    run instructions, and example output.
+
+
+./C/create_open.c
+    This example shows how to use to create a new file, close it, and
+    open the file for read only.
+
+
+./C/global_attributes.c
+    This example creates a new file and add 2 global attributes, one is of text
+    type and the other 10 short integers. The file is closed and re-opened to
+    read back the attributes.
+
+  ./C/get_vara.c
+./CXX/get_vara.cpp
+    This example is the read counterpart of example put_vara.c. It shows how to
+    use ncmpi_get_vara_int_all() to read a 2D 4-byte integer array in parallel.
+    It also reads a global attribute and two attribute of variable named "var".
+    The data partitioning pattern is a column-wise partitioning across all
+    processes.
+
+  ./C/transpose.c
+./CXX/transpose.cpp
+./F77/transpose.f
+./F90/transpose.f90
+  This example writes dimensional-transposed 3D arrays using varm APIs.
+
+  For example, when Z=4, Y=6, and X=8, an array partitioned among 4 processes
+  (P0,P1,P2,P3) and organized in dimension ZYX are illustrated below:
+  P0: var[Z=0][*][*]=  0,   1,   2,   3,  P1: var[Z=0][*][*]=  4,   5,   6,   7,
+                       8,   9,  10,  11,                      12,  13,  14,  15,
+                      16,  17,  18,  19,                      20,  21,  22,  23,
+                      24,  25,  26,  27,                      28,  29,  30,  31,
+                      32,  33,  34,  35,                      36,  37,  38,  39,
+                      40,  41,  42,  43,                      44,  45,  46,  47,
+
+  P2: var[Z=0][*][*]= 48,  49,  50,  51,  P3: var[Z=0][*][*]= 52,  53,  54,  55,
+                      56,  57,  58,  59,                      60,  61,  62,  63,
+                      64,  65,  66,  67,                      68,  69,  70,  71,
+                      72,  73,  74,  75,                      76,  77,  78,  79,
+                      80,  81,  82,  83,                      84,  85,  86,  87,
+                      88,  89,  90,  91,                      92,  93,  94,  95,
+
+  P0: var[Z=1][*][*]= 96,  97,  98,  99,  P1: var[Z=1][*][*]=100, 101, 102, 103,
+                     104, 105, 106, 107,                     108, 109, 110, 111,
+                     112, 113, 114, 115,                     116, 117, 118, 119,
+                     120, 121, 122, 123,                     124, 125, 126, 127,
+                     128, 129, 130, 131,                     132, 133, 134, 135,
+                     136, 137, 138, 139,                     140, 141, 142, 143,
+
+  P2: var[Z=1][*][*]=144, 145, 146, 147,  P3: var[Z=1][*][*]=148, 149, 150, 151,
+                     152, 153, 154, 155,                     156, 157, 158, 159,
+                     160, 161, 162, 163,                     164, 165, 166, 167,
+                     168, 169, 170, 171,                     172, 173, 174, 175,
+                     176, 177, 178, 179,                     180, 181, 182, 183,
+                     184, 185, 186, 187,                     188, 189, 190, 191 ;
+
+  When writing the subarray in parallel to a file, the array contents in file are:
+  var[Z=0][*][*]:  0,   1,   2,   3,   4,   5,   6,   7,
+                   8,   9,  10,  11,  12,  13,  14,  15,
+                  16,  17,  18,  19,  20,  21,  22,  23,
+                  24,  25,  26,  27,  28,  29,  30,  31,
+                  32,  33,  34,  35,  36,  37,  38,  39,
+                  40,  41,  42,  43,  44,  45,  46,  47,
+                  48,  49,  50,  51,  52,  53,  54,  55,
+                  56,  57,  58,  59,  60,  61,  62,  63,
+                  64,  65,  66,  67,  68,  69,  70,  71,
+                  72,  73,  74,  75,  76,  77,  78,  79,
+                  80,  81,  82,  83,  84,  85,  86,  87,
+                  88,  89,  90,  91,  92,  93,  94,  95,
+
+  var[Z=1][*][*]: 96,  97,  98,  99, 100, 101, 102, 103,
+                 104, 105, 106, 107, 108, 109, 110, 111,
+                 112, 113, 114, 115, 116, 117, 118, 119,
+                 120, 121, 122, 123, 124, 125, 126, 127,
+                 128, 129, 130, 131, 132, 133, 134, 135,
+                 136, 137, 138, 139, 140, 141, 142, 143,
+                 144, 145, 146, 147, 148, 149, 150, 151,
+                 152, 153, 154, 155, 156, 157, 158, 159,
+                 160, 161, 162, 163, 164, 165, 166, 167,
+                 168, 169, 170, 171, 172, 173, 174, 175,
+                 176, 177, 178, 179, 180, 181, 182, 183,
+                 184, 185, 186, 187, 188, 189, 190, 191 ;
+
+  When writing the transposed subarray (XYZ) in parallel to a file, the file contents are:
+  var[Z=0][*][*]= 0, 48,  96, 144,    var[Z=1][*][*]= 1, 49,  97, 145,
+                  8, 56, 104, 152,                    9, 57, 105, 153,
+                 16, 64, 112, 160,                   17, 65, 113, 161,
+                 24, 72, 120, 168,                   25, 73, 121, 169,
+                 32, 80, 128, 176,                   33, 81, 129, 177,
+                 40, 88, 136, 184,                   41, 89, 137, 185,
+
+  var[Z=2][*][*]= 2, 50,  98, 146,    var[Z=3][*][*]= 3, 51,  99, 147,
+                 10, 58, 106, 154,                   11, 59, 107, 155,
+                 18, 66, 114, 162,                   19, 67, 115, 163,
+                 26, 74, 122, 170,                   27, 75, 123, 171,
+                 34, 82, 130, 178,                   35, 83, 131, 179,
+                 42, 90, 138, 186,                   43, 91, 139, 187,
+
+  var[Z=4][*][*]= 4, 52, 100, 148,    var[Z=5][*][*]= 5, 53, 101, 149,
+                 12, 60, 108, 156,                   13, 61, 109, 157,
+                 20, 68, 116, 164,                   21, 69, 117, 165,
+                 28, 76, 124, 172,                   29, 77, 125, 173,
+                 36, 84, 132, 180,                   37, 85, 133, 181,
+                 44, 92, 140, 188,                   45, 93, 141, 189,
+
+  var[Z=6][*][*]= 6, 54, 102, 150,    var[Z=7][*][*]= 7, 55, 103, 151,
+                 14, 62, 110, 158,                   15, 63, 111, 159,
+                 22, 70, 118, 166,                   23, 71, 119, 167,
+                 30, 78, 126, 174,                   31, 79, 127, 175,
+                 38, 86, 134, 182,                   39, 87, 135, 183,
+                 46, 94, 142, 190,                   47, 95, 143, 191 ;
+
+
+  ./C/vard_int.c
+./CXX/vard_int.cpp
+./F77/vard_int.f
+./F90/vard_int.f90
+  These examples show how to use vard APIs to write/read record and fixed-size
+  variables.
+
+  ./C/bput_varn_uint.c
+./F77/bput_varn_int8.f
+  These examples show how to use nonblocking bput_varn APIs
+
+  ./C/i_varn_int64.c
+./F77/i_varn_real.f
+  These examples show how to use nonblocking iput_varn and iget_varn APIs
+
+  ./C/fill_mode.c
+./CXX/fill_mode.cpp
+./F77/fill_mode.f
+./F90/fill_mode.f90
+  These examples show how to enable file mode
+
+  ./C/req_all.c
+  This example show how to use NC_REQ_ALL to flush all pending nonblocking
+  requests without providing the request IDs and status array.
+
+  ./C/nonblocking_write_in_def.c
+  This example is the same as nonblocking_write.c except all nonblocking
+  write requests (calls to iput and bput) are posted in define mode. After
+  entering to data mode, a single call to ncmpi_wait_all() to flush all pending
+  nonblocking requests.
+
diff --git a/examples/tutorial/Makefile.in b/examples/tutorial/Makefile.in
new file mode 100644
index 0000000..a0947d6
--- /dev/null
+++ b/examples/tutorial/Makefile.in
@@ -0,0 +1,114 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2237 2015-12-18 07:11:47Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../macros.make
+
+# note the order of -L list matters
+INCLUDES    = -I../../src/lib
+FPPFLAGS   += -I../../src/libf @FC_MODINC at ../../src/libf90
+LDFLAGS    := -L../../src/lib $(LDFLAGS)
+FLDFLAGS   += $(LDFLAGS)
+F90LDFLAGS += $(LDFLAGS)
+LIBS       := -lpnetcdf $(LIBS)
+
+C_SRCS = pnetcdf-write-from-master.c \
+         pnetcdf-read-from-master.c \
+         pnetcdf-write-nfiles.c \
+         pnetcdf-read-nfiles.c \
+         pnetcdf-write-standard.c \
+         pnetcdf-read-standard.c \
+         pnetcdf-write-flexible.c \
+         pnetcdf-read-flexible.c \
+         pnetcdf-write-nb.c \
+         pnetcdf-read-nb.c \
+         pnetcdf-write-buffered.c \
+         pnetcdf-permute.c
+
+F77_SRCS = pnetcdf-write-bufferedf77.f
+
+F90_SRCS = pnetcdf-write-bufferedf.f90
+
+PROGS  = $(C_SRCS:.c=)
+OBJS   = $(C_SRCS:.c=.o)
+ifeq (@has_fortran@, yes)
+PROGS += $(F77_SRCS:.f=)
+OBJS  += $(F77_SRCS:.f=.o)
+PROGS += $(F90_SRCS:.f90=)
+OBJS  += $(F90_SRCS:.f90=.o)
+endif
+
+GARBAGE      = $(PROGS) *.nc
+PACKING_LIST = $(C_SRCS) $(F77_SRCS) $(F90_SRCS) Makefile.in depend
+
+all: $(PROGS)
+
+pnetcdf-write-from-master: pnetcdf-write-from-master.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+pnetcdf-read-from-master: pnetcdf-read-from-master.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+pnetcdf-write-nfiles: pnetcdf-write-nfiles.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+pnetcdf-read-nfiles: pnetcdf-read-nfiles.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+pnetcdf-write-standard: pnetcdf-write-standard.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+pnetcdf-read-standard: pnetcdf-read-standard.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+pnetcdf-write-flexible: pnetcdf-write-flexible.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+pnetcdf-read-flexible: pnetcdf-read-flexible.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+pnetcdf-write-nb: pnetcdf-write-nb.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+pnetcdf-read-nb: pnetcdf-read-nb.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+pnetcdf-write-buffered: pnetcdf-write-buffered.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+pnetcdf-write-bufferedf: pnetcdf-write-bufferedf.o $(LIBRARY)
+	$(LINK.F90) $< $(F90LDFLAGS) $(LIBS)
+
+pnetcdf-write-bufferedf77: pnetcdf-write-bufferedf77.o $(LIBRARY)
+	$(LINK.F77) $< $(FLDFLAGS) $(LIBS)
+
+pnetcdf-permute: pnetcdf-permute.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+
+ptest4: $(PROGS)
+	@for i in $(PROGS); do ( \
+        $(TEST_MPIRUN_4) ./$$i $(TEST_OUTDIR)/testfile.nc ; \
+        if [ $$? = 0 ] ; then \
+           echo "PASS:     parallel run on 4 processes --------------- $$i"; \
+        else \
+           echo "FAILED:     parallel run on 4 processes ------------- $$i"; \
+        fi ; ) ; done
+
+ptest: ptest4
+ptests: ptest4
+ptest2 ptest3 ptest6 ptest8 ptest10:
+
+include $(srcdir)/depend
+include $(srcdir)/../../rules.make
+
+$(LIBRARY): ;
+
diff --git a/examples/tutorial/depend b/examples/tutorial/depend
new file mode 100644
index 0000000..609c3bf
--- /dev/null
+++ b/examples/tutorial/depend
@@ -0,0 +1,14 @@
+pnetcdf-permute.o: pnetcdf-permute.c
+pnetcdf-read-flexible.o: pnetcdf-read-flexible.c
+pnetcdf-read-from-master.o: pnetcdf-read-from-master.c
+pnetcdf-read-nb.o: pnetcdf-read-nb.c
+pnetcdf-read-nfiles.o: pnetcdf-read-nfiles.c
+pnetcdf-read-standard.o: pnetcdf-read-standard.c
+pnetcdf-write-bufferedf77.o: pnetcdf-write-bufferedf77.f
+pnetcdf-write-bufferedf.o: pnetcdf-write-bufferedf.f90
+pnetcdf-write-buffered.o: pnetcdf-write-buffered.c
+pnetcdf-write-flexible.o: pnetcdf-write-flexible.c
+pnetcdf-write-from-master.o: pnetcdf-write-from-master.c
+pnetcdf-write-nb.o: pnetcdf-write-nb.c
+pnetcdf-write-nfiles.o: pnetcdf-write-nfiles.c
+pnetcdf-write-standard.o: pnetcdf-write-standard.c
diff --git a/examples/tutorial/pnetcdf-permute.c b/examples/tutorial/pnetcdf-permute.c
new file mode 100644
index 0000000..98d3cc5
--- /dev/null
+++ b/examples/tutorial/pnetcdf-permute.c
@@ -0,0 +1,158 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: pnetcdf-permute.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* simple demonstration of pnetcdf 
+ * knowing nothing about the file, read in the variables. 
+ *
+ * This example demonstrates the flexible interface, using the MPI derived
+ * datatype to transpose the matrix.
+ *
+ * Note this program demonstrates transposition for one process only
+ */
+
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <stdio.h>
+
+#include <assert.h>
+
+static void handle_error(int status, int lineno)
+{
+    fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
+    MPI_Abort(MPI_COMM_WORLD, 1);
+}
+
+int main(int argc, char **argv) {
+
+#define NDIMS 3
+    int i, j, k, rank, nprocs, ret;
+    int ncfile, ndims=NDIMS;
+    MPI_Offset dim_sizes[NDIMS];
+    MPI_Offset start[NDIMS], count[NDIMS], nitems;
+    int dimids[NDIMS], transposed_dims[NDIMS];
+    int varid1, transposed_varid, flexible_varid;
+    double *data, *transposed_data;
+    MPI_Datatype transposed_type, one_d, two_d;
+
+    MPI_Init(&argc, &argv);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc != 2) {
+        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
+        MPI_Finalize();
+        exit(-1);
+    }
+
+    ret = ncmpi_create(MPI_COMM_WORLD, argv[1], 
+	    NC_CLOBBER|NC_64BIT_OFFSET, MPI_INFO_NULL, &ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    dim_sizes[0] = 4;
+    dim_sizes[1] = 5;
+    dim_sizes[2] = 6;
+
+    ret = ncmpi_def_dim(ncfile, "x", dim_sizes[0], &(dimids[0]));
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_dim(ncfile, "y", dim_sizes[1], &(dimids[1]));
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_dim(ncfile, "z", dim_sizes[2], &(dimids[2]));
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_var(ncfile, "v1", NC_INT, ndims, dimids, &varid1);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* moab wants to permute {i,j,k} to {j,k,i} */
+    transposed_dims[0] = dimids[1];
+    transposed_dims[1] = dimids[2];
+    transposed_dims[2] = dimids[0];
+    ret = ncmpi_def_var(ncfile, "transposed-v1", NC_INT, ndims, transposed_dims,
+	    &transposed_varid);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* want this to end up looking like transposed-v1 */
+    ret = ncmpi_def_var(ncfile, "flexible-v1", NC_INT, ndims, transposed_dims,
+	    &flexible_varid);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_enddef(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    nitems = dim_sizes[0]*dim_sizes[1]*dim_sizes[2];
+    data = (double*) calloc(nitems, sizeof(double));
+    transposed_data = (double*) calloc(nitems, sizeof(double));
+
+    for (i=0; i<dim_sizes[0]; i++) {
+	for (j=0; j<dim_sizes[1]; j++) {
+	    for (k=0; k<dim_sizes[2]; k++) {
+		/* data in x,y,z order */
+		data[i*dim_sizes[1]*dim_sizes[2] + j*dim_sizes[2] + k] =
+		    100*i*dim_sizes[1]*dim_sizes[2] + 10*j*dim_sizes[2] + k;
+		/* permute the array data[X][Y][Z] to transpose[Y][Z][X] */
+		assert((j*dim_sizes[2]*dim_sizes[0] + k*dim_sizes[0] + i) < nitems);
+		transposed_data[j*dim_sizes[2]*dim_sizes[0] + k*dim_sizes[0] + i] = 
+		    100*i*dim_sizes[1]*dim_sizes[2] + 10*j*dim_sizes[2] + k;
+	    }
+	}
+    }
+
+    /* initial array written in i,j,k order  */
+
+    start[0] = start[1] = start[2] = 0;
+    count[0] = dim_sizes[0];
+    count[1] = dim_sizes[1];
+    count[2] = dim_sizes[2];
+    if (rank > 0) nitems = count[0] = count[1] = count[2] = 0;
+    ret = ncmpi_put_vara_all(ncfile, varid1, start, count, data, nitems, MPI_DOUBLE);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    count[0] = dim_sizes[1];
+    count[1] = dim_sizes[2];
+    count[2] = dim_sizes[0];
+    if (rank > 0) nitems = count[0] = count[1] = count[2] = 0;
+    ret = ncmpi_put_vara_all(ncfile, transposed_varid, start, count, 
+	    transposed_data, nitems, MPI_DOUBLE);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* permute ijk (4x5x6) into jki (5x6x4)*/
+    /* new innermost dimension is I items, strided across the old JK face*/
+    MPI_Type_vector(dim_sizes[0], 1, dim_sizes[1]*dim_sizes[2], MPI_DOUBLE, &one_d);
+    /* new middle dimension is K items, strided over the K row, which isn't
+     * actually a stride in this case.  We use hvector here because we 
+     * operate directly in terms of array items */
+    MPI_Type_create_hvector(dim_sizes[2], 1, sizeof(double), one_d, &two_d);
+    /* new outermost dimension is J items, strided over the old J row */
+    MPI_Type_create_hvector(dim_sizes[1], 1, dim_sizes[2]*sizeof(double), two_d, &transposed_type);
+
+    MPI_Type_commit(&transposed_type);
+    MPI_Type_free(&one_d);
+    MPI_Type_free(&two_d);
+
+    nitems = 1;
+    if (rank > 0) nitems = 0;
+    ret = ncmpi_put_vara_all(ncfile, flexible_varid, start, count, 
+	    data, nitems, transposed_type);
+
+    MPI_Type_free(&transposed_type);
+
+    ret = ncmpi_close(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    free(data);
+    free(transposed_data);
+
+    MPI_Finalize();
+    return 0;
+}
+
+/*
+ *vim: ts=8 sts=4 sw=4 noexpandtab */
diff --git a/examples/tutorial/pnetcdf-read-flexible.c b/examples/tutorial/pnetcdf-read-flexible.c
new file mode 100644
index 0000000..7a34695
--- /dev/null
+++ b/examples/tutorial/pnetcdf-read-flexible.c
@@ -0,0 +1,127 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: pnetcdf-read-flexible.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* simple demonstration of pnetcdf 
+ * knowing nothing about the file, read in the variables. 
+ *
+ * This example demonstrates the flexible interface */
+
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <stdio.h>
+
+static void handle_error(int status, int lineno)
+{
+    fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
+    MPI_Abort(MPI_COMM_WORLD, 1);
+}
+
+int main(int argc, char **argv) {
+
+    int i, j, rank, nprocs, ret;
+    int ncfile, ndims, nvars, ngatts, unlimited;
+    int var_ndims, var_natts;;
+    MPI_Offset *dim_sizes, var_size;
+    MPI_Offset *start, *count;
+    char varname[NC_MAX_NAME+1];
+    int dimids[NC_MAX_VAR_DIMS];
+    nc_type type;
+    int *data=NULL;
+
+    MPI_Init(&argc, &argv);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc != 2) {
+        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
+        MPI_Finalize();
+        exit(-1);
+    }
+
+    ret = ncmpi_open(MPI_COMM_WORLD, argv[1], NC_NOWRITE, MPI_INFO_NULL,
+                     &ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* reader knows nothing about dataset, but we can interrogate with query
+     * routines: ncmpi_inq tells us how many of each kind of "thing"
+     * (dimension, variable, attribute) we will find in the file  */
+
+    /* no communication needed after ncmpi_open: all processors have a cached
+     * view of the metadata once ncmpi_open returns */
+
+    ret = ncmpi_inq(ncfile, &ndims, &nvars, &ngatts, &unlimited);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* we do not really need the name of the dimension or the variable for
+     * reading in this example.  we could, in a different example, take the
+     * name of a variable on the command line and read just that one */
+
+    dim_sizes = (MPI_Offset*) calloc(ndims, sizeof(MPI_Offset));
+    /* netcdf dimension identifiers are allocated sequentially starting
+     * at zero; same for variable identifiers */
+    for(i=0; i<ndims; i++)  {
+        ret = ncmpi_inq_dimlen(ncfile, i, &(dim_sizes[i]) );
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+    }
+
+    for(i=0; i<nvars; i++) { 
+        /* much less coordination in this case compared to rank 0 doing all
+         * the i/o: everyone already has the necessary information */
+        ret = ncmpi_inq_var(ncfile, i, varname, &type, &var_ndims, dimids,
+                &var_natts);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        start = (MPI_Offset*) calloc(var_ndims, sizeof(MPI_Offset));
+        count = (MPI_Offset*) calloc(var_ndims, sizeof(MPI_Offset));
+
+        /* we will simply decompose along one dimension.  Generally the
+         * application has some algorithm for domain decomposition.  Note
+         * that data decomposition can have an impact on i/o performance.
+         * Often it's best just to do what is natural for the application,
+         * but something to consider if performance is not what was
+         * expected/desired */
+
+        start[0] = (dim_sizes[dimids[0]]/nprocs)*rank;
+        count[0] = (dim_sizes[dimids[0]]/nprocs);
+        var_size = count[0];
+
+        for (j=1; j<var_ndims; j++) {
+            start[j] = 0;
+            count[j] = dim_sizes[dimids[j]];
+            var_size *= count[j];
+        }
+
+        switch(type) {
+            case NC_INT:
+                data = (int*) calloc(var_size, sizeof(int));
+                ret = ncmpi_get_vara_all(ncfile, i, start, count, data,
+                        var_size, MPI_INT);
+                if (ret != NC_NOERR) handle_error(ret, __LINE__);
+                break;
+            default:
+                /* we can do this for all the known netcdf types but this
+                 * example is already getting too long  */
+                fprintf(stderr, "unsupported NetCDF type \n");
+        }
+
+        free(start);
+        free(count);
+        if (data != NULL) free(data);
+    }
+
+    ret = ncmpi_close(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    MPI_Finalize();
+    return 0;
+}
+
+/*
+ *vim: ts=8 sts=4 sw=4 noexpandtab */
diff --git a/examples/tutorial/pnetcdf-read-from-master.c b/examples/tutorial/pnetcdf-read-from-master.c
new file mode 100644
index 0000000..397cca6
--- /dev/null
+++ b/examples/tutorial/pnetcdf-read-from-master.c
@@ -0,0 +1,159 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: pnetcdf-read-from-master.c 1723 2014-07-06 05:41:41Z wkliao $ */
+
+/* simple demonstration of pnetcdf 
+ * text attribute on dataset
+ * rank 0 reads into 1-d array, broadcasts to all.  This is a dumb way
+ * to do parallel I/O, but folks do this sometimes... */
+
+/* This program reads a file created by pnetcdf-write-from-master.c, say file
+   named output.nc with the following contents, shown by running ncmpidump command .
+
+    % mpiexec -n 4 pnetcdf-read-from-master /orangefs/wkliao/output.nc
+
+    % ncmpidump /orangefs/wkliao/output.nc
+    netcdf output {
+    // file format: CDF-2 (large file)
+    dimensions:
+            d1 = 4 ;
+    variables:
+            int v1(d1) ;
+            int v2(d1) ;
+
+    // global attributes:
+                :string = "Hello World\n",
+        "" ;
+    data:
+
+         v1 = 0, 1, 2, 3 ;
+
+         v2 = 0, 1, 2, 3 ;
+    }
+*/
+
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <stdio.h>
+
+static void handle_error(int status, int lineno)
+{
+    fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
+    MPI_Abort(MPI_COMM_WORLD, 1);
+}
+
+
+int main(int argc, char **argv) {
+
+    int i, j=0, rank, nprocs, ret;
+    int ncfile, ndims, nvars, ngatts, unlimited, var_ndims, var_natts;;
+    int dimids[NC_MAX_VAR_DIMS];
+    char varname[NC_MAX_NAME+1];
+    MPI_Offset *dim_sizes=NULL, var_size;
+    nc_type type;
+    int *data=NULL;
+
+    MPI_Init(&argc, &argv);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc != 2) {
+        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
+        MPI_Finalize();
+        exit(-1);
+    }
+
+    if (rank == 0) {
+        ret = ncmpi_open(MPI_COMM_SELF, argv[1],
+                         NC_NOWRITE, MPI_INFO_NULL, &ncfile);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        /* reader knows nothing about dataset, but we can interrogate with
+         * query routines: ncmpi_inq tells us how many of each kind of
+         * "thing" (dimension, variable, attribute) we will find in the
+         * file  */
+
+        ret = ncmpi_inq(ncfile, &ndims, &nvars, &ngatts, &unlimited);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        /* we do not really need the name of the dimension or the variable
+         * for reading in this example.  we could, in a different example,
+         * take the name of a variable on the command line and read just
+         * that one */
+
+        dim_sizes = (MPI_Offset*) calloc(ndims, sizeof(MPI_Offset));
+        /* netcdf dimension identifiers are allocated sequentially starting
+         * at zero; same for variable identifiers */
+        for(i=0; i<ndims; i++)  {
+            ret = ncmpi_inq_dimlen(ncfile, i, &(dim_sizes[i]) );
+            if (ret != NC_NOERR) handle_error(ret, __LINE__);
+        }
+    }
+
+    /* need to inform other MPI processors how many variables we will send */
+    MPI_Bcast(&nvars, 1, MPI_INT, 0, MPI_COMM_WORLD);
+
+    for(i=0; i<nvars; i++) { 
+        /* rank 0 will find out the size of each variable, read it, and
+         * broadcast it to the rest of the processors */
+        if (rank == 0) {
+            ret = ncmpi_inq_var(ncfile, i, varname, &type, &var_ndims, dimids,
+                    &var_natts);
+            if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+            for (j=0, var_size=1; j<var_ndims; j++)  {
+                var_size *= dim_sizes[dimids[j]];
+            }
+        }
+        /* oddity: there's no predefined MPI_Offset type */
+        MPI_Bcast(&var_size, 1, MPI_OFFSET, 0, MPI_COMM_WORLD);
+
+        data = (int*) calloc(var_size, sizeof(int));
+
+        if (rank == 0) {
+            switch(type) {
+                case NC_INT:
+                    /* now we have the variable identifiers and we know how big
+                     * they are */
+
+                    /* this approach is not scalable: i/o happens from a single
+                     * processor.  This approach can be ok if the amount of
+                     * data is quite small, but almost always the underlying
+                     * MPI-IO library can do a better job */
+
+                    ret = ncmpi_get_var_int_all(ncfile, j, data);
+                    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+                    break;
+                default:
+                    /* we can do this for all the known netcdf types but this
+                     * example is already getting too long  */
+                    fprintf(stderr, "unsupported NetCDF type \n");
+            }
+        }
+
+        /*and finally all processors have the data */
+        MPI_Bcast(data, var_size, MPI_INT, 0, MPI_COMM_WORLD);
+
+        /* Here, every process can do computation on the local buffer, data,
+           or copy the contents to somewhere else */
+
+        free(data);
+    }
+
+    if (rank == 0) {
+        ret = ncmpi_close(ncfile);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
+/*
+ *vim: ts=8 sts=4 sw=4 noexpandtab */
diff --git a/examples/tutorial/pnetcdf-read-nb.c b/examples/tutorial/pnetcdf-read-nb.c
new file mode 100644
index 0000000..d29d82a
--- /dev/null
+++ b/examples/tutorial/pnetcdf-read-nb.c
@@ -0,0 +1,150 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: pnetcdf-read-nb.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* simple demonstration of pnetcdf:
+ * knowing nothing about the file, read in the variables. 
+ *
+ * This example demonstrates the non-blocking read interface */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+static void handle_error(int status, int lineno)
+{
+    fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
+    MPI_Abort(MPI_COMM_WORLD, 1);
+}
+
+int main(int argc, char **argv) {
+
+    int i, j, rank, nprocs, ret;
+    int ncfile, ndims, nvars, ngatts, unlimited, var_ndims, var_natts;;
+    MPI_Offset *dim_sizes, var_size, *start, *count;
+    int *requests, *statuses, dimids[NC_MAX_VAR_DIMS], **data; 
+    char varname[NC_MAX_NAME+1];
+    nc_type type;
+
+    MPI_Init(&argc, &argv);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc != 2) {
+        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
+        MPI_Finalize();
+        exit(-1);
+    }
+
+    ret = ncmpi_open(MPI_COMM_WORLD, argv[1], NC_NOWRITE, MPI_INFO_NULL,
+                     &ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* reader knows nothing about dataset, but we can interrogate with query
+     * routines: ncmpi_inq tells us how many of each kind of "thing"
+     * (dimension, variable, attribute) we will find in the file  */
+
+    /* no communication needed after ncmpi_open: all processors have a cached
+     * view of the metadata once ncmpi_open returns */
+
+    ret = ncmpi_inq(ncfile, &ndims, &nvars, &ngatts, &unlimited);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* we do not really need the name of the dimension or the variable for
+     * reading in this example.  we could, in a different example, take the
+     * name of a variable on the command line and read just that one */
+
+    dim_sizes = (MPI_Offset*) calloc(ndims, sizeof(MPI_Offset));
+    /* netcdf dimension identifiers are allocated sequentially starting
+     * at zero; same for variable identifiers */
+    for(i=0; i<ndims; i++)  {
+        ret = ncmpi_inq_dimlen(ncfile, i, &(dim_sizes[i]) );
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+    }
+
+    requests = (int*) calloc(nvars, sizeof(int));
+    statuses = (int*) calloc(nvars, sizeof(int));
+
+    data = (int**) calloc(nvars, sizeof(int*));
+
+    for(i=0; i<nvars; i++) { 
+        /* much less coordination in this case compared to rank 0 doing all
+         * the i/o: everyone already has the necessary information */
+        ret = ncmpi_inq_var(ncfile, i, varname, &type, &var_ndims, dimids,
+                            &var_natts);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        start = (MPI_Offset*) calloc(var_ndims, sizeof(MPI_Offset));
+        count = (MPI_Offset*) calloc(var_ndims, sizeof(MPI_Offset));
+
+        /* we will simply decompose along one dimension.  Generally the
+         * application has some algorithm for domain decomposition.  Note
+         * that data decomposition can have an impact on i/o performance.
+         * Often it's best just to do what is natural for the application,
+         * but something to consider if performance is not what was
+         * expected/desired */
+
+        start[0] = (dim_sizes[dimids[0]]/nprocs)*rank;
+        count[0] = (dim_sizes[dimids[0]]/nprocs);
+        var_size = count[0];
+
+        for (j=1; j<var_ndims; j++) {
+            start[j] = 0;
+            count[j] = dim_sizes[dimids[j]];
+            var_size *= count[j];
+        }
+
+        switch(type) {
+            case NC_INT:
+                data[i] = (int*) calloc(var_size, sizeof(int));
+                /* as with the writes, this call is independent: we
+                 * will do any coordination (if desired) in a
+                 * subsequent ncmpi_wait_all() call */
+                ret = ncmpi_iget_vara(ncfile, i, start, count, data[i],
+                                      var_size, MPI_INT, &requests[i]);
+                if (ret != NC_NOERR) handle_error(ret, __LINE__);
+                break;
+            default:
+                /* we can do this for all the known netcdf types but this
+                 * example is already getting too long  */
+                fprintf(stderr, "unsupported NetCDF type \n");
+        }
+
+        free(start);
+        free(count);
+    }
+
+    ret = ncmpi_wait_all(ncfile, nvars, requests, statuses);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* check status of each nonblocking call */
+    for (i=0; i<nvars; i++)
+        if (statuses[i] != NC_NOERR) handle_error(statuses[i], __LINE__);
+
+    /* now that the ncmpi_wait_all has returned, the caller can do stuff with
+     * the buffers passed in to the non-blocking operations.  The buffer reuse
+     * rules are similar to MPI non-blocking messages */
+
+    for (i=0; i<nvars; i++) {
+        if (data[i] != NULL) free(data[i]);
+    }
+    free(data);
+    free(dim_sizes);
+    free(requests);
+    free(statuses);
+
+    ret = ncmpi_close(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    MPI_Finalize();
+    return 0;
+}
+
+/*
+ *vim: ts=8 sts=4 sw=4 noexpandtab */
diff --git a/examples/tutorial/pnetcdf-read-nfiles.c b/examples/tutorial/pnetcdf-read-nfiles.c
new file mode 100644
index 0000000..5f9442a
--- /dev/null
+++ b/examples/tutorial/pnetcdf-read-nfiles.c
@@ -0,0 +1,137 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: pnetcdf-read-nfiles.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* simple demonstration of pnetcdf 
+ * text attribute on dataset
+ * rank 0 reads into 1-d array, broadcasts to all.  This is a dumb way
+ * to do parallel I/O but folks do this sometimes...
+ *
+ * This program reads the files generated from its counterpart program 
+ * pnetcdf-write-nfiles.c. See comments in pnetcdf-write-nfiles.c for
+ * the contents of the netCDF files.
+ */
+
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <stdio.h>
+
+static void handle_error(int status, int lineno)
+{
+    fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
+    MPI_Abort(MPI_COMM_WORLD, 1);
+}
+
+#define DSET_NAME_LEN 1024
+
+int main(int argc, char **argv) {
+
+    int i, j, rank, nprocs, ret;
+    int ncfile, ndims, nvars, ngatts, unlimited;
+    int var_ndims, var_natts;;
+    MPI_Offset *dim_sizes, var_size;
+    MPI_Offset *count;
+    char filename[DSET_NAME_LEN];
+    char varname[NC_MAX_NAME+1];
+    int dimids[NC_MAX_VAR_DIMS];
+    nc_type type;
+    int *data=NULL;
+
+    MPI_Init(&argc, &argv);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc != 2) {
+        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
+        MPI_Finalize();
+        exit(-1);
+    }
+
+    /* the most significant challenge with the "one file per processor"
+     * approach is the challenge in reading back on a different number of
+     * processors.  For example, 4k processors output data during a simulation.
+     * Later on, 100 processors do analysis or visualization of the data.
+     * Stitching together the many smaller files into a form usable by other
+     * programs poses a challenge */
+
+    ret = snprintf(filename, DSET_NAME_LEN, "%s.%d-%d.nc", argv[1], rank, nprocs);
+    if (ret >= DSET_NAME_LEN) {
+        fprintf(stderr, "name too long \n");
+        exit(-1);
+    }
+    ret = ncmpi_open(MPI_COMM_SELF, filename, NC_NOWRITE, MPI_INFO_NULL, &ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* reader knows nothing about dataset, but we can interrogate with query
+     * routines: ncmpi_inq tells us how many of each kind of "thing"
+     * (dimension, variable, attribute) we will find in the file  */
+
+    /* In the "one file per processor case" all processors open a file and
+     * interrogate it */
+
+    ret = ncmpi_inq(ncfile, &ndims, &nvars, &ngatts, &unlimited);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* we do not really need the name of the dimension or the variable for
+     * reading in this example.  we could, in a different example, take the
+     * name of a variable on the command line and read just that one */
+
+    dim_sizes = (MPI_Offset*) calloc(ndims, sizeof(MPI_Offset));
+    /* netcdf dimension identifiers are allocated sequentially starting
+     * at zero; same for variable identifiers */
+    for (i=0; i<ndims; i++)  {
+        ret = ncmpi_inq_dimlen(ncfile, i, &(dim_sizes[i]) );
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+    }
+
+    for (i=0; i<nvars; i++) { 
+        /* much less coordination in this case compared to rank 0 doing all
+         * the i/o: everyone already has the necessary information */
+        ret = ncmpi_inq_var(ncfile, i, varname, &type, &var_ndims, dimids,
+                            &var_natts);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        count = (MPI_Offset*) calloc(var_ndims, sizeof(MPI_Offset));
+
+        /* as long as the number of readers is identical to the number of
+         * writers, we can simply read entire variables back */
+
+        count[0] = dim_sizes[dimids[0]];
+
+        var_size = count[0];
+        for (j=1; j<var_ndims; j++) {
+            count[j] = dim_sizes[dimids[j]];
+            var_size *= count[j];
+        }
+
+        switch(type) {
+            case NC_INT:
+                data = (int*) calloc(var_size, sizeof(int));
+                ret = ncmpi_get_var_int_all(ncfile, i, data);
+                if (ret != NC_NOERR) handle_error(ret, __LINE__);
+                break;
+            default:
+                /* we can do this for all the known netcdf types but this
+                 * example is already getting too long  */
+                fprintf(stderr, "unsupported NetCDF type \n");
+        }
+
+        free(count);
+        if (data != NULL) free(data);
+    }
+
+    ret = ncmpi_close(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    MPI_Finalize();
+    return 0;
+}
+
+/*
+ *vim: ts=8 sts=4 sw=4 noexpandtab */
diff --git a/examples/tutorial/pnetcdf-read-standard.c b/examples/tutorial/pnetcdf-read-standard.c
new file mode 100644
index 0000000..952ddab
--- /dev/null
+++ b/examples/tutorial/pnetcdf-read-standard.c
@@ -0,0 +1,126 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: pnetcdf-read-standard.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* simple demonstration of pnetcdf:
+ * knowing nothing about the file, read in the variables. 
+ *
+ * This example demonstrates the standard read interface */
+
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <stdio.h>
+
+static void handle_error(int status, int lineno)
+{
+    fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
+    MPI_Abort(MPI_COMM_WORLD, 1);
+}
+
+int main(int argc, char **argv) {
+
+    int i, j, rank, nprocs, ret;
+    int ncfile, ndims, nvars, ngatts, unlimited;
+    int var_ndims, var_natts;;
+    MPI_Offset *dim_sizes, var_size;
+    MPI_Offset *start, *count;
+    char varname[NC_MAX_NAME+1];
+    int dimids[NC_MAX_VAR_DIMS];
+    nc_type type;
+    int *data=NULL;
+
+    MPI_Init(&argc, &argv);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc != 2) {
+        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
+        MPI_Finalize();
+        exit(-1);
+    }
+
+    ret = ncmpi_open(MPI_COMM_WORLD, argv[1], NC_NOWRITE, MPI_INFO_NULL,
+                     &ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* reader knows nothing about dataset, but we can interrogate with query
+     * routines: ncmpi_inq tells us how many of each kind of "thing"
+     * (dimension, variable, attribute) we will find in the file  */
+
+    /* no communication needed after ncmpi_open: all processors have a cached
+     * view of the metadata once ncmpi_open returns */
+
+    ret = ncmpi_inq(ncfile, &ndims, &nvars, &ngatts, &unlimited);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* we do not really need the name of the dimension or the variable for
+     * reading in this example.  we could, in a different example, take the
+     * name of a variable on the command line and read just that one */
+
+    dim_sizes = (MPI_Offset*) calloc(ndims, sizeof(MPI_Offset));
+    /* netcdf dimension identifiers are allocated sequentially starting
+     * at zero; same for variable identifiers */
+    for(i=0; i<ndims; i++)  {
+        ret = ncmpi_inq_dimlen(ncfile, i, &(dim_sizes[i]) );
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+    }
+
+    for(i=0; i<nvars; i++) { 
+        /* much less coordination in this case compared to rank 0 doing all
+         * the i/o: everyone already has the necessary information */
+        ret = ncmpi_inq_var(ncfile, i, varname, &type, &var_ndims, dimids,
+                &var_natts);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        start = (MPI_Offset*) calloc(var_ndims, sizeof(MPI_Offset));
+        count = (MPI_Offset*) calloc(var_ndims, sizeof(MPI_Offset));
+
+        /* we will simply decompose along one dimension.  Generally the
+         * application has some algorithm for domain decomposition.  Note
+         * that data decomposition can have an impact on i/o performance.
+         * Often it's best just to do what is natural for the application,
+         * but something to consider if performance is not what was
+         * expected/desired */
+
+        start[0] = (dim_sizes[dimids[0]]/nprocs)*rank;
+        count[0] = (dim_sizes[dimids[0]]/nprocs);
+        var_size = count[0];
+
+        for (j=1; j<var_ndims; j++) {
+            start[j] = 0;
+            count[j] = dim_sizes[dimids[j]];
+            var_size *= count[j];
+        }
+
+        switch(type) {
+            case NC_INT:
+                data = (int*) calloc(var_size, sizeof(int));
+                ret = ncmpi_get_vara_int_all(ncfile, i, start, count, data);
+                if (ret != NC_NOERR) handle_error(ret, __LINE__);
+                break;
+            default:
+                /* we can do this for all the known netcdf types but this
+                 * example is already getting too long  */
+                fprintf(stderr, "unsupported NetCDF type \n");
+        }
+
+        free(start);
+        free(count);
+        if (data != NULL) free(data);
+    }
+
+    ret = ncmpi_close(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    MPI_Finalize();
+    return 0;
+}
+
+/*
+ *vim: ts=8 sts=4 sw=4 noexpandtab */
diff --git a/examples/tutorial/pnetcdf-write-buffered.c b/examples/tutorial/pnetcdf-write-buffered.c
new file mode 100644
index 0000000..cdc0b87
--- /dev/null
+++ b/examples/tutorial/pnetcdf-write-buffered.c
@@ -0,0 +1,129 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: pnetcdf-write-buffered.c 1153 2013-02-03 17:45:55Z wkliao $ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#define ERRCODE 2
+#define ERR(e) {printf("Error at line %d: err=%d %s\n", __LINE__, e, ncmpi_strerror(e)); exit(ERRCODE);}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv) {
+    int i, j, ncid, dimid[2], varid, err, rank, nprocs, cmode;
+    int req[2], status[2]; 
+    float  var[4][6];
+    MPI_Offset start[2], count[2], stride[2], imap[2];
+    MPI_Offset bufsize;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc != 2) {
+        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
+        MPI_Finalize();
+        exit(-1);
+    }
+
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    if (NC_NOERR != (err = ncmpi_create(MPI_COMM_WORLD, argv[1],
+                                        cmode, MPI_INFO_NULL, &ncid)))
+       ERR(err);
+
+    /* define a variable of a 6 x (4*nprocs) int64 array in the nc file */
+    if (NC_NOERR != (err = ncmpi_def_dim(ncid, "Y", 6, &dimid[0])))
+        ERR(err);
+    if (NC_NOERR != (err = ncmpi_def_dim(ncid, "X", 4*nprocs, &dimid[1])))
+        ERR(err);
+    if (NC_NOERR != (err = ncmpi_def_var(ncid, "var", NC_INT64, 2, dimid,
+                                         &varid)))
+        ERR(err);
+    if (NC_NOERR != (err = ncmpi_enddef(ncid)))
+        ERR(err);
+
+    /* set the contents of the local write buffer var, a 4 x 6 float array
+       for example, for rank == 2, var[4][6] =
+          48, 49, 50, 51, 52, 53,
+          54, 55, 56, 57, 58, 59,
+          60, 61, 62, 63, 64, 65,
+          66, 67, 68, 69, 70, 71
+     */
+    for (j=0; j<4; j++)
+        for (i=0; i<6; i++)
+            var[j][i] = j*6+i + rank*24;
+
+    /* bufsize must be the max of data type converted before and after */
+    bufsize = 4*6*sizeof(long long);  /* as var is of NC_INT64 */
+    if (NC_NOERR != (err = ncmpi_buffer_attach(ncid, bufsize)))
+        ERR(err);
+
+    /* write var to the NC variable in the matrix transposed way */
+    count[0]  = 6; count[1]  = 2;
+    stride[0] = 1; stride[1] = 1;
+    imap[0]   = 1; imap[1]   = 6;
+
+    /* write to the 1st two columns of the variable in matrix transposed way */
+    start[0]  = 0;
+    start[1]  = rank*4;
+    if (NC_NOERR != (err = ncmpi_bput_varm_float(ncid, varid, start, count,
+                                           stride, imap, &var[0][0], &req[0])))
+        ERR(err);
+
+    /* write to the 2nd two columns of the variable in transposed way */
+    start[0]  = 0;
+    start[1]  = rank*4+2;
+    if (NC_NOERR != (err = ncmpi_bput_varm_float(ncid, varid, start, count,
+                                           stride, imap, &var[2][0], &req[1])))
+        ERR(err);
+
+    /* You are now free to change contents of the buffer, var.
+       It will not change the data supposed to be written in the file.
+     */
+    for (j=0; j<4; j++)
+        for (i=0; i<6; i++)
+            var[j][i] = -1.1;  /* or any numbers */
+
+    if (NC_NOERR != (err = ncmpi_wait_all(ncid, 2, req, status)))
+        ERR(err);
+
+    /* check each bput status */
+    for (i=0; i<2; i++)
+        if (status[i] != NC_NOERR) ERR(status[i]);
+
+    if (NC_NOERR != (err = ncmpi_buffer_detach(ncid)))
+        ERR(err);
+
+    if (NC_NOERR != (err = ncmpi_close(ncid))) ERR(err);
+
+    /* The output from command "ncmpidump test.nc" is shown below if run
+       this example on 4 processes.
+
+       netcdf test {
+       // file format: CDF-5 (big variables)
+       dimensions:
+              Y = 6 ;
+              X = 16 ;
+       variables:
+              int64 var(Y, X) ;
+      data:
+
+       var =
+        0,  6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90,
+        1,  7, 13, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 79, 85, 91,
+        2,  8, 14, 20, 26, 32, 38, 44, 50, 56, 62, 68, 74, 80, 86, 92,
+        3,  9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, 87, 93,
+        4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 76, 82, 88, 94,
+        5, 11, 17, 23, 29, 35, 41, 47, 53, 59, 65, 71, 77, 83, 89, 95 ;
+        <---- P0 ---->|<---- P1 ----->|<---- P2 ----->|<---- P3 ---->
+     */
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/examples/tutorial/pnetcdf-write-bufferedf.f90 b/examples/tutorial/pnetcdf-write-bufferedf.f90
new file mode 100644
index 0000000..8540ecb
--- /dev/null
+++ b/examples/tutorial/pnetcdf-write-bufferedf.f90
@@ -0,0 +1,147 @@
+!
+!   Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: pnetcdf-write-bufferedf.f90 2245 2015-12-20 18:39:52Z wkliao $
+
+      program main
+
+      use mpi
+      use pnetcdf
+      implicit none
+
+      integer i, j, ncid, varid, cmode, err, rank, nprocs
+      integer dimid(2), req(2), status(2)
+      integer(kind=MPI_OFFSET_KIND) start(2)
+      integer(kind=MPI_OFFSET_KIND) count(2)
+      integer(kind=MPI_OFFSET_KIND) stride(2)
+      integer(kind=MPI_OFFSET_KIND) imap(2)
+      integer(kind=MPI_OFFSET_KIND) bufsize
+      integer(kind=MPI_OFFSET_KIND) put_size
+      real  var(6,4)
+      character(len=256) filename
+
+      call MPI_INIT(err)
+      call MPI_COMM_RANK(MPI_COMM_WORLD, rank, err)
+      call MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, err)
+
+      filename = "testfile.nc"
+      cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+      err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                         MPI_INFO_NULL, ncid)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_create ', &
+                                   nf90mpi_strerror(err)
+
+      ! define a variable of a (4*nprocs) x 6 integer array in the nc file
+      err = nf90mpi_def_dim(ncid, 'X', 4_MPI_OFFSET_KIND*nprocs, dimid(1))
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_def_dim ', &
+                                   nf90mpi_strerror(err)
+
+      err = nf90mpi_def_dim(ncid, 'Y', 6_MPI_OFFSET_KIND, dimid(2))
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_def_dim ', &
+                                   nf90mpi_strerror(err)
+
+      err = nf90mpi_def_var(ncid, 'var', NF90_INT64, dimid, varid)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_def_var ', &
+                                   nf90mpi_strerror(err)
+
+      err = nf90mpi_enddef(ncid)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_enddef ', &
+                                   nf90mpi_strerror(err)
+
+      ! set the contents of the local write buffer var, a 4 x 6 real array
+      ! for example, for rank == 2, var(4,6) =
+      !     48, 54, 60, 65,
+      !     49, 55, 61, 67,
+      !     50, 56, 62, 68,
+      !     51, 57, 63, 69,
+      !     52, 58, 64, 70,
+      !     53, 59, 65, 71
+      do j = 1, 4
+         do i = 1, 6
+            var(i,j) = (j-1)*6+(i-1) + rank*24
+         enddo
+      enddo
+
+      ! bufsize must be max of data type converted before and after
+      bufsize = 4*6*8
+      err = nf90mpi_buffer_attach(ncid, bufsize)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_buffer_attach ', &
+                                   nf90mpi_strerror(err)
+
+      ! write var to the NC variable in the matrix transposed way
+      count(1)  = 2
+      count(2)  = 6
+      stride(1) = 1
+      stride(2) = 1
+      imap(1)   = 6
+      imap(2)   = 1
+
+      req(:) = NF90_REQ_NULL  ! actually not necessary, added for testing
+
+      ! write to the 1st two columns of the variable in matrix transposed way
+      start(1)  = 1 + rank*4
+      start(2)  = 1
+      err = nf90mpi_bput_var(ncid, varid, var(1:,1:), req(1), &
+                             start, count, stride, imap)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_bput_varm_real ', &
+                                   nf90mpi_strerror(err)
+
+      ! write to the 2nd two columns of the variable in transposed way
+      start(1)  = 3 + rank*4
+      start(2)  = 1
+      err = nf90mpi_bput_var(ncid, varid, var(1:,3:), req(2), &
+                             start, count, stride, imap)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_bput_varm_real ', &
+                                   nf90mpi_strerror(err)
+
+      err = nf90mpi_wait_all(ncid, 2, req, status)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_wait_all ', &
+                                   nf90mpi_strerror(err)
+
+      ! check each bput status
+      do i = 1, 2
+          if (status(i) .ne. NF90_NOERR) then
+              print*,'Error at bput status ', &
+                     nf90mpi_strerror(status(i))
+          endif
+      enddo
+
+      err = nf90mpi_buffer_detach(ncid)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_buffer_detach ', &
+                                   nf90mpi_strerror(err)
+
+      ! The output from command "ncmpidump test.nc" is shown below if run
+      ! this example on 4 processes.
+      !
+      ! netcdf test {
+      ! // file format: CDF-5 (big variables)
+      ! dimensions:
+      !        Y = 6 ;
+      !        X = 16 ;
+      ! variables:
+      !        int64 var(Y, X) ;
+      !data:
+      !
+      ! var =
+      !  0,  6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90,
+      !  1,  7, 13, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 79, 85, 91,
+      !  2,  8, 14, 20, 26, 32, 38, 44, 50, 56, 62, 68, 74, 80, 86, 92,
+      !  3,  9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, 87, 93,
+      !  4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 76, 82, 88, 94,
+      !  5, 11, 17, 23, 29, 35, 41, 47, 53, 59, 65, 71, 77, 83, 89, 95 ;
+      !
+      ! note that the display of ncmpidump is in C array dimensional order
+
+      err = nf90mpi_inq_put_size(ncid, put_size)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_inq_put_size ', &
+                                   nf90mpi_strerror(err)
+      ! print*,'pnetcdf reports total put size by this proc =', put_size
+
+      err = nf90mpi_close(ncid)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_close ', &
+                                   nf90mpi_strerror(err)
+
+      CALL MPI_Finalize(err)
+      end program
+
diff --git a/examples/tutorial/pnetcdf-write-bufferedf77.f b/examples/tutorial/pnetcdf-write-bufferedf77.f
new file mode 100644
index 0000000..6b12b0e
--- /dev/null
+++ b/examples/tutorial/pnetcdf-write-bufferedf77.f
@@ -0,0 +1,149 @@
+!
+!   Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: pnetcdf-write-bufferedf77.f 2245 2015-12-20 18:39:52Z wkliao $
+
+      program main
+
+      implicit none
+      include "mpif.h"
+      include "pnetcdf.inc"
+
+      integer i, j, ncid, varid, cmode, err, rank, nprocs
+      integer dimid(2), req(2), status(2)
+      integer*8 start(2)
+      integer*8 count(2)
+      integer*8 stride(2)
+      integer*8 imap(2)
+      integer*8 bufsize
+      integer*8 put_size, dim_size
+      real  var(6,4)
+      character*256 filename
+
+      call MPI_INIT(err)
+      call MPI_COMM_RANK(MPI_COMM_WORLD, rank, err)
+      call MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, err)
+
+      filename = "testfile.nc"
+      cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+      err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                   MPI_INFO_NULL, ncid)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_create ',
+     +                           nfmpi_strerror(err)
+
+      ! define a variable of a (4*nprocs) x 6 integer array in the nc file
+      dim_size = 4
+      err = nfmpi_def_dim(ncid, 'X', dim_size*nprocs, dimid(1))
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_def_dim ',
+     +                           nfmpi_strerror(err)
+
+      dim_size = 6
+      err = nfmpi_def_dim(ncid, 'Y', dim_size, dimid(2))
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_def_dim ',
+     +                           nfmpi_strerror(err)
+
+      err = nfmpi_def_var(ncid, 'var', NF_INT64, 2, dimid, varid)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_def_var ',
+     +                           nfmpi_strerror(err)
+
+      err = nfmpi_enddef(ncid)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_enddef ',
+     +                           nfmpi_strerror(err)
+
+      ! set the contents of the local write buffer var, a 4 x 6 real array
+      ! for example, for rank == 2, var(4,6) =
+      !     48, 54, 60, 65,
+      !     49, 55, 61, 67,
+      !     50, 56, 62, 68,
+      !     51, 57, 63, 69,
+      !     52, 58, 64, 70,
+      !     53, 59, 65, 71
+      do j = 1, 4
+         do i = 1, 6
+            var(i,j) = (j-1)*6+(i-1) + rank*24
+         enddo
+      enddo
+
+      ! bufsize must be max of data type converted before and after
+      bufsize = 4*6*8
+      err = nfmpi_buffer_attach(ncid, bufsize)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_buffer_attach ',
+     +                           nfmpi_strerror(err)
+
+      ! write var to the NC variable in the matrix transposed way
+      count(1)  = 2
+      count(2)  = 6
+      stride(1) = 1
+      stride(2) = 1
+      imap(1)   = 6
+      imap(2)   = 1
+
+      req(1) = NF_REQ_NULL  ! actually not necessary, added for testing
+      req(2) = NF_REQ_NULL  ! actually not necessary, added for testing
+
+      ! write to the 1st two columns of the variable in matrix transposed way
+      start(1)  = 1 + rank*4
+      start(2)  = 1
+      err = nfmpi_bput_varm_real(ncid, varid, start, count, stride,
+     +                           imap, var(1,1), req(1))
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_bput_varm_real ',
+     +                           nfmpi_strerror(err)
+
+      ! write to the 2nd two columns of the variable in transposed way
+      start(1)  = 3 + rank*4
+      start(2)  = 1
+      err = nfmpi_bput_varm_real(ncid, varid, start, count, stride,
+     +                           imap, var(1,3), req(2))
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_bput_varm_real ',
+     +                           nfmpi_strerror(err)
+
+      err = nfmpi_wait_all(ncid, 2, req, status)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_wait_all ',
+     +                           nfmpi_strerror(err)
+
+      ! check each bput status
+      do i = 1, 2
+          if (status(i) .ne. NF_NOERR) then
+              print*,'Error at bput status ', nfmpi_strerror(status(i))
+          endif
+      enddo
+
+      err = nfmpi_buffer_detach(ncid)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_buffer_detach ',
+     +                           nfmpi_strerror(err)
+
+      ! The output from command "ncmpidump test.nc" is shown below if run
+      ! this example on 4 processes.
+      !
+      ! netcdf test {
+      ! // file format: CDF-5 (big variables)
+      ! dimensions:
+      !        Y = 6 ;
+      !        X = 16 ;
+      ! variables:
+      !        int64 var(Y, X) ;
+      !data:
+      !
+      ! var =
+      !  0,  6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90,
+      !  1,  7, 13, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 79, 85, 91,
+      !  2,  8, 14, 20, 26, 32, 38, 44, 50, 56, 62, 68, 74, 80, 86, 92,
+      !  3,  9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, 87, 93,
+      !  4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 76, 82, 88, 94,
+      !  5, 11, 17, 23, 29, 35, 41, 47, 53, 59, 65, 71, 77, 83, 89, 95 ;
+      !
+      ! note that the display of ncmpidump is in C array dimensional order
+
+      err = nfmpi_inq_put_size(ncid, put_size)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_inq_put_size ',
+     +                           nfmpi_strerror(err)
+      ! print*,'pnetcdf reports total put size by this proc =', put_size
+
+      err = nfmpi_close(ncid)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_close ',
+     +                           nfmpi_strerror(err)
+
+      CALL MPI_Finalize(err)
+      end ! program
+
diff --git a/examples/tutorial/pnetcdf-write-flexible.c b/examples/tutorial/pnetcdf-write-flexible.c
new file mode 100644
index 0000000..23bf02d
--- /dev/null
+++ b/examples/tutorial/pnetcdf-write-flexible.c
@@ -0,0 +1,111 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: pnetcdf-write-flexible.c 1123 2013-01-26 17:35:03Z wkliao $ */
+
+/* simple demonstration of pnetcdf 
+ * text attribute on dataset
+ * write out rank into 1-d array collectively.
+ * This example demonstrates the flexible interface */
+
+/* This program creates a file, say named output.nc, with the following
+   contents, shown by running ncmpidump command .
+
+    % mpiexec -n 4 pnetcdf-write-flexible /orangefs/wkliao/output.nc
+
+    % ncmpidump /orangefs/wkliao/output.nc
+    netcdf output {
+    // file format: CDF-2 (large file)
+    dimensions:
+            d1 = 4 ;
+    variables:
+            int v1(d1) ;
+            int v2(d1) ;
+
+    // global attributes:
+                :string = "Hello World\n",
+        "" ;
+    data:
+
+         v1 = 0, 1, 2, 3 ;
+
+         v2 = 0, 1, 2, 3 ;
+    }
+*/
+
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <stdio.h>
+
+static void handle_error(int status, int lineno)
+{
+    fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
+    MPI_Abort(MPI_COMM_WORLD, 1);
+}
+
+int main(int argc, char **argv) {
+
+    int ret, ncfile, nprocs, rank, dimid, varid1, varid2, ndims=1;
+    MPI_Offset start, count=1;
+    char buf[13] = "Hello World\n";
+    int data;
+
+    MPI_Init(&argc, &argv);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc != 2) {
+        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
+        MPI_Finalize();
+        exit(-1);
+    }
+
+    ret = ncmpi_create(MPI_COMM_WORLD, argv[1],
+                       NC_CLOBBER|NC_64BIT_OFFSET, MPI_INFO_NULL, &ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_dim(ncfile, "d1", nprocs, &dimid);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_var(ncfile, "v1", NC_INT, ndims, &dimid, &varid1);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_var(ncfile, "v2", NC_INT, ndims, &dimid, &varid2);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_put_att_text(ncfile, NC_GLOBAL, "string", 13, buf);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* all processors defined the dimensions, attributes, and variables,
+     * but here in ncmpi_enddef is the one place where metadata I/O
+     * happens.  Behind the scenes, rank 0 takes the information and writes
+     * the netcdf header.  All processes communicate to ensure they have
+     * the same (cached) view of the dataset */
+
+    ret = ncmpi_enddef(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    start=rank, count=1, data=rank;
+
+    /* in this simple example every process writes its rank to two 1d variables */
+    /* we used a basic MPI_INT type to this flexible mode call, but could
+     * have used any derived MPI datatype that describes application data
+     * structures */
+    ret = ncmpi_put_vara_all(ncfile, varid1, &start, &count, &data, count, MPI_INT);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_put_vara_all(ncfile, varid2, &start, &count, &data, count, MPI_INT);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_close(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    MPI_Finalize();
+
+    return 0;
+}
diff --git a/examples/tutorial/pnetcdf-write-from-master.c b/examples/tutorial/pnetcdf-write-from-master.c
new file mode 100644
index 0000000..d4add24
--- /dev/null
+++ b/examples/tutorial/pnetcdf-write-from-master.c
@@ -0,0 +1,117 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: pnetcdf-write-from-master.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* simple demonstration of pnetcdf 
+ * text attribute on dataset
+ * write out rank into 1-d array after sending to rank 0.  This is a dumb way
+ * to do parallel I/O, but folks do this sometimes... */
+
+/* This program creates a file, say named output.nc, with the following
+   contents, shown by running ncmpidump command .
+
+    % mpiexec -n 4 pnetcdf-write-from-master /orangefs/wkliao/output.nc
+
+    % ncmpidump /orangefs/wkliao/output.nc
+    netcdf output {
+    // file format: CDF-2 (large file)
+    dimensions:
+            d1 = 4 ;
+    variables:
+            int v1(d1) ;
+            int v2(d1) ;
+
+    // global attributes:
+                :string = "Hello World\n",
+        "" ;
+    data:
+
+         v1 = 0, 1, 2, 3 ;
+
+         v2 = 0, 1, 2, 3 ;
+    }
+*/
+
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <stdio.h>
+
+static void handle_error(int status, int lineno)
+{
+    fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
+    MPI_Abort(MPI_COMM_WORLD, 1);
+}
+
+int main(int argc, char **argv) {
+    int ret, ncfile, nprocs, rank, dimid, varid1, varid2, ndims=1;
+    MPI_Offset start, count=1;
+    char buf[13] = "Hello World\n";
+    int *data=NULL;
+
+    MPI_Init(&argc, &argv);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc != 2) {
+        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
+        MPI_Finalize();
+        exit(-1);
+    }
+
+    if (rank == 0) {
+        ret = ncmpi_create(MPI_COMM_SELF, argv[1],
+                           NC_CLOBBER|NC_64BIT_OFFSET, MPI_INFO_NULL, &ncfile);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        ret = ncmpi_def_dim(ncfile, "d1", nprocs, &dimid);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        ret = ncmpi_def_var(ncfile, "v1", NC_INT, ndims, &dimid, &varid1);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        ret = ncmpi_def_var(ncfile, "v2", NC_INT, ndims, &dimid, &varid2);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        ret = ncmpi_put_att_text(ncfile, NC_GLOBAL, "string", 13, buf);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+        
+        ret = ncmpi_enddef(ncfile);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        /* first reason this approach is not scalable:  need to allocate
+        * enough memory to hold data from all processors */
+        data = (int*)calloc(nprocs, sizeof(int));
+    }
+
+    /* second reason this approach is not scalable: sending to rank 0
+     * introduces a serialization point, even if using an optimized
+     * collective routine */
+    MPI_Gather(&rank, 1, MPI_INT, data, 1, MPI_INT, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        /* and lastly, the third reason this approach is not scalable: I/O
+         * happens from a single processor.  This approach can be ok if the
+         * amount of data is quite small, but almost always the underlying
+         * MPI-IO library can do a better job */
+        start=0, count=nprocs;
+        ret = ncmpi_put_vara_int_all(ncfile, varid1, &start, &count, data);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        ret = ncmpi_put_vara_int_all(ncfile, varid2, &start, &count, data);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        ret = ncmpi_close(ncfile);
+        if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+        free(data);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/examples/tutorial/pnetcdf-write-nb.c b/examples/tutorial/pnetcdf-write-nb.c
new file mode 100644
index 0000000..c0dc3ef
--- /dev/null
+++ b/examples/tutorial/pnetcdf-write-nb.c
@@ -0,0 +1,126 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: pnetcdf-write-nb.c 2095 2015-09-07 21:15:24Z wkliao $ */
+
+/* simple demonstration of pnetcdf 
+ * text attribute on dataset
+ * write out rank into 1-d array collectively.
+ * This example demonstrates the non-blocking write interface */
+
+/* This program creates a file, say named output.nc, with the following
+   contents, shown by running ncmpidump command .
+
+    % mpiexec -n 4 pnetcdf-write-nb /orangefs/wkliao/output.nc
+
+    % ncmpidump /orangefs/wkliao/output.nc 
+    netcdf output {
+    // file format: CDF-2 (large file)
+    dimensions:
+            d1 = 4 ;
+    variables:
+            int v1(d1) ;
+            int v2(d1) ;
+
+    // global attributes:
+                :string = "Hello World\n",
+        "" ;
+    data:
+
+         v1 = 0, 1, 2, 3 ;
+
+         v2 = 0, 1, 2, 3 ;
+    }
+*/
+
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <stdio.h>
+
+static void handle_error(int status, int lineno)
+{
+    fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
+    MPI_Abort(MPI_COMM_WORLD, 1);
+}
+
+int main(int argc, char **argv) {
+
+    int ret, ncfile, nprocs, rank, dimid, varid1, varid2, ndims=1;
+    MPI_Offset start, count=1;
+    char buf[13] = "Hello World\n";
+    int data1, data2;
+    int requests[2], statuses[2];
+
+    MPI_Init(&argc, &argv);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc != 2) {
+        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
+        MPI_Finalize();
+        exit(-1);
+    }
+
+    ret = ncmpi_create(MPI_COMM_WORLD, argv[1],
+                       NC_CLOBBER|NC_64BIT_OFFSET, MPI_INFO_NULL, &ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_dim(ncfile, "d1", nprocs, &dimid);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_var(ncfile, "v1", NC_INT, ndims, &dimid, &varid1);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_var(ncfile, "v2", NC_INT, ndims, &dimid, &varid2);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_put_att_text(ncfile, NC_GLOBAL, "string", 13, buf);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* all processors defined the dimensions, attributes, and variables,
+     * but here in ncmpi_enddef is the one place where metadata I/O
+     * happens.  Behind the scenes, rank 0 takes the information and writes
+     * the netcdf header.  All processes communicate to ensure they have
+     * the same (cached) view of the dataset */
+
+    ret = ncmpi_enddef(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    start=rank, count=1, data1=rank, data2=rank;
+
+    /* in this simple example every process writes its rank to two 1d variables */
+
+    /* we used a basic MPI_INT type to this flexible mode call, but could
+     * have used any derived MPI datatype that describes application data
+     * structures */
+
+    /* furthermore, we use the non-blocking interface to essentially
+     * schedule the two write operations.  No i/o actually happens here,
+     * which is why these routines do not need to be collective.   */
+    ret = ncmpi_iput_vara(ncfile, varid1, &start, &count, &data1, count,
+            MPI_INT, &requests[0]);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_iput_vara(ncfile, varid2, &start, &count, &data2, count, 
+            MPI_INT, &requests[1]);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_wait_all(ncfile, 2, requests, statuses);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* check status of each nonblocking call */
+    if (statuses[0] != NC_NOERR) handle_error(statuses[0], __LINE__);
+    if (statuses[1] != NC_NOERR) handle_error(statuses[1], __LINE__);
+
+    ret = ncmpi_close(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    MPI_Finalize();
+
+    return 0;
+}
diff --git a/examples/tutorial/pnetcdf-write-nfiles.c b/examples/tutorial/pnetcdf-write-nfiles.c
new file mode 100644
index 0000000..790cd5f
--- /dev/null
+++ b/examples/tutorial/pnetcdf-write-nfiles.c
@@ -0,0 +1,218 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: pnetcdf-write-nfiles.c 2245 2015-12-20 18:39:52Z wkliao $ */
+
+/* simple demonstration of pnetcdf 
+ * text attribute on dataset
+ * Each process writes out rank into 1-d array to a separate file.
+ * This is not a good way to do parallel I/O */
+
+/*
+To run on 4 processes for example,
+% mpiexec -l -n 4 pnetcdf-write-nfiles output.nc
+
+There will be 4+1 files created.
+    output.nc
+    output.nc.0-4.nc
+    output.nc.1-4.nc
+    output.nc.2-4.nc 
+    output.nc.3-4.nc  
+
+The contents of files are shown at the bottom of this files.
+*/
+
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <stdio.h>
+
+
+static void handle_error(int status, int lineno)
+{
+    fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
+    MPI_Abort(MPI_COMM_WORLD, 1);
+}
+
+#define DSET_NAME_LEN 1024
+
+int main(int argc, char **argv) {
+
+    int ret, ncfile, nprocs, rank, dimid, varid1, varid2, ndims=1;
+    char buf[13] = "Hello World\n";
+    int data;
+    char filename[DSET_NAME_LEN];
+
+    MPI_Init(&argc, &argv);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc != 2) {
+        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
+        MPI_Finalize();
+        exit(-1);
+    }
+
+    /* Many applications find "one file per process" easy, but there are
+     * several deficiencies with that approach:
+     * - here we need to construct a unique file name for each processor */
+    ret = snprintf(filename, DSET_NAME_LEN, "%s.%d-%d.nc", argv[1], rank, nprocs);
+    if (ret >= DSET_NAME_LEN) {
+        fprintf(stderr, "name too long \n");
+        exit(-1);
+    }
+
+    /* note that the communicator is still needed but now it is
+     * MPI_COMM_SELF: since each processor opens its own file we cannot use
+     * MPI_COMM_WORLD */
+    ret = ncmpi_create(MPI_COMM_SELF, filename,
+                       NC_CLOBBER|NC_64BIT_OFFSET, MPI_INFO_NULL, &ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* each processor writes its data to a file, so instead of an "nprocs"
+     * sized array, we just have an array big enough to hold one
+     * processor's data */
+    ret = ncmpi_def_dim(ncfile, "d1", 1, &dimid);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_var(ncfile, "v1", NC_INT, ndims, &dimid, &varid1);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_var(ncfile, "v2", NC_INT, ndims, &dimid, &varid2);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_put_att_text(ncfile, NC_GLOBAL, "string", 13, buf);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* ncmpi_enddef writes the header out as in other examples, but because
+     * each processor opened the file independently, there can be no "write
+     * and broadcast" optimization.  Instead, every processor does header
+     * i/o.  */        
+    ret = ncmpi_enddef(ncfile); if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* the one advantage to this approach: data decomposition is easy the
+     * application does not need to worry about the shape and location of
+     * the data (the 'start' and 'count' parameters in the 'vara' family of
+     * functions) and can instead just write the entire (small) variable */
+
+    data=rank;
+
+    /* in this simple example every process writes its rank to two 1d
+     * variables */
+    /* When each processor writes to its own file, a whole host of
+     * optimizations cannot take place.   */
+        
+    ret = ncmpi_put_var_int_all(ncfile, varid1, &data);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_put_var_int_all(ncfile, varid2, &data);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_close(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    MPI_Finalize();
+
+    return 0;
+}
+
+/* The contents of files created by this program are:
+% ncmpidump  output.nc
+netcdf output {
+// file format: CDF-2 (large file)
+dimensions:
+        d1 = 4 ;
+variables:
+        int v1(d1) ;
+        int v2(d1) ;
+
+// global attributes:
+                :string = "Hello World\n",
+    "" ;
+data:
+
+ v1 = 0, 1, 2, 3 ;
+
+ v2 = 0, 1, 2, 3 ;
+}
+
+% ncmpidump output.nc.0-4.nc
+netcdf output.nc.0-4 {
+// file format: CDF-2 (large file)
+dimensions:
+        d1 = 1 ;
+variables:
+        int v1(d1) ;
+        int v2(d1) ;
+
+// global attributes:
+                :string = "Hello World\n",
+    "" ;
+data:
+
+ v1 = 0 ;
+
+ v2 = 0 ;
+}
+
+% ncmpidump output.nc.1-4.nc
+netcdf output.nc.1-4 {
+// file format: CDF-2 (large file)
+dimensions:
+        d1 = 1 ;
+variables:
+        int v1(d1) ;
+        int v2(d1) ;
+
+// global attributes:
+                :string = "Hello World\n",
+    "" ;
+data:
+
+ v1 = 1 ;
+
+ v2 = 1 ;
+}
+
+% ncmpidump output.nc.2-4.nc
+netcdf output.nc.2-4 {
+// file format: CDF-2 (large file)
+dimensions:
+        d1 = 1 ;
+variables:
+        int v1(d1) ;
+        int v2(d1) ;
+
+// global attributes:
+                :string = "Hello World\n",
+    "" ;
+data:
+
+ v1 = 2 ;
+
+ v2 = 2 ;
+}
+
+% ncmpidump output.nc.3-4.nc
+netcdf output.nc.3-4 {
+// file format: CDF-2 (large file)
+dimensions:
+        d1 = 1 ;
+variables:
+        int v1(d1) ;
+        int v2(d1) ;
+
+// global attributes:
+                :string = "Hello World\n",
+    "" ;
+data:
+
+ v1 = 3 ;
+
+ v2 = 3 ;
+}
+*/
diff --git a/examples/tutorial/pnetcdf-write-standard.c b/examples/tutorial/pnetcdf-write-standard.c
new file mode 100644
index 0000000..cfeaca4
--- /dev/null
+++ b/examples/tutorial/pnetcdf-write-standard.c
@@ -0,0 +1,108 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: pnetcdf-write-standard.c 1123 2013-01-26 17:35:03Z wkliao $ */
+
+/* simple demonstration of pnetcdf 
+ * text attribute on dataset
+ * write out rank into 1-d array collectively.
+ * The most basic way to do parallel i/o with pnetcdf */
+
+/* This program creates a file, say named output.nc, with the following
+   contents, shown by running ncmpidump command .
+
+    % mpiexec -n 4 pnetcdf-write-standard /orangefs/wkliao/output.nc
+
+    % ncmpidump /orangefs/wkliao/output.nc 
+    netcdf output {
+    // file format: CDF-2 (large file)
+    dimensions:
+            d1 = 4 ;
+    variables:
+            int v1(d1) ;
+            int v2(d1) ;
+
+    // global attributes:
+                :string = "Hello World\n",
+        "" ;
+    data:
+
+         v1 = 0, 1, 2, 3 ;
+
+         v2 = 0, 1, 2, 3 ;
+    }
+*/
+
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <stdio.h>
+
+static void handle_error(int status, int lineno)
+{
+    fprintf(stderr, "Error at line %d: %s\n", lineno, ncmpi_strerror(status));
+    MPI_Abort(MPI_COMM_WORLD, 1);
+}
+
+int main(int argc, char **argv) {
+
+    int ret, ncfile, nprocs, rank, dimid, varid1, varid2, ndims=1;
+    MPI_Offset start, count=1;
+    char buf[13] = "Hello World\n";
+    int data;
+
+    MPI_Init(&argc, &argv);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc != 2) {
+        if (rank == 0) printf("Usage: %s filename\n", argv[0]);
+        MPI_Finalize();
+        exit(-1);
+    }
+
+    ret = ncmpi_create(MPI_COMM_WORLD, argv[1],
+                       NC_CLOBBER|NC_64BIT_OFFSET, MPI_INFO_NULL, &ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_dim(ncfile, "d1", nprocs, &dimid);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_var(ncfile, "v1", NC_INT, ndims, &dimid, &varid1);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_def_var(ncfile, "v2", NC_INT, ndims, &dimid, &varid2);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_put_att_text(ncfile, NC_GLOBAL, "string", 13, buf);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    /* all processors defined the dimensions, attributes, and variables,
+     * but here in ncmpi_enddef is the one place where metadata I/O
+     * happens.  Behind the scenes, rank 0 takes the information and writes
+     * the netcdf header.  All processes communicate to ensure they have
+     * the same (cached) view of the dataset */
+
+    ret = ncmpi_enddef(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    start=rank, count=1, data=rank;
+
+    /* in this simple example every process writes its rank to two 1d variables */
+    ret = ncmpi_put_vara_int_all(ncfile, varid1, &start, &count, &data);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_put_vara_int_all(ncfile, varid2, &start, &count, &data);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    ret = ncmpi_close(ncfile);
+    if (ret != NC_NOERR) handle_error(ret, __LINE__);
+
+    MPI_Finalize();
+
+    return 0;
+}
diff --git a/macros.make.in b/macros.make.in
new file mode 100644
index 0000000..3e0acbd
--- /dev/null
+++ b/macros.make.in
@@ -0,0 +1,138 @@
+# $Id: macros.make.in 2264 2015-12-22 15:42:59Z wkliao $
+
+# The purpose of this file is to contain common make(1) macros.
+# It should be processed by every execution of that utility.
+
+ at SET_MAKE@
+
+# POSIX shell.  Shouldn't be necessary -- but is under IRIX 5.3.
+SHELL		= /bin/sh
+RM		= @RM@
+LN_S		= @LN_S@
+
+# Installation Directories:
+# SRCDIR	= @SRCDIR@
+prefix		= @prefix@
+INCDIR		= $(prefix)/include
+LIBDIR		= $(prefix)/lib
+BINDIR		= $(prefix)/bin
+MANDIR		= $(prefix)/man
+BUILDDIR	= @BUILDDIR@
+LIBRARY		= @BUILDDIR@/src/lib/libpnetcdf.a
+
+
+# Useful tools
+M4		= @M4@
+M4FLAGS		= @M4FLAGS@
+EGREP		= @EGREP@
+
+# AC_PROG_SED and AC_PROG_GREP are only available on autoconf 2.60 and later
+# SED		= @SED@
+# GREP		= @GREP@
+SED		= sed
+GREP		= grep
+
+# Preprocessing:
+DEFS		= @DEFS@
+FC_DEFINE	= @FC_DEFINE@
+CPP		= @CPP@
+CPPFLAGS	= $(INCLUDES) $(DEFS) @CPPFLAGS@
+CXXCPPFLAGS     = $(INCLUDES) $(DEFS) @CXXCPPFLAGS@
+FPP		= @FPP@
+FPPFLAGS	= $(INCLUDES) @FPPFLAGS@ @NAGf90FPPFLAGS@
+
+
+# Compilation:
+MPICC		= @MPICC@
+MPICXX		= @MPICXX@
+MPIF77		= @MPIF77@
+MPIF90		= @MPIF90@
+
+SEQ_CC          = @SEQ_CC@
+
+# debugging and optimization options for compiling and linking
+CFLAGS		= @CFLAGS@
+CXXFLAGS	= @CXXFLAGS@
+F77FLAGS	= @F77FLAGS@ @NAG_FCFLAGS@
+F90FLAGS	= @F90FLAGS@ @NAG_FCFLAGS@
+
+# compiler options for different file extensions: .f .F .f90 .F90
+F77FLAGS_f	= @F77FLAGS_f@
+F77FLAGS_F	= @F77FLAGS_F@
+F90FLAGS_f90	= @F90FLAGS_f90@
+F90FLAGS_F90	= @F90FLAGS_F90@
+
+# preprocessor options for different file extensions: .f .F .f90 .F90
+F77PPFLAGS_f	= @F77PPFLAGS_f@
+F77PPFLAGS_F	= @F77PPFLAGS_F@
+F90PPFLAGS_f90	= @F90PPFLAGS_f90@
+F90PPFLAGS_F90	= @F90PPFLAGS_F90@
+
+# NETCDF.MOD	= @NETCDF_MOD@
+CC_MAKEDEPEND	= @CC_MAKEDEPEND@
+
+COMPILE.c	= $(MPICC)  $(CFLAGS)       $(CPPFLAGS) -c
+COMPILE.cxx	= $(MPICXX) $(CXXFLAGS)     $(CXXCPPFLAGS) -c
+COMPILE.f	= $(MPIF77) $(F77FLAGS_f)   $(FPPFLAGS) $(F77FLAGS) -c
+COMPILE.f90	= $(MPIF90) $(F90FLAGS_f90) $(FPPFLAGS) $(F90FLAGS) -c
+COMPILE.F	= $(MPIF77) $(F77FLAGS_F)   $(FPPFLAGS) $(F77FLAGS) $(F77PPFLAGS_F) -c
+COMPILE.F90	= $(MPIF90) $(F90FLAGS_F90) $(FPPFLAGS) $(F90FLAGS) $(F90PPFLAGS_F90) -c
+# In PnetCDF, we follow the file extension convention that .F and .F90 files
+# require preprocessing, while .f and .f90 do not.
+
+
+# Linking:
+FLIBS		= @FLIBS@
+FCLIBS		= @FCLIBS@
+F90LIBS		= @F90LIBS@
+FLDFLAGS	= @FLDFLAGS@
+F90LDFLAGS	= @F90LDFLAGS@
+LDFLAGS		= @LDFLAGS@ 
+LIBS		= @LIBS@
+
+LINK.c		= $(MPICC)  $(CFLAGS)   -o $@
+LINK.cxx	= $(MPICXX) $(CXXFLAGS) -o $@
+LINK.F77	= $(MPIF77) $(F77FLAGS) -o $@
+LINK.F90	= $(MPIF90) $(F90FLAGS) -o $@
+
+TEST_MPIRUN	= @TEST_MPIRUN@
+TEST_OUTDIR	= @TEST_OUTDIR@
+TEST_SEQRUN	= @TEST_SEQRUN@
+
+# Manual pages:
+WHATIS		= @WHATIS@
+# The following macro should be empty on systems that don't
+# allow users to create their own manual-page indexes.
+MAKEWHATIS_CMD	= @MAKEWHATIS_CMD@
+
+
+# Misc. Utilities:
+AR		= @AR@
+ARFLAGS		= @ARFLAGS@
+AWK		= @AWK@
+RANLIB		= @RANLIB@
+INSTALL 	= @INSTALL@
+INSTALL_DATA	= @INSTALL_DATA@
+TARFLAGS	= -chf
+
+
+# Dummy macros: used only as placeholders to silence GNU make.  They are
+# redefined, as necessary, in subdirectory makefiles.
+HEADER		= dummy_header
+HEADER1		= dummy_header1
+HEADER2		= dummy_header2
+HEADER3		= dummy_header3
+MANUAL		= dummy_manual
+PROGRAM		= dummy_program
+
+
+# Distribution macros:
+FTPDIR		= /home/ftp/pub/$(PACKAGE)
+FTPBINDIR	= @FTPBINDIR@
+
+PNETCDF_VERSION_MAJOR = @PNETCDF_VERSION_MAJOR@
+PNETCDF_VERSION_MINOR = @PNETCDF_VERSION_MINOR@
+PNETCDF_VERSION_SUB   = @PNETCDF_VERSION_SUB@
+PNETCDF_VERSION_PRE   = @PNETCDF_VERSION_PRE@
+PNETCDF_VERSION       = @PNETCDF_VERSION@
+
diff --git a/man/Makefile.in b/man/Makefile.in
new file mode 100644
index 0000000..1d0db89
--- /dev/null
+++ b/man/Makefile.in
@@ -0,0 +1,60 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 1507 2013-11-17 05:18:16Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include ../macros.make
+
+MANUAL_C   = pnetcdf.3
+MANUAL_F77 = pnetcdf_f77.3
+MANUAL_F90 = pnetcdf_f90.3
+
+MANUAL = $(MANUAL_C)
+ifeq (@has_fortran@, yes)
+MANUAL += $(MANUAL_F77)
+MANUAL += $(MANUAL_F90)
+endif
+
+PACKING_LIST = pnetcdf.m4 pnetcdf_f90.m4 \
+               Makefile.in
+
+GARBAGE = $(MANUAL)
+
+all: $(MANUAL)
+
+RELEASE_DATE = "@PNETCDF_RELEASE_DATE2@"
+RELEASE_STR  = "@PNETCDF_VERSION@ of @PNETCDF_RELEASE_DATE@"
+
+pnetcdf.3: pnetcdf.m4
+	$(M4) $(M4FLAGS) -DAPI=C -DRELEASE_STR=$(RELEASE_STR) -DRELEASE_DATE=$(RELEASE_DATE) $? > $@  || $(RM) -f $@
+
+pnetcdf_f77.3: pnetcdf.m4
+	$(M4) $(M4FLAGS) -DAPI=F -DRELEASE_STR=$(RELEASE_STR) -DRELEASE_DATE=$(RELEASE_DATE) $? > $@  || $(RM) -f $@
+
+pnetcdf_f90.3: pnetcdf_f90.m4
+	$(M4) $(M4FLAGS) -DRELEASE_STR=$(RELEASE_STR) -DRELEASE_DATE=$(RELEASE_DATE) $? > $@  || $(RM) -f $@
+
+test:
+
+install: $(MANUAL)
+	$(INSTALL) -d -m 755 $(MANDIR)/man3
+	@for i in $(MANUAL) ; do ( \
+	    if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	    else file=$$i; fi; \
+	    fn=`basename $$i` ; \
+	    $(INSTALL_DATA) $$file $(MANDIR)/man3/$$fn \
+	; ) ; done
+
+uninstall:
+	@for i in $(MANUAL) ; do ( \
+	    fn=`basename $$i` ; \
+	    $(RM) -f $(MANDIR)/man3/$$fn \
+	; ) ; done
+
+include $(srcdir)/../rules.make
diff --git a/man/pnetcdf.m4 b/man/pnetcdf.m4
new file mode 100644
index 0000000..1791ad6
--- /dev/null
+++ b/man/pnetcdf.m4
@@ -0,0 +1,1269 @@
+divert(-1)
+
+changequote(<<,>>)
+define(<<index>>, defn(index))
+
+define(<<CODE>>, <<\fB$1\fR>>)
+
+define(<<ARG>>, <<\fI$1\fP>>)
+
+define(<<HEADER_FILE>>, 
+    <<ifelse(API,C,
+	$1.h,
+	$1.inc)>>)
+
+define(<<INCLUDE>>, 
+    <<ifelse(API,C,
+	<<#include>> <HEADER_FILE($1)>,
+	<<<<include>>>> "HEADER_FILE($1)")>>)
+
+define(<<COMPILER>>,
+    <<ifelse(API,C,
+	mpicc,
+	mpif77)>>)
+
+define(<<LANGUAGE>>,
+    <<ifelse(API,C,
+	C,
+	FORTRAN)>>)
+
+define(<<RETSTR>>,
+    <<ifelse(API,C,
+	const char*,
+	character*80)>>)
+
+define(<<FNAME>>,
+    <<ifelse(API,C,
+	ncmpi_$1,
+	nfmpi_$1)>>)
+
+define(<<VOID_ARG>>,
+    <<ifelse(API,C,,void)>>)
+
+define(<<MACRO>>,
+    <<CODE(ifelse(API,C,
+	NC_$1,
+	NF_$1))>>)
+
+dnl AQUAL(io, rank)
+define(<<AQUAL>>, <<ifelse(API,C,
+    <<ifelse($1, output, , <<ifelse($2, 0, , const )>>)>>)>>)
+
+dnl CTYPE(type)
+define(<<CTYPE>>,
+    <<ifelse($1,text,char,
+    <<ifelse($1,uchar,unsigned char,
+    <<ifelse($1,schar,signed char,
+    <<ifelse($1,short,short,
+    <<ifelse($1,int,int,
+    <<ifelse($1,nc_type,nc_type,
+    <<ifelse($1,size_t,MPI_Offset,
+    <<ifelse($1,ptrdiff_t,MPI_Offset,
+    <<ifelse($1,long,long,
+    <<ifelse($1,int64,long long,
+    <<ifelse($1,float,float,
+    <<ifelse($1,double,double,
+    <<ifelse($1,ubyte,unsigned char,
+    <<ifelse($1,ushort,unsigned short,
+    <<ifelse($1,uint,unsigned int,
+    <<ifelse($1,int64,long long,
+    <<ifelse($1,uint64,unsigned long long,
+    <<ifelse($1,string,char *,
+    <<ifelse($1,voidp,void *,
+    <<ifelse($1,MPI_Comm,MPI_Comm,
+    <<ifelse($1,MPI_Info,MPI_Info,
+    )>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)
+
+dnl CSTAR(io, rank)
+define(<<CSTAR>>, <<ifelse($1,input,,<<ifelse($2,0,*)>>)>>)
+
+dnl FTYPE(type, rank)
+define(<<FTYPE>>, 
+    <<ifelse($1,text,<<character*ifelse($2,0,1,(*))>>,
+    <<ifelse($1,schar,integer*1,
+    <<ifelse($1,short,integer*2,
+    <<ifelse($1,int,integer,
+    <<ifelse($1,nc_type,integer,
+    <<ifelse($1,size_t,integer(kind=MPI_OFFSET),
+    <<ifelse($1,ptrdiff_t,integer(kind=MPI_OFFSET),
+    <<ifelse($1,long,integer,
+    <<ifelse($1,int64,integer*8,
+    <<ifelse($1,float,real,
+    <<ifelse($1,double,doubleprecision,
+    <<ifelse($1,ubyte,integer*1,
+    <<ifelse($1,ushort,integer*2,
+    <<ifelse($1,uint,integer*4,
+    <<ifelse($1,int64,integer*8,
+    <<ifelse($1,uint64,integer*8,
+    <<ifelse($1,string,character*,
+    <<ifelse($1,voidp,void *,
+    <<ifelse($1,MPI_Comm,integer,
+    <<ifelse($1,MPI_Info,integer,
+)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)
+
+dnl ATYPE(io,rank,type)
+define(<<ATYPE>>, <<ifelse(API,C,
+    <<CTYPE($3)<<>>CSTAR($1,$2)>>, 
+    <<FTYPE($3,$2)>>)>>)
+
+dnl AID(name, rank, type)
+define(<<AID>>, <<ARG($1)<<>>ifelse(API,C,
+    <<ifelse($2,0,,[])>>, 
+    <<ifelse($3,text,,<<ifelse($2,0,,(1))>>)>>)>>)
+
+dnl ADECL(io, rank, type, name)
+define(<<ADECL>>, <<AQUAL($1,$2)ATYPE($1,$2,$3) AID($4,$2,$3)>>)
+
+define(<<ITEXT>>,	<<ADECL(input,0,text,$1)>>)
+define(<<ITEXTV>>,	<<ADECL(input,1,text,$1)>>)
+define(<<OTEXT>>,	<<ADECL(output,0,text,$1)>>)
+define(<<OTEXTV>>,	<<ADECL(output,1,text,$1)>>)
+
+define(<<IUCHAR>>,	<<ADECL(input,0,uchar,$1)>>)
+define(<<IUCHARV>>,	<<ADECL(input,1,uchar,$1)>>)
+define(<<OUCHAR>>,	<<ADECL(output,0,uchar,$1)>>)
+define(<<OUCHARV>>,	<<ADECL(output,1,uchar,$1)>>)
+
+define(<<ISCHAR>>,	<<ADECL(input,0,schar,$1)>>)
+define(<<ISCHARV>>,	<<ADECL(input,1,schar,$1)>>)
+define(<<OSCHAR>>,	<<ADECL(output,0,schar,$1)>>)
+define(<<OSCHARV>>,	<<ADECL(output,1,schar,$1)>>)
+
+define(<<ISHORT>>,	<<ADECL(input,0,short,$1)>>)
+define(<<ISHORTV>>,	<<ADECL(input,1,short,$1)>>)
+define(<<OSHORT>>,	<<ADECL(output,0,short,$1)>>)
+define(<<OSHORTV>>,	<<ADECL(output,1,short,$1)>>)
+
+define(<<IINT>>,	<<ADECL(input,0,int,$1)>>)
+define(<<IINTV>>,	<<ADECL(input,1,int,$1)>>)
+define(<<OINT>>,	<<ADECL(output,0,int,$1)>>)
+define(<<OINTV>>,	<<ADECL(output,1,int,$1)>>)
+
+define(<<IINT64>>,	<<ADECL(input,0,int64,$1)>>)
+define(<<IINT64V>>,	<<ADECL(input,1,int64,$1)>>)
+define(<<OINT64>>,	<<ADECL(output,0,int64,$1)>>)
+define(<<OINT64V>>,	<<ADECL(output,1,int64,$1)>>)
+
+define(<<INCTYPE>>,	<<ADECL(input,0,nc_type,$1)>>)
+define(<<INCTYPEV>>,	<<ADECL(input,1,nc_type,$1)>>)
+define(<<ONCTYPE>>,	<<ADECL(output,0,nc_type,$1)>>)
+define(<<ONCTYPEV>>,	<<ADECL(output,1,nc_type,$1)>>)
+
+define(<<ISIZET>>,	<<ADECL(input,0,size_t,$1)>>)
+define(<<ISIZETV>>,	<<ADECL(input,1,size_t,$1)>>)
+define(<<OSIZET>>,	<<ADECL(output,0,size_t,$1)>>)
+define(<<OSIZETV>>,	<<ADECL(output,1,size_t,$1)>>)
+
+define(<<IPTRDIFFT>>,	<<ADECL(input,0,ptrdiff_t,$1)>>)
+define(<<IPTRDIFFTV>>,	<<ADECL(input,1,ptrdiff_t,$1)>>)
+define(<<ISIZETV>>,	<<ADECL(input,1,size_t,$1)>>)
+define(<<OPTRDIFFT>>,	<<ADECL(output,0,ptrdiff_t,$1)>>)
+define(<<OPTRDIFFTV>>,	<<ADECL(output,1,ptrdiff_t,$1)>>)
+
+define(<<ILONG>>,	<<ADECL(input,0,long,$1)>>)
+define(<<ILONGV>>,	<<ADECL(input,1,long,$1)>>)
+define(<<OLONG>>,	<<ADECL(output,0,long,$1)>>)
+define(<<OLONGV>>,	<<ADECL(output,1,long,$1)>>)
+
+define(<<IFLOAT>>,	<<ADECL(input,0,float,$1)>>)
+define(<<IFLOATV>>,	<<ADECL(input,1,float,$1)>>)
+define(<<OFLOAT>>,	<<ADECL(output,0,float,$1)>>)
+define(<<OFLOATV>>,	<<ADECL(output,1,float,$1)>>)
+
+define(<<IDOUBLE>>,	<<ADECL(input,0,double,$1)>>)
+define(<<IDOUBLEV>>,	<<ADECL(input,1,double,$1)>>)
+define(<<ODOUBLE>>,	<<ADECL(output,0,double,$1)>>)
+define(<<ODOUBLEV>>,	<<ADECL(output,1,double,$1)>>)
+
+define(<<IUBYTE>>,	<<ADECL(input,0,ubyte,$1)>>)
+define(<<IUBYTEV>>,	<<ADECL(input,1,ubyte,$1)>>)
+define(<<OUBYTE>>,	<<ADECL(output,0,ubyte,$1)>>)
+define(<<OUBYTEV>>,	<<ADECL(output,1,ubyte,$1)>>)
+
+define(<<IUSHORT>>,	<<ADECL(input,0,ushort,$1)>>)
+define(<<IUSHORTV>>,	<<ADECL(input,1,ushort,$1)>>)
+define(<<OUSHORT>>,	<<ADECL(output,0,ushort,$1)>>)
+define(<<OUSHORTV>>,	<<ADECL(output,1,ushort,$1)>>)
+
+define(<<IUINT>>,	<<ADECL(input,0,uint,$1)>>)
+define(<<IUINTV>>,	<<ADECL(input,1,uint,$1)>>)
+define(<<OUINT>>,	<<ADECL(output,0,uint,$1)>>)
+define(<<OUINTV>>,	<<ADECL(output,1,uint,$1)>>)
+
+define(<<IINT64>>,	<<ADECL(input,0,int64,$1)>>)
+define(<<IINT64V>>,	<<ADECL(input,1,int64,$1)>>)
+define(<<OINT64>>,	<<ADECL(output,0,int64,$1)>>)
+define(<<OINT64V>>,	<<ADECL(output,1,int64,$1)>>)
+
+define(<<IUINT64>>,	<<ADECL(input,0,uint64,$1)>>)
+define(<<IUINT64V>>,	<<ADECL(input,1,uint64,$1)>>)
+define(<<OUINT64>>,	<<ADECL(output,0,uint64,$1)>>)
+define(<<OUINT64V>>,	<<ADECL(output,1,uint64,$1)>>)
+
+define(<<ISTRING>>,	<<ADECL(input,0,string,$1)>>)
+define(<<ISTRINGV>>,	<<ADECL(input,1,string,$1)>>)
+define(<<OSTRING>>,	<<ADECL(output,0,string,$1)>>)
+define(<<OSTRINGV>>,	<<ADECL(output,1,string,$1)>>)
+
+define(<<IVOIDP>>,	<<ADECL(input,0,voidp,$1)>>)
+define(<<IVOIDPV>>,	<<ADECL(input,1,voidp,$1)>>)
+define(<<OVOIDP>>,	<<ADECL(output,0,voidp,$1)>>)
+define(<<OVOIDPV>>,	<<ADECL(output,1,voidp,$1)>>)
+
+define(<<IMPICOMM>>,    <<ADECL(input,0,MPI_Comm,$1)>>)
+define(<<OMPICOMM>>,    <<ADECL(output,0,MPI_Comm,$1)>>)
+define(<<IMPIINFO>>,    <<ADECL(input,0,MPI_Info,$1)>>)
+define(<<OMPIINFO>>,    <<ADECL(output,0,MPI_Info,$1)>>)
+
+dnl CCOMP(type)
+define(<<CCOMP>>, 
+    <<ifelse($1,text,text,
+    <<ifelse($1,uchar,uchar,
+    <<ifelse($1,schar,schar,
+    <<ifelse($1,short,short,
+    <<ifelse($1,int,int,
+    <<ifelse($1,long,long,
+    <<ifelse($1,float,float,
+    <<ifelse($1,double,double,
+    <<ifelse($1,ubyte,ubyte,
+    <<ifelse($1,ushort,ushort,
+    <<ifelse($1,uint,uint,
+    <<ifelse($1,int64,int64,
+    <<ifelse($1,uint64,uint64,
+    <<ifelse($1,string,string,
+    <<ifelse($1,voidp,void *,
+)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)
+
+dnl FCOMP(type)
+define(<<FCOMP>>, 
+    <<ifelse($1,text,text,
+    <<ifelse($1,schar,int1,
+    <<ifelse($1,short,int2,
+    <<ifelse($1,int,int,
+    <<ifelse($1,float,real,
+    <<ifelse($1,double,double,
+    <<ifelse($1,ubyte,ubyte,
+    <<ifelse($1,ushort,ushort,
+    <<ifelse($1,uint,uint,
+    <<ifelse($1,uint64,uint64,
+    <<ifelse($1,string,string,
+    <<ifelse($1,voidp,any,
+)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)
+
+dnl COMP(type)
+define(<<COMP>>, <<ifelse(API,C,<<CCOMP($1)>>,<<FCOMP($1)>>)>>)
+
+define(<<FDECL_TYPE>>,
+    <<ifelse(API,C, 
+	int,
+	integer function)>>)
+
+dnl DECL(return-type, name, argument-list)
+define(<<DECL>>, <<CODE($1 FNAME($2)$3)>>)
+
+dnl FDECL(name, argument-list)
+define(<<FDECL>>, <<DECL(FDECL_TYPE, $1, $2)
+
+FOLD($1)>>)
+
+dnl IODECL(name, type, argument-list)
+define(<<IODECL>>, <<FDECL($1_<<>>COMP($2), $3)>>)
+
+dnl FREF(name)
+define(<<FREF>>, <<CODE(FNAME($1)(\|))>>)
+
+dnl FOLD(cname, fname)
+define(<<FOLD>>, <<(Corresponds to CODE(ifelse(API,C, nc_$1, nf_$1)(\|)) in netCDF)>>)
+
+dnl Function Input Arguments:
+define(<<IATTNUM>>, <<IINT(attnum)>>)
+define(<<ICMODE>>, <<IINT(cmode)>>)
+define(<<ICOUNT>>, <<ISIZETV(count)>>)
+define(<<IDIMID>>, <<IINT(dimid)>>)
+define(<<IDIMIDS>>, <<IINTV(dimids)>>)
+define(<<IFILLMODE>>, <<IINT(fillmode)>>)
+define(<<IH_MINFREE>>, <<ISIZET(h_minfree)>>)
+define(<<IINDEX>>, <<ISIZETV(index)>>)
+define(<<IINITSIZE>>, <<ISIZET(initialsize)>>)
+define(<<ILEN>>, <<ISIZET(<<len>>)>>)
+define(<<IIMAP>>, <<IPTRDIFFTV(imap)>>)
+define(<<IMODE>>, <<IINT(mode)>>)
+define(<<INAME>>, <<ITEXTV(name)>>)
+define(<<INCID>>, <<IINT(ncid)>>)
+define(<<INCIDIN>>, <<IINT(ncid_in)>>)
+define(<<INCIDOUT>>, <<IINT(ncid_out)>>)
+define(<<INDIMS>>, <<IINT(ndims)>>)
+define(<<INEWNAME>>, <<ITEXTV(newname)>>)
+define(<<IPATH>>, ITEXTV(path))
+define(<<IPE>>, <<IINT(pe)>>)
+define(<<IR_ALIGN>>, <<ISIZET(r_align)>>)
+define(<<ISTART>>, <<ISIZETV(start)>>)
+define(<<ISTATUS>>, <<IINT(status)>>)
+define(<<ISTRIDE>>, <<ISIZETV(stride)>>)
+define(<<IV_ALIGN>>, <<ISIZET(v_align)>>)
+define(<<IV_MINFREE>>, <<ISIZET(v_minfree)>>)
+define(<<IVARID>>, <<IINT(varid)>>)
+define(<<IVARIDIN>>, <<IINT(varid_in)>>)
+define(<<IVARIDOUT>>, <<IINT(varid_out)>>)
+define(<<IXTYPE>>, <<INCTYPE(xtype)>>)
+define(<<IPARACCESS>>, <<IINT(par_access)>>)
+
+define(<<ICOMM>>, <<IMPICOMM(comm)>>)
+define(<<IINFO>>, <<IMPIINFO(info)>>)
+
+dnl Function Output Arguments:
+define(<<OATTNUM>>, <<OINT(attnum)>>)
+define(<<OCHUNKSIZE>>, <<OSIZET(chunksize)>>)
+define(<<ODIMID>>, <<OINT(dimid)>>)
+define(<<ODIMIDS>>, <<OINTV(dimids)>>)
+define(<<OLEN>>, <<OSIZET(<<len>>)>>)
+define(<<ONAME>>, <<OTEXTV(name)>>)
+define(<<ONATTS>>, <<OINT(natts)>>)
+define(<<ONCID>>, <<OINT(ncid)>>)
+define(<<ONDIMS>>, <<OINT(ndims)>>)
+define(<<ONVARS>>, <<OINT(nvars)>>)
+define(<<OOLDFILLMODE>>, <<OINT(old_fillemode)>>)
+define(<<OPE>>, <<OINT(pe)>>)
+define(<<OVARID>>, <<OINT(varid)>>)
+define(<<OUNLIMDIMID>>, <<OINT(unlimdimid)>>)
+define(<<OFORMATN>>, <<OINT(formatn)>>)
+define(<<OXTYPE>>, <<ONCTYPE(xtype)>>)
+
+dnl Argument References:
+define(<<ATTNUM>>, <<ARG(attnum)>>)
+define(<<COUNT>>, <<ARG(count)>>)
+define(<<DIMID>>, <<ARG(dimid)>>)
+define(<<DIMIDS>>, <<ARG(dimids)>>)
+define(<<FILLMODE>>, <<ARG(fillmode)>>)
+define(<<IN>>, <<ARG(in)>>)
+define(<<INDEX>>, <<ARG(index)>>)
+define(<<LEN>>, <<ARG(<<len>>)>>)
+define(<<IMAP>>, <<ARG(imap)>>)
+define(<<NAME>>, <<ARG(name)>>)
+define(<<NATTS>>, <<ARG(natts)>>)
+define(<<NCID>>, <<ARG(ncid)>>)
+define(<<NCIDIN>>, <<ARG(ncid_in)>>)
+define(<<NCIDOUT>>, <<ARG(ncid_out)>>)
+define(<<NDIMS>>, <<ARG(ndims)>>)
+define(<<NEWNAME>>, <<ARG(newname)>>)
+define(<<NULL>>, <<CODE(<<<<NULL>>>>)>>)
+define(<<NVARS>>, <<ARG(nvars)>>)
+define(<<NVATTS>>, <<ARG(nvatts)>>)
+define(<<OLDFILLMODE>>, <<ARG(old_fillmode)>>)
+define(<<OUT>>, <<ARG(out)>>)
+define(<<START>>, <<ARG(start)>>)
+define(<<STRIDE>>, <<ARG(stride)>>)
+define(<<UNLIMDIMID>>, <<ARG(unlimdimid)>>)
+define(<<FORMATN>>, <<ARG(formatn)>>)
+define(<<VARID>>, <<ARG(varid)>>)
+define(<<VARIDIN>>, <<ARG(varid_in)>>)
+define(<<VARIDOUT>>, <<ARG(varid_out)>>)
+define(<<XTYPE>>, <<ARG(xtype)>>)
+
+define(<<UPCASE>>, 
+<<translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ)>>)
+
+dnl Variable "Put" Functions:
+define(<<VOUT>>, <<I<<>>UPCASE($1)<<>>ifelse($2,1,,V)(ifelse($2,1,*)out)>>)
+define(<<VPUT>>, <<IODECL(put_var$1, $2, (INCID(), IVARID()$3, VOUT($2,$1)))>>)
+define(<<PUT_VAR>>, <<VPUT(,$1)>>)
+define(<<PUT_VAR1>>,<<VPUT(1,$1,<<, IINDEX()>>)>>)
+define(<<PUT_VARA>>,<<VPUT(a,$1,<<, ISTART(), ICOUNT()>>)>>)
+define(<<PUT_VARS>>,<<VPUT(s,$1,<<, ISTART(), ICOUNT(), ISTRIDE()>>)>>)
+define(<<PUT_VARM>>,<<VPUT(m,$1,<<, ISTART(), ICOUNT(), ISTRIDE(), IIMAP()>>)>>)
+
+dnl Variable "Get" Functions:
+define(<<VIN>>, <<O<<>>UPCASE($1)<<>>ifelse($2,1,,V)(in)>>)
+define(<<VGET>>, <<IODECL(get_var$1, $2, (INCID(), IVARID()$3, VIN($2,$1)))>>)
+define(<<GET_VAR>>, <<VGET(,$1)>>)
+define(<<GET_VAR1>>,<<VGET(1,$1,<<, IINDEX()>>)>>)
+define(<<GET_VARA>>,<<VGET(a,$1,<<, ISTART(), ICOUNT()>>)>>)
+define(<<GET_VARS>>,<<VGET(s,$1,<<, ISTART(), ICOUNT(), ISTRIDE()>>)>>)
+define(<<GET_VARM>>,<<VGET(m,$1,<<, ISTART(), ICOUNT(), ISTRIDE(), IIMAP()>>)>>)
+
+dnl Attribute "Put" Functions:
+define(<<AOUT>>, <<I<<>>UPCASE($1)<<>>V(out)>>)
+define(<<APUT>>,<<IODECL(put_att,$1,(INCID(), IVARID(), INAME(), IXTYPE(), ILEN(), AOUT($1)))>>)
+
+dnl Attribute "Get" Functions:
+define(<<AIN>>, <<O<<>>UPCASE($1)<<>>V(in)>>)
+define(<<AGET>>,<<IODECL(get_att,$1,(INCID(), IVARID(), INAME(), AIN($1)))>>)
+
+dnl Function Family Listing:
+define(<<FUNC_FAMILY>>,
+<<.HP
+$1(text)
+ifelse(API,C,
+<<.HP
+$1(uchar)>>)
+.HP
+$1(schar)
+.HP
+$1(short)
+.HP
+$1(int)
+ifelse(API,C,
+<<.HP
+$1(long)>>)
+.HP
+$1(float)
+.HP
+$1(double)
+ifelse(NETCDF4,TRUE,
+<<.HP
+$1(ubyte)
+.HP
+$1(ushort)
+.HP
+$1(uint)
+.HP
+$1(int64)
+.HP
+$1(uint64)
+.HP
+$1(string)>>
+)
+>>)
+
+divert(0)dnl
+.nr yr \n(yr+1900
+.af mo 01
+.af dy 01
+.TH PNETCDF 3 RELEASE_DATE "Printed: \n(yr-\n(mo-\n(dy" "LIBRARY FUNCTIONS"
+.SH N<<>>AME
+PnetCDF \- Parallel library for accessing files in Network Common Data Form (CDF, CDF-2 and CDF-5 formats)
+.SH SYNOPSIS
+.ft B
+.na
+.nh
+INCLUDE(pnetcdf)
+.sp
+ifelse(API,C,,
+.SS Most Systems:)
+COMPILER() ...  -lpnetcdf
+ifelse(API,C,,
+.sp
+.SS CRAY PVP Systems:
+f90 -dp -i64 ... -lnetcdf
+)
+.ad
+.hy
+Complete documentation for the PnetCDF libraries can be found at the PnetCDF website: http://cucis.ece.northwestern.edu/projects/PnetCDF/.
+.sp
+.SH "LIBRARY VERSION"
+.LP
+This document describes Parallel netCDF APIs
+for the LANGUAGE() programming language.
+.HP
+DECL(RETSTR(), inq_libvers, (VOID_ARG))
+.sp
+FOLD(inq_libvers)
+.sp
+Returns a string identifying the version of the PnetCDF library, and
+when it was built, like: "RELEASE_STR".
+.LP
+The RCS \fBident(1)\fP command will find a string like
+"$\|Id: @\|(#) PnetCDF library version 
+RELEASE_STR $"
+in the library. The SCCS \fBwhat(1)\fP command will find a string like
+"PnetCDF library version RELEASE_STR".
+.SH "RETURN VALUES"
+.LP
+All PnetCDF functions (except
+FREF(inq_libvers) and FREF(strerror)) return an integer status.
+
+If this returned status value is not equal to
+MACRO(NOERR) (zero), it
+indicates that an error occurred. The possible status values are defined in 
+ifelse(API,C, system <<<<include>>>> file <errno.h> and in )<<>>dnl
+ifelse(API,C,")HEADER_FILE(pnetcdf)<<>>ifelse(API,C,").
+.HP
+DECL(RETSTR(), strerror, (ISTATUS()))
+.sp
+FOLD(strerror)
+.sp
+Returns a string textual translation of the \fIstatus\fP
+value, like "Attribute or variable name contains illegal characters"
+or "No such file or directory".
+.sp
+.SH "FILE OPERATIONS"
+.LP
+.HP
+FDECL(create, (ICOMM(), IPATH(), ICMODE(), IINFO(), ONCID()))
+.sp
+Creates a new netCDF dataset at ARG(path) collectively by a group of MPI
+processes specified by ARG(comm), returning a netCDF ID in ARG(ncid).  The
+argument ARG(cmode) may <<include>> the bitwise-or of the following flags:
+MACRO(NOCLOBBER) to protect existing datasets (default is MACRO(CLOBBER),
+silently blows them away), MACRO(SHARE) for stronger metadata data consistency
+control, MACRO(64BIT_OFFSET) to create a file in the 64-bit offset format
+(CDF-2), as opposed to classic format, the default, or MACRO(64BIT_DATA) to
+create a file in the 64-bit data format (CDF-5).
+Use either MACRO(64BIT_OFFSET) or MACRO(64BIT_DATA).
+The 64-bit offset format allows the creation of very large files with far fewer
+restrictions than netCDF classic format, but can only be read by the netCDF
+library version 3.6 or greater. Users are cautioned that files that use the
+64-bit offset format will not be recognized by netCDF applications linked to an
+earlier version of the netCDF library than 3.6.  Applications linked to version
+3.6 or later will be able to transparently access either the classic format or
+64-bit offset format.
+The 64-bit data format allows the creation of very large array variables.
+CDF-5 files currently will not be recognized by netCDF 3 or 4 library.
+ifelse(NETCDF4,TRUE,
+<<MACRO(NETCDF4) to create a netCDF-4/HDF5 file, 
+and MACRO(CLASSIC_MODEL) to guarantee that netCDF-4/HDF5 files maintain compatibility 
+with the netCDF classic data model.>>,
+.
+)
+The argument ARG(cmode) must be consistent among all MPI processes that
+collectively create the file.  The argument ARG(info) is an MPI info object.
+Users can use it to supply the file access hints further performance
+improvement.  The hints include existing MPI-IO hints as well as hints defined
+and used in PnetCDF.
+.sp
+When a netCDF dataset is created, it is opened in MACRO(WRITE) mode.
+When this function returns, the new netCDF dataset is in <<define>> mode.
+.HP
+FDECL(open, (ICOMM(), IPATH(), IMODE(), IINFO(), ONCID()))
+.sp
+Opens an existing netCDF dataset at ARG(path) collectively by a group of MPI
+processes specified by ARG(comm), returning a netCDF ID in ARG(ncid).  The type
+of access is described by the ARG(mode) parameter, which may <<include>> the
+bitwise-or of the following flags: MACRO(WRITE) for read-write access (default
+read-only), MACRO(SHARE) for stronger metadata data consistency control.
+.sp
+ifelse(DAP,TRUE,
+<<As of NetCDF version 4.1, and if DAP support was enabled
+when the NetCDF library was built, the path parameter
+may specify a DAP URL. In this case, the access mode is
+forced to be read-only.>>)
+The argument ARG(mode) must be consistent among all MPI processes that
+collectively open the file.  The argument ARG(info) is an MPI info object.
+Users can use it to supply the file access hints further performance
+improvement.  The hints include existing MPI-IO hints as well as hints defined
+and used in PnetCDF.
+.HP
+FDECL(redef, (INCID()))
+.sp
+Puts an open netCDF dataset into <<define>> mode, 
+so dimensions, variables, and attributes can be added or renamed and 
+attributes can be deleted.
+.HP
+FDECL(enddef, (INCID()))
+.sp
+Takes an open netCDF dataset out of <<define>> mode.
+The changes made to the netCDF dataset
+while it was in <<define>> mode are checked and committed to disk if no
+problems occurred.
+After a successful call, variable data can be read or written to the dataset.
+.HP
+FDECL(sync, (INCID()))
+.sp
+Unless the
+MACRO(SHARE)
+bit is set in
+FREF(open) or FREF(create),
+data written by PnetCDF APIs may be cached by local file system on each compute
+node.  This <<API>> flushes cached data by calling MPI_File_sync.
+.HP
+FDECL(abort, (INCID()))
+.sp
+You don't need to call this function.  This function is called automatically by
+FREF(close) if the netCDF was in <<define>> mode and something goes wrong with
+the commit.  If the netCDF dataset isn't in <<define>> mode, then this function
+is equivalent to FREF(close).  If it is called after FREF(redef), but before
+FREF(enddef), the new definitions are not committed and the dataset is closed.
+If it is called after FREF(create) but before FREF(enddef), the dataset
+disappears.
+.HP
+FDECL(close, (INCID()))
+.sp
+Closes an open netCDF dataset.  If the dataset is in <<define>> mode,
+FREF(enddef) will be called before closing.  After a dataset is closed, its ID
+may be reassigned to another dataset.
+.HP
+FDECL(inq, (INCID(), ONDIMS(), ONVARS(),
+ONATTS(), OUNLIMDIMID()))
+.HP
+FDECL(inq_ndims, (INCID(), ONDIMS()))
+.HP
+FDECL(inq_nvars, (INCID(), ONVARS()))
+.HP
+FDECL(inq_natts, (INCID(), ONATTS()))
+.HP
+FDECL(inq_unlimdim, (INCID(), OUNLIMDIMID()))
+.HP
+FDECL(inq_format, (INCID(), OFORMATN()))
+.sp
+Use these functions to find out what is in a netCDF dataset.
+Upon successful return,
+NDIMS() will contain  the
+number of dimensions defined for this netCDF dataset,
+NVARS() will contain the number of variables,
+NATTS() will contain the number of attributes, and
+UNLIMDIMID() will contain the
+dimension ID of the unlimited dimension if one exists, or
+ifelse(API,C, <<-1>>, <<0>>) otherwise.
+FORMATN() will contain the version number of the dataset <format>, one of
+MACRO(FORMAT_CLASSIC), MACRO(FORMAT_64BIT), or MACRO(FORMAT_64BIT_DATA).
+ifelse(API,C,
+<<If any of the
+return parameters is a NULL() pointer, then the corresponding information
+will not be returned; hence, no space need be allocated for it.>>)
+.HP
+FDECL(def_dim, (INCID(), INAME(), ILEN(), ODIMID()))
+.sp
+Adds a new dimension to an open netCDF dataset, which must be 
+in <<define>> mode.
+NAME() is the dimension name.
+ifelse(API,C,dnl
+<<If DIMID() is not a NULL() pointer then upon successful completion >>)<<>>dnl
+DIMID() will contain the dimension ID of the newly created dimension.
+ifelse(NETCDF4,TRUE,
+<<
+.SH "USER DEFINED TYPES"
+.LP
+Users many define types for a netCDF-4/HDF5 file (unless the
+MACRO(CLASSIC_MODEL) was used when the file was creates). Users may
+define compound types, variable length arrays, enumeration types, and
+opaque types.
+.sp
+
+.HP
+FDECL(def_compound, (INCID(), ISIZET(size), INAME(), OINT(typeidp)))
+.sp
+Define a compound type.
+.HP
+FDECL(insert_compound, (INCID(), INCTYPE(), INAME(), ISIZET(offset), INCTYPE(field_typeid)))
+.sp
+Insert an element into a compound type. May not be done after type has been used, or after the type has been written by an enddef.
+.HP
+FDECL(insert_array_compound, (INCID(), INCTYPE(), INAME(), ISIZET(offset), INCTYPE(field_typeid), INDIMS(), IINTV(dim_sizes)))
+.sp 
+Insert an array into a compound type.
+.HP
+FDECL(inq_type, (INCID(), INCTYPE(), ONAME(), OSIZET(sizep)))
+.sp
+Learn about a type.
+.HP
+FDECL(inq_compound, (INCID(), INCTYPE(), ONAME(), OSIZET(sizep), OSIZET(nfieldsp)))
+.HP
+FDECL(inq_compound_name, (INCID(), INCTYPE(), ONAME()))
+.HP
+FDECL(inq_compound_size, (INCID(), INCTYPE(), OSIZET(sizep)))
+.HP
+FDECL(inq_compound_nfields, (INCID(), INCTYPE(), OSIZET(nfieldsp)))
+.HP
+FDECL(inq_compound_fieldname, (INCID(), INCTYPE(), IINT(fieldid), ONAME()))
+.HP
+FDECL(inq_compound_fieldindex, (INCID(), INCTYPE(), INAME(), OINT(fieldidp)))
+.HP
+FDECL(inq_compound_fieldoffset, (INCID(), INCTYPE(), IINT(fieldid), OSIZET(offsetp)))
+.HP
+FDECL(inq_compound_fieldtype, (INCID(), INCTYPE(), IINT(fieldid), ONCTYPE(field_typeid)))
+.HP
+FDECL(inq_compound_fieldndims, (INCID(), INCTYPE(), IINT(fieldid), ONDIMS()))
+.HP
+FDECL(inq_compound_fielddim_sizes, (INCID(), INCTYPE(), IINT(fieldid), OINTV(dim_sizes)))
+.sp
+Learn about a compound type.
+.HP
+FDECL(def_vlen, (INCID(), INAME(), INCTYPE(base_typeid), ONCTYPE(xtypep)))
+.sp
+Create a varaible length array type.
+.HP
+FDECL(inq_vlen, (INCID(), INCTYPE(), ONAME(), OSIZET(datum_sizep), ONCTYPE(base_nc_typep)))
+.sp
+Learn about a varaible length array type.
+.HP
+FDECL(free_vlen, (nc_vlen_t *vl))
+.sp
+Free memory consumed by reading data of a variable length array type.
+.HP
+FDECL(put_vlen_element, (INCID(), INCTYPE(), IVOIDP(vlen_element), ISIZET(len), IVOIDP(data)))
+.sp
+Write one VLEN.
+.HP
+FDECL(get_vlen_element, (INCID(), INCTYPE(), OVOIDP(vlen_element), ISIZET(len), OVOIDP(data)))
+.sp
+Read one VLEN.
+.HP
+FDECL(free_string, (ISIZET(len), char **data))
+.sp
+Free memory consumed by reading data of a string type.
+.HP
+FDECL(inq_user_type, (INCID(), INCTYPE(), ONAME(), OSIZET(), ONCTYPE(), OSIZET(), OINT()))
+.sp
+Learn about a user define type.
+.HP
+FDECL(def_enum, (INCID(), INCTYPE(base_typeid), INAME(), ONCTYPE(typeidp)))
+.sp
+Define an enumeration type.
+.HP
+FDECL(insert_enum, (INCID(), INCTYPE(base_typeid), INAME(), const void *value))
+.sp
+Insert a name-value pair into enumeration type.
+.HP
+FDECL(inq_enum_member, (INCID(), INCTYPE(xtype), IINT(idx), ONAME(), void *value))
+.HP
+FDECL(inq_enum_ident, (INCID(), INCTYPE(xtype), IINT(idx), IINT64(value), OTEXTV(identifier)))
+.sp
+Learn about a name-value pair into enumeration type.
+.HP
+FDECL(def_opaque, (INCID(), ISIZET(size), INAME(), ONCTYPE(xtypep)))
+.sp
+Create an opaque type.
+.HP
+FDECL(inq_opaque, (INCID(), INCTYPE(xtype), ONAME(), OSIZET(sizep)))
+.sp
+Learn about opaque type.
+.HP
+.SH "GROUPS"
+.sp
+Users may organize data into hierarchical groups in netCDF-4/HDF5 files (unless MACRO(CLASSIC_MODEL) was used when creating the file).
+.HP
+FDECL(inq_grps, (INCID(), OINT(numgrps), OINTV(ncids)))
+.sp
+Learn how many groups (and their ncids) are available from the group represented by ncid.
+.HP
+FDECL(inq_grpname, (INCID(), ONAME()))
+.HP
+FDECL(inq_grpname_full, (INCID(), OLEN(), ONAME()))
+.HP
+FDECL(inq_grpname_len, (INCID(), OLEN()))
+.HP
+FDECL(inq_grp_parent, (INCID(), ONCID()))
+.HP
+FDECL(inq_grp_ncid, (INCID(), ONAME(), ONCID()))
+.HP
+FDECL(inq_full_ncid, (INCID(), ONAME(), ONCID()))
+.sp
+Learn about a group.
+.HP
+FDECL(inq_varids, (INCID(), ONVARS(), OINT()))
+.sp
+Get the varids in a group.
+.HP
+FDECL(inq_dimids, (INCID(), ONDIMS(), OINT(dimids), IINT(include_parents)))
+.sp
+Get the dimids in a group and (potentially) its parents.
+.HP
+FDECL(inq_typeids, (INCID(), OINT(ntypes), OINTV(typeids)))
+.sp
+Get the typeids of user-defined types in a group.
+.HP
+FDECL(def_grp, (INCID(), ONAME(), ONCID()))
+.sp
+Create a group.
+.LP
+>>)
+.SH "DIMENSIONS"
+.LP
+.HP
+FDECL(inq_dimid, (INCID(), INAME(), ODIMID()))
+.sp
+Given a dimension name, returns the ID of a netCDF dimension in DIMID().
+.HP
+FDECL(inq_dim, (INCID(), IDIMID(), ONAME(), OLEN()))
+.HP
+FDECL(inq_dimname, (INCID(), IDIMID(), ONAME()))
+.HP
+FDECL(inq_dimlen, (INCID(), IDIMID(), OLEN()))
+.sp
+Use these functions to find out about a dimension.
+ifelse(API,C,
+<<If either the NAME()
+argument or LEN() argument is a NULL() pointer, then
+the associated information will not be returned.  Otherwise,>>)
+NAME() should be  big enough (MACRO(MAX_NAME))
+to hold the dimension name as the name will be copied into your storage.
+The length return parameter, LEN()
+will contain the size of the dimension.
+For the unlimited dimension, the returned length is the current
+maximum value used for writing into any of the variables which use
+the dimension.
+.HP
+FDECL(rename_dim, (INCID(), IDIMID(), INAME()))
+.sp
+Renames an existing dimension in an open netCDF dataset.
+If the new name is longer than the old name, the netCDF dataset must be in 
+<<define>> mode.
+You cannot rename a dimension to have the same name as another dimension.
+.SH "VARIABLES"
+.LP
+.HP
+FDECL(def_var, (INCID(), INAME(), IXTYPE(), INDIMS(), IDIMIDS(), OVARID()))
+.sp
+Adds a new variable to a netCDF dataset. The netCDF must be in <<define>> mode.
+ifelse(API,C, <<If not NULL(), then >>)dnl
+VARID() will be set to the netCDF variable ID.
+\fIndims\fP will be the number of dimensions for the variable.
+\fIname\fP will be the name of the netCDF variable.
+\fIxtype\fP is the external, netCDF type of the variable and should be one of
+MACRO(BYTE)
+MACRO(CHAR),
+MACRO(SHORT),
+MACRO(INT),
+MACRO(FLOAT), or
+MACRO(DOUBLE),
+for CDF-1 and CDF-2 file formats.
+CDF-5 defines additional external types:
+MACRO(UBYTE),
+MACRO(USHORT),
+MACRO(UINT),
+MACRO(INT64), and
+MACRO(UINT64).
+\fIdimids\fP argument is a vector of ndims dimension IDs corresponding to the
+variable dimensions.
+.HP
+FDECL(inq_varid, (INCID(), INAME(), OVARID()))
+.sp
+Returns the ID of a netCDF variable in VARID() given its name.
+.HP
+FDECL(inq_var, (INCID(), IVARID(), ONAME(), OXTYPE(), ONDIMS(), ODIMIDS(),
+ONATTS()))
+.HP
+FDECL(inq_varname, (INCID(), IVARID(), ONAME()))
+.HP
+FDECL(inq_vartype, (INCID(), IVARID(), OXTYPE()))
+.HP
+FDECL(inq_varndims, (INCID(), IVARID(), ONDIMS()))
+.HP
+FDECL(inq_vardimid, (INCID(), IVARID(), ODIMIDS()))
+.HP
+FDECL(inq_varnatts, (INCID(), IVARID(), ONATTS()))
+.sp
+Returns information about a netCDF variable, given its ID.
+ifelse(API,C,
+<<If any of the
+return parameters (NAME(), XTYPE(), NDIMS(), DIMIDS(), or
+NATTS()) is a NULL() pointer, then the corresponding information
+will not be returned; hence, no space need be allocated for it.>>)
+.HP
+FDECL(rename_var, (INCID(), IVARID(), INAME()))
+.sp
+Changes the name of a netCDF variable.
+If the new name is longer than the old name, the netCDF must be in <<define>> mode.
+You cannot rename a variable to have the name of any existing variable.
+ifelse(NETCDF4,TRUE,
+<<
+.SH "VARIABLES IN NETCDF-4 FILES"
+.LP
+The following functions may only be used on variables in a
+netCDF-4/HDF5 data file. These functions must be called after the
+variable is defined, but before an enddef call.
+.sp
+FDECL(def_var_deflate, (INCID(), IVARID(), IINT(shuffle), IINT(deflate), IINT(deflate_level)))
+.sp
+Turn on compression and/or shuffle filter. (Shuffle filter is only useful for integer data.)
+.HP
+FDECL(inq_var_deflate, (INCID(), IVARID(), OINT(shufflep), OINT(deflatep), OINT(deflate_levelp)))
+.sp
+Learn about a variable's deflate settings.
+.HP
+FDECL(def_var_fletcher32, (INCID(), IVARID(), IINT(fletcher32)))
+.sp
+Turn on checksumming for a variable.
+.HP
+FDECL(inq_var_fletcher32, (INCID(), IVARID(), OINT(fletcher32)))
+.sp
+Learn about checksumming for a variable.
+.HP
+FDECL(def_var_chunking, (INCID(), IVARID(), IINT(storage), ISIZETV(chunksizesp)))
+.sp
+Set chunksizes for a variable.
+.HP
+FDECL(inq_var_chunking, (INCID(), IVARID(), OINT(storagep), OSIZETV(chunksizesp)))
+.sp
+Learn about chunksizes for a variable.
+.HP
+FDECL(def_var_fill, (INCID(), IVARID(), IINT(no_fill), ISIZETV(chunksizesp)))
+.sp
+Set a fill value for a variable.
+.HP
+FDECL(inq_var_fill, (INCID(), IVARID(), OINT(storagep), OSIZETV(chunksizesp)))
+.sp
+Learn the fill value for a variable.
+.HP
+FDECL(def_var_endian, (INCID(), IVARID(), IINT(endian)))
+.sp
+Set endianness of variable.
+.HP
+FDECL(inq_var_endian, (INCID(), IVARID(), OINT(endianp)))
+.sp
+Learn the endianness of a variable.
+.HP
+>>)
+.SH "WRITING AND READING WHOLE VARIABLES"
+.LP
+FUNC_FAMILY(<<PUT_VAR>>)
+.sp
+Writes an entire netCDF variable (i.e. all the values).  The netCDF
+dataset must be open and in data mode.  The type of the data is
+specified in the function name, and it is converted to the external
+type of the specified variable, if possible, otherwise an
+MACRO(ERANGE) error is returned. Note that rounding is not performed
+during the conversion. Floating point numbers are truncated when
+converted to integers.
+FUNC_FAMILY(<<GET_VAR>>)
+.sp
+Reads an entire netCDF variable (i.e. all the values).
+The netCDF dataset must be open and in data mode.  
+The data is converted from the external type of the specified variable,
+if necessary, to the type specified in the function name.  If conversion is
+not possible, an MACRO(ERANGE) error is returned.
+.SH "WRITING AND READING ONE DATUM"
+.LP
+FUNC_FAMILY(<<PUT_VAR1>>)
+.sp
+Puts a single data value into a variable at the position INDEX() of an
+open netCDF dataset that is in data mode.  The type of the data is
+specified in the function name, and it is converted to the external type
+of the specified variable, if possible, otherwise an MACRO(ERANGE)
+error is returned.
+FUNC_FAMILY(<<GET_VAR1>>)
+.sp
+Gets a single data value from a variable at the position INDEX()
+of an open netCDF dataset that is in data mode.  
+The data is converted from the external type of the specified variable,
+if necessary, to the type specified in the function name.  If conversion is
+not possible, an MACRO(ERANGE) error is returned.
+.SH "WRITING AND READING AN ARRAY"
+.LP
+FUNC_FAMILY(<<PUT_VARA>>)
+.sp
+Writes an array section of values into a netCDF variable of an open
+netCDF dataset, which must be in data mode.  The array section is specified
+by the START() and COUNT() vectors, which give the starting <<index>>
+and count of values along each dimension of the specified variable.
+The type of the data is
+specified in the function name and is converted to the external type
+of the specified variable, if possible, otherwise an MACRO(ERANGE)
+error is returned.
+FUNC_FAMILY(<<GET_VARA>>)
+.sp
+Reads an array section of values from a netCDF variable of an open
+netCDF dataset, which must be in data mode.  The array section is specified
+by the START() and COUNT() vectors, which give the starting <<index>>
+and count of values along each dimension of the specified variable.
+The data is converted from the external type of the specified variable,
+if necessary, to the type specified in the function name.  If conversion is
+not possible, an MACRO(ERANGE) error is returned.
+.SH "WRITING AND READING A SLICED ARRAY"
+.LP
+FUNC_FAMILY(<<PUT_VARS>>)
+.sp
+These functions are used for \fIstrided output\fP, which is like the
+array section output described above, except that
+the sampling stride (the interval between accessed values) is
+specified for each dimension.
+For an explanation of the sampling stride
+vector, see COMMON ARGUMENTS DESCRIPTIONS below.
+FUNC_FAMILY(<<GET_VARS>>)
+.sp
+These functions are used for \fIstrided input\fP, which is like the
+array section input described above, except that 
+the sampling stride (the interval between accessed values) is
+specified for each dimension.
+For an explanation of the sampling stride
+vector, see COMMON ARGUMENTS DESCRIPTIONS below.
+.SH "WRITING AND READING A MAPPED ARRAY"
+.LP
+FUNC_FAMILY(<<PUT_VARM>>)
+.sp
+These functions are used for \fImapped output\fP, which is like
+strided output described above, except that an additional <<index>> mapping
+vector is provided to specify the in-memory arrangement of the data
+values.
+For an explanation of the <<index>>
+mapping vector, see COMMON ARGUMENTS DESCRIPTIONS below.
+FUNC_FAMILY(<<GET_VARM>>)
+.sp
+These functions are used for \fImapped input\fP, which is like
+strided input described above, except that an additional <<index>> mapping
+vector is provided to specify the in-memory arrangement of the data
+values.
+For an explanation of the <<index>>
+mapping vector, see COMMON ARGUMENTS DESCRIPTIONS below.
+.SH "ATTRIBUTES"
+.LP
+FUNC_FAMILY(<<APUT>>)
+.HP
+FDECL(put_att, (INCID(), IVARID(), INAME(), INCTYPE(xtype), ISIZET(len), IVOIDP(ip)))
+.HP
+FDECL(get_att, (INCID(), IVARID(), INAME(), OVOIDP(ip)))
+.sp
+Unlike variables, attributes do not have 
+separate functions for defining and writing values.
+This family of functions defines a new attribute with a value or changes
+the value of an existing attribute.
+If the attribute is new, or if the space required to
+store the attribute value is greater than before,
+the netCDF dataset must be in <<define>> mode.
+The parameter LEN() is the number of values from OUT() to transfer.
+It is often one, except that for
+FREF(put_att_text) it will usually be
+ifelse(API,C, <<CODE(strlen(OUT())).>>, <<CODE(len_trim(OUT())).>>)
+.sp
+For these functions, the type component of the function name refers to
+the in-memory type of the value, whereas the XTYPE() argument refers to the
+external type for storing the value.  An MACRO(ERANGE)
+error results if
+a conversion between these types is not possible.  In this case the value
+is represented with the appropriate fill-value for the associated 
+external type.
+.HP
+FDECL(inq_attname, (INCID(), IVARID(), IATTNUM(), ONAME()))
+.sp
+Gets the
+name of an attribute, given its variable ID and attribute number.
+This function is useful in generic applications that
+need to get the names of all the attributes associated with a variable,
+since attributes are accessed by name rather than number in all other
+attribute functions.  The number of an attribute is more volatile than
+the name, since it can change when other attributes of the same variable
+are deleted.  The attributes for each variable are numbered
+from ifelse(API,C,0,1) (the first attribute) to
+NVATTS()<<>>ifelse(API,C,-1),
+where NVATTS() is
+the number of attributes for the variable, as returned from a call to
+FREF(inq_varnatts).
+ifelse(API,C,
+<<If the NAME() parameter is a NULL() pointer, no name will be
+returned and no space need be allocated.>>)
+.HP
+FDECL(inq_att, (INCID(), IVARID(), INAME(), OXTYPE(), OLEN()))
+.HP
+FDECL(inq_attid, (INCID(), IVARID(), INAME(), OATTNUM()))
+.HP
+FDECL(inq_atttype, (INCID(), IVARID(), INAME(), OXTYPE()))
+.HP
+FDECL(inq_attlen, (INCID(), IVARID(), INAME(), OLEN()))
+.sp
+These functions return information about a netCDF attribute,
+given its variable ID and name.  The information returned is the
+external type in XTYPE()
+and the number of elements in the attribute as LEN().
+ifelse(API,C,
+<<If any of the return arguments is a NULL() pointer,
+the specified information will not be returned.>>)
+.HP
+FDECL(copy_att, (INCID(), IVARIDIN(), INAME(), INCIDOUT(), IVARIDOUT()))
+.sp
+Copies an
+attribute from one netCDF dataset to another.  It can also be used to
+copy an attribute from one variable to another within the same netCDF.
+NCIDIN() is the netCDF ID of an input netCDF dataset from which the
+attribute will be copied.
+VARIDIN()
+is the ID of the variable in the input netCDF dataset from which the
+attribute will be copied, or MACRO(GLOBAL)
+for a global attribute.
+NAME()
+is the name of the attribute in the input netCDF dataset to be copied.
+NCIDOUT()
+is the netCDF ID of the output netCDF dataset to which the attribute will be 
+copied.
+It is permissible for the input and output netCDF ID's to be the same.  The
+output netCDF dataset should be in <<define>> mode if the attribute to be
+copied does not already exist for the target variable, or if it would
+cause an existing target attribute to grow.
+VARIDOUT()
+is the ID of the variable in the output netCDF dataset to which the attribute will
+be copied, or MACRO(GLOBAL) to copy to a global attribute.
+.HP
+FDECL(rename_att, (INCID(), IVARID(), INAME(), INEWNAME()))
+.sp
+Changes the
+name of an attribute.  If the new name is longer than the original name,
+the netCDF must be in <<define>> mode.  You cannot rename an attribute to
+have the same name as another attribute of the same variable.
+NAME() is the original attribute name.
+NEWNAME()
+is the new name to be assigned to the specified attribute.  If the new name
+is longer than the old name, the netCDF dataset must be in <<define>> mode.
+.HP
+FDECL(del_att, (INCID(), IVARID(), INAME()))
+.sp
+Deletes an attribute from a netCDF dataset.  The dataset must be in
+<<define>> mode.
+FUNC_FAMILY(<<AGET>>)
+.sp
+Gets the value(s) of a netCDF attribute, given its
+variable ID and name.  Converts from the external type to the type
+specified in
+the function name, if possible, otherwise returns an MACRO(ERANGE)
+error.
+All elements of the vector of attribute
+values are returned, so you must allocate enough space to hold
+them.  If you don't know how much space to reserve, call
+FREF(inq_attlen)
+first to find out the length of the attribute.
+.SH "COMMON ARGUMENT DESCRIPTIONS"
+.LP
+In this section we <<define>> some common arguments which are used in the 
+"FUNCTION DESCRIPTIONS" section.
+.TP
+INCID()
+is the netCDF ID returned from a previous, successful call to
+FREF(open) or FREF(create)
+.TP
+ONAME()
+is the name of a dimension, variable, or attribute. The names of 
+dimensions, variables and attributes consist of arbitrary
+sequences of alphanumeric characters (as well as underscore '_',
+period '.' and hyphen '-'), beginning with a letter or
+underscore. (However names commencing with underscore are reserved for
+system use.) Case is significant in netCDF names. A zero-length name
+is not allowed.
+ifelse(API,C,<<As an input argument, 
+it shall be a pointer to a 0-terminated string; as an output argument, it 
+shall be the address of a buffer in which to hold such a string.>>)
+The maximum allowable number of characters 
+ifelse(API,C,(excluding the terminating 0)) is MACRO(MAX_NAME).
+.TP
+IXTYPE()
+specifies the external data type of a netCDF variable or attribute and
+is one of the following:
+MACRO(BYTE), MACRO(CHAR), MACRO(SHORT), MACRO(INT), 
+MACRO(FLOAT), or MACRO(DOUBLE) for CDF-1 and CDF-2 file formats.
+These are used to specify 8-bit integers,
+characters, 16-bit integers, 32-bit integers, 32-bit IEEE floating point
+numbers, and 64-bit IEEE floating-point numbers, respectively.
+ifelse(API,C,
+<<(MACRO(LONG) in netCDF version 2 is now obsolete and set to MACRO(INT)).>>)
+CDF-5 defines additional external types:
+MACRO(UBYTE), MACRO(USHORT), MACRO(UINT), MACRO(INT64), and MACRO(UINT64).
+.TP
+ODIMIDS()
+is a vector of dimension ID's and defines the shape of a netCDF variable.
+The size of the vector shall be greater than or equal to the
+rank (i.e. the number of dimensions) of the variable (NDIMS()).
+The vector shall be ordered by the speed with which a dimension varies:
+DIMIDS()<<>>ifelse(API,C,<<[NDIMS()-1]>>,<<(1)>>)
+shall be the dimension ID of the most rapidly
+varying dimension and
+DIMIDS()<<>>ifelse(API,C,<<[0]>>,<<(NDIMS())>>)
+shall be the dimension ID of the most slowly
+varying dimension.
+The maximum possible number of
+dimensions for a variable is given by the symbolic constant
+MACRO(MAX_VAR_DIMS).
+.TP
+IDIMID()
+is the ID of a netCDF dimension.
+netCDF dimension ID's are allocated sequentially from the 
+ifelse(API,C,non-negative, positive)
+integers beginning with ifelse(API,C,0,1).
+.TP
+INDIMS()
+is either the total number of dimensions in a netCDF dataset or the rank
+(i.e. the number of dimensions) of a netCDF variable.
+The value shall not be negative or greater than the symbolic constant 
+MACRO(MAX_VAR_DIMS).
+.TP
+IVARID()
+is the ID of a netCDF variable or (for the attribute-access functions) 
+the symbolic constant
+MACRO(GLOBAL),
+which is used to reference global attributes.
+netCDF variable ID's are allocated sequentially from the 
+ifelse(API,C,non-negative,positive)
+integers beginning with ifelse(API,C,0,1).
+.TP
+ONATTS()
+is the number of global attributes in a netCDF dataset  for the
+FREF(inquire)
+function or the number
+of attributes associated with a netCDF variable for the
+FREF(varinq)
+function.
+.TP
+IINDEX()
+specifies the  coordinates of the netCDF data value to be accessed.
+The indices start at ifelse(API,C,0,1);
+thus, for example, the first data value of a
+two-dimensional variable is ifelse(API,C,(0,0),(1,1)).
+The size of the vector shall be at least the rank of the associated
+netCDF variable and its elements shall correspond, in order, to the
+variable's dimensions.
+.TP
+ISTART()
+specifies the starting point
+for accessing a netCDF variable's data values
+in terms of the indicial coordinates of 
+the corner of the array section.
+The indices start at ifelse(API,C,0,1);
+thus, the first data
+value of a variable is ifelse(API,C,(0, 0, ..., 0),(1, 1, ..., 1)).
+The size of the vector shall be at least the rank of the associated
+netCDF variable and its elements shall correspond, in order, to the
+variable's dimensions.
+.TP
+ICOUNT()
+specifies the number of indices selected along each dimension of the
+array section.
+Thus, to access a single value, for example, specify COUNT() as
+(1, 1, ..., 1).
+Note that, for strided I/O, this argument must be adjusted
+to be compatible with the STRIDE() and START() arguments so that 
+the interaction of the
+three does not attempt to access an invalid data co-ordinate.
+The elements of the
+COUNT() vector correspond, in order, to the variable's dimensions.
+.TP
+ISTRIDE()
+specifies the sampling interval along each dimension of the netCDF
+variable.   The elements of the stride vector correspond, in order,
+to the netCDF variable's dimensions (ARG(stride)<<>>ifelse(API,C,[0],<<(1)>>))
+gives the sampling interval along the most ifelse(API,C,slowly,rapidly) 
+varying dimension of the netCDF variable).  Sampling intervals are
+specified in type-independent units of elements (a value of 1 selects
+consecutive elements of the netCDF variable along the corresponding
+dimension, a value of 2 selects every other element, etc.).
+ifelse(API,C,<<A NULL() stride argument is treated as (1, 1, ... , 1).>>)
+.TP
+IIMAP()
+specifies the mapping between the dimensions of a netCDF variable and
+the in-memory structure of the internal data array.  The elements of
+the <<index>> mapping vector correspond, in order, to the netCDF variable's
+dimensions (ARG(imap)<<>>ifelse(API,C,[0],<<(1)>>) gives the distance
+between elements of the internal array corresponding to the most
+ifelse(API,C,slowly,rapidly) varying dimension of the netCDF variable).
+Distances between elements are specified in type-independent units of
+elements (the distance between internal elements that occupy adjacent
+memory locations is 1 and not the element's byte-length as in netCDF 2).
+ifelse(API,C,<<A NULL() pointer means the memory-resident values have
+the same structure as the associated netCDF variable.>>)
+.SH "VARIABLE PREFILLING"
+.LP
+PnetCDF does not support data filling.
+.SH "ENVIRONMENT VARIABLES"
+.TP 4
+.B PNETCDF_SAFE_MODE
+Set to 1 to enable metadata consistency check. Warning messages will
+be printed to stdout if any inconsistency is detected.
+.SH "MAILING-LISTS"
+.LP
+A mailing list is available for
+discussion of the PnetCDF interface and announcements about PnetCDF bugs,
+fixes, and enhancements.
+To subscribe or unsubscribe to the PnetCDF mailing list,
+visit https://lists.mcs.anl.gov/mailman/listinfo/parallel-netcdf
+.RE
+.SH "SEE ALSO"
+.LP
+.BR ncmpidump (1),
+.BR ncmpigen (1),
+.BR ncmpidiff (1),
+.BR ncmpivalid (1),
+.BR pnetcdf (3<<>>ifelse(API,C,,f)).
+.LP
+\fIPnetCDF User's Guide\fP, published
+by Northwestern University and Argonne National Laboratory.
+This document is adopted from the
+\fInetCDF User's Guide\fP, developed at
+the Unidata Program Center, University Corporation for Atmospheric
+Research, located in Boulder, Colorado.
+
+PnetCDF home page at http://cucis.ece.northwestern.edu/projects/PnetCDF/.
diff --git a/man/pnetcdf_f90.m4 b/man/pnetcdf_f90.m4
new file mode 100644
index 0000000..101cc4f
--- /dev/null
+++ b/man/pnetcdf_f90.m4
@@ -0,0 +1,768 @@
+.nr yr \n(yr+1900
+.af mo 01
+.af dy 01
+.TH PNETCDF 3f90 "RELEASE_DATE" "Printed: \n(yr.\n(mo.\n(dy" "LIBRARY FUNCTIONS"
+.SH NAME
+PnetCDF \- Parallel library for accessing files in Network Common Data Form (CDF, CDF-2 and CDF-5 formats)
+.SH SYNOPSIS
+.ft B
+.na
+.nh
+use pnetcdf
+.sp
+.SS Most Systems:
+mpif90 ... -lpnetcdf
+.sp
+.SS CRAY PVP Systems:
+f90 -dp -i64 ... -lpnetcdf
+
+.ad
+.hy
+.SH "LIBRARY VERSION"
+.LP
+This document describes Parallel netCDF APIs
+for the Fortran-90 programming language.
+.HP
+\fBcharacter*80 nf90mpi_inq_libvers(\|)
+.RS
+character(len=80) :: nf90mpi_inq_libvers\fR
+.RE
+.sp
+Returns a string identifying the version of the PnetCDF library, and
+when it was built, like: "RELEASE_STR".
+.LP
+The RCS \fBident(1)\fP command will find a string like
+"$\|Id: @\|(#) PnetCDF library version
+RELEASE_STR $"
+in the library. The SCCS \fBwhat(1)\fP command will find a string like
+"PnetCDF library version RELEASE_STR".
+.SH "ROUTINE DESCRIPTIONS"
+.LP
+All PnetCDF functions (except
+\fBnf90mpi_inq_libvers(\|)\fR and \fBnf90mpi_strerror(\|)\fR) return an integer 
+status.
+This behavior replaces the \fBrcode\fR argument
+used in previous versions of the library.
+If this returned status value is not equal to
+\fBnf90_noerr\fR (zero), it
+indicates that an error occurred. The possible status values are defined in 
+the module \fBpnetcdf\fP.
+.HP
+\fBfunction nf90mpi_strerror(\fIncerr\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncerr
+character(len=80) :: nf90mpi_strerror
+.fi
+.sp
+Returns a string textual translation of the \fIncerr\fP
+value, like "Attribute or variable name contains illegal characters"
+or "No such file or directory".
+.RE
+.HP
+\fBfunction nf90mpi_create(\fIcomm\fP, \fIpath\fP, \fIcmode\fP, \fIinfo\fP, \fIncid\fP)\fR
+.RS
+.nf
+integer, intent(in) :: comm
+character(len=*), intent(in) :: path
+integer, intent(in) :: cmode
+integer, intent(in) :: info
+integer, intent(out) :: ncid
+integer :: nf90mpi_create
+.fi
+.sp
+Creates a new netCDF dataset at \fIpath\fP collectively by a group of MPI
+processes specified by \fIcomm\fP, returning a netCDF ID in \fIncid\fP.  The
+argument \fIcmode\fP may include the bitwise-or of the following flags:
+\fBnf90_noclobber\fR to protect existing datasets (default is \fBnf90_clobber\fR,
+silently blows them away), \fBnf90_share\fR for stronger metadata data consistency
+control, \fBnf90_64bit_offset\fR to create a file in the 64-bit offset format
+(CDF-2), as opposed to classic format, the default, or \fBnf90_64bit_data\fR to
+create a file in the 64-bit data format (CDF-5).
+Use either \fBnf90_64bit_offset\fR or \fBnf90_64bit_data\fR.
+The 64-bit offset format allows the creation of very large files with far fewer
+restrictions than netCDF classic format, but can only be read by the netCDF
+library version 3.6 or greater. Users are cautioned that files that use the
+64-bit offset format will not be recognized by netCDF applications linked to an
+earlier version of the netCDF library than 3.6.  Applications linked to version
+3.6 or later will be able to transparently access either the classic format or
+64-bit offset format.
+The 64-bit data format allows the creation of very large array variables.
+CDF-5 files currently will not be recognized by netCDF 3 or 4 library.
+.
+
+The argument \fIcmode\fP must be consistent among all MPI processes that
+collectively create the file.  The argument \fIinfo\fP is an MPI info object.
+Users can use it to supply the file access hints further performance
+improvement.  The hints include existing MPI-IO hints as well as hints defined
+and used in PnetCDF.
+.sp
+When a netCDF dataset is created, it is opened in \fbnf90_write\fR mode.
+When this function returns, the new netCDF dataset is in define mode.
+.RE
+.HP
+\fBfunction nf90mpi_open(\fIcomm\fP, \fIpath\fP, \fImode\fP, \fIinfo\fP, \fIncid\fP)\fR
+.RS
+.nf
+integer, intent(in) :: comm
+character(len=*), intent(in) :: path
+integer, intent(in) :: mode
+integer, intent(in) :: info
+integer, intent(out) :: ncid
+integer :: nf90mpi_open
+.fi
+.sp
+Opens an existing netCDF dataset at \fIpath\fP collectively by a group of MPI
+processes specified by \fIcomm\fP, returning a netCDF ID in \fIncid\fP.  The type
+of access is described by the \fImode\fP parameter, which may include the
+bitwise-or of the following flags: \fBnf90_write\fR for read-write access (default
+read-only), \fBnf90_share\fR for stronger metadata data consistency control.
+.sp
+
+The argument \fImode\fP must be consistent among all MPI processes that
+collectively open the file.  The argument \fIinfo\fP is an MPI info object.
+Users can use it to supply the file access hints further performance
+improvement.  The hints include existing MPI-IO hints as well as hints defined
+and used in PnetCDF.
+.RE
+.HP
+\fBfunction nf90mpi_redef(\fIncid\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid
+integer :: nf90mpi_redef
+.fi
+.sp
+Puts an open netCDF dataset into define mode, 
+so dimensions, variables, and attributes can be added or renamed and 
+attributes can be deleted.
+.RE
+.HP
+\fBfunction nf90mpi_enddef(\fIncid\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid
+integer :: nf90mpi_enddef
+.fi
+.sp
+Takes an open netCDF dataset out of define mode.
+The changes made to the netCDF dataset
+while it was in define mode are checked and committed to disk if no
+problems occurred.
+After a successful call, variable data can be read or written to the dataset.
+.RE
+.HP
+\fBfunction nf90mpi_sync(\fIncid\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid
+integer :: nf90mpi_sync
+.fi
+.sp
+Unless the
+\fBnf90_share\fR
+bit is set in
+\fBnf90mpi_open(\|)\fR or \fBnf90mpi_create(\|)\fR,
+data written by PnetCDF APIs may be cached by local file system on each compute
+node.  This API flushes cached data by calling MPI_File_sync.
+.RE
+.HP
+\fBfunction nf90mpi_abort(\fIncid\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid
+integer :: nf90mpi_abort
+.fi
+.sp
+You don't need to call this function.
+This function is called automatically by
+\fBnf90mpi_close(\|)\fR
+if the netCDF dataset was in define mode and something 
+goes wrong with the commit.
+If the netCDF dataset isn't in define mode, then this function is equivalent to
+\fBnf90mpi_close(\|)\fR.
+If it is called after
+\fBnf90mpi_redef(\|)\fR,
+but before
+\fBnf90mpi_enddef(\|)\fR,
+the new definitions are not committed and the dataset is closed.
+If it is called after
+\fBnf90mpi_create(\|)\fR
+but before
+\fBnf90mpi_enddef(\|)\fR,
+the dataset disappears.
+.RE
+.HP
+\fBfunction nf90mpi_close(\fIncid\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid
+integer :: nf90mpi_close
+.fi
+.sp
+.sp
+Closes an open netCDF dataset.
+If the dataset is in define mode,
+\fBnf90mpi_enddef(\|)\fR
+will be called before closing.
+After a dataset is closed, its ID may be reassigned to another dataset.
+.RE
+.HP
+\fBfunction nf90mpi_inquire(\fIncid\fP, \fIndims\fP, \fInvars\fP,
+\fInatts\fP, \fIunlimdimid\fP, \fInformat\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid
+integer, optional, intent(out) :: ndims, nvars
+integer, optional, intent(out) :: natts, unlimdimid
+integer, optional, intent(out) :: nformat
+integer :: nf90mpi_inquire
+.fi
+.sp
+Inquire about an open netCDF dataset.
+\fIncid\fP is the netCDF ID of the open dataset.
+Upon successful return,
+\fIndims\fP will contain  the
+number of dimensions defined for this netCDF dataset,
+\fInvars\fP will contain the number of variables,
+\fInatts\fP will contain the number of attributes, and
+\fIunlimdimid\fP will contain the
+dimension ID of the unlimited dimension if one exists, or
+0 otherwise.
+\fInformat\fP will contain the format version number, rarely needed
+because the library detects the format version and behaves
+appropriately.
+.RE
+.HP
+\fBfunction nf90mpi_def_dim(\fIncid\fP, \fIname\fP, \fIlen\fP, \fIdimid\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid
+character(len=*), intent(in) :: name
+integer, intent(in) :: len
+integer, intent(out) :: dimid
+integer :: nf90mpi_def_dim
+.fi
+.sp
+Adds a new dimension to an open netCDF dataset, which must be 
+in define mode.
+\fIname\fP is the dimension name.
+\fIlen\fP is the size of the new dimension or \fBnf90mpi_unlimited\fP to define
+the unlimited dimension.
+On return, \fIdimid\fP will contain the dimension ID of the newly created 
+dimension.
+.RE
+.HP
+\fBfunction nf90mpi_inq_dimid(\fIncid\fP, \fIname\fP, \fIdimid\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid
+character(len=*), intent(in) :: name
+integer, intent(out) :: dimid
+integer :: nf90mpi_inq_dimid
+.fi
+.sp
+Given an open netCDF dataset and dimension name, returns the dimension ID of the
+netCDF dimension in \fIdimid\fP.
+.RE
+.HP
+\fBfunction nf90mpi_inquire_dimension(\fIncid\fP, \fIdimid\fP, \fIname\fP, \fIlen\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid, dimid
+character(len=*), optional, intent(out) :: name
+integer, optional, intent(out) :: len
+integer :: nf90mpi_inquire_dimension
+.fi
+.sp
+Inquire about a dimension.
+\fIname\fP should be  big enough (\fBnf90_max_name\fR)
+to hold the dimension name as the name will be copied into your storage.
+The length return parameter, \fIlen\fP
+will contain the size of the dimension.
+For the unlimited dimension, the returned length is the current
+maximum value used for writing into any of the variables which use
+the dimension.
+.RE
+.HP
+\fBfunction nf90mpi_rename_dim(\fIncid\fP, \fIdimid\fP, \fIname\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid
+character(len=*), intent(in) :: name
+integer, intent(in) :: dimid
+integer :: nf90mpi_rename_dim
+.fi
+.sp
+Renames an existing dimension in an open netCDF dataset.
+If the new name is longer than the old name, the netCDF dataset must be in 
+define mode.
+You cannot rename a dimension to have the same name as another dimension.
+.RE
+.HP
+\fBfunction nf90mpi_def_var(\fIncid\fP, \fIname\fP, \fIxtype\fP, \fIdimids\fP, \fIvarid\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid
+character(len=*), intent(in) :: name
+integer, intent(in) :: xtype
+integer, optional, dimension(:), intent(in) :: dimids
+integer :: nf90mpi_def_var
+.fi
+.sp
+Adds a new variable to a netCDF dataset. The netCDF must be in define mode.
+\fIname\fP will be the name of the netCDF variable.
+\fIxtype\fP is the external, netCDF type of the variable and should be one of
+\fBnf90_byte\fP,
+\fBnf90_char\fP,
+\fBnf90_short\fP,
+\fBnf90_int\fP,
+\fBnf90_float\fP, or
+\fBnf90_double\fP
+for CDF-1 and CDF-2 file formats.
+CDF-5 defines additional external types:
+\fBnf90_ubyte\fP,
+\fBnf90_ushort\fP,
+\fBnf90_uint\fP,
+\fBnf90_int64\fP, and
+\fBnf90_uint64\fP.
+The optional \fIdimids\fP argument contains the dimension ID-s of the domain
+of the netCDF variable and, consequently, determines the rank of the
+created variable:
+if \fIdimids\fP is omitted, then the netCDF variable will be a scalar;
+if \fIdimids\fP is a scalar, then the netCDF variable will be 1 dimensional;
+and if \fIdimids\fP is a vector, then the netCDF variable will
+have rank equal to the number of elements in \fIdimids\fP.
+\fIvarid\fP will be set to the netCDF variable ID.
+.RE
+.HP
+\fBfunction nf90mpi_inq_varid(\fIncid\fP, \fIname\fP, \fIvarid\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid
+character(len=*), intent(in) :: name
+integer, intent(out) :: varid
+integer :: nf90mpi_inq_varid
+.fi
+.sp
+Returns the ID of a netCDF variable in \fIvarid\fP given an open netCDF dataset
+and the name of the variable.
+.RE
+.HP
+\fBfunction nf90mpi_inquire_variable(\fIncid\fP, \fIvarid\fP, \fIname\fP, 
+\fIxtype\fP, \fIndims\fP, \fIdimids\fP, \fInatts\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid, varid
+character(len=*), optional, intent(out) :: name
+integer, optional, intent(out) :: xtype, ndims
+integer, dimension(*), optional, intent(out) :: dimids
+integer, optional, intent(out) :: natts
+integer :: nf90mpi_inquire_variable
+.fi
+.sp
+Inquire about a netCDF variable in an open netCDF dataset, given its 
+variable ID.
+On return, \fIname\fP will contain the name of the variable and should 
+be capacious enough (\fBnf90_max_name\fP).
+\fIxtype\fP will contain the external, netCDF type of the variable.
+\fIndims\fP will contain the dimensionality of the netCDF variable: if the
+variable is a scalar, then size(\fIndims\fP) will be zero; otherwise,
+size(\fIndims\fP) will be the rank of the variable and \fIndims\fP will contain
+the dimension ID-s of the netCDF dimensions that constitute the domain of the
+variable.
+\fInatts\fP will contain the number of attributes associated with the netCDF
+variable.
+.RE
+.HP
+\fBfunction nf90mpi_rename_var(\fIncid\fP, \fIvarid\fP, \fIname\fP)\fR
+.RS
+.nf
+integer, intent9in) :: ncid, varid
+character(len=*), intent(in) :: newname
+integer :: nf90mpi_rename_var
+.fi
+.sp
+Changes the name of a netCDF variable.
+If the new name is longer than the old name, the netCDF must be in define mode.
+You cannot rename a variable to have the name of any existing variable.
+.RE
+.HP
+\fBfunction nf90mpi_put_var(\fIncid\fP, \fIvarid\fP, \fIvalues\fP, 
+\fIstart\fP, \fIstride\fP, \fIimap\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid, varid
+<<whatever>>, intent(in) :: values
+integer, dimension(:), optional, intent(in) :: start
+integer, dimension(:), optional, intent(in) ::  stride
+integer, dimension(:), optional, intent(in) ::  imap
+integer :: nf90mpi_put_var
+.fi
+.sp
+Writes a value or values to a netCDF variable.
+The netCDF dataset must be open and in data mode.
+\fIvalues\fP contains the value(s) what will be written to the netCDF variable
+identified by \fIncid\fP and \fIvarid\fP; it may be a scalar or an array and
+must be of type
+\fBcharacter\fP,
+\fBinteger(kind=OneByteInt)\fP,
+\fBinteger(kind=TwoByteInt)\fP,
+\fBinteger(kind=FourByteInt)\fP,
+\fBinteger(kind=EightByteInt)\fP,
+\fBreal(kind=FourByteReal)\fP, or
+\fBreal(kind=EightByteReal)\fP.
+All values are converted to the external type
+of the netCDF variable, if possible; otherwise, an
+\fBnf90_erange\fR error is returned.
+The optional argument \fIstart\fP specifies
+the starting index in the netCDF variable for writing for each
+dimension of the netCDF variable.
+The optional argument \fIstride\fP specifies the sampling stride
+(the interval between accessed values in the netCDF variable)
+for each dimension of the netCDF variable (see COMMON ARGUMENT DESCRIPTIONS
+below).
+The optional argument \fIimap\fP specifies the in-memory arrangement of the data
+values (see COMMON ARGUMENT DESCRIPTIONS below).
+.RE
+.HP
+\fBfunction nf90mpi_get_var(\fIncid\fP, \fIvarid\fP, \fIvalues\fP, 
+\fIstart\fP, \fIstride\fP, \fIimap\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid, varid
+<<whatever>>, intent(out) :: values
+integer, dimension(:), optional, intent(in) :: start
+integer, dimension(:), optional, intent(in) ::  stride
+integer, dimension(:), optional, intent(in) ::  imap
+integer :: nf90mpi_get_var
+.fi
+.sp
+Reads a value or values from a netCDF variable.
+The netCDF dataset must be open and in data mode.
+\fIvalues\fP will receive the value(s) what will be read from the netCDF
+ variable
+identified by \fIncid\fP and \fIvarid\fP; it may be a scalar or an array and
+must be of type
+\fBcharacter\fP,
+\fBinteger(kind=OneByteInt)\fP,
+\fBinteger(kind=TwoByteInt)\fP,
+\fBinteger(kind=FourByteInt)\fP,
+\fBinteger(kind=EightByteInt)\fP,
+\fBreal(kind=FourByteReal)\fP, or
+\fBreal(kind=EightByteReal)\fP.
+All values are converted from the external type
+of the netCDF variable, if possible; otherwise, an
+\fBnf90_erange\fR error is returned.
+The optional argument \fIstart\fP specifies
+the starting index in the netCDF variable for reading for each
+dimension of the netCDF variable.
+The optional argument \fIstride\fP specifies the sampling stride
+(the interval between accessed values in the netCDF variable)
+for each dimension of the netCDF variable (see COMMON ARGUMENT DESCRIPTIONS
+below).
+The optional argument \fIimap\fP specifies the in-memory arrangement of the data
+values (see COMMON ARGUMENT DESCRIPTIONS below).
+.RE
+.HP
+\fBfunction nf90mpi_inquire_attribute(\fIncid\fP, \fIvarid\fP, \fIname\fP,
+\fIxtype\fP, \fIlen\fP, \fIattnum\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid, varid
+character(len=*), intent(in) :: name
+integer, optional, intent(out) :: xtype, len, attnum
+integer :: nf90mpi_inquire_attribute
+.fi
+.sp
+Inquires about the netCDF attribute named \fIname\fP, of variable \fIvarid\fP,
+in the open netCDF dataset \fIncid\fP.
+\fIxtype\fP will contain the external, netCDF type of the variable.
+\fIlen\fP will contain the number of elements in the attribute.
+\fIattnum\fP will contain the attribute number.
+.RE
+.HP
+\fBfunction nf90mpi_inq_attname(\fIncid\fP, \fIvarid\fP, \fIattnum\fP, 
+\fIname\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid, varid, attnum
+character(len=*), intent(out) :: name
+integer :: nf90mpi_inq_attname
+.fi
+.sp
+Gets the
+name of an attribute, given its variable ID and attribute number.
+This function is useful in generic applications that
+need to get the names of all the attributes associated with a variable
+because attributes are accessed by name rather than number in all other
+attribute functions (the number of an attribute is more volatile than
+the name because it can change when other attributes of the same variable
+are deleted).  The attributes for each variable are numbered
+from 1 (the first attribute) to
+\fInatts\fP, where \fInatts\fP is
+the number of attributes for the variable, as returned from a call to
+\fBnf90mpi_inquire_variable(\|)\fR.
+.RE
+.HP
+\fBfunction nf90mpi_put_att(\fIncid\fP, \fIvarid\fP, \fIname\fP,
+\fIvalues\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid, varid
+character(len=*), intent(in) :: name
+<<whatever>>, intent(in) :: values
+integer :: nf90mpi_put_att
+.fi
+.sp
+Unlike variables, attributes do not have 
+separate functions for defining and writing values.
+This function defines a new attribute with a value or changes
+the value of an existing attribute.
+If the attribute is new, or if the space required to
+store the attribute value is greater than before,
+the netCDF dataset must be in define mode.
+\fIvalues\fP contains the attribute values to be written; it may be a scalar
+or a vector and must be of type
+\fBcharacter\fP,
+\fBinteger(kind=OneByteInt)\fP,
+\fBinteger(kind=TwoByteInt)\fP,
+\fBinteger(kind=FourByteInt)\fP,
+\fBinteger(kind=EightByteInt)\fP,
+\fBreal(kind=FourByteReal)\fP, or
+\fBreal(kind=EightByteReal)\fP.
+.RE
+.HP
+\fBfunction nf90mpi_get_att(\fIncid\fP, \fIvarid\fP, \fIname\fP, \
+fIvalues\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid, varid
+character(len=*), intent(in) :: name
+<<whatever>>, intent(out) :: values
+integer :: nf90mpi_get_att
+.fi
+.sp
+Gets the value(s) of a netCDF attribute, given its
+variable ID and name.
+The values are returned in \fIvalues\fP, which must be of type
+\fBcharacter\fP,
+\fBinteger(kind=OneByteInt)\fP,
+\fBinteger(kind=TwoByteInt)\fP,
+\fBinteger(kind=FourByteInt)\fP,
+\fBinteger(kind=EightByteInt)\fP,
+\fBreal(kind=FourByteReal)\fP, or
+\fBreal(kind=EightByteReal)\fP.
+Converts from the external type to the type
+of the receiving variable, if possible; otherwise returns an \fBnf90_erange\fR
+error.
+All values of the attribute
+are returned, so you must allocate enough space to hold
+them.  If you don't know how much space to reserve, call
+\fBnf90mpi_inquire_attribute(\|)\fR
+first to find out the length of the attribute.
+.RE
+.HP
+\fBfunction nf90mpi_copy_att(\fIncid_in\fP, \fIvarid_in\fP, \fIname\fP, 
+\fIncid_out\fP, \fIvarid_out\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid_in, varid_in
+character(len=*), intent(in) :: name
+integer, intent(in) :: ncid_out, varid_out
+integer :: nf90mpi_copy_att
+.fi
+.sp
+Copies an
+attribute from one netCDF dataset to another.  It can also be used to
+copy an attribute from one variable to another within the same netCDF
+dataset.
+\fIncid_in\fP is the netCDF ID of an input netCDF dataset from which the
+attribute will be copied.
+\fIvarid_in\fP
+is the ID of the variable in the input netCDF dataset from which the
+attribute will be copied, or \fBnf90_global\fR
+for a global attribute.
+\fIname\fP
+is the name of the attribute in the input netCDF dataset to be copied.
+\fIncid_out\fP
+is the netCDF ID of the output netCDF dataset to which the attribute will be 
+copied.
+It is permissible for the input and output netCDF ID's to be the same.  The
+output netCDF dataset should be in define mode if the attribute to be
+copied does not already exist for the target variable, or if it would
+cause an existing target attribute to grow.
+\fIvarid_out\fP
+is the ID of the variable in the output netCDF dataset to which the 
+attribute will
+be copied, or \fBnf90_global\fR to copy to a global attribute.
+.RE
+.HP
+\fBfunction nf90mpi_rename_att(\fIncid\fP, \fIvarid\fP, \fIname\fP, 
+\fInewname\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid, varid
+character(len=*), intent(in) :: name, newname
+integer :: nf90mpi_rename_att
+.fi
+.sp
+Changes the
+name of an attribute.  If the new name is longer than the original name,
+the netCDF must be in define mode.  You cannot rename an attribute to
+have the same name as another attribute of the same variable.
+\fIname\fP is the original attribute name.
+\fInewname\fP
+is the new name to be assigned to the specified attribute.  If the new name
+is longer than the old name, the netCDF dataset must be in define mode.
+.RE
+.HP
+\fBfunction nf90mpi_del_att(\fIncid\fP, \fIvarid\fP, \fIname\fP)\fR
+.RS
+.nf
+integer, intent(in) :: ncid, varid
+character(len=*), intent(in) :: name
+integer :: nf90mpi_del_att
+.fi
+.sp
+Deletes an attribute from a netCDF dataset.  The dataset must be in
+define mode.
+.RE
+.SH "COMMON ARGUMENT DESCRIPTIONS"
+.LP
+In this section we define some common arguments which are used in the 
+"FUNCTION DESCRIPTIONS" section.
+.TP
+integer \fIncid\fP
+is the netCDF ID returned from a previous, successful call to
+\fBnf90mpi_open(\|)\fR or \fBnf90mpi_create(\|)\fR
+.TP
+character(len=*) \fIname\fP
+is the name of a dimension, variable, or attribute.
+It shall begin with an alphabetic character, followed by
+zero or more alphanumeric characters including the underscore
+(`_') or hyphen (`-').  Case is significant.
+The maximum allowable number of characters 
+is \fBnf90_max_name\fR.
+Names that begin with an underscore (`_') are reserved for use
+by the netCDF and PnetCDF interfaces.
+.TP
+integer \fIxtype\fP
+specifies the external data type of a netCDF variable or attribute and
+is one of the following:
+\fBnf90_byte\fR, \fBnf90_char\fR, \fBnf90_short\fR, \fBnf90_int\fR, 
+\fBnf90_float\fR, or \fBnf90_double\fR.
+These are used to specify 8-bit integers,
+characters, 16-bit integers, 32-bit integers, 32-bit IEEE floating point
+numbers, and 64-bit IEEE floating-point numbers, respectively.
+
+.TP
+integer \fIdimids\fP
+is a vector of dimension ID's and defines the shape of a netCDF variable.
+The size of the vector shall be greater than or equal to the
+rank (i.e. the number of dimensions) of the variable (\fIndims\fP).
+The vector shall be ordered by the speed with which a dimension varies:
+\fIdimids\fP(\|1) shall be the dimension ID of the most rapidly
+varying dimension and
+\fIdimids\fP(\fIndims\fP)
+shall be the dimension ID of the most slowly
+varying dimension.
+The maximum possible number of
+dimensions for a variable is given by the symbolic constant
+\fBnf90_max_var_dims\fR.
+.TP
+integer \fIdimid\fP
+is the ID of a netCDF dimension.
+netCDF dimension ID's are allocated sequentially from the 
+positive
+integers beginning with 1.
+.TP
+integer \fIndims\fP
+is either the total number of dimensions in a netCDF dataset or the rank
+(i.e. the number of dimensions) of a netCDF variable.
+The value shall not be negative or greater than the symbolic constant 
+\fBnf90_max_var_dims\fR.
+.TP
+integer \fIvarid\fP
+is the ID of a netCDF variable or (for the attribute-access functions) 
+the symbolic constant
+\fBnf90_global\fR,
+which is used to reference global attributes.
+netCDF variable ID's are allocated sequentially from the 
+positive
+integers beginning with 1.
+.TP
+integer \fInatts\fP
+is the number of global attributes in a netCDF dataset  for the
+\fBnf90mpi_inquire(\|)\fR
+function or the number
+of attributes associated with a netCDF variable for the
+\fBnf90mpi_varinq(\|)\fR
+function.
+.TP
+integer(kind=MPI_OFFSET) \fIstart\fP
+specifies the starting point
+for accessing a netCDF variable's data values
+in terms of the indicial coordinates of 
+the corner of the array section.
+The indices start at 1;
+thus, the first data
+value of a variable is (1, 1, ..., 1).
+The size of the vector shall be at least the rank of the associated
+netCDF variable and its elements shall correspond, in order, to the
+variable's dimensions.
+.TP
+integer(kind=MPI_OFFSET) \fIstride\fP
+specifies the sampling interval along each dimension of the netCDF
+variable.   The elements of the stride vector correspond, in order,
+to the netCDF variable's dimensions (\fIstride\fP(1))
+gives the sampling interval along the most rapidly 
+varying dimension of the netCDF variable).  Sampling intervals are
+specified in type-independent units of elements (a value of 1 selects
+consecutive elements of the netCDF variable along the corresponding
+dimension, a value of 2 selects every other element, etc.).
+
+.TP
+integer(kind=MPI_OFFSET) \fIimap\fP
+specifies the mapping between the dimensions of a netCDF variable and
+the in-memory structure of the internal data array.  The elements of
+the index mapping vector correspond, in order, to the netCDF variable's
+dimensions (\fIimap\fP gives the distance
+between elements of the internal array corresponding to the most
+rapidly varying dimension of the netCDF variable).
+Distances between elements are specified in type-independent units of
+elements (the distance between internal elements that occupy adjacent
+memory locations is 1 and not the element's byte-length as in netCDF 2).
+
+.SH "VARIABLE PREFILLING"
+.LP
+PnetCDF does not support data filling.
+.SH "ENVIRONMENT VARIABLES"
+.TP 4
+.B PNETCDF_SAFE_MODE
+Set to 1 to enable metadata consistency check. Warning messages will
+be printed to stdout if any inconsistency is detected.
+.SH "MAILING-LISTS"
+.LP
+A mailing list is available for
+discussion of the PnetCDF interface and announcements about PnetCDF bugs,
+fixes, and enhancements.
+To subscribe or unsubscribe to the PnetCDF mailing list,
+visit https://lists.mcs.anl.gov/mailman/listinfo/parallel-netcdf
+.RE
+.SH "SEE ALSO"
+.LP
+.BR ncmpidump (1),
+.BR ncmpigen (1),
+.BR ncmpidiff (1),
+.BR ncmpivalid (1),
+.BR pnetcdf (3f90).
+.LP
+\fIPnetCDF User's Guide\fP, published
+by Northwestern University and Argonne National Laboratory.
+This document is adopted from the
+\fInetCDF User's Guide\fP, developed at
+the Unidata Program Center, University Corporation for Atmospheric
+Research, located in Boulder, Colorado.
+
+PnetCDF home page at http://cucis.ece.northwestern.edu/projects/PnetCDF/.
diff --git a/pbs.script b/pbs.script
new file mode 100644
index 0000000..8494a0d
--- /dev/null
+++ b/pbs.script
@@ -0,0 +1,18 @@
+#PBS -q debug
+#PBS -l walltime=00:10:00
+#PBS -l mppwidth=8
+#PBS -N pnetcdf_test
+#PBS -j oe
+#PBS -V
+
+cd $PBS_O_WORKDIR
+
+set OUT_DIR = /output/file/directory
+
+# test seqential programs
+make check TEST_MPIRUN="aprun -n NP" TEST_OUTDIR=$OUT_DIR TEST_SEQRUN="aprun -n 1"
+
+# test parallel programs
+make ptest TEST_MPIRUN="aprun -n NP" TEST_OUTDIR=$OUT_DIR TEST_SEQRUN="aprun -n 1"
+
+
diff --git a/rules.make b/rules.make
new file mode 100644
index 0000000..6e88e3d
--- /dev/null
+++ b/rules.make
@@ -0,0 +1,260 @@
+# $Id: rules.make 2285 2015-12-30 20:48:25Z wkliao $
+
+# The purpose of this file is to contain common make(1) rules.
+# It should be processed by every execution of the that utility.
+
+.SUFFIXES:
+.SUFFIXES:	.a .o .i .f .c .cpp .F .y .l .m4 .f90 .F90
+
+
+################################################################################
+# Compilation (including preprocessing):
+
+.c.o:
+	$(COMPILE.c) $<
+
+.c.i:
+	$(CPP) $(CPPFLAGS) $< >$@
+
+.cpp.o:
+	$(COMPILE.cxx) $<
+
+.f.o:
+	$(COMPILE.f) $<
+
+.f90.o:
+	$(COMPILE.f90) $<
+
+.F90.o:
+	$(COMPILE.F90) $<
+
+.F.o:
+	$(COMPILE.F) $<
+
+# Not all FORTRAN compilers support C-preprocessing of *.F files; ergo, a 
+# relatively complicated rule ensues.
+# .F.o:
+# 	@case "$(COMPILE.F)" in	\
+# 	    '')	\
+# 		set -x;	\
+# 		$(FPP) $(FPPFLAGS) -C $*.F | grep -v '^#' >$*-tmp.f || 	\
+# 		    ($(RM) -f $*-tmp.f ; exit 1);	\
+# 		$(COMPILE.f) -o $@ $*-tmp.f || ($(RM) -f $*-tmp.f; exit 1);	\
+# 		$(RM) -f $*-tmp.f;	\
+# 		;;	\
+# 	    *)	\
+# 		$(COMPILE.F) $<;	\
+# 		;;	\
+# 	esac
+
+#.F.f:
+#	$(FPP) $(FPPFLAGS) $*.F | grep -v '^#' >$*.f || ($(RM) -f $*.f; exit 1)
+
+.m4.c:
+	$(M4) $(M4FLAGS) $< >$@
+
+.m4.F:
+	$(M4) $(M4FLAGS) $< >$@
+
+.m4.f90:
+	$(M4) $(M4FLAGS) $< >$@
+
+.m4.F90:
+	$(M4) $(M4FLAGS) $< >$@
+
+
+################################################################################
+# Libraries:
+
+# lib:		$(LIBRARY)
+
+#-------------------------------------------------------------------------------
+# Shared Libraries:
+#
+# Here only as a place holder and notebook.  Don't try to use this stuff
+# unless you really, really know what you're doing!  (And even then we
+# guarantee nothing!)
+#
+shared_library:
+	@case `uname -sr` in \
+	HP-UX*) \
+	    $(MAKE) $(MFLAGS) hpux_shared_library;; \
+	IRIX*) \
+	    $(MAKE) $(MFLAGS) irix_shared_library;; \
+	Linux*) \
+	    $(MAKE) $(MFLAGS) linux_shared_library;; \
+	OSF1*) \
+	    $(MAKE) $(MFLAGS) osf1_shared_library;; \
+	'SunOS 4'*) \
+	    $(MAKE) $(MFLAGS) sunos4_shared_library;; \
+	'SunOS 5'*) \
+	    $(MAKE) $(MFLAGS) sunos5_shared_library;; \
+	*) \
+	    echo 1>&2 "Don't know how to make a shared library" \
+		"on this system"; \
+	    exit 1;; \
+	esac
+
+hpux_shared_library:
+	nm libpnetcdf.a | grep extern | grep entry | \
+	    awk '-F|' '{print $$1}' | sed 's/^/-u /' >symbols.log
+	ld -o $(LIBRARY:.a=.sl) -b -c symbols.log $(LIBRARY)
+	$(RM) -f symbols.log
+irix_shared_library:
+	ld -o $(LIBRARY:.a=.so) -shared -no_archive \
+	    -all $(LIBRARY) -none -lc -lC $(LIBS)
+linux_shared_library:
+	ld -o $(LIBRARY:.a=.so) -shared --whole-archive $(LIBRARY)
+osf1_shared_library:
+	ld -o $(LIBRARY:.a=.so) -shared -all $(LIBRARY)
+sunos4_shared_library:
+	undefopts=`/bin/nm $(LIBRARY) | awk '$$2~/^T$$/{print $$3}' | \
+		   sed 's/^/-u /'` && \
+	    ld -o $(LIBRARY:.a=.so) $$undefopts $(LIBRARY)
+sunos5_shared_library:
+	undefopts=`/usr/ccs/bin/nm $(LIBRARY) | grep GLOB | grep FUNC | \
+		   awk '-F|' '{print $$8}' | sed 's/^/-u /'` && \
+	    ld -o $(LIBRARY:.a=.so) -G $$undefopts $(LIBRARY)
+
+
+################################################################################
+# Linking:
+
+
+################################################################################
+# $(INSTALL)ation:
+
+$(INCDIR)/$(HEADER):	$(INCDIR) $(HEADER)
+	$(INSTALL) $(srcdir)/$(HEADER) $@
+$(INCDIR)/$(HEADER1):	$(INCDIR) $(HEADER1)
+	$(INSTALL) $(srcdir)/$(HEADER1) $@
+$(INCDIR)/$(HEADER2):	$(INCDIR) $(HEADER2)
+	$(INSTALL) $(srcdir)/$(HEADER2) $@
+$(INCDIR)/$(HEADER3):	$(INCDIR) $(HEADER3)
+	$(INSTALL) $(srcdir)/$(HEADER3) $@
+
+$(LIBDIR)/$(LIBRARY):	$(LIBDIR) $(LIBRARY)
+	$(INSTALL) -d -m 755 $(LIBDIR)
+	$(INSTALL) -m 644  $(LIBRARY) $@
+
+$(BINDIR)/$(PROGRAM):	$(BINDIR) $(PROGRAM)
+	$(INSTALL) -d -m 755 $(BINDIR)
+	$(INSTALL) -m 755  $(PROGRAM) $@
+
+#$(BINDIR) \
+#$(INCDIR) \
+#$(LIBDIR) \
+#$(MANDIR) :
+#	-test -d $@ || mkdir $@
+
+#$(MANDIR)/man1 \
+#$(MANDIR)/man3 \
+#$(MANDIR)/man3f \
+#$(MANDIR)/man3f90 :		$(MANDIR)
+#	-test -d $@ || mkdir $@
+
+# $(MANDIR)/man1/$(MANUAL):	$(MANDIR)/man1 $(MANUAL)
+# 	$(INSTALL) $(srcdir)/$(MANUAL) $@
+# $(MANDIR)/man3/$(MANUAL):	$(MANDIR)/man3 $(MANUAL)
+# 	$(INSTALL) $(srcdir)/$(MANUAL) $@
+# $(MANDIR)/man3f/$(MANUAL):	$(MANDIR)/man3 $(MANDIR)/man3/$(MANUAL) \
+# 				$(MANDIR)/man3f
+# 	$(RM) -f $@
+# 	$(LN_S) $(MANDIR)/man3/$(MANUAL) $@
+# $(MANDIR)/man3f90/$(MANUAL):	$(MANDIR)/man3 $(MANDIR)/man3/$(MANUAL) \
+# 				$(MANDIR)/man3f90
+# 	$(RM) -f $@
+# 	$(LN_S) $(MANDIR)/man3/$(MANUAL) $@
+
+################################################################################
+# Cleanup:
+
+clean:		FORCE
+	@if [ -n "$(SUBDIRS)" ]; then \
+	    subdirs="$(SUBDIRS)"; \
+	    for subdir in $$subdirs; do \
+		(cd $$subdir && $(MAKE) $(MFLAGS) clean) ; \
+	    done; \
+	fi
+	@$(RM) -f *.o *.a *.so *.sl *.i *.Z core core.* $(GARBAGE) \
+		  *.gcda *.gcno gmon.out
+
+distclean:	FORCE
+	@if [ -n "$(PACKING_SUBDIRS)" ]; then \
+	    subdirs="$(PACKING_SUBDIRS)"; \
+	    for subdir in $$subdirs; do \
+		(cd $$subdir && $(MAKE) $(MFLAGS) distclean) ; \
+	    done; \
+	fi
+	@if [ -n "$(PACKING_SUBDIRS)" ]; then \
+	    subdirs="$(PACKING_SUBDIRS)"; \
+	    for subdir in $$subdirs; do \
+		if ! [ $(srcdir) -ef `pwd` ] ; then rmdir $$subdir ; fi \
+	    done; \
+	fi
+	@$(RM) -rf SunWS_cache
+	@$(RM) -f *.o *.a *.so *.sl *.i *.Z core core.* $(GARBAGE) \
+		  *.gcda *.gcno gmon.out \
+	          MANIFEST *.log $(DIST_GARBAGE) cscope.out cscope.files
+	@$(RM) -f Makefile
+
+################################################################################
+# Dependencies:
+
+# This target should only need to be made at the UPC.
+# NOTES:
+#   *  The target file might be a symbolic link.
+#   *  The name of the target doesn't match the name of the created file to
+#      prevent constant updating of the included file `depend' by make(1).
+#
+deps:		FORCE
+	$(CC_MAKEDEPEND) $(CPPFLAGS) *.c | grep -v '/usr/include' >>depend
+	sort -u -o depend depend
+
+
+################################################################################
+# Distribution:
+
+# The following rule echoes the contents of $(PACKING_LIST) in the
+# current directory and in all subdirectories.  All pathnames are made
+# relative to the current directory.
+#
+MANIFEST.echo:	FORCE
+	echo $(PACKING_LIST) | fmt -1
+	if [ -n "$(PACKING_SUBDIRS)" ]; then \
+	    subdirs="$(PACKING_SUBDIRS)"; \
+	    for subdir in $$subdirs; do \
+		(cd $$subdir && \
+		echo 1>&2 Creating $@ in `pwd` && \
+		$(MAKE) $(MFLAGS) MANIFEST.echo | sed "s|^|$$subdir/|") || exit 1; \
+	    done; \
+	else \
+	   :; \
+	fi
+
+# The following rule ensures that all files in $(PACKING_LIST) exist in
+# the current directory and in all subdirectories.
+#
+ensure_manifest:	$(PACKING_LIST) FORCE
+	if [ -n "$(SUBDIRS)" ]; then \
+	    subdirs="$(SUBDIRS)"; \
+	    for subdir in $$subdirs; do \
+		(cd $$subdir && \
+		echo 1>&2 Creating $@ in `pwd` && \
+		$(MAKE) $(MFLAGS) ensure_manifest) || exit 1; \
+	    done; \
+	else \
+	   :; \
+	fi
+
+
+################################################################################
+# Misc:
+
+FORCE:
+
+.PHONY: FORCE all library clean distclean TAGS clean_macros rmdir_src_test b-test c-test f-test
+.PHONY: subdirs $(SUBDIRS) install $(INSTALLDIRS) uninstall $(UNINSTALLDIRS)
+.PHONY: tests check testing $(CHECK_DIRS) $(PTEST_DIRS) verbose_check verbose_testing $(VCHECK_DIRS)
+.PHONY: ptest ptests ptest2 ptest4 ptest6 ptest8 ptest10
+
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
new file mode 100644
index 0000000..99fe19e
--- /dev/null
+++ b/scripts/Makefile.in
@@ -0,0 +1,24 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 1388 2013-08-30 19:25:21Z wkliao $
+#
+# @configure_input@
+
+srcdir  = @srcdir@
+VPATH   = @srcdir@
+
+include ../macros.make
+
+GARBAGE      =
+
+PACKING_LIST = config.guess \
+               config.sub \
+               install-sh \
+               Makefile.in
+
+all:
+
+include $(srcdir)/../rules.make
+
diff --git a/scripts/config.guess b/scripts/config.guess
new file mode 100755
index 0000000..43f0cdb
--- /dev/null
+++ b/scripts/config.guess
@@ -0,0 +1,1519 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+#   2011 Free Software Foundation, Inc.
+
+timestamp='2011-10-01'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner.  Please send patches (context
+# diff format) to <config-patches at gnu.org> and include a ChangeLog
+# entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
+Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi at noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep -q __ELF__
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+		os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+	echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee at wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    s390x:SunOS:*:*)
+	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux${UNAME_RELEASE}
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	eval $set_cc_for_build
+	SUN_ARCH="i386"
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH="x86_64"
+	    fi
+	fi
+	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[4567])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH="hppa2.0n" ;;
+			  64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+			esac ;;
+		    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^		//' << EOF >$dummy.c
+
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
+
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
+
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep -q __LP64__
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+	exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+	exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+	exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+	exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    5000:UNIX_System_V:4.*:*)
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case ${UNAME_PROCESSOR} in
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:windows32*:*)
+	# uname -m includes "-pc" on this system.
+	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:*)
+	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    authenticamd | genuineintel | EM64T)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    8664:Windows_NT:*)
+	echo x86_64-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-gnu
+	else
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+	    fi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit ;;
+    crisv32:Linux:*:*)
+	echo crisv32-axis-linux-gnu
+	exit ;;
+    frv:Linux:*:*)
+	echo frv-unknown-linux-gnu
+	exit ;;
+    hexagon:Linux:*:*)
+	echo hexagon-unknown-linux-gnu
+	exit ;;
+    i*86:Linux:*:*)
+	LIBC=gnu
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+	echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef ${UNAME_MACHINE}
+	#undef ${UNAME_MACHINE}el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=${UNAME_MACHINE}el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=${UNAME_MACHINE}
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    or32:Linux:*:*)
+	echo or32-unknown-linux-gnu
+	exit ;;
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-gnu
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-gnu
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit ;;
+    sh64*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-gnu
+	exit ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit ;;
+    xtensa*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+	# Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configury will decide that
+	# this is a cross-build.
+	echo i586-pc-msdosdjgpp
+	exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel at ccMail.Census.GOV>
+	echo i586-unisys-sysv4
+	exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes at openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf at swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green at stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green at stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+		echo mips-nec-sysv${UNAME_RELEASE}
+	else
+		echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+	exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    i386)
+		eval $set_cc_for_build
+		if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+		  if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		      (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		      grep IS_64BIT_ARCH >/dev/null
+		  then
+		      UNAME_PROCESSOR="x86_64"
+		  fi
+		fi ;;
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NEO-?:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+	echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+    i*86:AROS:*:*)
+	echo ${UNAME_MACHINE}-pc-aros
+	exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+	"4"
+#else
+	""
+#endif
+	); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    c34*)
+	echo c34-convex-bsd
+	exit ;;
+    c38*)
+	echo c38-convex-bsd
+	exit ;;
+    c4*)
+	echo c4-convex-bsd
+	exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches at gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/scripts/config.sub b/scripts/config.sub
new file mode 100755
index 0000000..5b87368
--- /dev/null
+++ b/scripts/config.sub
@@ -0,0 +1,1767 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+#   2011 Free Software Foundation, Inc.
+
+timestamp='2011-10-08'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches at gnu.org>.  Submit a context
+# diff and a properly formatted GNU ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches at gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
+Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray | -microblaze)
+		os=
+		basic_machine=$1
+		;;
+	-bluegene*)
+		os=-cnk
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+	-chorusrdb)
+		os=-chorusrdb
+		basic_machine=$1
+		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+        | be32 | be64 \
+	| bfin \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| epiphany \
+	| fido | fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| hexagon \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| le32 | le64 \
+	| lm32 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore | mep | metag \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64octeon | mips64octeonel \
+	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| moxie \
+	| mt \
+	| msp430 \
+	| nds32 | nds32le | nds32be \
+	| nios | nios2 \
+	| ns16k | ns32k \
+	| open8 \
+	| or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
+	| pyramid \
+	| rx \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| we32k \
+	| x86 | xc16x | xstormy16 | xtensa \
+	| z8k | z80)
+		basic_machine=$basic_machine-unknown
+		;;
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | picochip)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| be32-* | be64-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
+	| clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| hexagon-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| le32-* | le64-* \
+	| lm32-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64octeon-* | mips64octeonel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nds32-* | nds32le-* | nds32be-* \
+	| nios-* | nios2-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+	| pyramid-* \
+	| romp-* | rs6000-* | rx-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+	| tahoe-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tile*-* \
+	| tron-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aros)
+		basic_machine=i386-pc
+		os=-aros
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	bluegene*)
+		basic_machine=powerpc-ibm
+		os=-cnk
+		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16 | cr16-*)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	microblaze)
+		basic_machine=microblaze-xilinx
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc | ppcbe)	basic_machine=powerpc-unknown
+		;;
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tile*)
+		basic_machine=$basic_machine-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	z80-*-coff)
+		basic_machine=z80-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+	# First match some system type aliases
+	# that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-auroraux)
+		os=-auroraux
+		;;
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* | -aros* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* | -cegcc* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-dicos*)
+		os=-dicos
+		;;
+	-nacl*)
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	score-*)
+		os=-elf
+		;;
+	spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-cnk*|-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/scripts/install-sh b/scripts/install-sh
new file mode 100755
index 0000000..a9244eb
--- /dev/null
+++ b/scripts/install-sh
@@ -0,0 +1,527 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2011-01-19.21; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""	$nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+	shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+	case $mode in
+	  *' '* | *'	'* | *'
+'*	  | *'*'* | *'?'* | *'['*)
+	    echo "$0: invalid mode: $mode" >&2
+	    exit 1;;
+	esac
+	shift;;
+
+    -o) chowncmd="$chownprog $2"
+	shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+	# Protect names problematic for `test' and other utilities.
+	case $dst_arg in
+	  -* | [=\(\)!]) dst_arg=./$dst_arg;;
+	esac
+	shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)	shift
+	break;;
+
+    -*)	echo "$0: invalid option: $1" >&2
+	exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+    # Protect names problematic for `test' and other utilities.
+    case $dst_arg in
+      -* | [=\(\)!]) dst_arg=./$dst_arg;;
+    esac
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  do_exit='(exit $ret); exit $ret'
+  trap "ret=129; $do_exit" 1
+  trap "ret=130; $do_exit" 2
+  trap "ret=141; $do_exit" 13
+  trap "ret=143; $do_exit" 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+	u_plus_rw=
+      else
+	u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names problematic for `test' and other utilities.
+  case $src in
+    -* | [=\(\)!]) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+    dst=$dst_arg
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+	echo "$0: $dst_arg: Is a directory" >&2
+	exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+	(dirname "$dst") 2>/dev/null ||
+	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	     X"$dst" : 'X\(//\)[^/]' \| \
+	     X"$dst" : 'X\(//\)$' \| \
+	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+	echo X"$dst" |
+	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)[^/].*/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\/\)$/{
+		   s//\1/
+		   q
+		 }
+		 /^X\(\/\).*/{
+		   s//\1/
+		   q
+		 }
+		 s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+	# Create intermediate dirs using mode 755 as modified by the umask.
+	# This is like FreeBSD 'install' as of 1997-10-28.
+	umask=`umask`
+	case $stripcmd.$umask in
+	  # Optimize common cases.
+	  *[2367][2367]) mkdir_umask=$umask;;
+	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+	  *[0-7])
+	    mkdir_umask=`expr $umask + 22 \
+	      - $umask % 100 % 40 + $umask % 20 \
+	      - $umask % 10 % 4 + $umask % 2
+	    `;;
+	  *) mkdir_umask=$umask,go-w;;
+	esac
+
+	# With -d, create the new directory with the user-specified mode.
+	# Otherwise, rely on $mkdir_umask.
+	if test -n "$dir_arg"; then
+	  mkdir_mode=-m$mode
+	else
+	  mkdir_mode=
+	fi
+
+	posix_mkdir=false
+	case $umask in
+	  *[123567][0-7][0-7])
+	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
+	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+	    ;;
+	  *)
+	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+	    if (umask $mkdir_umask &&
+		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+	    then
+	      if test -z "$dir_arg" || {
+		   # Check for POSIX incompatibilities with -m.
+		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+		   # other-writeable bit of parent directory when it shouldn't.
+		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
+		   case $ls_ld_tmpdir in
+		     d????-?r-*) different_mode=700;;
+		     d????-?--*) different_mode=755;;
+		     *) false;;
+		   esac &&
+		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+		   }
+		 }
+	      then posix_mkdir=:
+	      fi
+	      rmdir "$tmpdir/d" "$tmpdir"
+	    else
+	      # Remove any dirs left behind by ancient mkdir implementations.
+	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+	    fi
+	    trap '' 0;;
+	esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+	umask $mkdir_umask &&
+	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+	/*) prefix='/';;
+	[-=\(\)!]*) prefix='./';;
+	*)  prefix='';;
+      esac
+
+      eval "$initialize_posix_glob"
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
+      shift
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+	test X"$d" = X && continue
+
+	prefix=$prefix$d
+	if test -d "$prefix"; then
+	  prefixes=
+	else
+	  if $posix_mkdir; then
+	    (umask=$mkdir_umask &&
+	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+	    # Don't fail if two instances are running concurrently.
+	    test -d "$prefix" || exit 1
+	  else
+	    case $prefix in
+	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+	      *) qprefix=$prefix;;
+	    esac
+	    prefixes="$prefixes '$qprefix'"
+	  fi
+	fi
+	prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+	# Don't fail if two instances are running concurrently.
+	(umask $mkdir_umask &&
+	 eval "\$doit_exec \$mkdirprog $prefixes") ||
+	  test -d "$dstdir" || exit 1
+	obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+	# Now remove or move aside any old file at destination location.
+	# We try this two ways since rm can't unlink itself on some
+	# systems and the destination file might be busy for other
+	# reasons.  In this case, the final cleanup might fail but the new
+	# file should still install successfully.
+	{
+	  test ! -f "$dst" ||
+	  $doit $rmcmd -f "$dst" 2>/dev/null ||
+	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+	  } ||
+	  { echo "$0: cannot unlink or rename $dst" >&2
+	    (exit 1); exit 1
+	  }
+	} &&
+
+	# Now rename the file to the real destination.
+	$doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..ed50fc2
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2285 2015-12-30 20:48:25Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../macros.make
+
+OPT_DIRS =
+ifeq (@has_mpicxx@, yes)
+   OPT_DIRS += libcxx
+endif
+ifeq (@has_fortran@, yes)
+   OPT_DIRS += libf
+   OPT_DIRS += libf90
+endif
+SUBDIRS = lib utils $(OPT_DIRS)
+
+PACKING_LIST = Makefile.in
+
+PACKING_SUBDIRS = lib libcxx libf libf90 utils
+
+all: $(SUBDIRS) library
+$(SUBDIRS):
+	$(MAKE) $(MFLAGS) -C $@
+
+library: $(SUBDIRS)
+	@set -e; for i in $(OPT_DIRS); do ( $(MAKE) $(MFLAGS) -C $$i library; ) ; done
+
+# utils must be built after lib
+utils: lib
+
+INSTALLDIRS = $(SUBDIRS:%=install-%)
+install: $(INSTALLDIRS)
+$(INSTALLDIRS): all
+	$(MAKE) $(MFLAGS) -C $(@:install-%=%) install
+
+UNINSTALLDIRS = $(SUBDIRS:%=uninstall-%)
+uninstall: $(UNINSTALLDIRS)
+$(UNINSTALLDIRS): 
+	$(MAKE) $(MFLAGS) -C $(@:uninstall-%=%) uninstall
+
+include $(srcdir)/../rules.make
+
diff --git a/src/lib/Makefile.in b/src/lib/Makefile.in
new file mode 100644
index 0000000..b4fd504
--- /dev/null
+++ b/src/lib/Makefile.in
@@ -0,0 +1,117 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2285 2015-12-30 20:48:25Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+# generated by configure, so it's in the build dir, not srcdirr
+include ../../macros.make
+
+# For VPATH build:
+# Add . into search path because ./pnetcdf.h and ./ncconfig.h are created at
+# the configure time in this folder and they are included by many C source
+# files in this folder.
+# Add $(srcdir) into search path because those C files created from their m4
+# source files at the configure time include some header files in $(srcdir).
+INCLUDES = -I. -I$(srcdir)
+
+LIBRARY  = libpnetcdf.a
+HEADER   = pnetcdf.h
+
+M4_SRCS   = getput.m4 \
+            i_getput.m4 \
+            bput.m4 \
+            ncx.m4 \
+            m_getput_varx.m4 \
+            varn.m4 \
+            i_varn.m4 \
+            attr.m4 \
+            convert_swap.m4
+
+HEADER_SRCS = fbits.h \
+              nc.h \
+              nctypes.h \
+              ncio.h \
+              ncx.h \
+              rnd.h \
+              ncmpidtype.h \
+              macro.h \
+              utf8proc_data.h \
+              utf8proc.h
+
+LIB_CSRCS = mpinetcdf.c \
+            header.c \
+            mpincio.c \
+            dim.c \
+            error.c \
+            nc.c \
+            string.c \
+            var.c \
+            ncmpidtype.c \
+            filetype.c \
+            nonblocking.c   \
+            malloc.c \
+            utf8proc.c \
+            vard.c \
+            fill.c \
+            util.c
+
+ifeq (@enable_subfiling@, yes)
+LIB_CSRCS   += subfile.c
+HEADER_SRCS += subfile.h
+endif
+
+PACKING_LIST = $(LIB_CSRCS) \
+               $(M4_SRCS) \
+               $(HEADER_SRCS) \
+               pnetcdf.h.in \
+               depend \
+               Makefile.in \
+               ncconfig.h.in
+
+ifeq (@enable_subfiling@, no)
+PACKING_LIST += subfile.c subfile.h
+endif
+
+LIB_OBJS   = $(LIB_CSRCS:.c=.o) $(M4_SRCS:.m4=.o)
+
+GARBAGE    = $(LIBRARY) $(M4_SRCS:.m4=.c)
+
+DIST_GARBAGE = ncconfig.h pnetcdf.h
+
+all: $(LIBRARY)
+
+$(LIBRARY): $(LIB_OBJS)
+	$(AR) $(ARFLAGS) $(LIBRARY) $(LIB_OBJS)
+	$(RANLIB) $(LIBRARY)
+
+install: $(LIBRARY)
+	$(INSTALL) -d -m 755 $(LIBDIR)
+	$(INSTALL_DATA) $(LIBRARY) $(LIBDIR)/$(LIBRARY)
+	$(INSTALL) -d -m 755 $(INCDIR)
+	$(INSTALL_DATA) $(HEADER) $(INCDIR)/$(HEADER)
+
+uninstall:
+	$(RM) -f $(LIBDIR)/$(LIBRARY)
+	$(RM) -f $(INCDIR)/$(HEADER)
+
+include $(srcdir)/../../rules.make
+
+.SUFFIXES: .ln
+LINT = lint
+LINT.c = $(LINT) $(LINTFLAGS) $(CPPFLAGS)
+.c.ln:
+	$(LINT.c) -c $<
+
+llib-lpnetcdf.ln: $(LIB_CSRCS)
+	$(LINT.c) $(LIB_CSRCS) -y -o pnetcdf
+
+lint: llib-lpnetcdf.ln
+	$(LINT.c) t_nc.c llib-lpnetcdf.ln
+
+include $(srcdir)/depend
diff --git a/src/lib/attr.m4 b/src/lib/attr.m4
new file mode 100644
index 0000000..124c64b
--- /dev/null
+++ b/src/lib/attr.m4
@@ -0,0 +1,1282 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id$ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "fbits.h"
+#include "rnd.h"
+#include "macro.h"
+#include "utf8proc.h"
+
+/*----< ncmpii_free_NC_attr() >-----------------------------------------------*/
+/*
+ * Free attr
+ * Formerly
+NC_free_attr()
+ */
+inline void
+ncmpii_free_NC_attr(NC_attr *attrp)
+{
+    if (attrp == NULL) return;
+
+    ncmpii_free_NC_string(attrp->name);
+
+    NCI_Free(attrp);
+}
+
+
+/*----< ncmpix_len_NC_attrV() >----------------------------------------------*/
+/*
+ * How much space will 'nelems' of 'type' take in
+ * external representation (as the values of an attribute)?
+ */
+inline static MPI_Offset
+ncmpix_len_NC_attrV(nc_type    type,
+                    MPI_Offset nelems)
+{
+    switch(type) {
+        case NC_BYTE:
+        case NC_CHAR:
+        case NC_UBYTE:  return ncmpix_len_char(nelems);
+        case NC_SHORT:  return ncmpix_len_short(nelems);
+        case NC_USHORT: return ncmpix_len_ushort(nelems);
+        case NC_INT:    return ncmpix_len_int(nelems);
+        case NC_UINT:   return ncmpix_len_uint(nelems);
+        case NC_FLOAT:  return ncmpix_len_float(nelems);
+        case NC_DOUBLE: return ncmpix_len_double(nelems);
+        case NC_INT64:  return ncmpix_len_int64(nelems);
+        case NC_UINT64: return ncmpix_len_uint64(nelems);
+        default: assert("ncmpix_len_NC_attr bad type" == 0);
+    }
+    return 0;
+}
+
+
+NC_attr *
+ncmpii_new_x_NC_attr(NC_string  *strp,
+                     nc_type     type,
+                     MPI_Offset  nelems)
+{
+    NC_attr *attrp;
+    const MPI_Offset xsz = ncmpix_len_NC_attrV(type, nelems);
+    size_t sz = M_RNDUP(sizeof(NC_attr));
+
+    assert(!(xsz == 0 && nelems != 0));
+
+    sz += (size_t)xsz;
+
+    attrp = (NC_attr *) NCI_Malloc(sz);
+    if (attrp == NULL ) return NULL;
+
+    attrp->xsz    = xsz;
+    attrp->name   = strp;
+    attrp->type   = type;
+    attrp->nelems = nelems;
+
+    if (xsz != 0)
+        attrp->xvalue = (char *)attrp + M_RNDUP(sizeof(NC_attr));
+    else
+        attrp->xvalue = NULL;
+
+    return(attrp);
+}
+
+
+/*----< ncmpii_new_NC_attr() >------------------------------------------------*/
+/*
+ * Formerly
+NC_new_attr(name,type,count,value)
+ */
+static NC_attr *
+ncmpii_new_NC_attr(const char *uname,  /* attribute name (NULL terminated) */
+                   nc_type     type,
+                   MPI_Offset  nelems)
+{
+    NC_string *strp;
+    NC_attr *attrp;
+
+    char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
+    if (name == NULL) return NULL;
+
+    assert(name != NULL && *name != 0);
+
+    strp = ncmpii_new_NC_string(strlen(name), name);
+    free(name);
+    if (strp == NULL) return NULL;
+
+    attrp = ncmpii_new_x_NC_attr(strp, type, nelems);
+    if (attrp == NULL) {
+        ncmpii_free_NC_string(strp);
+        return NULL;
+    }
+
+    return(attrp);
+}
+
+
+/*----< dup_NC_attr() >-------------------------------------------------------*/
+NC_attr *
+dup_NC_attr(const NC_attr *rattrp)
+{
+    NC_attr *attrp = ncmpii_new_NC_attr(rattrp->name->cp,
+                                        rattrp->type,
+                                        rattrp->nelems);
+    if (attrp == NULL) return NULL;
+    memcpy(attrp->xvalue, rattrp->xvalue, (size_t)rattrp->xsz);
+    return attrp;
+}
+
+/* attrarray */
+
+/*----< ncmpii_free_NC_attrarray() >------------------------------------------*/
+/*
+ * Free NC_attrarray values.
+ * formerly
+NC_free_array()
+ */
+void
+ncmpii_free_NC_attrarray(NC_attrarray *ncap)
+{
+    int i;
+
+    assert(ncap != NULL);
+
+    if (ncap->nalloc == 0) return;
+
+    assert(ncap->value != NULL);
+
+    for (i=0; i<ncap->ndefined; i++)
+        ncmpii_free_NC_attr(ncap->value[i]);
+
+    NCI_Free(ncap->value);
+    ncap->value    = NULL;
+    ncap->nalloc   = 0;
+    ncap->ndefined = 0;
+}
+
+/*----< ncmpii_dup_NC_attrarray() >-------------------------------------------*/
+int
+ncmpii_dup_NC_attrarray(NC_attrarray *ncap, const NC_attrarray *ref)
+{
+    int i, status=NC_NOERR;
+
+    assert(ref != NULL);
+    assert(ncap != NULL);
+
+    if (ref->nalloc == 0) {
+        ncap->nalloc   = 0;
+        ncap->ndefined = 0;
+        ncap->value    = NULL;
+        return NC_NOERR;
+    }
+
+    if (ref->nalloc > 0) {
+        ncap->value = (NC_attr **) NCI_Calloc((size_t)ref->nalloc, sizeof(NC_attr*));
+        if (ncap->value == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+        ncap->nalloc = ref->nalloc;
+    }
+
+    ncap->ndefined = 0;
+    for (i=0; i<ref->ndefined; i++) {
+        ncap->value[i] = dup_NC_attr(ref->value[i]);
+        if (ncap->value[i] == NULL) {
+            DEBUG_ASSIGN_ERROR(status, NC_ENOMEM)
+            break;
+        }
+    }
+
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_attrarray(ncap);
+        return status;
+    }
+
+    ncap->ndefined = ref->ndefined;
+
+    return NC_NOERR;
+}
+
+
+/*
+ * Add a new handle on the end of an array of handles
+ * Formerly
+NC_incr_array(array, tail)
+ */
+int
+incr_NC_attrarray(NC_attrarray *ncap, NC_attr *newelemp)
+{
+	NC_attr **vp;
+
+	assert(ncap != NULL);
+
+	if(ncap->nalloc == 0)
+	{
+		assert(ncap->ndefined == 0);
+		vp = (NC_attr **) NCI_Malloc(sizeof(NC_attr*) * NC_ARRAY_GROWBY);
+		if(vp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+		ncap->value = vp;
+		ncap->nalloc = NC_ARRAY_GROWBY;
+	}
+	else if(ncap->ndefined +1 > ncap->nalloc)
+	{
+		vp = (NC_attr **) NCI_Realloc(ncap->value,
+			(size_t)(ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_attr*));
+		if(vp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+		ncap->value = vp;
+		ncap->nalloc += NC_ARRAY_GROWBY;
+	}
+
+	if(newelemp != NULL)
+	{
+		ncap->value[ncap->ndefined] = newelemp;
+		ncap->ndefined++;
+	}
+	return NC_NOERR;
+}
+
+
+static NC_attr *
+elem_NC_attrarray(const NC_attrarray *ncap, MPI_Offset elem)
+{
+	assert(ncap != NULL);
+	if((elem < 0) || ncap->ndefined == 0 || elem >= ncap->ndefined)
+		return NULL;
+
+	assert(ncap->value != NULL);
+
+	return ncap->value[elem];
+}
+
+/* End attrarray per se */
+
+/*----< NC_attrarray0() >----------------------------------------------------*/
+/*
+ * Given ncp and varid, return ptr to array of attributes
+ * else NULL on error. This is equivalent to validate varid.
+ */
+static NC_attrarray *
+NC_attrarray0(NC  *ncp,
+              int  varid)
+{
+    if (varid == NC_GLOBAL) /* Global attribute, attach to cdf */
+        return &ncp->attrs;
+
+    if (varid >= 0 && varid < ncp->vars.ndefined)
+        return &ncp->vars.value[varid]->attrs;
+
+    return NULL;
+}
+
+
+/*----< ncmpii_NC_findattr() >------------------------------------------------*/
+/*
+ * Step thru NC_ATTRIBUTE array, seeking match on name.
+ *  return match or -1 if Not Found.
+ */
+int
+ncmpii_NC_findattr(const NC_attrarray *ncap,
+                   const char         *uname)
+{
+    int i;
+    size_t nchars;
+    char *name;
+
+    assert(ncap != NULL);
+
+    if (ncap->ndefined == 0) return -1; /* none created yet */
+
+    name = (char *)utf8proc_NFC((const unsigned char *)uname);
+    nchars = strlen(name);
+
+    for (i=0; i<ncap->ndefined; i++) {
+        if (ncap->value[i]->name->nchars == nchars &&
+            strncmp(ncap->value[i]->name->cp, name, nchars) == 0) {
+            free(name);
+            return i;
+        }
+    }
+    free(name);
+
+    return -1;
+}
+
+
+/*
+ * Look up by ncid, varid and name, return NULL if not found
+ */
+static int
+NC_lookupattr(int ncid,
+    int varid,
+    const char *name, /* attribute name */
+    NC_attr **attrpp) /* modified on return */
+{
+    int indx, status;
+    NC *ncp;
+    NC_attrarray *ncap;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if(status != NC_NOERR)
+        return status;
+
+    ncap = NC_attrarray0(ncp, varid);
+    if(ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    indx = ncmpii_NC_findattr(ncap, name);
+    if(indx == -1) DEBUG_RETURN_ERROR(NC_ENOTATT)
+
+    if(attrpp != NULL)
+        *attrpp = ncap->value[indx];
+
+    return NC_NOERR;
+}
+
+/* Public */
+
+/*----< ncmpi_inq_attname() >------------------------------------------------*/
+int
+ncmpi_inq_attname(int   ncid,
+                  int   varid,
+                  int   attid,
+                  char *name)
+
+{
+    int status;
+    NC *ncp;
+    NC_attrarray *ncap;
+    NC_attr *attrp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    ncap = NC_attrarray0(ncp, varid);
+    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    attrp = elem_NC_attrarray(ncap, attid);
+    if (attrp == NULL) DEBUG_RETURN_ERROR(NC_ENOTATT)
+
+    /* in PnetCDF, name->cp is always NULL character terminated */
+    assert(name != NULL);
+    strcpy(name, attrp->name->cp);
+
+    return NC_NOERR;
+}
+
+
+/*----< ncmpi_inq_attid() >--------------------------------------------------*/
+int
+ncmpi_inq_attid(int         ncid,
+                int         varid,
+                const char *name,
+                int        *attidp)
+{
+    int indx, status;
+    NC *ncp;
+    NC_attrarray *ncap;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    ncap = NC_attrarray0(ncp, varid);
+    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    indx = ncmpii_NC_findattr(ncap, name);
+    if (indx == -1) DEBUG_RETURN_ERROR(NC_ENOTATT)
+
+    if (attidp != NULL)
+        *attidp = indx;
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_att() >----------------------------------------------------*/
+int
+ncmpi_inq_att(int         ncid,
+              int         varid,
+              const char *name, /* input, attribute name */
+              nc_type    *datatypep,
+              MPI_Offset *lenp)
+{
+    int status;
+    NC_attr *attrp;
+
+    status = NC_lookupattr(ncid, varid, name, &attrp);
+    if (status != NC_NOERR) return status;
+
+    if (datatypep != NULL)
+        *datatypep = attrp->type;
+
+    if (lenp != NULL)
+        *lenp = attrp->nelems;
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_atttype() >------------------------------------------------*/
+int
+ncmpi_inq_atttype(int         ncid,
+                  int         varid,
+                  const char *name,
+                  nc_type    *datatypep)
+{
+    return ncmpi_inq_att(ncid, varid, name, datatypep, NULL);
+}
+
+/*----< ncmpi_inq_attlen() >-------------------------------------------------*/
+int
+ncmpi_inq_attlen(int         ncid,
+                 int         varid,
+                 const char *name,
+                 MPI_Offset *lenp)
+{
+    return ncmpi_inq_att(ncid, varid, name, NULL, lenp);
+}
+
+
+/*----< ncmpi_rename_att() >--------------------------------------------------*/
+/* This API is collective if called in data mode */
+int
+ncmpi_rename_att(int         ncid,
+                 int         varid,
+                 const char *name,
+                 const char *newname)
+{
+    int indx, file_ver, status, err, mpireturn;
+    NC *ncp;
+    NC_attrarray *ncap;
+    NC_attr *attrp;
+
+    /* sortof inline clone of NC_lookupattr() */
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM)
+
+    ncap = NC_attrarray0(ncp, varid);
+    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    file_ver = 1;
+    if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
+        file_ver = 2;
+    else if (fIsSet(ncp->flags, NC_64BIT_DATA))
+        file_ver = 5;
+
+    status = ncmpii_NC_check_name(newname, file_ver);
+    if (status != NC_NOERR) return status;
+
+    indx = ncmpii_NC_findattr(ncap, name);
+    if (indx < 0) DEBUG_RETURN_ERROR(NC_ENOTATT)
+
+    attrp = ncap->value[indx];
+    /* end inline clone NC_lookupattr() */
+
+    if (ncmpii_NC_findattr(ncap, newname) >= 0)
+        /* name in use */
+        DEBUG_RETURN_ERROR(NC_ENAMEINUSE)
+
+    if (NC_indef(ncp)) {
+        NC_string *newStr = ncmpii_new_NC_string(strlen(newname), newname);
+        if (newStr == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+        ncmpii_free_NC_string(attrp->name);
+        attrp->name = newStr;
+        return NC_NOERR;
+    }
+    /* else, not in define mode.
+     * If called in data mode (collective or independent), this function must
+     * be called collectively, i.e. all processes must participate
+     */
+
+    if (ncp->safe_mode) {
+        int nchars = (int) strlen(newname);
+        TRACE_COMM(MPI_Bcast)(&nchars, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+
+        if (nchars != strlen(newname)) {
+            /* newname's length is inconsistent with root's */
+            printf("Warning: attribute name(%s) used in %s() is inconsistent\n",
+                   newname, __func__);
+            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_ATTR_NAME)
+        }
+    }
+
+    /* ncmpii_set_NC_string() will check for strlen(newname) > nchars error */
+    err = ncmpii_set_NC_string(attrp->name, newname);
+    if (status == NC_NOERR) status = err;
+
+    /* PnetCDF expects all processes use the same name, However, when names
+     * are not the same, only root's value is significant. Broadcast the
+     * new name at root to overwrite new names at other processes.
+     * (This API is collective if called in data mode)
+     */
+    TRACE_COMM(MPI_Bcast)(attrp->name->cp, (int)attrp->name->nchars, MPI_CHAR, 0,
+                          ncp->nciop->comm);
+
+    /* Let root write the entire header to the file. Note that we cannot just
+     * update the variable name in its space occupied in the file header,
+     * because if the file space occupied by the name shrinks, all the metadata
+     * following it must be moved ahead.
+     */
+    err = ncmpii_write_header(ncp);
+    if (status == NC_NOERR) status = err;
+
+    return status;
+}
+
+
+/*----< ncmpi_copy_att() >----------------------------------------------------*/
+/* This API is collective if called in data mode */
+int
+ncmpi_copy_att(int         ncid_in,
+               int         varid_in,
+               const char *name,
+               int         ncid_out,
+               int         varid_out)
+{
+    int indx, status, mpireturn;
+    NC *ncp;
+    NC_attrarray *ncap;
+    NC_attr *iattrp, *attrp, *old=NULL;
+
+    status = NC_lookupattr(ncid_in, varid_in, name, &iattrp);
+    if (status != NC_NOERR) return status;
+
+    status = ncmpii_NC_check_id(ncid_out, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM)
+
+    ncap = NC_attrarray0(ncp, varid_out);
+    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    indx = ncmpii_NC_findattr(ncap, name);
+    if (indx >= 0) { /* name in use */
+        if (!NC_indef(ncp)) {
+            /* if called in data mode (collective or independent), this
+             * function must be called collectively, i.e. all processes must
+             * participate
+             */
+
+            attrp = ncap->value[indx]; /* convenience */
+
+            if (iattrp->xsz > attrp->xsz) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+            /* else, we can reuse existing without redef */
+
+            if (iattrp->xsz != (int)iattrp->xsz) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+
+            attrp->xsz = iattrp->xsz;
+            attrp->type = iattrp->type;
+            attrp->nelems = iattrp->nelems;
+
+            memcpy(attrp->xvalue, iattrp->xvalue, (size_t)iattrp->xsz);
+
+            /* PnetCDF expects all processes use the same name, However, when
+             * new attributes are not the same, only root's value is
+             * significant. Broadcast the new attribute at root to overwrite
+             * new names at other processes.
+             */
+            TRACE_COMM(MPI_Bcast)((void*)attrp->xvalue, (int)attrp->xsz,
+                                  MPI_CHAR, 0, ncp->nciop->comm);
+            if (mpireturn != MPI_SUCCESS)
+                return ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+
+            /* Let root write the entire header to the file. Note that we
+             * cannot just update the variable name in its space occupied in
+             * the file header, because if the file space occupied by the name
+             * shrinks, all the metadata following it must be moved ahead.
+             */
+            return ncmpii_write_header(ncp);
+        }
+        /* else, redefine using existing array slot */
+        old = ncap->value[indx];
+    }
+    else {
+        if (!NC_indef(ncp)) /* add new attribute is not allowed in data mode */
+            DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+
+        if (ncap->ndefined >= NC_MAX_ATTRS)
+            DEBUG_RETURN_ERROR(NC_EMAXATTS)
+    }
+
+    attrp = ncmpii_new_NC_attr(name, iattrp->type, iattrp->nelems);
+    if (attrp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    memcpy(attrp->xvalue, iattrp->xvalue, (size_t)iattrp->xsz);
+
+    if (indx >= 0) {
+        assert(old != NULL);
+        ncap->value[indx] = attrp;
+        ncmpii_free_NC_attr(old);
+    }
+    else {
+        status = incr_NC_attrarray(ncap, attrp);
+        if (status != NC_NOERR) {
+            ncmpii_free_NC_attr(attrp);
+            return status;
+        }
+    }
+    return NC_NOERR;
+}
+
+/*----< ncmpi_del_att() >---------------------------------------------------*/
+int
+ncmpi_del_att(int         ncid,
+              int         varid,
+              const char *name)
+{
+    int status, attrid;
+    NC *ncp;
+    NC_attrarray *ncap;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (!NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+
+    ncap = NC_attrarray0(ncp, varid);
+    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    attrid = ncmpii_NC_findattr(ncap, name);
+    if (attrid == -1) DEBUG_RETURN_ERROR(NC_ENOTATT)
+
+    /* deleting attribute _FillValue means disabling fill mode */
+    if (!strcmp(name, _FillValue)) {
+        NC_var *varp;
+        status = ncmpii_NC_lookupvar(ncp, varid, &varp);
+        if (status != NC_NOERR) return status;
+        varp->no_fill = 1;
+    }
+
+    ncmpii_free_NC_attr(ncap->value[attrid]);
+
+    /* shuffle down */
+    for (; attrid < ncap->ndefined; attrid++)
+        ncap->value[attrid] = ncap->value[attrid+1];
+
+    /* decrement count */
+    ncap->ndefined--;
+
+    return NC_NOERR;
+}
+
+static nc_type longtype = (SIZEOF_LONG == SIZEOF_INT ? NC_INT : NC_INT64);
+
+/* ncmpi_pad_xxx APIs are only applicable for filetypes of size smaller
+ * than 4 bytes
+ */
+dnl
+dnl PAD_GETN_FILETYPE(filetype)
+dnl
+define(`PAD_GETN_FILETYPE',dnl
+`dnl
+/*----< ncmpix_pad_getn_$1() >-----------------------------------------------*/
+inline static int
+ncmpix_pad_getn_$1(const void **xpp,
+                   MPI_Offset   nelems,
+                   void        *tp,
+                   nc_type      buftype)
+{
+    switch(buftype) {
+        case NC_CHAR:
+        case NC_BYTE:
+            return ncmpix_pad_getn_$1_schar (xpp, nelems, (schar*)tp);
+        case NC_UBYTE:
+            return ncmpix_pad_getn_$1_uchar (xpp, nelems, (uchar*)tp);
+        case NC_SHORT:
+            return ncmpix_pad_getn_$1_short (xpp, nelems, (short*)tp);
+        case NC_USHORT:
+            return ncmpix_pad_getn_$1_ushort(xpp, nelems, (ushort*)tp);
+        case NC_INT:
+            return ncmpix_pad_getn_$1_int   (xpp, nelems, (int*)tp);
+        case NC_UINT:
+            return ncmpix_pad_getn_$1_uint  (xpp, nelems, (uint*)tp);
+        case NC_FLOAT:
+            return ncmpix_pad_getn_$1_float (xpp, nelems, (float*)tp);
+        case NC_DOUBLE:
+            return ncmpix_pad_getn_$1_double(xpp, nelems, (double*)tp);
+        case NC_INT64:
+            return ncmpix_pad_getn_$1_longlong (xpp, nelems, (longlong*)tp);
+        case NC_UINT64:
+            return ncmpix_pad_getn_$1_ulonglong(xpp, nelems, (ulonglong*)tp);
+        default:
+            assert("ncmpix_pad_getn_$1 invalid buffer type" == 0);
+            DEBUG_RETURN_ERROR(NC_EBADTYPE)
+    }
+}
+')dnl
+
+PAD_GETN_FILETYPE(schar)
+PAD_GETN_FILETYPE(uchar)
+PAD_GETN_FILETYPE(short)
+PAD_GETN_FILETYPE(ushort)
+
+dnl
+dnl GETN_FILETYPE(filetype)
+dnl
+define(`GETN_FILETYPE',dnl
+`dnl
+/*----< ncmpix_getn_$1() >---------------------------------------------------*/
+inline static int
+ncmpix_getn_$1(const void **xpp,
+               MPI_Offset   nelems,
+               void        *tp,
+               nc_type      buftype)
+{
+    switch(buftype) {
+        case NC_CHAR:
+        case NC_BYTE:
+            return ncmpix_getn_$1_schar (xpp, nelems, (schar*)tp);
+        case NC_UBYTE:
+            return ncmpix_getn_$1_uchar (xpp, nelems, (uchar*)tp);
+        case NC_SHORT:
+            return ncmpix_getn_$1_short (xpp, nelems, (short*)tp);
+        case NC_USHORT:
+            return ncmpix_getn_$1_ushort(xpp, nelems, (ushort*)tp);
+        case NC_INT:
+            return ncmpix_getn_$1_int   (xpp, nelems, (int*)tp);
+        case NC_UINT:
+            return ncmpix_getn_$1_uint  (xpp, nelems, (uint*)tp);
+        case NC_FLOAT:
+            return ncmpix_getn_$1_float (xpp, nelems, (float*)tp);
+        case NC_DOUBLE:
+            return ncmpix_getn_$1_double(xpp, nelems, (double*)tp);
+        case NC_INT64:
+            return ncmpix_getn_$1_longlong (xpp, nelems, (longlong*)tp);
+        case NC_UINT64:
+            return ncmpix_getn_$1_ulonglong(xpp, nelems, (ulonglong*)tp);
+        default:
+            assert("ncmpix_pad_getn_$1 invalid buffer type" == 0);
+            DEBUG_RETURN_ERROR(NC_EBADTYPE)
+    }
+}
+')dnl
+
+GETN_FILETYPE(int)
+GETN_FILETYPE(uint)
+GETN_FILETYPE(float)
+GETN_FILETYPE(double)
+GETN_FILETYPE(int64)
+GETN_FILETYPE(uint64)
+
+/*----< ncmpix_pad_getn() >--------------------------------------------------*/
+/* padding only applicable to file types of size smaller than 4 bytes */
+inline static int
+ncmpix_pad_getn(const void **xpp,
+                MPI_Offset   nelems,
+                void        *tp,
+                nc_type      filetype,
+                nc_type      buftype)
+{
+    /* get n elements from (filetype*)*xpp to (buftype*)tp */
+    /* Checking for character-number conversion should have already been done */
+
+    switch(filetype) {
+        case NC_CHAR:
+        case NC_BYTE:
+            return ncmpix_pad_getn_schar (xpp, nelems, tp, buftype);
+        case NC_UBYTE:
+            return ncmpix_pad_getn_uchar (xpp, nelems, tp, buftype);
+        case NC_SHORT:
+            return ncmpix_pad_getn_short (xpp, nelems, tp, buftype);
+        case NC_USHORT:
+            return ncmpix_pad_getn_ushort(xpp, nelems, tp, buftype);
+        case NC_INT:
+            return ncmpix_getn_int       (xpp, nelems, tp, buftype);
+        case NC_UINT:
+            return ncmpix_getn_uint      (xpp, nelems, tp, buftype);
+        case NC_FLOAT:
+            return ncmpix_getn_float     (xpp, nelems, tp, buftype);
+        case NC_DOUBLE:
+            return ncmpix_getn_double    (xpp, nelems, tp, buftype);
+        case NC_INT64:
+            return ncmpix_getn_int64     (xpp, nelems, tp, buftype);
+        case NC_UINT64:
+            return ncmpix_getn_uint64    (xpp, nelems, tp, buftype);
+        default:
+            assert("ncmpix_pad_getn invalid filetype" == 0);
+            DEBUG_RETURN_ERROR(NC_EBADTYPE)
+    }
+}
+
+/*----< ncmpii_get_att() >---------------------------------------------------*/
+static int
+ncmpii_get_att(int         ncid,
+               int         varid,
+               const char *name,
+               void       *tp,       /* I/O buffer */
+               nc_type     buftype)  /* I/O buffer data type */
+{
+    int status;
+    NC_attr *attrp;
+
+    status = NC_lookupattr(ncid, varid, name, &attrp);
+    if (status != NC_NOERR) return status;
+
+    if (attrp->nelems == 0) return NC_NOERR;
+
+    /* No character conversions are allowed. */
+    if (attrp->type != buftype &&
+        (attrp->type == NC_CHAR || buftype == NC_CHAR))
+        DEBUG_RETURN_ERROR(NC_ECHAR)
+
+    const void *xp = attrp->xvalue;
+    return ncmpix_pad_getn(&xp, attrp->nelems, tp, attrp->type, buftype);
+}
+
+/*----< ncmpi_get_att() >-----------------------------------------------------*/
+int
+ncmpi_get_att(int         ncid,
+              int         varid,
+              const char *name,
+              void       *value)
+{
+    int status;
+    nc_type atttype;
+
+    status = ncmpi_inq_atttype(ncid, varid, name, &atttype);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_get_att(ncid, varid, name, value, atttype);
+}
+
+dnl
+dnl GET_ATT_TYPE(fntype, ext_buftype, nc_buftype)
+dnl
+define(`GET_ATT_TYPE',dnl
+`dnl
+/*----< ncmpi_get_att_$1() >-------------------------------------------------*/
+int
+ncmpi_get_att_$1(int ncid, int varid, const char  *name, $2 *value)
+{
+    return ncmpii_get_att(ncid, varid, name, value, $3);
+}
+')dnl
+
+GET_ATT_TYPE(text,      char,               NC_CHAR)
+GET_ATT_TYPE(schar,     signed char,        NC_BYTE)
+GET_ATT_TYPE(uchar,     unsigned char,      NC_UBYTE)
+GET_ATT_TYPE(ubyte,     unsigned char,      NC_UBYTE)
+GET_ATT_TYPE(short,     short,              NC_SHORT)
+GET_ATT_TYPE(ushort,    unsigned short,     NC_USHORT)
+GET_ATT_TYPE(int,       int,                NC_INT)
+GET_ATT_TYPE(uint,      unsigned int,       NC_UINT)
+GET_ATT_TYPE(long,      long,               longtype)
+GET_ATT_TYPE(float,     float,              NC_FLOAT)
+GET_ATT_TYPE(double,    double,             NC_DOUBLE)
+GET_ATT_TYPE(longlong,  long long,          NC_INT64)
+GET_ATT_TYPE(ulonglong, unsigned long long, NC_UINT64)
+
+dnl
+dnl PAD_PUTN_FILETYPE(ftype)
+dnl
+define(`PAD_PUTN_FILETYPE',dnl
+`dnl
+/*----< ncmpix_pad_putn_$1() >-----------------------------------------------*/
+inline static int
+ncmpix_pad_putn_$1(void       **xpp,
+                   MPI_Offset   nelems,
+                   const void  *tp,
+                   nc_type      btype)
+{
+    switch(btype) {
+        case NC_CHAR:
+        case NC_BYTE:
+            return ncmpix_pad_putn_$1_schar (xpp, nelems, (schar*)tp);
+        case NC_UBYTE:
+            return ncmpix_pad_putn_$1_uchar (xpp, nelems, (uchar*)tp);
+        case NC_SHORT:
+            return ncmpix_pad_putn_$1_short (xpp, nelems, (short*)tp);
+        case NC_USHORT:
+            return ncmpix_pad_putn_$1_ushort(xpp, nelems, (ushort*)tp);
+        case NC_INT:
+            return ncmpix_pad_putn_$1_int   (xpp, nelems, (int*)tp);
+        case NC_UINT:
+            return ncmpix_pad_putn_$1_uint  (xpp, nelems, (uint*)tp);
+        case NC_FLOAT:
+            return ncmpix_pad_putn_$1_float (xpp, nelems, (float*)tp);
+        case NC_DOUBLE:
+            return ncmpix_pad_putn_$1_double(xpp, nelems, (double*)tp);
+        case NC_INT64:
+            return ncmpix_pad_putn_$1_longlong (xpp, nelems, (longlong*)tp);
+        case NC_UINT64:
+            return ncmpix_pad_putn_$1_ulonglong(xpp, nelems, (ulonglong*)tp);
+        default:
+            assert("ncmpix_pad_putn_$1 invalid type" == 0);
+            DEBUG_RETURN_ERROR(NC_EBADTYPE)
+    }
+}
+')dnl
+
+PAD_PUTN_FILETYPE(schar)
+PAD_PUTN_FILETYPE(uchar)
+PAD_PUTN_FILETYPE(short)
+PAD_PUTN_FILETYPE(ushort)
+
+dnl
+dnl PUTN_FILETYPE(ftype)
+dnl
+define(`PUTN_FILETYPE',dnl
+`dnl
+/*----< ncmpix_putn_$1() >---------------------------------------------------*/
+inline static int
+ncmpix_putn_$1(void       **xpp,
+               MPI_Offset   nelems,
+               const void  *tp,
+               nc_type      btype)
+{
+    switch(btype) {
+        case NC_CHAR:
+        case NC_BYTE:
+            return ncmpix_putn_$1_schar (xpp, nelems, (schar*)tp);
+        case NC_UBYTE:
+            return ncmpix_putn_$1_uchar (xpp, nelems, (uchar*)tp);
+        case NC_SHORT:
+            return ncmpix_putn_$1_short (xpp, nelems, (short*)tp);
+        case NC_USHORT:
+            return ncmpix_putn_$1_ushort(xpp, nelems, (ushort*)tp);
+        case NC_INT:
+            return ncmpix_putn_$1_int   (xpp, nelems, (int*)tp);
+        case NC_UINT:
+            return ncmpix_putn_$1_uint  (xpp, nelems, (uint*)tp);
+        case NC_FLOAT:
+            return ncmpix_putn_$1_float (xpp, nelems, (float*)tp);
+        case NC_DOUBLE:
+            return ncmpix_putn_$1_double(xpp, nelems, (double*)tp);
+        case NC_INT64:
+            return ncmpix_putn_$1_longlong (xpp, nelems, (longlong*)tp);
+        case NC_UINT64:
+            return ncmpix_putn_$1_ulonglong(xpp, nelems, (ulonglong*)tp);
+        default:
+            assert("ncmpix_putn_$1 invalid type" == 0);
+            DEBUG_RETURN_ERROR(NC_EBADTYPE)
+    }
+}
+')dnl
+
+PUTN_FILETYPE(int)
+PUTN_FILETYPE(uint)
+PUTN_FILETYPE(float)
+PUTN_FILETYPE(double)
+PUTN_FILETYPE(int64)
+PUTN_FILETYPE(uint64)
+
+/*----< ncmpix_pad_putn() >--------------------------------------------------*/
+/* padding only applicable to file types of size smaller than 4 bytes */
+inline static int
+ncmpix_pad_putn(void       **xpp,
+                MPI_Offset   nelems,
+                const void  *tp,
+                nc_type      filetype,
+                nc_type      buftype)
+{
+    /* put n elements from (buftype*)tp to (filetype*)*xpp */
+    /* Checking for character-number conversion should have been done */
+
+    switch(filetype) {
+        case NC_CHAR:
+        case NC_BYTE:
+            return ncmpix_pad_putn_schar (xpp, nelems, tp, buftype);
+        case NC_UBYTE:
+            return ncmpix_pad_putn_uchar (xpp, nelems, tp, buftype);
+        case NC_SHORT:
+            return ncmpix_pad_putn_short (xpp, nelems, tp, buftype);
+        case NC_USHORT:
+            return ncmpix_pad_putn_ushort(xpp, nelems, tp, buftype);
+        case NC_INT:
+            return ncmpix_putn_int       (xpp, nelems, tp, buftype);
+        case NC_UINT:
+            return ncmpix_putn_uint      (xpp, nelems, tp, buftype);
+        case NC_FLOAT:
+            return ncmpix_putn_float     (xpp, nelems, tp, buftype);
+        case NC_DOUBLE:
+            return ncmpix_putn_double    (xpp, nelems, tp, buftype);
+        case NC_INT64:
+            return ncmpix_putn_int64     (xpp, nelems, tp, buftype);
+        case NC_UINT64:
+            return ncmpix_putn_uint64    (xpp, nelems, tp, buftype);
+        default:
+            assert("ncmpix_pad_putn invalid filetype" == 0);
+            DEBUG_RETURN_ERROR(NC_EBADTYPE)
+    }
+}
+
+/*----< ncmpii_put_att() >---------------------------------------------------*/
+/* Note from netCDF user guide:
+ * Attributes are always single values or one-dimensional arrays. This works
+ * out well for a string, which is a one-dimensional array of ASCII characters
+ *
+ * This PnetCDF API is collective if called in data mode.
+ */
+static int
+ncmpii_put_att(int         ncid,
+               int         varid,
+               const char *name,     /* attribute name */
+               nc_type     filetype, /* type defined in file header */
+               MPI_Offset  nelems,   /* number of elements of type buftype */
+               const void *buf,      /* I/O buffer */
+               nc_type     buftype)  /* I/O buffer type */
+{
+    int indx, file_ver, err, status=NC_NOERR, mpireturn;
+    NC *ncp;
+    NC_attrarray *ncap;
+    NC_attr *attrp, *old=NULL;
+
+    if (!name || strlen(name) > NC_MAX_NAME)
+        DEBUG_RETURN_ERROR(NC_EBADNAME)
+
+    /* Should CDF-5 allow very large file header? */
+    /* if (len > X_INT_MAX) DEBUG_RETURN_ERROR(NC_EINVAL) */
+
+    /* get the file ID */
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* file should be opened with writable permission */
+    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM)
+
+    /* nelems can be zero, i.e. an attribute with only its name */
+    if (nelems > 0 && buf == NULL)
+        DEBUG_RETURN_ERROR(NC_EINVAL) /* Null arg */
+
+    /* If this is the _FillValue attribute, then let PnetCDF return the
+     * same error codes as netCDF
+     */
+    if (!strcmp(name, "_FillValue")) {
+        NC_var *varp;
+        status = ncmpii_NC_lookupvar(ncp, varid, &varp);
+        if (status != NC_NOERR) return status;
+
+        /* Fill value must be same type and have exactly one value */
+        if (filetype != varp->type)
+            DEBUG_RETURN_ERROR(NC_EBADTYPE)
+
+        if (nelems != 1)
+            DEBUG_RETURN_ERROR(NC_EINVAL)
+    }
+
+    /* get the file format version */
+    file_ver = 1;
+    if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
+        file_ver = 2;
+    else if (fIsSet(ncp->flags, NC_64BIT_DATA))
+        file_ver = 5;
+
+    if (nelems < 0 || (nelems > X_INT_MAX && file_ver <= 2))
+        DEBUG_RETURN_ERROR(NC_EINVAL) /* Invalid nelems */
+
+    /* check if filetype is valid, as filetype is given by user
+     * no need to check buftype, as buftype is set internally
+     */
+    status = ncmpii_cktype(file_ver, filetype);
+    if (status != NC_NOERR) return status;
+
+    /* No character conversions are allowed. */
+    if (filetype != buftype &&
+        (filetype == NC_CHAR || buftype == NC_CHAR))
+        DEBUG_RETURN_ERROR(NC_ECHAR)
+
+    /* check if the attribute name is legal */
+    status = ncmpii_NC_check_name(name, file_ver);
+    if (status != NC_NOERR) return status;
+
+    /* get the pointer to the attribute array */
+    ncap = NC_attrarray0(ncp, varid);
+    if (ncap == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    indx = ncmpii_NC_findattr(ncap, name);
+    if (indx >= 0) { /* name in use */
+        if (!NC_indef(ncp)) {
+            /* in data mode, meaning to over-write an existing attribute
+             * if called in data mode (collective or independent), this
+             * function must be called collectively, i.e. all processes must
+             * participate
+             */
+
+            const MPI_Offset xsz = ncmpix_len_NC_attrV(filetype, nelems);
+            /* xsz is the total size of this attribute */
+
+            attrp = ncap->value[indx]; /* convenience */
+
+            if (xsz > attrp->xsz) /* new attribute requires a larger space */
+                DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+            /* else, we can reuse existing without redef */
+
+            if (xsz != (int)xsz) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+
+            attrp->xsz = xsz;
+            attrp->type = filetype;
+            attrp->nelems = nelems;
+
+            if (nelems != 0) {
+                void *xp = attrp->xvalue;
+                /* using xp to prevent change the pointer attr->xvalue,
+                 * as ncmpix_pad_putn() advances the first argument
+                 * with nelems elements
+                 */
+                status = ncmpix_pad_putn(&xp, nelems, buf, filetype, buftype);
+                /* wkliao: why not return here if status != NC_NOERR? */
+
+                /* PnetCDF expects all processes use the same argument values.
+                 * However, when argument values are not the same, only root's
+                 * value is significant. Broadcast the new attribute at root to
+                 * overwrite new attribute at other processes.
+                 */
+                TRACE_COMM(MPI_Bcast)(attrp->xvalue, (int)attrp->xsz, MPI_BYTE,
+                                      0, ncp->nciop->comm);
+                if (mpireturn != MPI_SUCCESS) {
+                    err = ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+                    if (status == NC_NOERR) status = err;
+                }
+            }
+
+            /* Let root write the entire header to the file. Note that we
+             * cannot just update the attribute in its space occupied in the
+             * file header, because if the file space occupied by the attribute
+             * shrinks, all the metadata following it must be moved ahead.
+             */
+            err = ncmpii_write_header(ncp);
+            return (status == NC_NOERR) ? err : status;
+        }
+        /* else, redefine using existing array slot */
+        old = ncap->value[indx];
+    }
+    else { /* name never been used */
+        /* creating new attributes must be done in define mode */
+        if (!NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+
+        if (ncap->ndefined >= NC_MAX_ATTRS)
+            DEBUG_RETURN_ERROR(NC_EMAXATTS)
+    }
+
+    /* create a new attribute object */
+    attrp = ncmpii_new_NC_attr(name, filetype, nelems);
+    if (attrp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    if (nelems != 0) { /* non-zero length attribute */
+        void *xp = attrp->xvalue;
+        status = ncmpix_pad_putn(&xp, nelems, buf, filetype, buftype);
+        /* wkliao: no immediately return error code here? Strange ... 
+         *         Instead, we continue and call incr_NC_attrarray() to add
+         *         this attribute (for create case) as it is legal. But if
+         *         we return error and reject this attribute, then nc_test will
+         *         fail with this error message below:
+         *         FAILURE at line 252 of test_read.c: ncmpi_inq: wrong number
+         *         of global atts returned, 3
+         *         Check netCDF-4, it is doing the same thing!
+         *
+         *         One of the error codes returned from ncmpix_pad_putn() is
+         *         NC_ERANGE, meaning one or more elements are type overflow.
+         *         Should we reject the entire attribute array if only part of
+         *         the array overflow? For netCDF4, the answer is NO.
+         */ 
+/*
+        if (status != NC_NOERR) {
+            ncmpii_free_NC_attr(attrp);
+            return status;
+        }
+*/
+    }
+
+    if (indx >= 0) { /* modify the existing attribute */
+        assert(old != NULL);
+        ncap->value[indx] = attrp;
+        ncmpii_free_NC_attr(old);
+    }
+    else { /* creating a new attribute */
+        err = incr_NC_attrarray(ncap, attrp);
+        if (err != NC_NOERR) {
+            ncmpii_free_NC_attr(attrp);
+            return err;
+        }
+    }
+
+    return status;
+}
+
+/*----< ncmpi_put_att() >-----------------------------------------------------*/
+int
+ncmpi_put_att(int         ncid,
+              int         varid,
+              const char *name,
+              nc_type     xtype,
+              MPI_Offset  nelems,
+              const void *value)
+{
+    return ncmpii_put_att(ncid, varid, name, xtype, nelems, value, xtype);
+}
+
+/*----< ncmpi_put_att_text() >-----------------------------------------------*/
+int
+ncmpi_put_att_text(int ncid, int varid, const char *name,
+                   MPI_Offset nelems, const char *value)
+{
+    return ncmpii_put_att(ncid, varid, name, NC_CHAR,
+                          nelems, value, NC_CHAR);
+}
+
+dnl
+dnl PUT_ATT_TYPE(fntype, ext_buftype, nc_buftype)
+dnl
+define(`PUT_ATT_TYPE',dnl
+`dnl
+/*----< ncmpi_put_att_$1() >-------------------------------------------------*/
+int
+ncmpi_put_att_$1(int ncid, int varid, const char *name, nc_type xtype,
+                 MPI_Offset nelems, const $2 *value)
+{
+    return ncmpii_put_att(ncid, varid, name, xtype, nelems, value, $3);
+}
+')dnl
+
+PUT_ATT_TYPE(schar,     signed char,        NC_BYTE)
+PUT_ATT_TYPE(uchar,     unsigned char,      NC_UBYTE)
+PUT_ATT_TYPE(ubyte,     unsigned char,      NC_UBYTE)
+PUT_ATT_TYPE(short,     short,              NC_SHORT)
+PUT_ATT_TYPE(ushort,    unsigned short,     NC_USHORT)
+PUT_ATT_TYPE(int,       int,                NC_INT)
+PUT_ATT_TYPE(uint,      unsigned int,       NC_UINT)
+PUT_ATT_TYPE(long,      long,               longtype)
+PUT_ATT_TYPE(float,     float,              NC_FLOAT)
+PUT_ATT_TYPE(double,    double,             NC_DOUBLE)
+PUT_ATT_TYPE(longlong,  long long,          NC_INT64)
+PUT_ATT_TYPE(ulonglong, unsigned long long, NC_UINT64)
+
+/* For netCDF, the type mapping between file types and buffer types
+ * are based on netcdf4. Check APIs of nc_put_att_xxx from source files
+ *     netCDF/netcdf-4.1.3/libdispatch/att.c
+ *     netCDF/netcdf-4.1.3/libsrc4/nc4attr.c
+ *
+ * Note that schar means signed 1-byte integers in attributes. Hence the call
+ * below is illegal. NC_ECHAR will return, indicating the error on trying
+ * type conversion between characters and numbers.
+ *
+ * ncmpi_put_att_schar(ncid, varid, "attr name", NC_CHAR, strlen(attrp), attrp);
+ *
+ * This rule and mapping apply for variables as well. See APIs of
+ * nc_put_vara_xxx from source files
+ *     netCDF/netcdf-4.1.3/libdispatch/var.c
+ *     netCDF/netcdf-4.1.3/libsrc4/nc4var.c
+ *
+ */
diff --git a/src/lib/bput.m4 b/src/lib/bput.m4
new file mode 100644
index 0000000..5e69fea
--- /dev/null
+++ b/src/lib/bput.m4
@@ -0,0 +1,551 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: bput.m4 2290 2016-01-02 18:37:46Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "ncmpidtype.h"
+#include "macro.h"
+
+
+/*----< ncmpi_bput_var() >----------------------------------------------------*/
+int
+ncmpi_bput_var(int           ncid,
+               int           varid,
+               const void   *buf,
+               MPI_Offset    bufcount,
+               MPI_Datatype  buftype,
+               int          *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    MPI_Offset *start, *count;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VAR,
+                                 0, 1, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    GET_FULL_DIMENSIONS(start, count)
+
+    /* bput_var is a special case of bput_varm */
+    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                                 (void*)buf, bufcount, buftype, reqid,
+                                 WRITE_REQ, 1, 0);
+    if (varp->ndims > 0) NCI_Free(start);
+    return status;
+}
+
+
+dnl
+dnl BPUT_VAR_TYPE(ncid, varid, op, reqid)
+dnl
+define(`BPUT_VAR_TYPE',dnl
+`dnl
+/*----< ncmpi_bput_var_$1() >-------------------------------------------------*/
+int
+ncmpi_bput_var_$1(int       ncid,
+                  int       varid,
+                  const $2 *op,
+                  int      *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    MPI_Offset  *start, *count;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, 0, API_VAR,
+                                 0, 0, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    GET_FULL_DIMENSIONS(start, count)
+
+    /* bput_var is a special case of bput_varm */
+    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                                 (void*)op, -1, $3, reqid, WRITE_REQ, 1, 0);
+    if (varp->ndims > 0) NCI_Free(start);
+    return status;
+}
+')dnl
+
+BPUT_VAR_TYPE(text,      char,               MPI_CHAR)
+BPUT_VAR_TYPE(schar,     schar,              MPI_SIGNED_CHAR)
+BPUT_VAR_TYPE(uchar,     uchar,              MPI_UNSIGNED_CHAR)
+BPUT_VAR_TYPE(short,     short,              MPI_SHORT)
+BPUT_VAR_TYPE(ushort,    ushort,             MPI_UNSIGNED_SHORT)
+BPUT_VAR_TYPE(int,       int,                MPI_INT)
+BPUT_VAR_TYPE(uint,      uint,               MPI_UNSIGNED)
+BPUT_VAR_TYPE(long,      long,               MPI_LONG)
+BPUT_VAR_TYPE(float,     float,              MPI_FLOAT)
+BPUT_VAR_TYPE(double,    double,             MPI_DOUBLE)
+BPUT_VAR_TYPE(longlong,  long long,          MPI_LONG_LONG_INT)
+BPUT_VAR_TYPE(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+
+/*----< ncmpi_bput_var1() >---------------------------------------------------*/
+int
+ncmpi_bput_var1(int               ncid,
+                int               varid,
+                const MPI_Offset *start,
+                const void       *buf,
+                MPI_Offset        bufcount,
+                MPI_Datatype      buftype,
+                int              *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    MPI_Offset *count;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, NULL, bufcount, API_VAR1,
+                                 0, 1, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    GET_ONE_COUNT(count)
+
+    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                                 (void*)buf, bufcount, buftype, reqid,
+                                 WRITE_REQ, 1, 0);
+    if (varp->ndims > 0) NCI_Free(count);
+    return status;
+}
+
+dnl
+dnl BPUT_VAR1_TYPE(ncid, varid, start, op, reqid)
+dnl
+define(`BPUT_VAR1_TYPE',dnl
+`dnl
+/*----< ncmpi_bput_var1_$1() >------------------------------------------------*/
+int
+ncmpi_bput_var1_$1(int               ncid,
+                   int               varid,
+                   const MPI_Offset  start[],
+                   const $2         *op,
+                   int              *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    MPI_Offset *count;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, NULL, 0, API_VAR1,
+                                 0, 0, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    GET_ONE_COUNT(count)
+
+    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                                 (void*)op, -1, $3, reqid, WRITE_REQ, 1, 0);
+    if (varp->ndims > 0) NCI_Free(count);
+    return status;
+}
+')dnl
+
+BPUT_VAR1_TYPE(text,      char,               MPI_CHAR)
+BPUT_VAR1_TYPE(schar,     schar,              MPI_SIGNED_CHAR)
+BPUT_VAR1_TYPE(uchar,     uchar,              MPI_UNSIGNED_CHAR)
+BPUT_VAR1_TYPE(short,     short,              MPI_SHORT)
+BPUT_VAR1_TYPE(ushort,    ushort,             MPI_UNSIGNED_SHORT)
+BPUT_VAR1_TYPE(int,       int,                MPI_INT)
+BPUT_VAR1_TYPE(uint,      uint,               MPI_UNSIGNED)
+BPUT_VAR1_TYPE(long,      long,               MPI_LONG)
+BPUT_VAR1_TYPE(float,     float,              MPI_FLOAT)
+BPUT_VAR1_TYPE(double,    double,             MPI_DOUBLE)
+BPUT_VAR1_TYPE(longlong,  long long,          MPI_LONG_LONG_INT)
+BPUT_VAR1_TYPE(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+
+/*----< ncmpi_bput_vara() >---------------------------------------------------*/
+int
+ncmpi_bput_vara(int               ncid,
+                int               varid,
+                const MPI_Offset *start,
+                const MPI_Offset *count,
+                const void       *buf,
+                MPI_Offset        bufcount,
+                MPI_Datatype      buftype,
+                int              *reqid)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARA,
+                                 0, 1, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    return ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                               (void*)buf, bufcount, buftype, reqid,
+                               WRITE_REQ, 1, 0);
+}
+
+dnl
+dnl BPUT_VARA_TYPE(ncid, varid, start, count, op, reqid)
+dnl
+define(`BPUT_VARA_TYPE',dnl
+`dnl
+/*----< ncmpi_bput_vara_$1() >------------------------------------------------*/
+int
+ncmpi_bput_vara_$1(int               ncid,
+                   int               varid,
+                   const MPI_Offset  start[],
+                   const MPI_Offset  count[],
+                   const $2         *op,
+                   int              *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARA,
+                                 0, 0, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    return ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                               (void*)op, -1, $3, reqid, WRITE_REQ, 1, 0);
+}
+')dnl
+
+BPUT_VARA_TYPE(text,      char,               MPI_CHAR)
+BPUT_VARA_TYPE(schar,     schar,              MPI_SIGNED_CHAR)
+BPUT_VARA_TYPE(uchar,     uchar,              MPI_UNSIGNED_CHAR)
+BPUT_VARA_TYPE(short,     short,              MPI_SHORT)
+BPUT_VARA_TYPE(ushort,    ushort,             MPI_UNSIGNED_SHORT)
+BPUT_VARA_TYPE(int,       int,                MPI_INT)
+BPUT_VARA_TYPE(uint,      uint,               MPI_UNSIGNED)
+BPUT_VARA_TYPE(long,      long,               MPI_LONG)
+BPUT_VARA_TYPE(float,     float,              MPI_FLOAT)
+BPUT_VARA_TYPE(double,    double,             MPI_DOUBLE)
+BPUT_VARA_TYPE(longlong,  long long,          MPI_LONG_LONG_INT)
+BPUT_VARA_TYPE(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+
+/*----< ncmpi_bput_vars() >---------------------------------------------------*/
+int
+ncmpi_bput_vars(int               ncid,
+                int               varid,
+                const MPI_Offset  start[],
+                const MPI_Offset  count[],
+                const MPI_Offset  stride[],
+                const void       *buf,
+                MPI_Offset        bufcount,
+                MPI_Datatype      buftype,
+                int              *reqid)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARS,
+                                 0, 1, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    return ncmpii_igetput_varm(ncp, varp, start, count, stride, NULL,
+                               (void*)buf, bufcount, buftype, reqid,
+                               WRITE_REQ, 1, 0);
+}
+
+dnl
+dnl BPUT_VARS_TYPE(ncid, varid, start, count, stride, op, reqid)
+dnl
+define(`BPUT_VARS_TYPE',dnl
+`dnl
+/*----< ncmpi_bput_vars_$1() >------------------------------------------------*/
+int
+ncmpi_bput_vars_$1(int               ncid,
+                   int               varid,
+                   const MPI_Offset  start[],
+                   const MPI_Offset  count[],
+                   const MPI_Offset  stride[],
+                   const $2         *op,
+                   int              *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARS,
+                                 0, 0, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    return ncmpii_igetput_varm(ncp, varp, start, count, stride, NULL,
+                               (void*)op, -1, $3, reqid, WRITE_REQ, 1, 0);
+}
+')dnl
+
+BPUT_VARS_TYPE(text,      char,               MPI_CHAR)
+BPUT_VARS_TYPE(schar,     schar,              MPI_SIGNED_CHAR)
+BPUT_VARS_TYPE(uchar,     uchar,              MPI_UNSIGNED_CHAR)
+BPUT_VARS_TYPE(short,     short,              MPI_SHORT)
+BPUT_VARS_TYPE(ushort,    ushort,             MPI_UNSIGNED_SHORT)
+BPUT_VARS_TYPE(int,       int,                MPI_INT)
+BPUT_VARS_TYPE(uint,      uint,               MPI_UNSIGNED)
+BPUT_VARS_TYPE(long,      long,               MPI_LONG)
+BPUT_VARS_TYPE(float,     float,              MPI_FLOAT)
+BPUT_VARS_TYPE(double,    double,             MPI_DOUBLE)
+BPUT_VARS_TYPE(longlong,  long long,          MPI_LONG_LONG_INT)
+BPUT_VARS_TYPE(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+/*----< ncmpi_bput_varm() >---------------------------------------------------*/
+int
+ncmpi_bput_varm(int               ncid,
+                int               varid,
+                const MPI_Offset  start[],
+                const MPI_Offset  count[],
+                const MPI_Offset  stride[],
+                const MPI_Offset  imap[],
+                const void       *buf,
+                MPI_Offset        bufcount,
+                MPI_Datatype      buftype,
+                int              *reqid)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARM,
+                                 0, 1, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    return ncmpii_igetput_varm(ncp, varp, start, count, stride, imap,
+                               (void*)buf, bufcount, buftype, reqid,
+                               WRITE_REQ, 1, 0);
+}
+
+dnl
+dnl BPUT_VARM_TYPE(ncid, varid, start, count, stride, imap, op, reqid)
+dnl
+define(`BPUT_VARM_TYPE',dnl
+`dnl
+/*----< ncmpi_bput_varm_$1() >------------------------------------------------*/
+int
+ncmpi_bput_varm_$1(int               ncid,
+                   int               varid,
+                   const MPI_Offset  start[],
+                   const MPI_Offset  count[],
+                   const MPI_Offset  stride[],
+                   const MPI_Offset  imap[],
+                   const $2         *op,
+                   int              *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARM,
+                                 0, 0, WRITE_REQ, NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    return ncmpii_igetput_varm(ncp, varp, start, count, stride, imap,
+                               (void*)op, -1, $3, reqid, WRITE_REQ, 1, 0);
+}
+')dnl
+
+BPUT_VARM_TYPE(text,      char,               MPI_CHAR)
+BPUT_VARM_TYPE(schar,     schar,              MPI_SIGNED_CHAR)
+BPUT_VARM_TYPE(uchar,     uchar,              MPI_UNSIGNED_CHAR)
+BPUT_VARM_TYPE(short,     short,              MPI_SHORT)
+BPUT_VARM_TYPE(ushort,    ushort,             MPI_UNSIGNED_SHORT)
+BPUT_VARM_TYPE(int,       int,                MPI_INT)
+BPUT_VARM_TYPE(uint,      uint,               MPI_UNSIGNED)
+BPUT_VARM_TYPE(long,      long,               MPI_LONG)
+BPUT_VARM_TYPE(float,     float,              MPI_FLOAT)
+BPUT_VARM_TYPE(double,    double,             MPI_DOUBLE)
+BPUT_VARM_TYPE(longlong,  long long,          MPI_LONG_LONG_INT)
+BPUT_VARM_TYPE(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+
+/*----< ncmpi_buffer_attach() >-----------------------------------------------*/
+int
+ncmpi_buffer_attach(int        ncid,
+                    MPI_Offset bufsize)
+{
+    int status;
+    NC *ncp;
+
+    if (bufsize <= 0) DEBUG_RETURN_ERROR(NC_ENULLBUF)
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* check if the buffer has been previously attached
+     * note that in nc.c, the NC object is allocated with calloc, so
+     * abuf should be initialized to NULL then
+     */
+    if (ncp->abuf != NULL) DEBUG_RETURN_ERROR(NC_EPREVATTACHBUF)
+
+    ncp->abuf = (NC_buf*) NCI_Malloc(sizeof(NC_buf));
+
+    ncp->abuf->size_allocated = bufsize;
+    ncp->abuf->size_used = 0;
+    ncp->abuf->table_size = NC_ABUF_DEFAULT_TABLE_SIZE;
+    ncp->abuf->occupy_table = (NC_buf_status*)
+               NCI_Calloc(NC_ABUF_DEFAULT_TABLE_SIZE, sizeof(NC_buf_status));
+    ncp->abuf->tail = 0;
+    ncp->abuf->buf = NCI_Malloc((size_t)bufsize);
+    return NC_NOERR;
+}
+
+/*----< ncmpi_buffer_detach() >-----------------------------------------------*/
+int
+ncmpi_buffer_detach(int ncid)
+{
+    int     status;
+    NC     *ncp;
+    NC_req *cur_req;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* check if the buffer has been previously attached */
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    /* this API assumes users are responsible for no pending bput */
+    cur_req = ncp->head;
+    while (cur_req != NULL) { /* check if there is a pending bput */
+        if (cur_req->abuf_index >= 0)
+            DEBUG_RETURN_ERROR(NC_EPENDINGBPUT)
+            /* return now, so users can call wait and try detach again */
+        cur_req = cur_req->next;
+    }
+
+    NCI_Free(ncp->abuf->buf);
+    NCI_Free(ncp->abuf->occupy_table);
+    NCI_Free(ncp->abuf);
+    ncp->abuf = NULL;
+
+    return NC_NOERR;
+}
+
+#ifdef THIS_SEEMS_OVER_DONE_IT
+/*----< ncmpi_buffer_detach() >-----------------------------------------------*/
+/* mimic MPI_Buffer_detach()
+ * Note from MPI: Even though the 'bufferptr' argument is declared as
+ * 'void *', it is really the address of a void pointer.
+ */
+int
+ncmpi_buffer_detach(int         ncid,
+                    void       *bufptr,
+                    MPI_Offset *bufsize)
+{
+    int     status;
+    NC     *ncp;
+    NC_req *cur_req;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* check if the buffer has been previously attached */
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    /* check MPICH2 src/mpi/pt2pt/bsendutil.c for why the bufptr is void* */
+    *(void **)bufptr = ncp->abuf->buf;
+    *bufsize         = ncp->abuf->size_allocated;
+
+    /* this API assumes users are responsible for no pending bput when called */
+    cur_req = ncp->head;
+    while (cur_req != NULL) { /* check if there is a pending bput */
+        if (cur_req->abuf_index >= 0)
+            DEBUG_RETURN_ERROR(NC_EPENDINGBPUT)
+        cur_req = cur_req->next;
+    }
+
+    NCI_Free(ncp->abuf->occupy_table);
+    NCI_Free(ncp->abuf);
+    ncp->abuf = NULL;
+
+    return NC_NOERR;
+}
+#endif
+
+
+/*----< ncmpi_inq_buffer_usage() >--------------------------------------------*/
+int
+ncmpi_inq_buffer_usage(int         ncid,
+                       MPI_Offset *usage) /* OUT: in bytes */
+{
+    int  status;
+    NC  *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* check if the buffer has been previously attached */
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    /* return the current usage in bytes */
+    *usage = ncp->abuf->size_used;
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_buffer_size() >---------------------------------------------*/
+int
+ncmpi_inq_buffer_size(int         ncid,
+                      MPI_Offset *buf_size) /* OUT: in bytes */
+{
+    int  status;
+    NC  *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* check if the buffer has been previously attached */
+    if (ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    /* return the current usage in bytes */
+    *buf_size = ncp->abuf->size_allocated;
+
+    return NC_NOERR;
+}
+
diff --git a/src/lib/convert_swap.m4 b/src/lib/convert_swap.m4
new file mode 100644
index 0000000..25792f1
--- /dev/null
+++ b/src/lib/convert_swap.m4
@@ -0,0 +1,311 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: convert_swap.m4 2290 2016-01-02 18:37:46Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <assert.h>
+#include <arpa/inet.h>   /* htonl(), htons() */
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "macro.h"
+
+/* Prototypes for functions used only in this file */
+#if 0
+static void swapn(void *dst, const void *src, MPI_Offset nn, int xsize);
+#endif
+
+/*
+ *  Datatype Mapping:
+ *
+ *  NETCDF    <--> MPI                    Description
+ *   NC_BYTE       MPI_SIGNED_CHAR        signed 1-byte integer
+ *   NC_CHAR       MPI_CHAR               char, text (cannot convert to other types)
+ *   NC_SHORT      MPI_SHORT              signed 2-byte integer
+ *   NC_INT        MPI_INT                signed 4-byte integer
+ *   NC_FLOAT      MPI_FLOAT              single precision floating point
+ *   NC_DOUBLE     MPI_DOUBLE             double precision floating point
+ *   NC_UBYTE      MPI_UNSIGNED_CHAR      unsigned 1-byte int
+ *   NC_USHORT     MPI_UNSIGNED_SHORT     unsigned 2-byte int
+ *   NC_UINT       MPI_UNSIGNED           unsigned 4-byte int
+ *   NC_INT64      MPI_LONG_LONG_INT      signed 8-byte int
+ *   NC_UINT64     MPI_UNSIGNED_LONG_LONG unsigned 8-byte int
+ *
+ *  Assume: MPI_Datatype and nc_type are both enumerable types
+ *          (this might not conform with MPI, as MPI_Datatype is intended to be
+ *           an opaque data type.)
+ *
+ *  In OpenMPI, this assumption will fail
+ */
+
+inline MPI_Datatype
+ncmpii_nc2mpitype(nc_type type)
+{
+    switch(type){
+        case NC_BYTE :   return MPI_SIGNED_CHAR;
+        case NC_CHAR :   return MPI_CHAR;
+        case NC_SHORT :  return MPI_SHORT;
+        case NC_INT :    return MPI_INT;
+        case NC_FLOAT :  return MPI_FLOAT;
+        case NC_DOUBLE : return MPI_DOUBLE;
+        case NC_UBYTE :  return MPI_UNSIGNED_CHAR;
+        case NC_USHORT : return MPI_UNSIGNED_SHORT;
+        case NC_UINT :   return MPI_UNSIGNED;
+        case NC_INT64 :  return MPI_LONG_LONG_INT;
+        case NC_UINT64 : return MPI_UNSIGNED_LONG_LONG;
+        default:         return MPI_DATATYPE_NULL;
+    }
+}
+
+/*----< ncmpii_need_convert() >----------------------------------------------*/
+/* netCDF specification make a special case for type conversion between
+ * uchar and scahr: do not check for range error. See
+ * http://www.unidata.ucar.edu/software/netcdf/docs_rc/data_type.html#type_conversion
+ */
+inline int
+ncmpii_need_convert(nc_type nctype,MPI_Datatype mpitype) {
+    return !( (nctype == NC_CHAR   && mpitype == MPI_CHAR)           ||
+              (nctype == NC_BYTE   && mpitype == MPI_SIGNED_CHAR)    ||
+              (nctype == NC_BYTE   && mpitype == MPI_UNSIGNED_CHAR)  ||
+#if defined(__CHAR_UNSIGNED__) && __CHAR_UNSIGNED__ != 0
+              (nctype == NC_BYTE   && mpitype == MPI_CHAR)           ||
+#endif
+              (nctype == NC_SHORT  && mpitype == MPI_SHORT)          ||
+              (nctype == NC_INT    && mpitype == MPI_INT)            ||
+              (nctype == NC_INT    && mpitype == MPI_LONG &&
+               X_SIZEOF_INT == SIZEOF_LONG)                          ||
+              (nctype == NC_FLOAT  && mpitype == MPI_FLOAT)          ||
+              (nctype == NC_DOUBLE && mpitype == MPI_DOUBLE)         ||
+              (nctype == NC_UBYTE  && mpitype == MPI_UNSIGNED_CHAR)  ||
+              (nctype == NC_USHORT && mpitype == MPI_UNSIGNED_SHORT) ||
+              (nctype == NC_UINT   && mpitype == MPI_UNSIGNED)       ||
+              (nctype == NC_INT64  && mpitype == MPI_LONG_LONG_INT)  ||
+              (nctype == NC_UINT64 && mpitype == MPI_UNSIGNED_LONG_LONG)
+            );
+}
+
+/*----< ncmpii_need_swap() >-------------------------------------------------*/
+inline int
+ncmpii_need_swap(nc_type      nctype,
+                 MPI_Datatype mpitype)
+{
+#ifdef WORDS_BIGENDIAN
+    return 0;
+#else
+    if ((nctype == NC_CHAR   && mpitype == MPI_CHAR)           ||
+        (nctype == NC_BYTE   && mpitype == MPI_SIGNED_CHAR)    ||
+        (nctype == NC_UBYTE  && mpitype == MPI_UNSIGNED_CHAR))
+        return 0;
+
+    return 1;
+#endif
+}
+
+#if 0
+/*----< swapn() >------------------------------------------------------------*/
+inline static void
+swapn(void       *dst,
+      const void *src,
+      MPI_Offset  nn,
+      int         xsize)
+{
+    int i;
+    uchar *op = dst;
+    const uchar *ip = src;
+    while (nn-- != 0) {
+        for (i=0; i<xsize; i++)
+            op[i] = ip[xsize-1-i];
+        op += xsize;
+        ip += xsize;
+    }
+}
+#endif
+
+/* Endianness byte swap: done in-place */
+#define SWAP(x,y) {tmp = (x); (x) = (y); (y) = tmp;}
+
+/*----< ncmpii_swap() >-------------------------------------------------------*/
+void
+ncmpii_swapn(void       *dest_p,  /* destination array */
+             const void *src_p,   /* source array */
+             MPI_Offset  nelems,  /* number of elements in buf[] */
+             int         esize)   /* byte size of each element */
+{
+    int  i;
+
+    if (esize <= 1 || nelems <= 0) return;  /* no need */
+
+    if (esize == 4) { /* this is the most common case */
+              uint32_t *dest = (uint32_t*)       dest_p;
+        const uint32_t *src  = (const uint32_t*) src_p;
+        for (i=0; i<nelems; i++)
+            dest[i] = htonl(src[i]);
+    }
+    else if (esize == 2) {
+              uint16_t *dest =       (uint16_t*) dest_p;
+        const uint16_t *src  = (const uint16_t*) src_p;
+        for (i=0; i<nelems; i++)
+            dest[i] = htons(src[i]);
+    }
+    else {
+              uchar *op = (uchar*) dest_p;
+        const uchar *ip = (uchar*) src_p;
+        /* for esize is not 1, 2, or 4 */
+        while (nelems-- > 0) {
+            for (i=0; i<esize; i++)
+                op[i] = ip[esize-1-i];
+            op += esize;
+            ip += esize;
+        }
+    }
+}
+
+/*----< ncmpii_in_swap() >---------------------------------------------------*/
+void
+ncmpii_in_swapn(void       *buf,
+                MPI_Offset  nelems,  /* number of elements in buf[] */
+                int         esize)   /* byte size of each element */
+{
+    int  i;
+    uchar tmp, *op = (uchar*)buf;
+
+    if (esize <= 1 || nelems <= 0) return;  /* no need */
+
+    if (esize == 4) { /* this is the most common case */
+        uint32_t *dest = (uint32_t*) buf;
+        for (i=0; i<nelems; i++)
+            dest[i] = htonl(dest[i]);
+    }
+    else if (esize == 2) {
+        uint16_t *dest = (uint16_t*) buf;
+        for (i=0; i<nelems; i++)
+            dest[i] = htons(dest[i]);
+    }
+    else {
+        /* for esize is not 1, 2, or 4 */
+        while (nelems-- > 0) {
+            for (i=0; i<esize/2; i++)
+                SWAP(op[i], op[esize-1-i])
+            op += esize;
+        }
+    }
+}
+
+
+dnl
+dnl X_PUTN_FILETYPE(xtype)
+dnl
+define(`X_PUTN_FILETYPE',dnl
+`dnl
+/*----< ncmpii_x_putn_$1() >--------------------------------------------------*/
+inline int
+ncmpii_x_putn_$1(void         *xp,      /* file buffer of type schar */
+                 const void   *putbuf,  /* put buffer of type puttype */
+                 MPI_Offset    nelems,
+                 MPI_Datatype  puttype)
+{
+    if (puttype == MPI_CHAR || /* assume ECHAR has been checked before */
+        puttype == MPI_SIGNED_CHAR)
+        return ncmpix_putn_$1_schar    (&xp, nelems, (const schar*)     putbuf);
+    else if (puttype == MPI_UNSIGNED_CHAR)
+        return ncmpix_putn_$1_uchar    (&xp, nelems, (const uchar*)     putbuf);
+    else if (puttype == MPI_SHORT)
+        return ncmpix_putn_$1_short    (&xp, nelems, (const short*)     putbuf);
+    else if (puttype == MPI_UNSIGNED_SHORT)
+        return ncmpix_putn_$1_ushort   (&xp, nelems, (const ushort*)    putbuf);
+    else if (puttype == MPI_INT)
+        return ncmpix_putn_$1_int      (&xp, nelems, (const int*)       putbuf);
+    else if (puttype == MPI_UNSIGNED)
+        return ncmpix_putn_$1_uint     (&xp, nelems, (const uint*)      putbuf);
+    else if (puttype == MPI_LONG)
+        return ncmpix_putn_$1_long     (&xp, nelems, (const long*)      putbuf);
+    else if (puttype == MPI_FLOAT)
+        return ncmpix_putn_$1_float    (&xp, nelems, (const float*)     putbuf);
+    else if (puttype == MPI_DOUBLE)
+        return ncmpix_putn_$1_double   (&xp, nelems, (const double*)    putbuf);
+    else if (puttype == MPI_LONG_LONG_INT)
+        return ncmpix_putn_$1_longlong (&xp, nelems, (const longlong*)  putbuf);
+    else if (puttype == MPI_UNSIGNED_LONG_LONG)
+        return ncmpix_putn_$1_ulonglong(&xp, nelems, (const ulonglong*) putbuf);
+    DEBUG_RETURN_ERROR(NC_EBADTYPE)
+}
+')dnl
+
+X_PUTN_FILETYPE(schar)
+X_PUTN_FILETYPE(uchar)
+X_PUTN_FILETYPE(short)
+X_PUTN_FILETYPE(ushort)
+X_PUTN_FILETYPE(int)
+X_PUTN_FILETYPE(uint)
+X_PUTN_FILETYPE(float)
+X_PUTN_FILETYPE(double)
+X_PUTN_FILETYPE(int64)
+X_PUTN_FILETYPE(uint64)
+
+dnl
+dnl X_GETN_FILETYPE(xtype)
+dnl
+define(`X_GETN_FILETYPE',dnl
+`dnl
+/*----< ncmpii_x_getn_$1() >-------------------------------------------------*/
+inline int
+ncmpii_x_getn_$1(const void   *xp,      /* file buffer of type schar */
+                 void         *getbuf,  /* get buffer of type gettype */
+                 MPI_Offset    nelems,
+                 MPI_Datatype  gettype)
+{
+    if (gettype == MPI_CHAR || /* assume ECHAR has been checked before */
+        gettype == MPI_SIGNED_CHAR)
+        return ncmpix_getn_$1_schar    (&xp, nelems, (schar*)     getbuf);
+    else if (gettype == MPI_UNSIGNED_CHAR)
+        return ncmpix_getn_$1_uchar    (&xp, nelems, (uchar*)     getbuf);
+    else if (gettype == MPI_SHORT)
+        return ncmpix_getn_$1_short    (&xp, nelems, (short*)     getbuf);
+    else if (gettype == MPI_UNSIGNED_SHORT)
+        return ncmpix_getn_$1_ushort   (&xp, nelems, (ushort*)    getbuf);
+    else if (gettype == MPI_INT)
+        return ncmpix_getn_$1_int      (&xp, nelems, (int*)       getbuf);
+    else if (gettype == MPI_UNSIGNED)
+        return ncmpix_getn_$1_uint     (&xp, nelems, (uint*)      getbuf);
+    else if (gettype == MPI_LONG)
+        return ncmpix_getn_$1_long     (&xp, nelems, (long*)      getbuf);
+    else if (gettype == MPI_FLOAT)
+        return ncmpix_getn_$1_float    (&xp, nelems, (float*)     getbuf);
+    else if (gettype == MPI_DOUBLE)
+        return ncmpix_getn_$1_double   (&xp, nelems, (double*)    getbuf);
+    else if (gettype == MPI_LONG_LONG_INT)
+        return ncmpix_getn_$1_longlong (&xp, nelems, (longlong*)  getbuf);
+    else if (gettype == MPI_UNSIGNED_LONG_LONG)
+        return ncmpix_getn_$1_ulonglong(&xp, nelems, (ulonglong*) getbuf);
+    DEBUG_RETURN_ERROR(NC_EBADTYPE)
+}
+')dnl
+
+X_GETN_FILETYPE(schar)
+X_GETN_FILETYPE(uchar)
+X_GETN_FILETYPE(short)
+X_GETN_FILETYPE(ushort)
+X_GETN_FILETYPE(int)
+X_GETN_FILETYPE(uint)
+X_GETN_FILETYPE(float)
+X_GETN_FILETYPE(double)
+X_GETN_FILETYPE(int64)
+X_GETN_FILETYPE(uint64)
+
diff --git a/src/lib/depend b/src/lib/depend
new file mode 100644
index 0000000..d07d4da
--- /dev/null
+++ b/src/lib/depend
@@ -0,0 +1,31 @@
+#
+# generated from command "gcc -MM file.c"
+#
+mpinetcdf.o: mpinetcdf.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h macro.h
+header.o: header.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h macro.h
+mpincio.o: mpincio.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h rnd.h macro.h
+attr.o: attr.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h macro.h
+dim.o: dim.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h macro.h
+error.o: error.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h
+nc.o: nc.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h rnd.h ncx.h nctypes.h macro.h
+ncx.o: ncx.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h macro.h
+string.o: string.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h macro.h utf8proc.h
+var.o: var.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h macro.h
+ncmpidtype.o: ncmpidtype.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncmpidtype.h macro.h
+convert_swap.o: convert_swap.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h macro.h
+filetype.o: filetype.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h macro.h
+m_getput_varx.o: m_getput_varx.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h ncmpidtype.h macro.h
+varn.o: varn.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h ncmpidtype.h macro.h
+i_varn.o: i_varn.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h ncmpidtype.h macro.h
+nonblocking.o: nonblocking.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h ncmpidtype.h macro.h
+malloc.o: malloc.c ncconfig.h nc.h
+utf8proc.o: utf8proc.c ncconfig.h utf8proc.h utf8proc_data.h
+ncx.o: ncx.c ncconfig.h nc.h pnetcdf.h ncx.h
+swap.o: swap.c ncconfig.h ncx.h rnd.h nctypes.h pnetcdf.h
+bput.o: bput.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h ncmpidtype.h macro.h
+getput.o: getput.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h ncmpidtype.h macro.h
+i_getput.o: i_getput.c ncconfig.h nc.h pnetcdf.h ncio.h fbits.h ncx.h rnd.h nctypes.h ncmpidtype.h macro.h
+subfile.o: subfile.c ncconfig.h subfile.h pnetcdf.h nc.h ncio.h fbits.h macro.h ncmpidtype.h
+vard.o: vard.c ncconfig.h pnetcdf.h nc.h ncio.h fbits.h rnd.h ncx.h nctypes.h macro.h ncmpidtype.h
+fill.o: fill.c nc.h ncio.h pnetcdf.h fbits.h macro.h
+util.o: util.c nc.h ncio.h pnetcdf.h fbits.h macro.h
diff --git a/src/lib/dim.c b/src/lib/dim.c
new file mode 100644
index 0000000..792f290
--- /dev/null
+++ b/src/lib/dim.c
@@ -0,0 +1,525 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: dim.c 2302 2016-01-10 20:33:45Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "fbits.h"
+#include "macro.h"
+#include "utf8proc.h"
+
+/*
+ * Free dim
+ * Formerly
+NC_free_dim(dim)
+ */
+inline void
+ncmpii_free_NC_dim(NC_dim *dimp)
+{
+    if (dimp == NULL) return;
+    ncmpii_free_NC_string(dimp->name);
+    NCI_Free(dimp);
+}
+
+
+/* allocate and return a new NC_dim object */
+inline NC_dim *
+ncmpii_new_x_NC_dim(NC_string *name)
+{
+    NC_dim *dimp;
+
+    dimp = (NC_dim *) NCI_Malloc(sizeof(NC_dim));
+    if (dimp == NULL) return NULL;
+
+    dimp->name = name;
+    dimp->size = 0;
+
+    return(dimp);
+}
+
+/*----< ncmpii_new_NC_dim() >------------------------------------------------*/
+/*
+ * Formerly, NC_new_dim(const char *name, long size)
+ */
+static NC_dim *
+ncmpii_new_NC_dim(const char *uname,  /* dimension name */
+                  MPI_Offset  size)
+{
+    NC_string *strp;
+    NC_dim *dimp;
+
+    char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
+    if (name == NULL) return NULL;
+
+    strp = ncmpii_new_NC_string(strlen(name), name);
+    free(name);
+    if (strp == NULL) return NULL;
+
+    dimp = ncmpii_new_x_NC_dim(strp);
+    if (dimp == NULL) {
+        ncmpii_free_NC_string(strp);
+        return NULL;
+    }
+
+    dimp->size = size;
+
+    return(dimp);
+}
+
+
+NC_dim *
+dup_NC_dim(const NC_dim *dimp)
+{
+    return ncmpii_new_NC_dim(dimp->name->cp, dimp->size);
+}
+
+/*----< ncmpii_find_NC_Udim() >----------------------------------------------*/
+/*
+ * Step thru NC_DIMENSION array, seeking the UNLIMITED dimension.
+ * Return dimid or -1 on not found.
+ * *dimpp is set to the appropriate NC_dim.
+ */
+int
+ncmpii_find_NC_Udim(const NC_dimarray  *ncap,
+                    NC_dim            **dimpp)
+{
+    int dimid;
+
+    assert(ncap != NULL);
+
+    if (ncap->ndefined == 0) return -1;
+
+    /* note that the number of dimensions allowed is < 2^32 */
+    for (dimid=0; dimid<ncap->ndefined; dimid++)
+        if (ncap->value[dimid]->size == NC_UNLIMITED) {
+            /* found the matched name */
+            if (dimpp != NULL)
+                *dimpp = ncap->value[dimid];
+            return dimid;
+        }
+
+    /* not found */
+    return -1;
+}
+
+/*----< NC_finddim() >-------------------------------------------------------*/
+/*
+ * Step thru NC_DIMENSION array, seeking match on name.
+ * Return dimid or -1 on not found.
+ * *dimpp is set to the appropriate NC_dim.
+ */
+static int
+NC_finddim(const NC_dimarray  *ncap,
+           const char         *uname,
+           NC_dim            **dimpp)
+{
+    int dimid;
+    size_t nchars;
+
+    assert(ncap != NULL);
+
+    if (ncap->ndefined == 0) return -1;
+
+    char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
+    nchars = strlen(name);
+
+    /* note that the number of dimensions allowed is < 2^32 */
+    for (dimid=0; dimid<ncap->ndefined; dimid++) {
+        if (ncap->value[dimid]->name->nchars == nchars &&
+            strncmp(ncap->value[dimid]->name->cp, name, nchars) == 0) {
+            /* found the matched name */
+            if (dimpp != NULL)
+                *dimpp = ncap->value[dimid];
+            free(name);
+            return dimid;
+        }
+    }
+    free(name);
+
+    /* the name is not found */
+    return -1;
+}
+
+
+/* dimarray */
+
+
+/*----< ncmpii_free_NC_dimarray() >------------------------------------------*/
+/*
+ * Free NC_dimarray values.
+ * formerly
+NC_free_array()
+ */
+inline void
+ncmpii_free_NC_dimarray(NC_dimarray *ncap)
+{
+    int i;
+
+    assert(ncap != NULL);
+    if (ncap->nalloc == 0) return;
+
+    assert(ncap->value != NULL);
+    for (i=0; i<ncap->ndefined; i++)
+        ncmpii_free_NC_dim(ncap->value[i]);
+
+    NCI_Free(ncap->value);
+    ncap->value    = NULL;
+    ncap->nalloc   = 0;
+    ncap->ndefined = 0;
+}
+
+
+/*----< ncmpii_dup_NC_dimarray() >-------------------------------------------*/
+int
+ncmpii_dup_NC_dimarray(NC_dimarray *ncap, const NC_dimarray *ref)
+{
+    int i, status=NC_NOERR;
+
+    assert(ref != NULL);
+    assert(ncap != NULL);
+
+    if (ref->nalloc == 0) {
+        ncap->nalloc   = 0;
+        ncap->ndefined = 0;
+        ncap->value    = NULL;
+        return NC_NOERR;
+    }
+
+    if (ref->nalloc > 0) {
+        ncap->value = (NC_dim **) NCI_Calloc((size_t)ref->nalloc, sizeof(NC_dim *));
+        if (ncap->value == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+        ncap->nalloc = ref->nalloc;
+    }
+
+    ncap->ndefined = 0;
+    for (i=0; i<ref->ndefined; i++) {
+        ncap->value[i] = dup_NC_dim(ref->value[i]);
+        if (ncap->value[i] == NULL) {
+            DEBUG_ASSIGN_ERROR(status, NC_ENOMEM)
+            break;
+        }
+    }
+
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_dimarray(ncap);
+        return status;
+    }
+
+    ncap->ndefined = ref->ndefined;
+
+    return NC_NOERR;
+}
+
+
+/*----< incr_NC_dimarray() >---------------------------------------------- --*/
+/*
+ * Add a new handle to the end of an array of handles
+ * Formerly, NC_incr_array(array, tail)
+ */
+int
+incr_NC_dimarray(NC_dimarray *ncap,
+                 NC_dim      *newdimp)
+{
+    NC_dim **vp;
+
+    assert(ncap != NULL);
+
+    if (ncap->nalloc == 0) {
+        assert(ncap->ndefined == 0);
+        vp = (NC_dim **) NCI_Malloc(NC_ARRAY_GROWBY * sizeof(NC_dim *));
+        if (vp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+        ncap->value = vp;
+        ncap->nalloc = NC_ARRAY_GROWBY;
+    }
+    else if (ncap->ndefined + 1 > ncap->nalloc) {
+        vp = (NC_dim **) NCI_Realloc(ncap->value,
+             (size_t)(ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_dim *));
+        if (vp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+        ncap->value = vp;
+        ncap->nalloc += NC_ARRAY_GROWBY;
+    }
+    /* else here means some space still available */
+
+    if (newdimp != NULL) {
+        ncap->value[ncap->ndefined] = newdimp;
+        ncap->ndefined++;
+    }
+
+    return NC_NOERR;
+}
+
+
+/*----< ncmpii_elem_NC_dimarray() >------------------------------------------*/
+inline NC_dim *
+ncmpii_elem_NC_dimarray(const NC_dimarray *ncap,
+                        int                dimid)
+{
+    /* returns the dimension ID defined earlier */
+    assert(ncap != NULL);
+
+    if (dimid < 0 || ncap->ndefined == 0 || dimid >= ncap->ndefined)
+        return NULL;
+
+    assert(ncap->value != NULL);
+
+    return ncap->value[dimid];
+}
+
+
+/* Public */
+
+/*----< ncmpi_def_dim() >----------------------------------------------------*/
+int
+ncmpi_def_dim(int         ncid,    /* IN:  file ID */
+              const char *name,    /* IN:  name of dimension */
+              MPI_Offset  size,    /* IN:  dimension size */
+              int        *dimidp)  /* OUT: dimension ID */
+{
+    int dimid, file_ver, status;
+    NC *ncp;
+    NC_dim *dimp;
+
+    /* check if ncid is valid */
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* check if called in define mode */
+    if (!NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+
+    /* check if the name string is legal for netcdf format */
+    file_ver = 1;
+    if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
+        file_ver = 2;
+    else if (fIsSet(ncp->flags, NC_64BIT_DATA))
+        file_ver = 5;
+
+    status = ncmpii_NC_check_name(name, file_ver);
+    if (status != NC_NOERR) return status;
+
+    /* MPI_Offset is usually a signed value, but serial netcdf uses
+     * size_t -- normally unsigned
+     * In 1999 ISO C standard, size_t is a unsigned integer type of at least
+     * 16 bit. */
+    if ((ncp->flags & NC_64BIT_OFFSET) && SIZEOF_OFF_T > 4) {
+        /* CDF2 format and LFS, max is 2^32-4 */
+        if (size > X_UINT_MAX - 3 || (size < 0))
+            /* "-3" handles rounded-up size */
+            DEBUG_RETURN_ERROR(NC_EDIMSIZE)
+    } else if ((ncp->flags & NC_64BIT_DATA)) {
+        /* CDF5 format*/
+        if (size < 0)
+            DEBUG_RETURN_ERROR(NC_EDIMSIZE)
+    } else {
+        /* CDF1 format, max is 2^31-4 */
+        if (size > X_INT_MAX - 3 || (size < 0))
+            /* "-3" handles rounded-up size */
+            DEBUG_RETURN_ERROR(NC_EDIMSIZE)
+    }
+
+    if (size == NC_UNLIMITED) {
+        /* check for any existing unlimited dimension, netcdf allows
+         * one per file
+         */
+        dimid = ncmpii_find_NC_Udim(&ncp->dims, &dimp);
+        if (dimid != -1) DEBUG_RETURN_ERROR(NC_EUNLIMIT) /* found an existing one */
+    }
+
+    /* check if exceeds the upperbound has reached */
+    if (ncp->dims.ndefined >= NC_MAX_DIMS) DEBUG_RETURN_ERROR(NC_EMAXDIMS)
+
+    /* check if the name string is previously used */
+    dimid = NC_finddim(&ncp->dims, name, &dimp);
+    if (dimid != -1) DEBUG_RETURN_ERROR(NC_ENAMEINUSE)
+
+    /* create a new dimension object */
+    dimp = ncmpii_new_NC_dim(name, size);
+    if (dimp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    /* Add a new handle to the end of an array of handles */
+    status = incr_NC_dimarray(&ncp->dims, dimp);
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_dim(dimp);
+        return status;
+    }
+
+    if (dimidp != NULL)
+        *dimidp = (int)ncp->dims.ndefined -1;
+        /* ncp->dims.ndefined has been increased in incr_NC_dimarray() */
+
+    return NC_NOERR;
+}
+
+
+/*----< ncmpi_inq_dimid() >--------------------------------------------------*/
+int
+ncmpi_inq_dimid(int         ncid,
+                const char *name,
+                int        *dimid_ptr)
+{
+    int status;
+    NC *ncp;
+    int dimid;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    dimid = NC_finddim(&ncp->dims, name, NULL);
+    if (dimid == -1) DEBUG_RETURN_ERROR(NC_EBADDIM)
+
+    *dimid_ptr = dimid;
+    return NC_NOERR;
+}
+
+
+/*----< ncmpi_inq_dim() >----------------------------------------------------*/
+int
+ncmpi_inq_dim(int         ncid,
+              int         dimid,
+              char       *name,
+              MPI_Offset *sizep)
+{
+    int status;
+    NC *ncp;
+    NC_dim *dimp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    dimp = ncmpii_elem_NC_dimarray(&ncp->dims, dimid);
+    if (dimp == NULL) DEBUG_RETURN_ERROR(NC_EBADDIM)
+
+    if (name != NULL)
+        /* in PnetCDF, name->cp is always NULL character terminated */
+        strcpy(name, dimp->name->cp);
+
+    if (sizep != NULL) {
+        if (dimp->size == NC_UNLIMITED)
+            *sizep = NC_get_numrecs(ncp);
+        else
+            *sizep = dimp->size;
+    }
+    return NC_NOERR;
+}
+
+
+/*----< ncmpi_inq_dimname() >------------------------------------------------*/
+int
+ncmpi_inq_dimname(int   ncid,
+                  int   dimid,
+                  char *name)
+{
+    return ncmpi_inq_dim(ncid, dimid, name, NULL);
+}
+
+
+/*----< ncmpi_inq_dimlen() >-------------------------------------------------*/
+int
+ncmpi_inq_dimlen(int         ncid,
+                 int         dimid,
+                 MPI_Offset *lenp)
+{
+    return ncmpi_inq_dim(ncid, dimid, NULL, lenp);
+}
+
+
+/*----< ncmpi_rename_dim() >--------------------------------------------------*/
+/* This API is collective if called in data mode */
+int
+ncmpi_rename_dim(int         ncid,
+                 int         dimid,
+                 const char *newname)
+{
+    int file_ver, status, existid, err, mpireturn;
+    NC *ncp;
+    NC_dim *dimp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM)
+
+    file_ver = 1;
+    if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
+        file_ver = 2;
+    else if (fIsSet(ncp->flags, NC_64BIT_DATA))
+        file_ver = 5;
+
+    status = ncmpii_NC_check_name(newname, file_ver);
+    if (status != NC_NOERR) return status;
+
+    existid = NC_finddim(&ncp->dims, newname, &dimp);
+    if (existid != -1) DEBUG_RETURN_ERROR(NC_ENAMEINUSE)
+
+    dimp = ncmpii_elem_NC_dimarray(&ncp->dims, dimid);
+    if (dimp == NULL) DEBUG_RETURN_ERROR(NC_EBADDIM)
+
+    if (NC_indef(ncp)) {
+        NC_string *newStr = ncmpii_new_NC_string(strlen(newname), newname);
+        if (newStr == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+        ncmpii_free_NC_string(dimp->name);
+        dimp->name = newStr;
+        return NC_NOERR;
+    }
+    /* else, not in define mode.
+     * if called in data mode (collective or independent), this function must
+     * be called collectively, i.e. all processes must participate.
+     */
+
+    if (ncp->safe_mode) {
+        int nchars = (int)strlen(newname);
+        TRACE_COMM(MPI_Bcast)(&nchars, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+
+        if (nchars != strlen(newname)) {
+            /* newname's length is inconsistent with root's */
+            printf("Warning: dimension name(%s) used in %s() is inconsistent\n",
+                   newname, __func__);
+            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_DIM_NAME)
+        }
+    }
+
+    /* ncmpii_set_NC_string() will check for strlen(newname) > nchars error */
+    err = ncmpii_set_NC_string(dimp->name, newname);
+    if (status == NC_NOERR) status = err;
+
+    /* PnetCDF expects all processes use the same name, However, when names
+     * are not the same, only root's value is significant. Broadcast the
+     * new name at root to overwrite new names at other processes.
+     * (This API is collective if called in data mode)
+     */
+    TRACE_COMM(MPI_Bcast)(dimp->name->cp, (int)dimp->name->nchars, MPI_CHAR, 0,
+                          ncp->nciop->comm);
+    if (mpireturn != MPI_SUCCESS) {
+        err = ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+        if (status == NC_NOERR) status = err;
+    }
+
+    /* Let root write the entire header to the file. Note that we cannot just
+     * update the variable name in its space occupied in the file header,
+     * because if the file space occupied by the name shrinks, all the metadata
+     * following it must be moved ahead.
+     */
+    err = ncmpii_write_header(ncp);
+    if (status == NC_NOERR) status = err;
+
+    return status;
+}
diff --git a/src/lib/error.c b/src/lib/error.c
new file mode 100644
index 0000000..e8a8384
--- /dev/null
+++ b/src/lib/error.c
@@ -0,0 +1,761 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: error.c 2282 2015-12-26 17:44:27Z wkliao $ */
+
+/*LINTLIBRARY*/
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <mpi.h>
+
+#include "nc.h"
+
+#ifdef HAVE_STRERROR
+#include <string.h> /* contains prototype for ansi libc function strerror() */
+#else
+/* provide a strerror function for older unix systems */
+inline static char *
+strerror(int errnum)
+{
+    extern int sys_nerr;
+    extern char *sys_errlist[];
+
+    if(errnum < 0 || errnum >= sys_nerr) return NULL;
+    /* else */
+    return sys_errlist[errnum];
+}
+#endif /* HAVE_STRERROR */
+
+
+#ifdef vms
+/* UNTESTED */
+/*
+ * On the vms system, when a system error occurs which is not
+ * mapped into the unix styled errno values, errno is set EVMSERR
+ * and a VMS error code is set in vaxc$errno.
+ * This routine prints the systems message associated with status return
+ * from a system services call.
+ */
+
+#include <errno.h>
+#include <descrip.h>
+#include <ssdef.h>
+
+static const char *
+vms_strerror( int status )
+{
+    short msglen;
+    static char msgbuf[256];
+    $DESCRIPTOR(message, msgbuf);
+    register ret;
+
+    msgbuf[0] = 0;
+    ret = SYS$GETMSG(status, &msglen, &message, 15, 0);
+
+    if(ret != SS$_BUFFEROVF && ret != SS$_NORMAL) {
+        (void) strcpy(msgbuf, "EVMSERR");
+    }
+    return(msgbuf);
+}
+#endif /* vms */
+
+
+/* must copy nc_strerror() from netCDF release */
+static const char* nc_strerror(int ncerr1);
+
+static char nc_unknown_err_msg[128];
+
+const char *
+ncmpi_strerror(int err)
+{
+    sprintf(nc_unknown_err_msg,"Unknown Error: Unrecognized error code %5d\n",err);
+
+#ifdef vms
+    if(err == EVMSERR)
+    {
+        return vms_strerror(err);
+    }
+    /* else */
+#endif /* vms */
+
+    if(NC_ISSYSERR(err))
+    {
+        const char *cp = (const char *) strerror(err);
+        if(cp == NULL)
+            return nc_unknown_err_msg;
+        /* else */
+        return cp;
+    }
+    /* else */
+
+    switch (err) {
+        /* PnetCDF errors */
+        case NC_ESMALL:
+            return "Size of MPI_Offset or MPI_Aint too small for requested format";
+            /* this usually happens on 32-bit machines where MPI_Offset and
+             * MPI_Aint may be 4-byte integers and when the I/O request amount
+             * or accessing file offset is > 2GB.
+             */
+        case NC_ENOTINDEP:
+            return "Operation not allowed in collective data mode";
+            /* this means your program is now in independent data mode, but
+             * making a call to a collective API
+             */
+        case NC_EINDEP:
+            return "Operation not allowed in independent data mode";
+            /* this means your program is now in collective data mode, but
+             * making a call to an independent API
+             */
+        case NC_EFILE:
+            return "Unknown error in file operation";
+            /* this error is caused by an unsuccessful MPI-IO call and usually
+             * accompany with additional MPI error messages
+             */
+        case NC_EREAD:
+            return "Unknow error occurs in reading file";
+            /* this error is caused by an unsuccessful call to MPI_File_read or
+             * MPI_File_read_all and usually accompany with additional MPI
+             * error messages
+             */
+        case NC_EWRITE:
+            return "Unknow error occurs in writting file";
+            /* this error is caused by an unsuccessful call to MPI_File_write or
+             * MPI_File_write_all and usually accompany with additional MPI
+             * error messages
+             */
+        case NC_EOFILE:
+            return "Can not open/create file";
+        case NC_EMULTITYPES:
+            return "Multiple types used in memory data";
+            /* when using flexible APIs, the argument MPI derived datatype is
+             * not allowed to contain more than one basic data type
+             */
+        case NC_EIOMISMATCH:
+            return "Input/Output data amount mismatch";
+            /* this error indicates the request amount is mismatched between
+             * bufcount and the value calculated from argument count[]
+             */
+        case NC_ENEGATIVECNT:
+            return "Negative count is prohibited";
+            /* In netCDF, count (or edge) argument is of type size_t, which is
+             * an unsigned integer. A negative count will make the value very
+             * large, causing NC_EEDGE error and hence netCDF need no such
+             * error code.
+             */
+        case NC_EUNSPTETYPE:
+            return "Unsupported etype is used in MPI datatype for memory data";
+            /* when using flexible APIs, the argument MPI derived datatype is
+             * only allowed to be constructed from the MPI basic data types
+             * known to PnetCDF
+             */
+        case NC_EINVAL_REQUEST:
+            return "Invalid nonblocking request ID.";
+        case NC_EAINT_TOO_SMALL:
+            return "MPI_Aint not large enough to hold requested value.";
+            /* this usually happens on 32-bit machines where MPI_Aint is a
+             * 4-byte integer and when the I/O request amount or accessing
+             * file offset is > 2GB.
+             */
+        case NC_ENOTSUPPORT:
+            return "Feature is not yet supported.";
+        case NC_ENULLBUF:
+            return "Trying to attach a NULL buffer or the buffer size is <= 0.";
+            /* an error returned from ncmpi_buffer_attach()
+             */
+        case NC_EPREVATTACHBUF:
+            return "Previous attached buffer is found.";
+            /* an error returned from ncmpi_buffer_attach() indicating a
+             * buffer has been attached previously
+             */
+        case NC_ENULLABUF:
+            return "No attached buffer is found.";
+            /* an error when calling bput APIs and no buffer has been attached
+             */
+        case NC_EPENDINGBPUT:
+            return "Cannot detach buffer as a pending bput request is found.";
+            /* an error returned from ncmpi_buffer_detach()
+             */
+        case NC_EINSUFFBUF:
+            return "Attached buffer is too small.";
+            /* an error when calling bput APIs
+             */
+        case NC_ENOENT:
+            return "The specified netCDF file does not exist.";
+            /* this error code corresponds to MPI error class
+             * MPI_ERR_NO_SUCH_FILE, an error generated from MPI_File_open(),
+             * MPI_File_delete() or others
+             */
+        case NC_EINTOVERFLOW:
+            return "Overflow when type cast to 4-byte integer.";
+            /* this usually happens on 32-bit machines where MPI_Offset is a
+             * 4-byte integer and when the I/O request amount or accessing
+             * file offset is > 2GB.
+             */
+        case NC_ENOTENABLED:
+            return "feature is not enabled at configure time.";
+            /* Some APIs require a specific feature enabled at the configure
+             * time, for example, ncmpi_inq_malloc_size() works only
+             * --enable-debug is used when configuring PnetCDF
+             */
+        case NC_EBAD_FILE:
+            return "Invalid file name (e.g., path name too long).";
+            /* this error code corresponds to MPI error class
+             * MPI_ERR_BAD_FILE, an error generated from MPI_File_open()
+             */
+        case NC_ENO_SPACE:
+            return "Not enough space.";
+            /* this error code corresponds to MPI error class
+             * MPI_ERR_NO_SPACE, an error generated from MPI_File_open()
+             */
+        case NC_EQUOTA:
+            return "Quota exceeded.";
+            /* this error code corresponds to MPI error class
+             * MPI_ERR_QUOTA, an error generated from MPI_File_open()
+             */
+        case NC_ENULLSTART:
+            return "argument start is a NULL pointer";
+            /* Some APIs require argument start not be a NULL pointer
+             */
+        case NC_ENULLCOUNT:
+            return "argument count is a NULL pointer";
+            /* Some APIs require argument count cannot be a NULL pointer
+             */
+        case NC_EINVAL_CMODE:
+            return "Invalid file create mode, cannot have both NC_64BIT_OFFSET & NC_64BIT_DATA";
+        case NC_ETYPESIZE:
+            return "MPI derived data type size error (bigger than the variable size)";
+        case NC_ETYPE_MISMATCH:
+            return "element type of the MPI derived data type mismatches the variable data type";
+        case NC_ETYPESIZE_MISMATCH:
+            return "filetype's size mismatches buftype's size * bufcount";
+        case NC_ESTRICTCDF2:
+            return "Attempting CDF-5 operation on strict CDF or CDF-2 file";
+        case NC_ENOTRECVAR:
+            return "Attempting operation only for record variables";
+        case NC_ENOTFILL:
+            return "Attempting to fill a variable when its fill mode is off";
+        case NC_EMULTIDEFINE:
+            return "File header is inconsistent among processes";
+            /* this error means the metadata (dimension names, variable names,
+             * variable's dimensions, attributes, and whatever will be stored
+             * in the file header) is inconsistent among all MPI processes.
+             */
+        case NC_EMULTIDEFINE_OMODE:
+            return "Bad file create/open mode or modes are inconsistent across processes.";
+        case NC_EMULTIDEFINE_DIM_NUM:
+            return "Number of dimensions is defined inconsistently among processes.";
+        case NC_EMULTIDEFINE_DIM_SIZE:
+            return "Dimension size is defined inconsistently among processes.";
+        case NC_EMULTIDEFINE_VAR_NUM:
+            return "Number of variables is defined inconsistently among processes.";
+        case NC_EMULTIDEFINE_VAR_NAME:
+            return "Variable names are defined inconsistently among processes.";
+        case NC_EMULTIDEFINE_VAR_NDIMS:
+            return "Dimensionality of this variable is defined inconsistently among processes.";
+        case NC_EMULTIDEFINE_VAR_DIMIDS:
+            return "Dimension IDs used to define this variable is inconsistent among processes.";
+        case NC_EMULTIDEFINE_VAR_TYPE:
+            return "Data type of this variable is defined inconsistently among processes.";
+        case NC_EMULTIDEFINE_VAR_LEN:
+            return "Number of elements of this variable is defined inconsistently among processes.";
+        case NC_EMULTIDEFINE_VAR_BEGIN:
+            return "Starting file offset of this variable is inconsistent among processes.";
+        case NC_EMULTIDEFINE_NUMRECS:
+            return "Number of records is inconsistent among processes.";
+        case NC_EMULTIDEFINE_ATTR_NUM:
+            return "Number of attributes is inconsistent among processes.";
+        case NC_EMULTIDEFINE_ATTR_SIZE:
+            return "Memory space used by attribute (internal use) is inconsistent among processes.";
+        case NC_EMULTIDEFINE_ATTR_NAME:
+            return "Attribute name is inconsistent among processes.";
+        case NC_EMULTIDEFINE_ATTR_TYPE:
+            return "Attribute type is inconsistent among processes.";
+        case NC_EMULTIDEFINE_ATTR_LEN:
+            return "Attribute length is inconsistent among processes.";
+        case NC_EMULTIDEFINE_ATTR_VAL:
+            return "Attribute value is inconsistent among processes.";
+        case NC_EMULTIDEFINE_FNC_ARGS:
+            return "inconsistent function arguments used in collective API.";
+        case NC_EMULTIDEFINE_FILL_MODE:
+            return "Dataset's file mode is inconsistent among processes.";
+        case NC_EMULTIDEFINE_VAR_FILL_MODE:
+            return "Variable's fill mode is inconsistent among processes.";
+        case NC_EMULTIDEFINE_VAR_FILL_VALUE:
+            return "Variable's fill value is inconsistent among processes.";
+
+        default:
+            /* check netCDF-3 and netCDF-4 errors */
+            return nc_strerror(err);
+    }
+}
+
+/*----< ncmpii_handle_error() ------------------------------------------------*/
+/* translate MPI error codes to PnetCDF/netCDF error codes */
+int ncmpii_handle_error(int   mpi_errorcode, /* returned value from MPI call */
+                        char *err_msg)       /* extra error message */
+{
+    int rank, errorclass, errorStringLen;
+    char errorString[MPI_MAX_ERROR_STRING];
+
+    /* check for specific error codes understood by PnetCDF */
+
+    /* When NC_NOCLOBBER is used in ioflags(cmode) for open to create,
+     * netCDF requires NC_EEXIST returned if the file already exists.
+     * In MPI 2.1, if MPI_File_open uses MPI_MODE_EXCL and the file has
+     * already existed, the error class MPI_ERR_FILE_EXISTS should be returned.
+     * For opening an existing file but the file does not exist, MPI 2.1
+     * will return MPI_ERR_NO_SUCH_FILE
+     * Note for MPI 2.1 and prior, we return MPI_ERR_IO, as these error class
+     * have not been defined.
+     */
+    MPI_Error_class(mpi_errorcode, &errorclass);
+#ifdef HAVE_MPI_ERR_FILE_EXISTS
+    if (errorclass == MPI_ERR_FILE_EXISTS) return NC_EEXIST;
+#endif
+#ifdef HAVE_MPI_ERR_NO_SUCH_FILE
+    if (errorclass == MPI_ERR_NO_SUCH_FILE) return NC_ENOENT;
+#endif
+#ifdef HAVE_MPI_ERR_NOT_SAME
+    /* MPI-IO should return MPI_ERR_NOT_SAME when one or more arguments of a
+     * collective MPI call are different. However, MPI-IO may not report this
+     * error code correctly. For instance, some MPI-IO returns MPI_ERR_AMODE
+     * instead when amode is found inconsistent. MPI_ERR_NOT_SAME can also
+     * report inconsistent file name. */
+    if (errorclass == MPI_ERR_NOT_SAME) return NC_EMULTIDEFINE_FNC_ARGS;
+#endif
+#ifdef HAVE_MPI_ERR_AMODE
+    /* MPI-IO may or may not report MPI_ERR_AMODE if inconsistent amode is
+     * detected. MPI_ERR_AMODE can also indicate other conflict amode used
+     * on each process. But in PnetCDF, MPI_ERR_AMODE can only be caused by
+     * inconsistent file open/create mode. So, if MPI-IO returns this error
+     * we are sure it is because of the inconsistent mode */
+    if (errorclass == MPI_ERR_AMODE) return NC_EMULTIDEFINE_OMODE;
+#endif
+#ifdef HAVE_MPI_ERR_READ_ONLY
+    if (errorclass == MPI_ERR_READ_ONLY) return NC_EPERM;
+#endif
+#ifdef HAVE_MPI_ERR_ACCESS
+    if (errorclass == MPI_ERR_ACCESS) return NC_EACCESS;
+#endif
+#ifdef HAVE_MPI_ERR_BAD_FILE
+    if (errorclass == MPI_ERR_BAD_FILE) return NC_EBAD_FILE;
+#endif
+#ifdef HAVE_MPI_ERR_NO_SPACE
+    if (errorclass == MPI_ERR_NO_SPACE) return NC_ENO_SPACE;
+#endif
+#ifdef HAVE_MPI_ERR_QUOTA
+    if (errorclass == MPI_ERR_QUOTA) return NC_EQUOTA;
+#endif
+
+    /* other errors that currently have no corresponding PnetCDF error codes */
+
+    /* we report the world rank */
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Error_string(mpi_errorcode, errorString, &errorStringLen);
+    if (err_msg == NULL) err_msg = "";
+    printf("rank %d: MPI error (%s) : %s\n", rank, err_msg, errorString);
+
+    return NC_EFILE; /* other unknown file I/O error */
+}
+
+
+/*-----------------------------------------------------------------------------
+ *     Copy nc_strerror() from netCDF release to ensure the same error
+ *     message is returned.
+ *----------------------------------------------------------------------------*/
+
+/*! NetCDF Error Handling
+
+\addtogroup error NetCDF Error Handling
+
+NetCDF functions return a non-zero status codes on error.
+
+Each netCDF function returns an integer status value. If the returned
+status value indicates an error, you may handle it in any way desired,
+from printing an associated error message and exiting to ignoring the
+error indication and proceeding (not recommended!). For simplicity,
+the examples in this guide check the error status and call a separate
+function, handle_err(), to handle any errors. One possible definition
+of handle_err() can be found within the documentation of
+nc_strerror().
+
+The nc_strerror() function is available to convert a returned integer
+error status into an error message string.
+
+Occasionally, low-level I/O errors may occur in a layer below the
+netCDF library. For example, if a write operation causes you to exceed
+disk quotas or to attempt to write to a device that is no longer
+available, you may get an error from a layer below the netCDF library,
+but the resulting write error will still be reflected in the returned
+status value.
+
+*/
+
+/** \{ */
+
+/*! Given an error number, return an error message.
+
+This function returns a static reference to an error message string
+corresponding to an integer netCDF error status or to a system error
+number, presumably returned by a previous call to some other netCDF
+function. The error codes are defined in netcdf.h.
+
+\param ncerr1 error number
+
+\returns short string containing error message.
+
+Here is an example of a simple error handling function that uses
+nc_strerror() to print the error message corresponding to the netCDF
+error status returned from any netCDF function call and then exit:
+
+\code
+     #include <netcdf.h>
+        ...
+     void handle_error(int status) {
+     if (status != NC_NOERR) {
+        fprintf(stderr, "%s\n", nc_strerror(status));
+        exit(-1);
+        }
+     }
+\endcode
+*/
+
+static const char *
+nc_strerror(int ncerr1)
+{
+   /* System error? */
+   if(NC_ISSYSERR(ncerr1))
+   {
+      const char *cp = (const char *) strerror(ncerr1);
+      if(cp == NULL)
+	 return "Unknown Error";
+      return cp;
+   }
+
+   /* If we're here, this is a netcdf error code. */
+   switch(ncerr1)
+   {
+      case NC_NOERR:
+	 return "No error";
+      case NC_EBADID:
+	 return "NetCDF: Not a valid ID";
+      case NC_ENFILE:
+	 return "NetCDF: Too many files open";
+      case NC_EEXIST:
+	 return "NetCDF: File exists && NC_NOCLOBBER";
+      case NC_EINVAL:
+	 return "NetCDF: Invalid argument";
+      case NC_EPERM:
+	 return "NetCDF: Write to read only";
+      case NC_ENOTINDEFINE:
+	 return "NetCDF: Operation not allowed in data mode";
+      case NC_EINDEFINE:
+	 return "NetCDF: Operation not allowed in define mode";
+      case NC_EINVALCOORDS:
+	 return "NetCDF: Index exceeds dimension bound";
+      case NC_EMAXDIMS:
+	 return "NetCDF: NC_MAX_DIMS exceeded";
+      case NC_ENAMEINUSE:
+	 return "NetCDF: String match to name in use";
+      case NC_ENOTATT:
+	 return "NetCDF: Attribute not found";
+      case NC_EMAXATTS:
+	 return "NetCDF: NC_MAX_ATTRS exceeded";
+      case NC_EBADTYPE:
+	 return "NetCDF: Not a valid data type or _FillValue type mismatch";
+      case NC_EBADDIM:
+	 return "NetCDF: Invalid dimension ID or name";
+      case NC_EUNLIMPOS:
+	 return "NetCDF: NC_UNLIMITED in the wrong index";
+      case NC_EMAXVARS:
+	 return "NetCDF: NC_MAX_VARS exceeded";
+      case NC_ENOTVAR:
+	 return "NetCDF: Variable not found";
+      case NC_EGLOBAL:
+	 return "NetCDF: Action prohibited on NC_GLOBAL varid";
+      case NC_ENOTNC:
+	 return "NetCDF: Unknown file format";
+      case NC_ESTS:
+	 return "NetCDF: In Fortran, string too short";
+      case NC_EMAXNAME:
+	 return "NetCDF: NC_MAX_NAME exceeded";
+      case NC_EUNLIMIT:
+	 return "NetCDF: NC_UNLIMITED size already in use";
+      case NC_ENORECVARS:
+	 return "NetCDF: nc_rec op when there are no record vars";
+      case NC_ECHAR:
+	 return "NetCDF: Attempt to convert between text & numbers";
+      case NC_EEDGE:
+	 return "NetCDF: Start+count exceeds dimension bound";
+      case NC_ESTRIDE:
+	 return "NetCDF: Illegal stride";
+      case NC_EBADNAME:
+	 return "NetCDF: Name contains illegal characters";
+      case NC_ERANGE:
+	 return "NetCDF: Numeric conversion not representable";
+      case NC_ENOMEM:
+	 return "NetCDF: Memory allocation (malloc) failure";
+      case NC_EVARSIZE:
+	 return "NetCDF: One or more variable sizes violate format constraints";
+      case NC_EDIMSIZE:
+	 return "NetCDF: Invalid dimension size";
+      case NC_ETRUNC:
+	 return "NetCDF: File likely truncated or possibly corrupted";
+      case NC_EAXISTYPE:
+	 return "NetCDF: Illegal axis type";
+      case NC_EDAP:
+	 return "NetCDF: DAP failure";
+      case NC_ECURL:
+	 return "NetCDF: libcurl failure";
+      case NC_EIO:
+	 return "NetCDF: I/O failure";
+      case NC_ENODATA:
+	 return "NetCDF: Variable has no data in DAP request";
+      case NC_EDAPSVC:
+	 return "NetCDF: DAP server error";
+      case NC_EDAS:
+	 return "NetCDF: Malformed or inaccessible DAP DAS";
+      case NC_EDDS:
+	 return "NetCDF: Malformed or inaccessible DAP DDS";
+      case NC_EDATADDS:
+	 return "NetCDF: Malformed or inaccessible DAP DATADDS";
+      case NC_EDAPURL:
+	 return "NetCDF: Malformed URL";
+      case NC_EDAPCONSTRAINT:
+	 return "NetCDF: Malformed or unexpected Constraint";
+      case NC_ETRANSLATION:
+	 return "NetCDF: Untranslatable construct";
+      case NC_EACCESS:
+	 return "NetCDF: Access failure";
+      case NC_EAUTH:
+	 return "NetCDF: Authorization failure";
+      case NC_ENOTFOUND:
+	 return "NetCDF: file not found";
+      case NC_ECANTEXTEND:
+	return "NetCDF: Attempt to extend dataset during NC_INDEPENDENT I/O operation. Use nc_var_par_access to set mode NC_COLLECTIVE before extending variable.";
+      case NC_ECANTREMOVE:
+	 return "NetCDF: cannot delete file";
+      case NC_EHDFERR:
+	 return "NetCDF: HDF error";
+      case NC_ECANTREAD:
+	 return "NetCDF: Can't read file";
+      case NC_ECANTWRITE:
+	 return "NetCDF: Can't write file";
+      case NC_ECANTCREATE:
+	 return "NetCDF: Can't create file";
+      case NC_EFILEMETA:
+	 return "NetCDF: Can't add HDF5 file metadata";
+      case NC_EDIMMETA:
+	 return "NetCDF: Can't define dimensional metadata";
+      case NC_EATTMETA:
+	 return "NetCDF: Can't open HDF5 attribute";
+      case NC_EVARMETA:
+	 return "NetCDF: Problem with variable metadata.";
+      case NC_ENOCOMPOUND:
+	 return "NetCDF: Can't create HDF5 compound type";
+      case NC_EATTEXISTS:
+	 return "NetCDF: Attempt to create attribute that alread exists";
+      case NC_ENOTNC4:
+	 return "NetCDF: Attempting netcdf-4 operation on netcdf-3 file";
+      case NC_ESTRICTNC3:
+	 return "NetCDF: Attempting netcdf-4 operation on strict nc3 netcdf-4 file";
+      case NC_ENOTNC3:
+	 return "NetCDF: Attempting netcdf-3 operation on netcdf-4 file";
+      case NC_ENOPAR:
+	 return "NetCDF: Parallel operation on file opened for non-parallel access";
+      case NC_EPARINIT:
+	 return "NetCDF: Error initializing for parallel access";
+      case NC_EBADGRPID:
+	 return "NetCDF: Bad group ID";
+      case NC_EBADTYPID:
+	 return "NetCDF: Bad type ID";
+      case NC_ETYPDEFINED:
+	 return "NetCDF: Type has already been defined and may not be edited";
+      case NC_EBADFIELD:
+	 return "NetCDF: Bad field ID";
+      case NC_EBADCLASS:
+	 return "NetCDF: Bad class";
+      case NC_EMAPTYPE:
+	 return "NetCDF: Mapped access for atomic types only";
+      case NC_ELATEFILL:
+	 return "NetCDF: Attempt to define fill value when data already exists.";
+      case NC_ELATEDEF:
+	 return "NetCDF: Attempt to define var properties, like deflate, after enddef.";
+      case NC_EDIMSCALE:
+	 return "NetCDF: Probem with HDF5 dimscales.";
+      case NC_ENOGRP:
+	 return "NetCDF: No group found.";
+      case NC_ESTORAGE:
+	 return "NetCDF: Cannot specify both contiguous and chunking.";
+      case NC_EBADCHUNK:
+	 return "NetCDF: Bad chunk sizes.";
+      case NC_ENOTBUILT:
+	 return "NetCDF: Attempt to use feature that was not turned on "
+	    "when netCDF was built.";
+      case NC_EDISKLESS:
+	 return "NetCDF: Error in using diskless access";
+      default:
+         return nc_unknown_err_msg;
+   }
+}
+/** \} */
+
+char* ncmpii_err_code_name(int err)
+{
+    static char unknown_str[32];
+    switch (err) {
+        case (NC_NOERR):			return "NC_NOERR";
+        case (NC_EBADID):			return "NC_EBADID";
+        case (NC_ENFILE):			return "NC_ENFILE";
+        case (NC_EEXIST):			return "NC_EEXIST";
+        case (NC_EINVAL):			return "NC_EINVAL";
+        case (NC_EPERM):			return "NC_EPERM";
+        case (NC_ENOTINDEFINE):			return "NC_ENOTINDEFINE";
+        case (NC_EINDEFINE):			return "NC_EINDEFINE";
+        case (NC_EINVALCOORDS):			return "NC_EINVALCOORDS";
+        case (NC_EMAXDIMS):			return "NC_EMAXDIMS";
+        case (NC_ENAMEINUSE):			return "NC_ENAMEINUSE";
+        case (NC_ENOTATT):			return "NC_ENOTATT";
+        case (NC_EMAXATTS):			return "NC_EMAXATTS";
+        case (NC_EBADTYPE):			return "NC_EBADTYPE";
+        case (NC_EBADDIM):			return "NC_EBADDIM";
+        case (NC_EUNLIMPOS):			return "NC_EUNLIMPOS";
+        case (NC_EMAXVARS):			return "NC_EMAXVARS";
+        case (NC_ENOTVAR):			return "NC_ENOTVAR";
+        case (NC_EGLOBAL):			return "NC_EGLOBAL";
+        case (NC_ENOTNC):			return "NC_ENOTNC";
+        case (NC_ESTS):				return "NC_ESTS";
+        case (NC_EMAXNAME):			return "NC_EMAXNAME";
+        case (NC_EUNLIMIT):			return "NC_EUNLIMIT";
+        case (NC_ENORECVARS):			return "NC_ENORECVARS";
+        case (NC_ECHAR):			return "NC_ECHAR";
+        case (NC_EEDGE):			return "NC_EEDGE";
+        case (NC_ESTRIDE):			return "NC_ESTRIDE";
+        case (NC_EBADNAME):			return "NC_EBADNAME";
+        case (NC_ERANGE):			return "NC_ERANGE";
+        case (NC_ENOMEM):			return "NC_ENOMEM";
+        case (NC_EVARSIZE):			return "NC_EVARSIZE";
+        case (NC_EDIMSIZE):			return "NC_EDIMSIZE";
+        case (NC_ETRUNC):			return "NC_ETRUNC";
+        case (NC_EAXISTYPE):			return "NC_EAXISTYPE";
+        case (NC_EDAP):				return "NC_EDAP";
+        case (NC_ECURL):			return "NC_ECURL";
+        case (NC_EIO):				return "NC_EIO";
+        case (NC_ENODATA):			return "NC_ENODATA";
+        case (NC_EDAPSVC):			return "NC_EDAPSVC";
+        case (NC_EDAS):				return "NC_EDAS";
+        case (NC_EDDS):				return "NC_EDDS";
+        case (NC_EDATADDS):			return "NC_EDATADDS";
+        case (NC_EDAPURL):			return "NC_EDAPURL";
+        case (NC_EDAPCONSTRAINT):		return "NC_EDAPCONSTRAINT";
+        case (NC_ETRANSLATION):			return "NC_ETRANSLATION";
+        case (NC_EACCESS):			return "NC_EACCESS";
+        case (NC_EAUTH):			return "NC_EAUTH";
+        case (NC_ENOTFOUND):			return "NC_ENOTFOUND";
+        case (NC_ECANTREMOVE):			return "NC_ECANTREMOVE";
+        case (NC_EHDFERR):			return "NC_EHDFERR";
+        case (NC_ECANTREAD):			return "NC_ECANTREAD";
+        case (NC_ECANTWRITE):			return "NC_ECANTWRITE";
+        case (NC_ECANTCREATE):			return "NC_ECANTCREATE";
+        case (NC_EFILEMETA):			return "NC_EFILEMETA";
+        case (NC_EDIMMETA):			return "NC_EDIMMETA";
+        case (NC_EATTMETA):			return "NC_EATTMETA";
+        case (NC_EVARMETA):			return "NC_EVARMETA";
+        case (NC_ENOCOMPOUND):			return "NC_ENOCOMPOUND";
+        case (NC_EATTEXISTS):			return "NC_EATTEXISTS";
+        case (NC_ENOTNC4):			return "NC_ENOTNC4";
+        case (NC_ESTRICTNC3):			return "NC_ESTRICTNC3";
+        case (NC_ENOTNC3):			return "NC_ENOTNC3";
+        case (NC_ENOPAR):			return "NC_ENOPAR";
+        case (NC_EPARINIT):			return "NC_EPARINIT";
+        case (NC_EBADGRPID):			return "NC_EBADGRPID";
+        case (NC_EBADTYPID):			return "NC_EBADTYPID";
+        case (NC_ETYPDEFINED):			return "NC_ETYPDEFINED";
+        case (NC_EBADFIELD):			return "NC_EBADFIELD";
+        case (NC_EBADCLASS):			return "NC_EBADCLASS";
+        case (NC_EMAPTYPE):			return "NC_EMAPTYPE";
+        case (NC_ELATEFILL):			return "NC_ELATEFILL";
+        case (NC_ELATEDEF):			return "NC_ELATEDEF";
+        case (NC_EDIMSCALE):			return "NC_EDIMSCALE";
+        case (NC_ENOGRP):			return "NC_ENOGRP";
+        case (NC_ESTORAGE):			return "NC_ESTORAGE";
+        case (NC_EBADCHUNK):			return "NC_EBADCHUNK";
+        case (NC_ENOTBUILT):			return "NC_ENOTBUILT";
+        case (NC_EDISKLESS):			return "NC_EDISKLESS";
+        case (NC_ECANTEXTEND):			return "NC_ECANTEXTEND";
+        case (NC_EMPI):				return "NC_EMPI";
+        // case (NC_EURL):				return "NC_EURL";
+        // case (NC_ECONSTRAINT):			return "NC_ECONSTRAINT";
+        case (NC_ESMALL):			return "NC_ESMALL";
+        case (NC_ENOTINDEP):			return "NC_ENOTINDEP";
+        case (NC_EINDEP):			return "NC_EINDEP";
+        case (NC_EFILE):			return "NC_EFILE";
+        case (NC_EREAD):			return "NC_EREAD";
+        case (NC_EWRITE):			return "NC_EWRITE";
+        case (NC_EOFILE):			return "NC_EOFILE";
+        case (NC_EMULTITYPES):			return "NC_EMULTITYPES";
+        case (NC_EIOMISMATCH):			return "NC_EIOMISMATCH";
+        case (NC_ENEGATIVECNT):			return "NC_ENEGATIVECNT";
+        case (NC_EUNSPTETYPE):			return "NC_EUNSPTETYPE";
+        case (NC_EINVAL_REQUEST):		return "NC_EINVAL_REQUEST";
+        case (NC_EAINT_TOO_SMALL):		return "NC_EAINT_TOO_SMALL";
+        case (NC_ENOTSUPPORT):			return "NC_ENOTSUPPORT";
+        case (NC_ENULLBUF):			return "NC_ENULLBUF";
+        case (NC_EPREVATTACHBUF):		return "NC_EPREVATTACHBUF";
+        case (NC_ENULLABUF):			return "NC_ENULLABUF";
+        case (NC_EPENDINGBPUT):			return "NC_EPENDINGBPUT";
+        case (NC_EINSUFFBUF):			return "NC_EINSUFFBUF";
+        case (NC_ENOENT):			return "NC_ENOENT";
+        case (NC_EINTOVERFLOW):			return "NC_EINTOVERFLOW";
+        case (NC_ENOTENABLED):			return "NC_ENOTENABLED";
+        case (NC_EBAD_FILE):			return "NC_EBAD_FILE";
+        case (NC_ENO_SPACE):			return "NC_ENO_SPACE";
+        case (NC_EQUOTA):			return "NC_EQUOTA";
+        case (NC_ENULLSTART):			return "NC_ENULLSTART";
+        case (NC_ENULLCOUNT):			return "NC_ENULLCOUNT";
+        case (NC_EINVAL_CMODE):			return "NC_EINVAL_CMODE";
+        case (NC_ETYPESIZE):			return "NC_ETYPESIZE";
+        case (NC_ETYPE_MISMATCH):		return "NC_ETYPE_MISMATCH";
+        case (NC_ETYPESIZE_MISMATCH):		return "NC_ETYPESIZE_MISMATCH";
+        case (NC_ESTRICTCDF2):			return "NC_ESTRICTCDF2";
+        case (NC_ENOTRECVAR):			return "NC_ENOTRECVAR";
+        case (NC_ENOTFILL):			return "NC_ENOTFILL";
+        case (NC_EMULTIDEFINE):			return "NC_EMULTIDEFINE";
+        case (NC_EMULTIDEFINE_OMODE):		return "NC_EMULTIDEFINE_OMODE";
+        case (NC_EMULTIDEFINE_DIM_NUM):		return "NC_EMULTIDEFINE_DIM_NUM";
+        case (NC_EMULTIDEFINE_DIM_SIZE):	return "NC_EMULTIDEFINE_DIM_SIZE";
+        case (NC_EMULTIDEFINE_DIM_NAME):	return "NC_EMULTIDEFINE_DIM_NAME";
+        case (NC_EMULTIDEFINE_VAR_NUM):		return "NC_EMULTIDEFINE_VAR_NUM";
+        case (NC_EMULTIDEFINE_VAR_NAME):	return "NC_EMULTIDEFINE_VAR_NAME";
+        case (NC_EMULTIDEFINE_VAR_NDIMS):	return "NC_EMULTIDEFINE_VAR_NDIMS";
+        case (NC_EMULTIDEFINE_VAR_DIMIDS):	return "NC_EMULTIDEFINE_VAR_DIMIDS";
+        case (NC_EMULTIDEFINE_VAR_TYPE):	return "NC_EMULTIDEFINE_VAR_TYPE";
+        case (NC_EMULTIDEFINE_VAR_LEN):		return "NC_EMULTIDEFINE_VAR_LEN";
+        case (NC_EMULTIDEFINE_NUMRECS):		return "NC_EMULTIDEFINE_NUMRECS";
+        case (NC_EMULTIDEFINE_VAR_BEGIN):	return "NC_EMULTIDEFINE_VAR_BEGIN";
+        case (NC_EMULTIDEFINE_ATTR_NUM):	return "NC_EMULTIDEFINE_ATTR_NUM";
+        case (NC_EMULTIDEFINE_ATTR_SIZE):	return "NC_EMULTIDEFINE_ATTR_SIZE";
+        case (NC_EMULTIDEFINE_ATTR_NAME):	return "NC_EMULTIDEFINE_ATTR_NAME";
+        case (NC_EMULTIDEFINE_ATTR_TYPE):	return "NC_EMULTIDEFINE_ATTR_TYPE";
+        case (NC_EMULTIDEFINE_ATTR_LEN):	return "NC_EMULTIDEFINE_ATTR_LEN";
+        case (NC_EMULTIDEFINE_ATTR_VAL):	return "NC_EMULTIDEFINE_ATTR_VAL";
+        case (NC_EMULTIDEFINE_FNC_ARGS):	return "NC_EMULTIDEFINE_FNC_ARGS";
+        case (NC_EMULTIDEFINE_FILL_MODE):	return "NC_EMULTIDEFINE_FILL_MODE";
+        case (NC_EMULTIDEFINE_VAR_FILL_MODE):	return "NC_EMULTIDEFINE_VAR_FILL_MODE";
+        case (NC_EMULTIDEFINE_VAR_FILL_VALUE):	return "NC_EMULTIDEFINE_VAR_FILL_VALUE";
+        default:
+              sprintf(unknown_str,"Unknown code %d",err);
+    }
+    return unknown_str;
+}
+
diff --git a/src/lib/fbits.h b/src/lib/fbits.h
new file mode 100644
index 0000000..c52d559
--- /dev/null
+++ b/src/lib/fbits.h
@@ -0,0 +1,26 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: fbits.h 1468 2013-10-26 16:53:18Z wkliao $ */
+
+#ifndef _FBITS_H_
+#define _FBITS_H_
+
+/*
+ * Macros for dealing with flag bits.
+ */
+#define fSet(t, f)       ((t) |= (f))
+#define fClr(t, f)       ((t) &= ~(f))
+#define fIsSet(t, f)     ((t) & (f))
+#define fMask(t, f)     ((t) & ~(f))
+
+/*
+ * Propositions
+ */
+/* a implies b */
+#define pIf(a,b) (!(a) || (b))
+/* a if and only if b, use == when it makes sense */
+#define pIff(a,b) (((a) && (b)) || (!(a) && !(b)))
+
+#endif /*!FBITS_H_*/
diff --git a/src/lib/filetype.c b/src/lib/filetype.c
new file mode 100644
index 0000000..2e94797
--- /dev/null
+++ b/src/lib/filetype.c
@@ -0,0 +1,967 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: filetype.c 2196 2015-11-27 22:31:05Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "macro.h"
+
+
+#if SIZEOF_MPI_AINT != SIZEOF_MPI_OFFSET
+/*----< check_recsize_too_big() >--------------------------------------------*/
+inline static int
+check_recsize_too_big(NC *ncp)
+{
+    int ret = NC_NOERR;
+    /* assertion: because recsize will be used to set up the file
+     * view, we must ensure there is no overflow when specifying
+     * how big a stride there is between items (think interleaved
+     * records).
+     *
+     * note: 'recsize' is the sum of the record size of all record
+     * variables in this dataset */
+    if (ncp->recsize != (MPI_Aint)ncp->recsize) {
+        fprintf(stderr, "Type overflow: unable to read/write multiple records in this dataset\non this platform. Please either access records of this record variable\none-at-a-time or run on a 64 bit platform\n");
+        DEBUG_ASSIGN_ERROR(ret, NC_ESMALL)
+    }
+    /* the assert here might be harsh, but without it, users will get corrupt
+     * data. Now, we just skip this request to avoid this assertion. */
+    /* assert (ncp->recsize == (MPI_Aint)ncp->recsize); */
+    return ret;
+}
+#endif
+
+/*----< NC_start_count_stride_ck() >-----------------------------------------*/
+/*
+ * Check whether start, count, stride values are valid for the variable.
+ * Note that even if the request size is zero, this check is enforced in both
+ * netCDF and PnetCDF. Otherwise, many test cases under test directory can fail.
+ * Arguments count and stride can be NULL.
+ */
+int
+NC_start_count_stride_ck(const NC         *ncp,
+                         const NC_var     *varp,
+                         const MPI_Offset *start,
+                         const MPI_Offset *count,
+                         const MPI_Offset *stride,
+                         const int         rw_flag) /* for read or write */
+{
+    int i=0;
+
+    if (varp->ndims == 0) return NC_NOERR; /* 'scalar' variable */
+
+    /* negative start[] is illegal */
+    if (start[0] < 0) DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
+
+    if (IS_RECVAR(varp)) {
+        if (!fIsSet(ncp->flags, NC_64BIT_DATA) && /* not CDF-5 */
+            start[0] > X_UINT_MAX) /* sanity check */
+            DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
+
+        if (count != NULL && count[0] < 0) /* no negative count[] */
+            DEBUG_RETURN_ERROR(NC_ENEGATIVECNT)
+
+        /* for record variable, [0] is the NC_UNLIMITED dimension */
+        if (rw_flag == READ_REQ) { /* read cannot go beyond current numrecs */
+            if (start[0] >= ncp->numrecs)
+                DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
+
+            if (count != NULL) {
+                if (stride == NULL) { /* for vara APIs */
+                    if (start[0] + count[0] > ncp->numrecs)
+                        DEBUG_RETURN_ERROR(NC_EEDGE)
+                }
+                else { /* for vars APIs */
+                    if (count[0] > 0 &&
+                        start[0] + (count[0]-1) * stride[0] >= ncp->numrecs)
+                        DEBUG_RETURN_ERROR(NC_EEDGE)
+                }
+            }
+            /* else is for var1 APIs */
+        }
+
+        if (stride != NULL && stride[0] == 0) DEBUG_RETURN_ERROR(NC_ESTRIDE)
+
+        /* In collective data mode where numrecs is always kept consistent
+         * across memory, then there is no need to update numrecs.
+         * (If NC_SHARE is set, then numrecs is even sync-ed with file.)
+         *
+         * In independent data mode, numrecs in memory across processes
+         * and file can be inconsistent. Even re-reading numrecs from file
+         * cannot get the latest value, because in independent mode,
+         * numrecs in file is not updated (due to race condition).
+         * For example, a subset of processes write a new record and at
+         * the same time another set writes 2 new records. Even if NC_SHARE
+         * is set, new values of numrecs cannot be written to the file,
+         * because it can cause a race condition (atomic read-modify IO is
+         * required to solve this problem and MPI-IO cannot do it). Simply
+         * said, numrecs is not automatically kept consistent in
+         * independent mode. Users must call ncmpi_sync_numrecs()
+         * collectively to sync the value. So, here what PnetCDF can do
+         * best is just to check numrecs against the local value.
+         */
+
+        /* skip checking the record dimension */
+        i = 1;
+    }
+
+    for (; i<varp->ndims; i++) {
+        if (start[i] < 0 || start[i] >= varp->shape[i])
+            DEBUG_RETURN_ERROR(NC_EINVALCOORDS)
+
+        if (varp->shape[i] < 0) DEBUG_RETURN_ERROR(NC_EEDGE)
+
+        if (count != NULL) {
+            if (count[i] < 0) /* no negative count[] */
+                DEBUG_RETURN_ERROR(NC_ENEGATIVECNT)
+
+            if (stride == NULL) { /* for vara APIs */
+                if (count[i] > varp->shape[i] ||
+                    start[i] + count[i] > varp->shape[i])
+                    DEBUG_RETURN_ERROR(NC_EEDGE)
+            }
+            else { /* for vars APIs */
+                if (count[i] > 0 &&
+                    start[i] + (count[i]-1) * stride[i] >= varp->shape[i])
+                    DEBUG_RETURN_ERROR(NC_EEDGE)
+                if (stride[i] == 0) DEBUG_RETURN_ERROR(NC_ESTRIDE)
+            }
+        }
+        /* else is for var1 APIs */
+    }
+    return NC_NOERR;
+}
+
+/*----< ncmpii_get_offset() >------------------------------------------------*/
+/* returns the file offset of the last byte accessed of this request */
+int
+ncmpii_get_offset(NC               *ncp,
+                  NC_var           *varp,
+                  const MPI_Offset  starts[],   /* [varp->ndims] */
+                  const MPI_Offset  counts[],   /* [varp->ndims] */
+                  const MPI_Offset  strides[],  /* [varp->ndims] */
+                  const int         rw_flag,
+                  MPI_Offset       *offset_ptr) /* return file offset */
+{
+    MPI_Offset offset, *end_off=NULL;
+    int status, i, ndims;
+
+    offset = varp->begin; /* beginning file offset of this variable */
+    ndims  = varp->ndims; /* number of dimensions of this variable */
+
+    if (counts != NULL)
+        end_off = (MPI_Offset*) NCI_Malloc((size_t)ndims * SIZEOF_MPI_OFFSET);
+
+    if (counts != NULL && strides != NULL) {
+        for (i=0; i<ndims; i++)
+            end_off[i] = starts[i] + (counts[i] - 1) * strides[i];
+    }
+    else if (counts != NULL) { /* strides == NULL */
+        for (i=0; i<ndims; i++)
+            end_off[i] = starts[i] + counts[i] - 1;
+    }
+    else { /* when counts == NULL strides is of no use */
+        end_off = (MPI_Offset*) starts;
+    }
+
+    /* check whether end_off is valid */
+    status = NC_start_count_stride_ck(ncp, varp, end_off, NULL, NULL, rw_flag);
+    if (status != NC_NOERR) {
+#ifdef CDEBUG
+        printf("%s(): NC_start_count_stride_ck() fails\n",__func__);
+#endif
+        return status;
+    }
+
+    if (ndims > 0) {
+        if (IS_RECVAR(varp))
+            /* no need to check recsize here: if MPI_Offset is only 32 bits we
+               will have had problems long before here */
+            offset += end_off[0] * ncp->recsize;
+        else
+            offset += end_off[ndims-1] * varp->xsz;
+
+        if (ndims > 1) {
+            if (IS_RECVAR(varp))
+                offset += end_off[ndims - 1] * varp->xsz;
+            else
+                offset += end_off[0] * varp->dsizes[1] * varp->xsz;
+
+            for (i=1; i<ndims-1; i++)
+                offset += end_off[i] * varp->dsizes[i+1] * varp->xsz;
+        }
+    }
+    if (counts != NULL && end_off != NULL)
+        NCI_Free(end_off);
+
+    *offset_ptr = offset;
+    return NC_NOERR;
+}
+
+/*----< ncmpii_is_request_contiguous() >-------------------------------------*/
+int
+ncmpii_is_request_contiguous(NC               *ncp,
+                             NC_var           *varp,
+                             const MPI_Offset  starts[],
+                             const MPI_Offset  counts[])
+{
+    /* determine whether the get/put request to this variable using
+       starts[] and counts[] is contiguous in file */
+    int i, j, most_sig_dim, ndims=varp->ndims;
+
+    /* this variable is a scalar */
+    if (ndims == 0) return 1;
+
+    for (i=0; i<ndims; i++)
+         if (counts[i] == 0) /* zero length request */
+             return 1;
+
+    most_sig_dim = 0; /* record dimension */
+
+    if (IS_RECVAR(varp)) {
+        /* if there are more than one record variable, then the record
+           dimensions, counts[0] must == 1. For now, we assume there
+           are more than one record variable.
+           TODO: we may need an API to inquire how many record variables
+           are defined */
+        if (ncp->vars.num_rec_vars > 1) {
+            /* or if (ncp->recsize > varp->len) more than one record variable */
+            if (counts[0] > 1) return 0;
+
+            /* we need to check from dimension ndims-1 up to dimension 1 */
+            most_sig_dim = 1;
+        }
+        /* if there is only one record variable, then we need to check from
+         * dimension ndims-1 up to dimension 0 */
+    }
+
+    for (i=ndims-1; i>most_sig_dim; i--) {
+        /* find the first counts[i] that is not the entire dimension */
+        if (counts[i] < varp->shape[i]) {
+            /* check dim from i-1, i-2, ..., most_sig_dim and
+               their counts[] should all be 1 */
+            for (j=i-1; j>=most_sig_dim; j--) {
+                if (counts[j] > 1)
+                    return 0;
+            }
+            break;
+        }
+        else { /* counts[i] == varp->shape[i] */
+            /* when accessing the entire dimension, starts[i] must be 0 */
+            if (starts[i] != 0) return 0; /* actually this should be error */
+        }
+    }
+    return 1;
+}
+
+#ifndef HAVE_MPI_TYPE_CREATE_SUBARRAY
+/*----< ncmpii_type_create_subarray() >--------------------------------------*/
+/* this is to be used when MPI_Type_create_subarray() is not available,
+ * typically for MPI-1 implementation only */
+static int
+ncmpii_type_create_subarray(int           ndims,
+                            int          *array_of_sizes,    /* [ndims] */
+                            int          *array_of_subsizes, /* [ndims] */
+                            int          *array_of_starts,   /* [ndims] */
+                            int           order,
+                            MPI_Datatype  oldtype,
+                            MPI_Datatype *newtype)
+{
+    int i, err, blklens[3] = {1, 1, 1};
+    MPI_Datatype type1, type2;
+    MPI_Aint extent, size, array_size, stride, disps[3];
+
+    if (ndims == 0) DEBUG_RETURN_ERROR(NC_EDIMMETA)
+
+#ifdef HAVE_MPI_TYPE_GET_EXTENT
+    MPI_Aint lb;
+    MPI_Type_get_extent(oldtype, &lb, &extent);
+#else
+    MPI_Type_extent(oldtype, &extent);
+#endif
+    array_size = extent;
+    for (i=0; i<ndims; i++) array_size *= array_of_sizes[i];
+
+    if (ndims == 1) {
+        /* blklens argument in MPI_Type_create_hindexed() is of type int */
+        blklens[1] = array_of_subsizes[0];
+        disps[1] = extent * array_of_starts[0];
+
+#if defined (HAVE_MPI_TYPE_CREATE_HINDEXED) && defined(HAVE_MPI_TYPE_CREATE_RESIZED)
+        /* take advantage of disps argument is of type MPI_Aint */
+        err = MPI_Type_create_hindexed(1, &blklens[1], &disps[1], oldtype, &type1);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_create_hindexed");
+        MPI_Type_commit(&type1);
+
+        /* add holes in the beginning and tail of type1 */
+        err = MPI_Type_create_resized(type1, 0, array_size, newtype);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_create_resized");
+        MPI_Type_free(&type1);
+#else
+        /* add holes in the beginning and tail of oldtype */
+        MPI_Datatype types[3];
+        types[0] = MPI_LB; types[1] = oldtype; types[2] = MPI_UB;
+        disps[0] = 0;                          disps[2] = array_size;
+        err = MPI_Type_struct(3, blklens, disps, types, newtype);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_struct");
+#endif
+        return NC_NOERR;
+    }
+    /* now, ndims > 1 */
+
+    /* first create a datatype for the least 2 significant dimensions */
+
+    /* blklens argument in MPI_Type_create_hvector() is of type int */
+    blklens[0] = array_of_subsizes[ndims-1];
+    stride = array_of_sizes[ndims-1] * extent;
+#ifdef HAVE_MPI_TYPE_CREATE_HVECTOR
+    err = MPI_Type_create_hvector(array_of_subsizes[ndims-2], blklens[0],
+                                  stride, oldtype, &type1);
+    if (err != MPI_SUCCESS)
+        return ncmpii_handle_error(err, "MPI_Type_create_hvector");
+#else
+    err = MPI_Type_hvector(array_of_subsizes[ndims-2], blklens[0],
+                           stride, oldtype, &type1);
+    if (err != MPI_SUCCESS)
+        return ncmpii_handle_error(err, "MPI_Type_hvector");
+#endif
+    MPI_Type_commit(&type1);
+
+    /* now iterate through the rest dimensions */
+    for (i=ndims-3; i>=0; i--) {
+        stride *= array_of_sizes[i+1];
+#ifdef HAVE_MPI_TYPE_CREATE_HVECTOR
+        err = MPI_Type_create_hvector(array_of_subsizes[i], 1, stride, type1, &type2);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_create_hvector");
+#else
+        err = MPI_Type_hvector(array_of_subsizes[i], 1, stride, type1, &type2);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_hvector");
+#endif
+        MPI_Type_commit(&type2);
+        MPI_Type_free(&type1);
+        type1 = type2;
+    }
+
+    /* disps[1] is the first byte displacement of the subarray */
+    disps[1] = array_of_starts[ndims-1] * extent;
+    size = 1;
+    for (i=ndims-2; i>=0; i--) {
+        size *= array_of_sizes[i+1];
+        disps[1] += size * array_of_starts[i];
+    }
+
+    /* disps[2] is the size of the global array */
+    disps[2] = array_size;
+
+    /* disps[0] is the beginning of the global array */
+    disps[0] = 0;
+
+    /* make filetype the same as calling MPI_Type_create_subarray() */
+    blklens[0] = 1;
+#if defined (HAVE_MPI_TYPE_CREATE_HINDEXED) && defined(HAVE_MPI_TYPE_CREATE_RESIZED)
+    /* adjust LB and UB without using MPI_LB or MPI_UB */
+    err = MPI_Type_create_hindexed(1, blklens, &disps[1], type1, &type2);
+    if (err != MPI_SUCCESS)
+        return ncmpii_handle_error(err, "MPI_Type_create_hindexed");
+    MPI_Type_commit(&type2);
+    err = MPI_Type_create_resized(type2, disps[0], disps[2], newtype);
+    if (err != MPI_SUCCESS)
+        return ncmpii_handle_error(err, "MPI_Type_create_resized");
+    MPI_Type_free(&type2);
+#else
+    MPI_Datatype types[3];
+    types[0] = MPI_LB;
+    types[1] = type1;
+    types[2] = MPI_UB;
+    err = MPI_Type_struct(3, blklens, disps, types, newtype);
+    if (err != MPI_SUCCESS)
+        return ncmpii_handle_error(err, "MPI_Type_struct");
+#endif
+    MPI_Type_free(&type1);
+
+    return NC_NOERR;
+}
+#endif
+
+/*----< ncmpii_type_create_subarray64() >------------------------------------*/
+/* This subroutine is to achieve the same result as MPI_Type_create_subarray()
+ * but it takes arguments in type of MPI_Offset, instead of int. It also
+ * checked for any possible 4-byte integer overflow.
+ */
+static int
+ncmpii_type_create_subarray64(int           ndims,
+                              MPI_Offset   *array_of_sizes,    /* [ndims] */
+                              MPI_Offset   *array_of_subsizes, /* [ndims] */
+                              MPI_Offset   *array_of_starts,   /* [ndims] */
+                              int           order,
+                              MPI_Datatype  oldtype,
+                              MPI_Datatype *newtype)
+{
+    int i, err, tag, blklens[3] = {1, 1, 1};
+    MPI_Datatype type1, type2;
+    MPI_Aint extent, size, array_size, stride, disps[3];
+#ifdef HAVE_MPI_TYPE_GET_EXTENT
+    MPI_Aint lb;
+#endif
+
+    if (ndims == 0) DEBUG_RETURN_ERROR(NC_EDIMMETA)
+
+    /* check if any of the dimensions is larger than 2^31-1 */
+    tag = 0;
+    for (i=0; i<ndims; i++) {
+        if (array_of_sizes[i] > 2147483647) {
+            tag = 1;
+            break;
+        }
+    }
+
+    if (tag == 0) {
+        /* none of dimensions > 2^31-1, we can safely use
+         * MPI_Type_create_subarray */
+        int *sizes    = (int*) NCI_Malloc((size_t)ndims * 3 * SIZEOF_INT);
+        int *subsizes = sizes    + ndims;
+        int *starts   = subsizes + ndims;
+        for (i=0; i<ndims; i++) {
+            sizes[i]    = (int)array_of_sizes[i];
+            subsizes[i] = (int)array_of_subsizes[i];
+            starts[i]   = (int)array_of_starts[i];
+            if (array_of_sizes[i]    != sizes[i] ||
+                array_of_subsizes[i] != subsizes[i] ||
+                array_of_starts[i]   != starts[i])
+                DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        }
+#ifdef HAVE_MPI_TYPE_CREATE_SUBARRAY
+        err = MPI_Type_create_subarray(ndims, sizes, subsizes, starts,
+                                       order, oldtype, newtype);
+        NCI_Free(sizes);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_create_subarray");
+#else
+        err = ncmpii_type_create_subarray(ndims, sizes, subsizes, starts,
+                                          order, oldtype, newtype);
+        NCI_Free(sizes);
+#endif
+        return err;
+    }
+
+    /* at least one dimension is of size > 2^31-1 and we cannot use
+     * MPI_Type_create_subarray() to create the newtype,
+     * as its arguments array_of_sizes[] and array_of_starts[] are of
+     * type int. One solution is to use a combination of
+     * MPI_Type_create_hvector(), MPI_Type_create_hindexed(),
+     * MPI_Type_create_resized(), and MPI_Type_struct(), as one
+     * of their arguments, stride and indices[], are of type MPI_Aint
+     * (a possible 8-byte integer) that can be used to store the value
+     * of the dimension whose size is > 2^31-1. However, on a machine
+     * where MPI_Aint is 4-byte integer, those MPI_Aint arguments will
+     * cause overflow.
+     */
+#if SIZEOF_MPI_AINT != SIZEOF_MPI_OFFSET
+    DEBUG_RETURN_ERROR(NC_EAINT_TOO_SMALL)
+#endif
+
+#ifdef HAVE_MPI_TYPE_GET_EXTENT
+    MPI_Type_get_extent(oldtype, &lb, &extent);
+#else
+    MPI_Type_extent(oldtype, &extent);
+#endif
+    array_size = extent;
+    for (i=0; i<ndims; i++) array_size *= array_of_sizes[i];
+
+    if (ndims == 1) {
+        /* blklens argument in MPI_Type_create_hindexed() is of type int */
+        blklens[1] = (int)array_of_subsizes[0];
+        if (array_of_subsizes[0] != blklens[1]) /* check int overflow */
+            DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        disps[1] = extent * array_of_starts[0];
+
+#if defined (HAVE_MPI_TYPE_CREATE_HINDEXED) && defined(HAVE_MPI_TYPE_CREATE_RESIZED)
+        /* take advantage of disps argument is of type MPI_Aint */
+        err = MPI_Type_create_hindexed(1, &blklens[1], &disps[1], oldtype, &type1);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_create_hindexed");
+        MPI_Type_commit(&type1);
+
+        /* add holes in the beginning and tail of type1 */
+        err = MPI_Type_create_resized(type1, 0, array_size, newtype);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_create_resized");
+        MPI_Type_free(&type1);
+#else
+        /* add holes in the beginning and tail of oldtype */
+        MPI_Datatype types[3];
+        types[0] = MPI_LB; types[1] = oldtype; types[2] = MPI_UB;
+        disps[0] = 0;                          disps[2] = array_size;
+        err = MPI_Type_struct(3, blklens, disps, types, newtype);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_struct");
+#endif
+        return NC_NOERR;
+    }
+    /* now, ndims > 1 */
+
+    /* first create a datatype for the least 2 significant dimensions */
+
+    /* count and blocklength arguments in MPI_Type_create_hvector() are of
+     * type int. We need to check for integer overflow */
+    int count, blocklength;
+    count = (int)array_of_subsizes[ndims-2];
+    blocklength = (int)array_of_subsizes[ndims-1];
+    if (array_of_subsizes[ndims-2] != count ||
+        array_of_subsizes[ndims-1] != blocklength) /* check int overflow */
+        DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    stride = array_of_sizes[ndims-1] * extent;
+#ifdef HAVE_MPI_TYPE_CREATE_HVECTOR
+    err = MPI_Type_create_hvector(count, blocklength, stride, oldtype, &type1);
+    if (err != MPI_SUCCESS)
+        return ncmpii_handle_error(err, "MPI_Type_create_hvector");
+#else
+    err = MPI_Type_hvector(count, blocklength, stride, oldtype, &type1);
+    if (err != MPI_SUCCESS)
+        return ncmpii_handle_error(err, "MPI_Type_hvector");
+#endif
+    MPI_Type_commit(&type1);
+
+    /* now iterate through the rest dimensions */
+    for (i=ndims-3; i>=0; i--) {
+        count = (int)array_of_subsizes[i];
+        if (array_of_subsizes[i] != count) /* check int overflow */
+            DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        stride *= array_of_sizes[i+1];
+#ifdef HAVE_MPI_TYPE_CREATE_HVECTOR
+        err = MPI_Type_create_hvector(count, 1, stride, type1, &type2);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_create_hvector");
+#else
+        err = MPI_Type_hvector(count, 1, stride, type1, &type2);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_hvector");
+#endif
+        MPI_Type_commit(&type2);
+        MPI_Type_free(&type1);
+        type1 = type2;
+    }
+
+    /* disps[0] is the displacement to the beginning of the global array */
+    disps[0] = 0;
+
+    /* disps[1] is the first byte displacement of the subarray */
+    disps[1] = array_of_starts[ndims-1] * extent;
+    size = 1;
+    for (i=ndims-2; i>=0; i--) {
+        size *= array_of_sizes[i+1];
+        disps[1] += size * array_of_starts[i];
+    }
+
+    /* disps[2] is the size of the global array */
+    disps[2] = array_size;
+
+    /* make filetype the same as calling MPI_Type_create_subarray() */
+#if defined(HAVE_MPI_TYPE_CREATE_HINDEXED) && defined(HAVE_MPI_TYPE_CREATE_RESIZED)
+    /* adjust LB and UB without using MPI_LB or MPI_UB */
+    err = MPI_Type_create_hindexed(1, blklens, &disps[1], type1, &type2);
+    if (err != MPI_SUCCESS)
+        return ncmpii_handle_error(err, "MPI_Type_create_hindexed");
+    MPI_Type_commit(&type2);
+    err = MPI_Type_create_resized(type2, disps[0], disps[2], newtype);
+    if (err != MPI_SUCCESS)
+        return ncmpii_handle_error(err, "MPI_Type_create_resized");
+    MPI_Type_free(&type2);
+#else
+    MPI_Datatype types[3];
+    types[0] = MPI_LB;
+    types[1] = type1;
+    types[2] = MPI_UB;
+    err = MPI_Type_struct(3, blklens, disps, types, newtype);
+    if (err != MPI_SUCCESS)
+        return ncmpii_handle_error(err, "MPI_Type_struct");
+#endif
+    MPI_Type_free(&type1);
+
+    return NC_NOERR;
+}
+
+/*----< ncmpii_vara_create_filetype() >--------------------------------------*/
+static int
+ncmpii_vara_create_filetype(NC               *ncp,
+                            NC_var           *varp,
+                            const MPI_Offset *start,
+                            const MPI_Offset *count,
+                            int               rw_flag,
+                            int              *blocklen,
+                            MPI_Offset       *offset_ptr,
+                            MPI_Datatype     *filetype_ptr,
+                            int              *is_filetype_contig)
+{
+    int          dim, status, err;
+    MPI_Offset   nbytes, offset;
+    MPI_Datatype filetype;
+
+    /* check whether start, count are valid */
+    status = NC_start_count_stride_ck(ncp, varp, start, count, NULL, rw_flag);
+    if (status != NC_NOERR) return status;
+
+    /* calculate the request size */
+    nbytes = varp->xsz;
+    for (dim=0; dim<varp->ndims; dim++) nbytes *= count[dim];
+    if (nbytes != (int)nbytes) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    if (blocklen != NULL) *blocklen = (int)nbytes;
+
+    /* when nbytes == 0 or varp is a scalar, i.e. varp->ndims == 0, no need to
+     * create a filetype
+     */
+    if (varp->ndims == 0 || nbytes == 0) {
+        *offset_ptr   = varp->begin;
+        *filetype_ptr = MPI_BYTE;
+        if (is_filetype_contig != NULL) *is_filetype_contig = 1;
+        return NC_NOERR;
+    }
+
+    /* if the request is contiguous in file, no need to create a filetype */
+    if (ncmpii_is_request_contiguous(ncp, varp, start, count)) {
+        status = ncmpii_get_offset(ncp, varp, start, NULL, NULL, rw_flag,
+                                   &offset);
+        *offset_ptr   = offset;
+        *filetype_ptr = MPI_BYTE;
+        if (is_filetype_contig != NULL) *is_filetype_contig = 1;
+        return status;
+    }
+
+    /* hereinafter fileview is noncontiguous, i.e. filetype != MPI_BYTE.
+     * Since we will construct a filetype, blocklen is set to 1.
+     */
+    if (blocklen           != NULL) *blocklen           = 1;
+    if (is_filetype_contig != NULL) *is_filetype_contig = 0;
+    offset = varp->begin;
+
+    /* previously, request size has been checked and it must > 0 */
+    if (IS_RECVAR(varp)) {
+        int blocklength;
+        MPI_Datatype rectype=MPI_BYTE;
+
+#if SIZEOF_MPI_AINT != SIZEOF_MPI_OFFSET
+        /* check overflow only if MPI_Aint is smaller than MPI_Offset */
+        status = check_recsize_too_big(ncp);
+        if (status != NC_NOERR) return status;
+#endif
+        /* check overflow, because 1st argument of hvector is of type int */
+        if (count[0] != (int) count[0]) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+
+        offset += start[0] * ncp->recsize;
+
+        if (varp->ndims > 1) {
+            /* when ndims > 1, we need to construct a subarray type for a
+             * single record, i.e. for dimension 1 ... ndims-1 */
+            MPI_Offset *shape64, *subcount64, *substart64;
+
+            shape64 = (MPI_Offset*) NCI_Malloc((size_t)varp->ndims * 3 * SIZEOF_MPI_OFFSET);
+            subcount64 = shape64    + varp->ndims;
+            substart64 = subcount64 + varp->ndims;
+
+            shape64[0]    = count[0];
+            subcount64[0] = count[0];
+            substart64[0] = 0;
+
+            for (dim=1; dim<varp->ndims; dim++) {
+                shape64[dim]    = varp->shape[dim];
+                subcount64[dim] = count[dim];
+                substart64[dim] = start[dim];
+            }
+            shape64[varp->ndims-1]    *= varp->xsz;
+            subcount64[varp->ndims-1] *= varp->xsz;
+            substart64[varp->ndims-1] *= varp->xsz;
+
+            status = ncmpii_type_create_subarray64(varp->ndims-1, shape64+1,
+                                 subcount64+1, substart64+1, MPI_ORDER_C,
+                                 MPI_BYTE, &rectype);
+            NCI_Free(shape64);
+            if (status != NC_NOERR) return status;
+
+            MPI_Type_commit(&rectype);
+            blocklength = 1;
+        }
+        else { /* no subarray datatype is needed */
+            blocklength = varp->xsz;
+        }
+
+#ifdef HAVE_MPI_TYPE_CREATE_HVECTOR
+        err = MPI_Type_create_hvector((int)count[0], blocklength, ncp->recsize,
+                                      rectype, &filetype);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_create_hvector");
+#else
+        err = MPI_Type_hvector((int)count[0], blocklength, ncp->recsize,
+                               rectype, &filetype);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_hvector");
+#endif
+        if (rectype != MPI_BYTE) MPI_Type_free(&rectype);
+    }
+    else { /* for non-record variable, just create a subarray datatype */
+        MPI_Offset *shape64, *subcount64, *substart64;
+        shape64 = (MPI_Offset*) NCI_Malloc((size_t)varp->ndims * 3 * SIZEOF_MPI_OFFSET);
+        subcount64 = shape64    + varp->ndims;
+        substart64 = subcount64 + varp->ndims;
+
+        for (dim=0; dim<varp->ndims; dim++) {
+            shape64[dim]    = varp->shape[dim];
+            subcount64[dim] = count[dim];
+            substart64[dim] = start[dim];
+        }
+        shape64[varp->ndims-1]    *= varp->xsz;
+        subcount64[varp->ndims-1] *= varp->xsz;
+        substart64[varp->ndims-1] *= varp->xsz;
+
+        status = ncmpii_type_create_subarray64(varp->ndims, shape64, subcount64,
+                                               substart64, MPI_ORDER_C,
+                                               MPI_BYTE, &filetype);
+        NCI_Free(shape64);
+        if (status != NC_NOERR) return status;
+    }
+    MPI_Type_commit(&filetype);
+
+    *offset_ptr   = offset;
+    *filetype_ptr = filetype;
+
+    return NC_NOERR;
+}
+
+/*----< ncmpii_vars_create_filetype() >--------------------------------------*/
+int
+ncmpii_vars_create_filetype(NC               *ncp,
+                            NC_var           *varp,
+                            const MPI_Offset  start[],
+                            const MPI_Offset  count[],
+                            const MPI_Offset  stride[],
+                            int               rw_flag,
+                            int              *blocklen,
+                            MPI_Offset       *offset_ptr,
+                            MPI_Datatype     *filetype_ptr,
+                            int              *is_filetype_contig)
+{
+    int          dim, status, err;
+    MPI_Offset   offset, stride_off, nelems;
+    MPI_Datatype filetype=MPI_BYTE;
+
+    if (stride == NULL)
+        return ncmpii_vara_create_filetype(ncp, varp, start, count, rw_flag,
+                                           blocklen, offset_ptr, filetype_ptr,
+                                           is_filetype_contig);
+
+    /* check if all stride[] == 1 */
+    for (dim=0; dim<varp->ndims && stride[dim]==1; dim++) ;
+    if (dim == varp->ndims) /* all stride[] == 1, same as stride == NULL */
+        return ncmpii_vara_create_filetype(ncp, varp, start, count, rw_flag,
+                                           blocklen, offset_ptr, filetype_ptr,
+                                           is_filetype_contig);
+
+    /* now stride[] indicates a non-contiguous fileview */
+
+    /* check whether start, count, stride are valid */
+    status = NC_start_count_stride_ck(ncp, varp, start, count, stride, rw_flag);
+    if (status != NC_NOERR) return status;
+
+    /* calculate request amount */
+    nelems = 1;
+    for (dim=0; dim<varp->ndims; dim++) nelems *= count[dim];
+
+    /* when nelems == 0 or varp is a scalar, i.e. varp->ndims == 0, no need to
+     * create a filetype
+     */
+    if (varp->ndims == 0 || nelems == 0) {
+        *offset_ptr   = varp->begin;
+        *filetype_ptr = MPI_BYTE;
+        if (blocklen           != NULL) *blocklen           = 0;
+        if (is_filetype_contig != NULL) *is_filetype_contig = 1;
+        return NC_NOERR;
+    }
+
+    /* hereinafter fileview is noncontiguous, i.e. filetype != MPI_BYTE.
+     * Since we will construct a filetype, blocklen is set to 1.
+     */
+    if (blocklen           != NULL) *blocklen           = 1;
+    if (is_filetype_contig != NULL) *is_filetype_contig = 0;
+    offset = varp->begin;
+
+    int ndims, *blockcounts, *blocklens;
+    MPI_Aint *blockstride;
+    MPI_Datatype tmptype;
+
+    ndims       = varp->ndims;
+    blockcounts = (int*) NCI_Malloc((size_t)ndims * 2 * SIZEOF_INT);
+    blocklens   = blockcounts + ndims;
+
+    blockstride = (MPI_Aint*) NCI_Malloc((size_t)ndims * SIZEOF_MPI_AINT);
+
+    tmptype = MPI_BYTE;
+
+    blockcounts[ndims-1] = (int)count[ndims-1];
+    /* check 4-byte integer overflow (blockcounts in MPI_Type_hvector
+       is of type int while count[] is of type MPI_Offset */
+    if (count[ndims-1] != blockcounts[ndims-1])
+        DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    /* blocklens[] is unlikely a big value */
+    blocklens[ndims-1] = varp->xsz;
+
+    if (ndims == 1 && IS_RECVAR(varp)) {
+#if SIZEOF_MPI_AINT != SIZEOF_MPI_OFFSET
+        status = check_recsize_too_big(ncp);
+        if (status != NC_NOERR) return status;
+#endif
+        stride_off = stride[ndims-1] * ncp->recsize;
+        blockstride[ndims-1] = stride_off;
+        offset += start[ndims-1] * ncp->recsize;
+    } else {
+        stride_off = stride[ndims-1] * varp->xsz;
+        blockstride[ndims-1] = stride_off;
+        offset += start[ndims-1] * varp->xsz;
+    }
+#if SIZEOF_MPI_AINT != SIZEOF_MPI_OFFSET
+    /* check 4-byte integer overflow */
+    if (stride_off != blockstride[ndims-1])
+        DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+#endif
+
+    for (dim=ndims-1; dim>=0; dim--) {
+#ifdef HAVE_MPI_TYPE_CREATE_HVECTOR
+        err = MPI_Type_create_hvector(blockcounts[dim], blocklens[dim],
+                                      blockstride[dim], tmptype, &filetype);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_create_hvector");
+#else
+        err = MPI_Type_hvector(blockcounts[dim], blocklens[dim],
+                               blockstride[dim], tmptype, &filetype);
+        if (err != MPI_SUCCESS)
+            return ncmpii_handle_error(err, "MPI_Type_hvector");
+#endif
+        MPI_Type_commit(&filetype);
+        if (tmptype != MPI_BYTE)
+            MPI_Type_free(&tmptype);
+        tmptype = filetype;
+
+        if (dim - 1 >= 0) {
+            blocklens[dim-1]  = 1;
+            blockcounts[dim-1] = (int)count[dim - 1];
+            /* check 4-byte integer overflow */
+            if (count[dim-1] != blockcounts[dim-1])
+                DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+
+            if (dim-1 == 0 && IS_RECVAR(varp)) {
+                stride_off = stride[dim-1] * ncp->recsize;
+                blockstride[dim-1] = stride_off;
+                offset += start[dim-1] * ncp->recsize;
+            } else {
+                stride_off = stride[dim-1] * varp->dsizes[dim] * varp->xsz;
+                blockstride[dim-1] = stride_off;
+                offset += start[dim-1] * varp->dsizes[dim] * varp->xsz;
+            }
+#if SIZEOF_MPI_AINT != SIZEOF_MPI_OFFSET
+            /* check 4-byte integer overflow */
+            if (stride_off != blockstride[dim-1])
+                DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+#endif
+        }
+    }
+    NCI_Free(blockstride);
+    NCI_Free(blockcounts);
+
+    *offset_ptr   = offset;
+    *filetype_ptr = filetype;
+
+    return NC_NOERR;
+}
+
+/*----< ncmpii_file_set_view() >---------------------------------------------*/
+/* This function handles the special case for root process for setting its
+ * file view: to keeps the whole file header visible to the root process.
+ * This function is collective if called in collective data mode
+ */
+int
+ncmpii_file_set_view(NC           *ncp,
+                     MPI_File      fh,
+                     MPI_Offset   *offset,
+                     MPI_Datatype  filetype)
+{
+    int rank, err, mpireturn, status=NC_NOERR;
+
+    if (filetype == MPI_BYTE) {
+        /* filetype is a contiguous space, make the whole file visible */
+        TRACE_IO(MPI_File_set_view)(fh, 0, MPI_BYTE, MPI_BYTE,
+                                    "native", MPI_INFO_NULL);
+        return NC_NOERR;
+    }
+
+    MPI_Comm_rank(ncp->nciop->comm, &rank);
+    if (rank == 0) {
+        /* prepend the whole file header to filetype */
+        int blocklens[2];
+        MPI_Aint disps[2];
+        MPI_Datatype root_filetype, ftypes[2];
+
+        /* first block is the header extent */
+        blocklens[0] = (int)ncp->begin_var;
+            disps[0] = 0;
+           ftypes[0] = MPI_BYTE;
+
+        /* check if header size > 2^31 */
+        if (ncp->begin_var != blocklens[0]) DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+
+        /* second block is filetype, the subarray request(s) to the variable */
+        blocklens[1] = 1;
+            disps[1] = *offset;
+           ftypes[1] = filetype;
+
+#if SIZEOF_MPI_AINT != SIZEOF_MPI_OFFSET
+        if (*offset != disps[1]) {
+            blocklens[1] = 0;
+            DEBUG_ASSIGN_ERROR(status, NC_EAINT_TOO_SMALL)
+        }
+#endif
+
+#ifdef HAVE_MPI_TYPE_CREATE_STRUCT
+        MPI_Type_create_struct(2, blocklens, disps, ftypes, &root_filetype);
+#else
+        MPI_Type_struct(2, blocklens, disps, ftypes, &root_filetype);
+#endif
+        MPI_Type_commit(&root_filetype);
+
+        TRACE_IO(MPI_File_set_view)(fh, 0, MPI_BYTE, root_filetype,
+                                        "native", MPI_INFO_NULL);
+        MPI_Type_free(&root_filetype);
+
+        /* now update the explicit offset to be used in MPI-IO call later */
+        *offset = ncp->begin_var;
+    }
+    else {
+        TRACE_IO(MPI_File_set_view)(fh, *offset, MPI_BYTE, filetype,
+                                    "native", MPI_INFO_NULL);
+        /* the explicit offset is already set in fileview */
+        *offset = 0;
+    }
+    if (mpireturn != MPI_SUCCESS) {
+        err = ncmpii_handle_error(mpireturn, "MPI_File_set_view");
+        if (status == NC_NOERR) status = err;
+    }
+
+    return status;
+}
diff --git a/src/lib/fill.c b/src/lib/fill.c
new file mode 100644
index 0000000..3da99cb
--- /dev/null
+++ b/src/lib/fill.c
@@ -0,0 +1,523 @@
+/*
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: fill.c 2198 2015-11-28 00:20:38Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "macro.h"
+
+#define CHECK_ERROR(status) {                                                \
+    if (ncp->safe_mode == 1) {                                               \
+        int g_status;                                                        \
+        TRACE_COMM(MPI_Allreduce)(&status, &g_status, 1, MPI_INT, MPI_MIN,   \
+                                  ncp->nciop->comm);                         \
+        if (g_status != NC_NOERR) return status;                             \
+    }                                                                        \
+    else if (status != NC_NOERR)                                             \
+        return status;                                                       \
+}
+
+/* The default fill values defined in pnetcdf.h.inc must be the same as the
+ * ones defined in netCDF-4 and match the hexadecimal values set below
+ *
+#define NC_FILL_BYTE    ((signed char)-127)
+#define NC_FILL_CHAR    ((char)0)
+#define NC_FILL_SHORT   ((short)-32767)
+#define NC_FILL_INT     (-2147483647L)
+#define NC_FILL_FLOAT   (9.9692099683868690e+36f)
+#define NC_FILL_DOUBLE  (9.9692099683868690e+36)
+#define NC_FILL_UBYTE   (255)
+#define NC_FILL_USHORT  (65535)
+#define NC_FILL_UINT    (4294967295U)
+#define NC_FILL_INT64   ((long long)-9223372036854775806LL)
+#define NC_FILL_UINT64  ((unsigned long long)18446744073709551614ULL)
+*/
+static unsigned char FILL_CHAR[1]   = {0x00};
+static unsigned char FILL_BYTE[1]   = {0x81};
+static unsigned char FILL_SHORT[2]  = {0x80, 0x01};
+static unsigned char FILL_INT[4]    = {0x80, 0x00, 0x00, 0x01};
+static unsigned char FILL_FLOAT[4]  = {0x7C, 0xF0, 0x00, 0x00};
+static unsigned char FILL_DOUBLE[8] = {0x47, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char FILL_UBYTE[1]  = {0xFF};
+static unsigned char FILL_USHORT[2] = {0xFF, 0xFF};
+static unsigned char FILL_UINT[4]   = {0xFF, 0xFF, 0xFF, 0xFF};
+static unsigned char FILL_INT64[8]  = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
+static unsigned char FILL_UINT64[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE};
+
+/*----< inq_default_fill_value() >-------------------------------------------*/
+/* copy the default fill value to the memory space pointed by fill_value */
+static int
+inq_default_fill_value(int type, void *fill_value)
+{
+    if (fill_value == NULL) return NC_NOERR;
+
+    switch(type) {
+        case NC_CHAR   :               *(char*)fill_value = NC_FILL_CHAR;   break;
+        case NC_BYTE   :        *(signed char*)fill_value = NC_FILL_BYTE;   break;
+        case NC_SHORT  :              *(short*)fill_value = NC_FILL_SHORT;  break;
+        case NC_INT    :                *(int*)fill_value = NC_FILL_INT;    break;
+        case NC_FLOAT  :              *(float*)fill_value = NC_FILL_FLOAT;  break;
+        case NC_DOUBLE :             *(double*)fill_value = NC_FILL_DOUBLE; break;
+        case NC_UBYTE  :      *(unsigned char*)fill_value = NC_FILL_UBYTE;  break;
+        case NC_USHORT :     *(unsigned short*)fill_value = NC_FILL_USHORT; break;
+        case NC_UINT   :       *(unsigned int*)fill_value = NC_FILL_UINT;   break;
+        case NC_INT64  :          *(long long*)fill_value = NC_FILL_INT64;  break;
+        case NC_UINT64 : *(unsigned long long*)fill_value = NC_FILL_UINT64; break;
+        default : DEBUG_RETURN_ERROR(NC_EBADTYPE)
+    }
+    return NC_NOERR;
+}
+
+/*----< ncmpii_fill_var_buf() >----------------------------------------------*/
+/* fill the buffer, buf, with either user-defined fill values or default
+ * values */
+static int
+ncmpii_fill_var_buf(const NC_var *varp,
+                    MPI_Offset    bnelems, /* number of elements in buf */
+                    void         *buf)
+{
+    int i, indx;
+
+    indx = ncmpii_NC_findattr(&varp->attrs, _FillValue);
+    if (indx >= 0) {
+        /* User defined fill value */
+        NC_attr *attrp = varp->attrs.value[indx];
+        if (attrp->type != varp->type || attrp->nelems != 1)
+            DEBUG_RETURN_ERROR(NC_EBADTYPE)
+
+        /* Use the user defined value */
+        char *bufp = buf;
+        for (i=0; i<bnelems; i++) {
+            memcpy(bufp, attrp->xvalue, (size_t)varp->xsz);
+            bufp += varp->xsz;
+        }
+    }
+    else { /* use the default */
+        void *xvalue;
+        switch(varp->type) {
+            case NC_CHAR   : xvalue = &FILL_CHAR[0];   break;
+            case NC_BYTE   : xvalue = &FILL_BYTE[0];   break;
+            case NC_SHORT  : xvalue = &FILL_SHORT[0];  break;
+            case NC_INT    : xvalue = &FILL_INT[0];    break;
+            case NC_FLOAT  : xvalue = &FILL_FLOAT[0];  break;
+            case NC_DOUBLE : xvalue = &FILL_DOUBLE[0]; break;
+            case NC_UBYTE  : xvalue = &FILL_UBYTE[0];  break;
+            case NC_USHORT : xvalue = &FILL_USHORT[0]; break;
+            case NC_UINT   : xvalue = &FILL_UINT[0];   break;
+            case NC_INT64  : xvalue = &FILL_INT64[0];  break;
+            case NC_UINT64 : xvalue = &FILL_UINT64[0]; break;
+            default : DEBUG_RETURN_ERROR(NC_EBADTYPE)
+        }
+
+        char *bufp = buf;
+        for (i=0; i<bnelems; i++) {
+            memcpy(bufp, xvalue, (size_t)varp->xsz);
+            bufp += varp->xsz;
+        }
+    }
+    return NC_NOERR;
+}
+
+/*----< ncmpii_fill_var() >--------------------------------------------------*/
+/* If the variable is fixed-size, then write the entire variable with fill
+ * values and recno is ignored. If it is a record variable, then write one
+ * record of that variable with fill values.
+ */
+static int
+ncmpii_fill_var_rec(NC         *ncp,
+                    NC_var     *varp,
+                    MPI_Offset  recno) /* record number */
+{
+    int err, mpireturn, rank, nprocs;
+    void *buf;
+    MPI_Offset var_len, start, count, offset;
+    MPI_File fh;
+    MPI_Status mpistatus;
+
+    MPI_Comm_rank(ncp->nciop->comm, &rank);
+    MPI_Comm_size(ncp->nciop->comm, &nprocs);
+
+    if (varp->ndims == 0) /* scalar variable */
+        var_len = 1;
+    else if (varp->ndims == 1 && IS_RECVAR(varp))
+        var_len = 1;
+    else if (IS_RECVAR(varp))
+        var_len = varp->dsizes[1];
+    else
+        var_len = varp->dsizes[0];
+
+    /* divide total number of elements of this variable among all processes */
+    count = var_len / nprocs;
+    start = count * rank;
+    if (rank < var_len % nprocs) {
+        start += rank;
+        count++;
+    }
+    else {
+        start += var_len % nprocs;
+    }
+
+    /* allocate buffer space */
+    buf = NCI_Malloc((size_t)(count * varp->xsz));
+
+    /* fill buffer with file values */
+    err = ncmpii_fill_var_buf(varp, count, buf);
+    if (err != NC_NOERR) return err;
+
+    offset = varp->begin;
+    if (IS_RECVAR(varp))
+        offset += ncp->recsize * recno;
+    offset += start * varp->xsz;
+
+    fh = ncp->nciop->collective_fh;
+
+    /* make the entire file visible */
+    TRACE_IO(MPI_File_set_view)(fh, 0, MPI_BYTE, MPI_BYTE, "native",
+                                MPI_INFO_NULL);
+
+    count *= varp->xsz;
+    if (count != (int)count) DEBUG_ASSIGN_ERROR(err, NC_EINTOVERFLOW)
+    TRACE_IO(MPI_File_write_at_all)(fh, offset, buf, (int)count,
+                                    MPI_BYTE, &mpistatus);
+    NCI_Free(buf);
+
+    if (err != NC_NOERR) return err;
+
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_File_write_at_all");
+
+    if (IS_RECVAR(varp)) { /* update header's number of records in memory */
+        err = ncmpii_sync_numrecs(ncp, recno+1);
+        if (err == NC_NOERR) return err;
+    }
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_fill_var() >---------------------------------------------------*/
+/* fill an entire record of a record variable
+ * this API is collective, must be called in data mode */
+int
+ncmpi_fill_var_rec(int        ncid,
+                   int        varid,
+                   MPI_Offset recno) /* record number, ignored if non-record var */
+{
+    int     indx, err;
+    NC     *ncp;
+    NC_var *varp;
+
+    /* check if ncid is valid */
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) return err;
+
+    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM) /* read-only */
+
+    /* This must be called in data mode */
+    if (NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_EINDEFINE)                                
+
+    /* must be called in collective data mode */
+    if (NC_indep(ncp)) DEBUG_RETURN_ERROR(NC_EINDEP)
+
+    err = ncmpii_NC_lookupvar(ncp, varid, &varp);
+    if (err != NC_NOERR) return err;
+
+    /* error if this is not a record variable */
+    if (!IS_RECVAR(varp)) DEBUG_RETURN_ERROR(NC_ENOTRECVAR)
+
+    /* check if _FillValue attribute is defined */
+    indx = ncmpii_NC_findattr(&varp->attrs, _FillValue);
+
+    /* error if the fill mode of this variable is not on */
+    if (varp->no_fill && indx == -1) DEBUG_RETURN_ERROR(NC_ENOTFILL)
+
+    return ncmpii_fill_var_rec(ncp, varp, recno);
+}
+
+/*----< ncmpi_set_fill() >---------------------------------------------------*/
+/* this API is collective, must be called in define mode, contrary to netCDF
+ * where nc_set_fill() can also be called in data mode. The reason of PnetCDF
+ * enforcing this requirement is because PnetCDF only fills fix-sized variables
+ * at ncmpi_enddef() and record variables in ncmpi_fill_var_rec().
+ */
+int
+ncmpi_set_fill(int  ncid,
+               int  fill_mode,
+               int *old_fill_mode)
+{
+    int i, status=NC_NOERR, mpireturn, oldmode;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM) /* read-only */
+
+    /* check if called in define mode */
+    if (!NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+
+    if (ncp->safe_mode) {
+        int root_fill_mode=fill_mode;
+        TRACE_COMM(MPI_Bcast)(&root_fill_mode, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return  ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+        if (fill_mode != root_fill_mode) {
+            /* dataset's fill mode is inconsistent with root's */
+            printf("Warning: fill mode set in %s() is inconsistent\n", __func__);
+            DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_FILL_MODE)
+        }
+    }
+
+    oldmode = fIsSet(ncp->flags, NC_NOFILL) ? NC_NOFILL : NC_FILL;
+
+    if (fill_mode == NC_NOFILL)
+        fSet(ncp->flags, NC_NOFILL);
+    else if (fill_mode == NC_FILL)
+        fClr(ncp->flags, NC_NOFILL);
+    else
+        DEBUG_RETURN_ERROR(NC_EINVAL) /* Invalid fill_mode */
+
+    if (old_fill_mode != NULL) *old_fill_mode = oldmode;
+
+    /* loop thru all variables defined so far to set/overwrite its fill mode */
+    for (i=0; i<ncp->vars.ndefined; i++)
+        ncp->vars.value[i]->no_fill = (fill_mode == NC_NOFILL) ? 1 : 0;
+
+    /* once the file's fill mode is set, any new variables defined after this
+     * call will check NC_dofill(ncp) and set their no_fill accordingly. See
+     * ncmpi_def_var() */
+
+    return status;
+}
+
+/*----< ncmpi_def_var_fill() >------------------------------------------------*/
+/* this API is collective, and must be called in define mode */
+int
+ncmpi_def_var_fill(int   ncid,
+                   int   varid,
+                   int   no_fill,    /* 1: no fill, 0: fill */
+                   void *fill_value) /* when NULL, use default fill value */
+{
+    int err, status=NC_NOERR, mpireturn, free_fill_value=0;
+    NC *ncp;
+    NC_var *varp;
+
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) return err;
+
+    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM) /* read-only */
+
+    /* must be called in define mode */
+    if (!NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+
+    /* find the pointer to this variable's object */
+    err = ncmpii_NC_lookupvar(ncp, varid, &varp);
+    if (err != NC_NOERR) return err;
+
+    if (ncp->safe_mode) {
+        int root_no_fill=no_fill;
+        TRACE_COMM(MPI_Bcast)(&root_no_fill, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return  ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+
+        if (no_fill != root_no_fill) {
+            /* variable's fill mode is inconsistent with root's */
+            printf("Warning: variable (%s) fill mode (%d) set in %s() is inconsistent\n",
+                   varp->name->cp, no_fill, __func__);
+            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_VAR_FILL_MODE)
+        }
+
+        /* check if fill_value is consistent among processes */
+        void *root_fill_value = NCI_Malloc((size_t)varp->xsz);
+        if (fill_value == NULL) {
+            /* user intends to use default fill value */
+            fill_value = NCI_Malloc((size_t)varp->xsz);
+            err = inq_default_fill_value(varp->type, fill_value);
+            if (err != NC_NOERR) return err;
+            free_fill_value=1;
+        }
+        memcpy(root_fill_value, fill_value, (size_t)varp->xsz);
+            
+        TRACE_COMM(MPI_Bcast)(root_fill_value, varp->xsz, MPI_BYTE, 0, ncp->nciop->comm);
+        if (memcmp(fill_value, root_fill_value, (size_t)varp->xsz)) {
+            /* variable's fill value is inconsistent with root's */
+            printf("Warning: variable (%s) fill value set in %s() is inconsistent\n",
+                   varp->name->cp, __func__);
+            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_VAR_FILL_VALUE)
+        }
+        if (free_fill_value) {
+            NCI_Free(fill_value);
+            fill_value = NULL;
+        }
+        NCI_Free(root_fill_value);
+    }
+
+    if (no_fill)
+        varp->no_fill = 1;
+    else
+        varp->no_fill = 0;
+
+    /* Are we setting a fill value? */
+    if (fill_value != NULL && !varp->no_fill) {
+
+        /* If there's a _FillValue attribute, delete it. */
+        err = ncmpi_del_att(ncid, varid, _FillValue);
+        if (err != NC_NOERR && err != NC_ENOTATT)
+            return err;
+
+        /* Create a _FillValue attribute. */
+        err = ncmpi_put_att(ncid, varid, _FillValue, varp->type, 1, fill_value);
+        if (err != NC_NOERR) return err;
+    }
+
+    return status;
+}
+
+/*----< ncmpi_inq_var_fill() >-----------------------------------------------*/
+/* this API can be called independently and in both data and define mode */
+int
+ncmpi_inq_var_fill(int   ncid,
+                   int   varid,
+                   int  *no_fill,    /* OUT: 1 not fill mode, 0 fill mode */
+                   void *fill_value) /* OUT: user-defined or default fill value */
+{
+    int err;
+    NC *ncp;
+    NC_var *varp;
+
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) return err;
+
+    /* find the pointer to this variable's object */
+    err = ncmpii_NC_lookupvar(ncp, varid, &varp);
+    if (err != NC_NOERR) return err;
+
+    *no_fill = varp->no_fill;
+
+    if (fill_value != NULL) {
+        err = ncmpi_get_att(ncid, varid, _FillValue, fill_value);
+        if (err != NC_NOERR && err != NC_ENOTATT)
+            return err;
+        if (err == NC_ENOTATT) {
+            err = inq_default_fill_value(varp->type, fill_value);
+            if (err != NC_NOERR) return err;
+        }
+    }
+
+    return NC_NOERR;
+}
+
+/*----< fillerup() >---------------------------------------------------------*/
+/* fill the newly created variables */
+static int
+fillerup(NC *ncp)
+{
+    int i, indx, err=NC_NOERR;
+
+    /* loop thru all variables */
+    for (i=0; i<ncp->vars.ndefined; i++) {
+        if (IS_RECVAR(ncp->vars.value[i]))
+            /* skip record variables */
+            continue;
+
+        /* check if _FillValue attribute is defined */
+        indx = ncmpii_NC_findattr(&ncp->vars.value[i]->attrs, _FillValue);
+
+        /* only if filling this variable is requested */
+        if (ncp->vars.value[i]->no_fill && indx == -1) continue;
+
+        /* collectively fill the entire variable */
+        err = ncmpii_fill_var_rec(ncp, ncp->vars.value[i], 0);
+        if (err != NC_NOERR) break;
+    }
+    return err;
+}
+
+/*----< fill_added() >-------------------------------------------------------*/
+/* fill the newly added variables */
+static int
+fill_added(NC *ncp, NC *old_ncp)
+{
+    int indx, err=NC_NOERR, varid;
+
+    /* loop thru all new variables */
+    varid = old_ncp->vars.ndefined;
+    for (; varid<ncp->vars.ndefined; varid++) {
+        if (IS_RECVAR(ncp->vars.value[varid]))
+            /* skip record variables */
+            continue;
+
+        /* check if _FillValue attribute is defined */
+        indx = ncmpii_NC_findattr(&ncp->vars.value[varid]->attrs, _FillValue);
+
+        /* only if filling this variable is requested */
+        if (ncp->vars.value[varid]->no_fill && indx == -1) continue;
+
+        /* collectively fill the entire variable */
+        err = ncmpii_fill_var_rec(ncp, ncp->vars.value[varid], 0);
+        if (err != NC_NOERR) break;
+    }
+    return err;
+}
+
+/*----< fill_added_recs() >--------------------------------------------------*/
+/* for each newly added record variable, we fill the records one at a time */
+static int
+fill_added_recs(NC *ncp, NC *old_ncp)
+{
+    MPI_Offset old_nrecs = NC_get_numrecs(old_ncp);
+    int indx, err, recno, varid;
+
+    /* loop thru all old records */
+    for (recno=0; recno<old_nrecs; recno++) {
+        /* check newly added variables only */
+        for (varid=old_ncp->vars.ndefined; varid<ncp->vars.ndefined; varid++) {
+            if (!IS_RECVAR(ncp->vars.value[varid]))
+                /* skip non-record variables */
+                continue;
+
+            /* check if _FillValue attribute is defined */
+            indx = ncmpii_NC_findattr(&ncp->vars.value[varid]->attrs, _FillValue);
+
+            /* only if filling this variable is requested */
+            if (ncp->vars.value[varid]->no_fill && indx == -1) continue;
+
+            /* collectively fill the record */
+            err = ncmpii_fill_var_rec(ncp, ncp->vars.value[varid], recno);
+            if (err != NC_NOERR) return err;
+        }
+    }
+    return NC_NOERR;
+}
+
+/*----< ncmpii_fill_vars() >-------------------------------------------------*/
+int
+ncmpii_fill_vars(NC *ncp)
+{
+    int status=NC_NOERR, err;
+
+    /* fill variables according to their fill mode settings */
+    if (NC_IsNew(ncp)) {
+        status = fillerup(ncp);
+    }
+    else if (ncp->vars.ndefined > ncp->old->vars.ndefined) {
+        status = fill_added(ncp, ncp->old);
+
+        err = fill_added_recs(ncp, ncp->old);
+        if (status == NC_NOERR) status = err;
+    }
+    return status;
+}
+
diff --git a/src/lib/getput.m4 b/src/lib/getput.m4
new file mode 100644
index 0000000..4d3cbe1
--- /dev/null
+++ b/src/lib/getput.m4
@@ -0,0 +1,1246 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: getput.m4 2290 2016-01-02 18:37:46Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h> /* memcpy() */
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "ncmpidtype.h"
+#include "macro.h"
+#ifdef ENABLE_SUBFILING
+#include "subfile.h"
+#endif
+
+
+/*----< ncmpii_calc_datatype_elems() >---------------------------------------*/
+/* check NC_ECHAR and obtain the following metadata about buftype:
+ * ptype: element data type (MPI primitive type) in buftype
+ * bufcount: If it is -1, then this is called from a high-level API and in
+ * this case buftype will be an MPI primitive data type. If not, then this
+ * is called from a flexible API. In that case, we recalculate bufcount to
+ * match with count[].
+ * bnelems: number of ptypes in user buffer
+ * nbytes: number of bytes (in external data representation) to read/write
+ * from/to the file
+ * el_size: size of ptype
+ * buftype_is_contig: whether buftype is contiguous
+ */
+int
+ncmpii_calc_datatype_elems(NC               *ncp,
+                           NC_var           *varp,
+                           const MPI_Offset *start,
+                           const MPI_Offset *count,
+                           const MPI_Offset *stride,
+                           int               rw_flag,
+                           MPI_Datatype      buftype,
+                           MPI_Datatype     *ptype,             /* out */
+                           MPI_Offset       *bufcount,          /* out */
+                           MPI_Offset       *bnelems,           /* out */
+                           MPI_Offset       *nbytes,            /* out */
+                           int              *el_size,           /* out */
+                           int              *buftype_is_contig) /* out */
+{
+    int i, err=NC_NOERR;
+    MPI_Offset fnelems;
+
+    /* In netCDF, error code reporting priority is NC_ECHAR, NC_EINVALCOORDS,
+     * NC_EEDGE, NC_ESTRIDE
+     */
+    if (*bufcount == -1) { /* same as if (IsPrimityMPIType(buftype)) */
+        /* this subroutine is called from a high-level API */
+        err = NCMPII_ECHAR(varp->type, buftype);
+        if (err != NC_NOERR) return err;
+    }
+    else if (buftype != MPI_DATATYPE_NULL) {
+        /* This subroutine is called from a flexible API */
+        int isderived;
+        err = ncmpii_dtype_decode(buftype, ptype, el_size, bnelems,
+                                  &isderived, buftype_is_contig);
+        if (err != NC_NOERR) return err;
+
+        err = NCMPII_ECHAR(varp->type, *ptype);
+        if (err != NC_NOERR) return err;
+    }
+
+    /* check whether start, count, and stride are valid */
+    err = NC_start_count_stride_ck(ncp, varp, start, count, stride, rw_flag);
+    if (err != NC_NOERR) return err;
+
+    /* fnelems is the total number of nc_type elements calculated from
+     * count[]. count[] is the access count to the variable defined in
+     * the netCDF file.
+     */
+    fnelems = 1;
+    for (i=0; i<varp->ndims; i++)
+        fnelems *= count[i];
+
+    if (*bufcount == -1) { /* if (IsPrimityMPIType(buftype)) */
+        /* this subroutine is called from a high-level API */
+        *bnelems = *bufcount = fnelems;
+        *ptype = buftype;
+        MPI_Type_size(buftype, el_size); /* buffer element size */
+        *buftype_is_contig = 1;
+        /* nbytes is the amount in bytes of this request to file */
+        *nbytes = *bnelems * varp->xsz; /* varp->xsz is external element size */
+    }
+    else if (buftype == MPI_DATATYPE_NULL) {
+        /* This is called from a flexible API and buftype is set by user
+         * to MPI_DATATYPE_NULL. In this case, bufcount is set to match
+         * count[], and buf's data type to match the data type of variable
+         * defined in the file - no data conversion will be done.
+         */
+        *bnelems = *bufcount = fnelems;
+        *ptype = buftype = ncmpii_nc2mpitype(varp->type);
+        *el_size = varp->xsz;
+        *buftype_is_contig = 1;
+        /* nbytes is the amount in bytes of this request to file */
+        *nbytes = *bnelems * varp->xsz;
+    }
+    else {
+        /* This is called from a flexible API */
+
+        /* make bnelems the number of ptype in the whole user buf */
+        *bnelems *= *bufcount;
+
+        /* check mismatch between bnelems and fnelems */
+        if (fnelems != *bnelems) {
+            DEBUG_ASSIGN_ERROR(err, NC_EIOMISMATCH)
+            (fnelems>*bnelems) ? (fnelems=*bnelems) : (*bnelems=fnelems);
+            /* only handle partial of the request, smaller number of the two */
+        }
+        /* now fnelems == *bnelems */
+
+        /* nbytes is the amount in bytes of this request to file */
+        *nbytes = *bnelems * varp->xsz;
+    }
+    return err;
+}
+
+/*----< ncmpii_create_imaptype() >-------------------------------------------*/
+/* Check if a request is a true varm call. If yes, create an MPI derived
+ * data type, imaptype, using imap[]
+ */
+int
+ncmpii_create_imaptype(NC_var           *varp,
+                       const MPI_Offset *count,
+                       const MPI_Offset *imap,
+                       const MPI_Offset  bnelems, /* no. elements in user buf */
+                       const int         el_size, /* user buf element size */
+                       MPI_Datatype      ptype,   /* element type in buftype */
+                       MPI_Datatype     *imaptype)/* out */
+{
+    int dim;
+    MPI_Offset imap_contig_blocklen;
+
+    /* check if this is a vars call or a true varm call */
+    *imaptype = MPI_DATATYPE_NULL;
+
+    if (varp->ndims == 0) /* scalar var, only one value at one fixed place */
+        return NC_NOERR;
+
+    if (bnelems == 1) /* one element, same as var1 */
+        return NC_NOERR;
+
+    if (imap == NULL) /* no mapping, same as vars */
+        return NC_NOERR;
+
+    /* test each dim's contiguity in imap[] until the 1st non-contiguous
+     * dim is reached */
+    imap_contig_blocklen = 1;
+    dim = varp->ndims;
+    while (--dim >= 0 && imap_contig_blocklen == imap[dim])
+        imap_contig_blocklen *= count[dim];
+
+    if (dim == -1) /* imap is a contiguous layout */
+        return NC_NOERR;
+
+    /* We have a true varm call, as imap gives non-contiguous layout.
+     * User buffer will be packed (write case) or unpacked (read case)
+     * to/from a contiguous buffer based on imap[], before MPI-IO.
+     * First, we construct a derived data type, imaptype, based on
+     * imap[], and use it to pack lbuf to cbuf (for write), or unpack
+     * cbuf to lbuf (for read).
+     * dim is the first dimension (C order, eg. ZYX) that has
+     * non-contiguous imap.
+     */
+    if (imap_contig_blocklen != (int)imap_contig_blocklen)
+        DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    if (count[dim] != (int)count[dim] || imap[dim] != (int)imap[dim])
+        DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+
+    MPI_Type_vector((int)count[dim], (int)imap_contig_blocklen, (int)imap[dim],
+                    ptype, imaptype);
+    MPI_Type_commit(imaptype);
+
+    for (dim--; dim>=0; dim--) {
+        MPI_Datatype tmptype;
+        if (count[dim] != (int)count[dim])
+            DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+#ifdef HAVE_MPI_TYPE_CREATE_HVECTOR
+        MPI_Type_create_hvector((int)count[dim], 1, imap[dim]*el_size,
+                                *imaptype, &tmptype);
+#else
+        MPI_Type_hvector((int)count[dim], 1, imap[dim]*el_size, *imaptype,
+                         &tmptype);
+#endif
+        MPI_Type_free(imaptype);
+        MPI_Type_commit(&tmptype);
+        *imaptype = tmptype;
+    }
+    return NC_NOERR;
+}
+
+/*----< ncmpii_getput_varm() >------------------------------------------------*/
+/* buffer layers:
+
+   User Level              buf     (user defined buffer of MPI_Datatype)
+   MPI Datatype Level      cbuf    (contiguous buffer of ptype)
+   NetCDF XDR Level        xbuf    (XDR I/O buffer)
+
+   varm: there maybe two layer of memory layout (remapping):
+         one is specified by MPI derived datatype,
+         the other is specified by imap[],
+         it's encouraged to use only one option of them,
+         though using both of them are supported.
+
+   user buffer:                         |--------------------------|
+
+   mpi derived datatype view:           |------|  |------|  |------|
+
+   logic (contig) memory datastream:       |------|------|------|
+
+   imap view:                              |--| |--|    |--| |--|
+
+   contig I/O datastream (internal represent): |--|--|--|--|
+
+   These two layers of memory layout will both be represented in MPI
+   derived datatype, and if double layers of memory layout is used,
+   we need to eliminate the upper one passed in MPI_Datatype parameter
+   from the user, by packing it to logic contig memory datastream view.
+
+   for put_varm:
+     1. pack buf to lbuf based on buftype
+     2. create imap_type based on imap
+     3. pack lbuf to cbuf based on imap_type
+     4. type convert and byte swap cbuf to xbuf
+     5. write from xbuf
+     6. byte swap the buf, if it is swapped
+     7. free up temp buffers
+
+   for get_varm:
+     1. allocate lbuf
+     2. create imap_type based on imap
+     3. allocate cbuf
+     4. allocate xbuf
+     5. read to xbuf
+     6. type convert and byte swap xbuf to cbuf
+     7. unpack cbuf to lbuf based on imap_type
+     8. unpack lbuf to buf based on buftype
+*/
+
+static int
+ncmpii_getput_varm(NC               *ncp,
+                   NC_var           *varp,
+                   const MPI_Offset  start[],
+                   const MPI_Offset  count[],
+                   const MPI_Offset  stride[],  /* can be NULL */
+                   const MPI_Offset  imap[],    /* can be NULL */
+                   void             *buf,
+                   MPI_Offset        bufcount,  /* -1: from high-level API */
+                   MPI_Datatype      buftype,
+                   int               rw_flag,   /* WRITE_REQ or READ_REQ */
+                   int               io_method) /* COLL_IO or INDEP_IO */
+{
+    void *lbuf=NULL, *cbuf=NULL, *xbuf=NULL;
+    int mpireturn, err=NC_NOERR, status=NC_NOERR, warning=NC_NOERR;
+    int el_size, buftype_is_contig;
+    int need_swap=0, need_convert=0, need_swap_back_buf=0;
+    MPI_Offset bnelems=0, nbytes=0, offset=0;
+    MPI_Status mpistatus;
+    MPI_Datatype ptype, filetype=MPI_BYTE, imaptype=MPI_DATATYPE_NULL;
+    MPI_File fh;
+
+#ifdef ENABLE_SUBFILING
+    /* call a separate routine if variable is stored in subfiles */
+    if (varp->num_subfiles > 1) {
+#ifdef SUBFILE_DEBUG
+        printf("var(%s) is stored in subfiles\n", varp->name->cp);
+#endif
+        if (imap != NULL) {
+            fprintf(stderr, "varm APIs for subfiling is yet to be implemented\n");
+            DEBUG_RETURN_ERROR(NC_ENOTSUPPORT)
+        }
+        
+        return ncmpii_subfile_getput_vars(ncp, varp, start, count, stride,
+                                          buf, bufcount, buftype,
+                                          rw_flag, io_method);
+    }
+#endif
+
+    /* check NC_ECHAR error and calculate the followings:
+     * ptype: element data type (MPI primitive type) in buftype
+     * bufcount: If it is -1, then this is called from a high-level API and in
+     * this case buftype will be an MPI primitive data type. If not, then this
+     * is called from a flexible API. In that case, we recalculate bufcount to
+     * match with count[].
+     * bnelems: number of ptypes in user buffer
+     * nbytes: number of bytes (in external data representation) to read/write
+     * from/to the file
+     * el_size: size of ptype
+     * buftype_is_contig: whether buftype is contiguous
+     */
+    err = ncmpii_calc_datatype_elems(ncp, varp, start, count, stride, rw_flag,
+                                     buftype, &ptype, &bufcount, &bnelems,
+                                     &nbytes, &el_size, &buftype_is_contig);
+    if (err == NC_EIOMISMATCH) DEBUG_ASSIGN_ERROR(warning, err) 
+    else if (err != NC_NOERR) goto err_check;
+
+    /* because nbytes will be used as the argument "count" in MPI-IO
+     * read/write calls and the argument "count" is of type int */
+    if (nbytes != (int)nbytes) {
+        DEBUG_ASSIGN_ERROR(err, NC_EINTOVERFLOW)
+        goto err_check;
+    }
+
+    if (nbytes == 0) /* this process has nothing to read/write */
+        goto err_check;
+
+    /* TODO: if record variables are too big (so big that we cannot store the
+     * stride between records in an MPI_Aint, for example) then we will
+     * have to process this one record at a time.
+     */
+
+    /* Create the filetype for this request and calculate the beginning
+     * file offset for this request.  If this request is contiguous in file,
+     * then filetype == MPI_BYTE. Otherwise filetype will be an MPI derived
+     * data type.
+     */
+    err = ncmpii_vars_create_filetype(ncp, varp, start, count, stride, rw_flag,
+                                      NULL, &offset, &filetype, NULL);
+    if (err != NC_NOERR) goto err_check;
+
+    if (bufcount != (int)bufcount) DEBUG_ASSIGN_ERROR(err, NC_EINTOVERFLOW)
+
+err_check:
+    /* If io_method is COLL_IO and an error occurs, we'll still conduct a
+     * zero-byte read/write (because every process must participate the
+     * collective I/O call).
+     */
+    if (err != NC_NOERR || nbytes == 0) {
+        if (io_method == INDEP_IO) return err;
+
+        /* COLL_IO: participate the collective I/O operations */
+        filetype = MPI_BYTE;
+        status   = err;
+        nbytes   = 0;
+        goto mpi_io;
+    }
+
+    /* check if type conversion and Endianness byte swap is needed */
+    need_convert = ncmpii_need_convert(varp->type, ptype);
+    need_swap    = ncmpii_need_swap(varp->type, ptype);
+
+    /* Check if this is a vars call or a true varm call.
+     * Construct a derived datatype, imaptype, if a true varm call
+     */
+    err = ncmpii_create_imaptype(varp, count, imap, bnelems, el_size, ptype,
+                                 &imaptype);
+    if (status == NC_NOERR) status = err;
+
+    if (rw_flag == WRITE_REQ) { /* pack request to xbuf */
+        int position;
+        MPI_Offset outsize=bnelems*el_size;
+        /* assert(bnelems > 0); */
+        if (outsize != (int)outsize && status == NC_NOERR)
+            DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+
+        /* Step 1: pack buf into a contiguous buffer, lbuf */
+        if (!buftype_is_contig) { /* buftype is not contiguous */
+            /* pack buf into lbuf, a contiguous buffer, using buftype */
+            lbuf = NCI_Malloc((size_t)outsize);
+            position = 0;
+            MPI_Pack(buf, (int)bufcount, buftype, lbuf, (int)outsize,
+                     &position, MPI_COMM_SELF);
+        }
+        else
+            lbuf = buf;
+
+        /* Step 2: pack lbuf to cbuf if imap is non-contiguous */
+        if (imaptype != MPI_DATATYPE_NULL) { /* true varm */
+            /* pack lbuf to cbuf, a contiguous buffer, using imaptype */
+            cbuf = NCI_Malloc((size_t)outsize);
+            position = 0;
+            MPI_Pack(lbuf, 1, imaptype, cbuf, (int)outsize, &position,
+                     MPI_COMM_SELF);
+            MPI_Type_free(&imaptype);
+        }
+        else /* reuse lbuf */
+            cbuf = lbuf;
+
+        /* lbuf is no longer needed */
+        if (lbuf != buf && lbuf != cbuf) NCI_Free(lbuf);
+
+        /* Step 3: pack cbuf to xbuf. The contents of xbuf will be in the
+         * external representation, ready to be written to file.
+         */
+        xbuf = cbuf;
+        if (need_convert) { /* user buf type != nc var type defined in file */
+            xbuf = NCI_Malloc((size_t)nbytes);
+
+            /* datatype conversion + byte-swap from cbuf to xbuf */
+            DATATYPE_PUT_CONVERT(varp->type, xbuf, cbuf, bnelems, ptype, status)
+            /* NC_ERANGE can be caused by a subset of buf that is out of range
+             * of the external data type, it is not considered a fatal error.
+             * The request must continue to finish.
+             */
+            if (status != NC_NOERR && status != NC_ERANGE) {
+                if (cbuf != buf)  NCI_Free(cbuf);
+                NCI_Free(xbuf);
+                xbuf = NULL;
+                if (io_method == INDEP_IO) return status;
+
+                /* COLL_IO: participate the collective I/O operations */
+                filetype  = MPI_BYTE;
+                nbytes    = 0;
+                goto mpi_io;
+            }
+        }
+        else if (need_swap) { /* no need to convert, just byte swap */
+#ifdef DISABLE_IN_PLACE_SWAP
+            if (cbuf == buf) {
+#else
+            if (cbuf == buf && nbytes <= NC_BYTE_SWAP_BUFFER_SIZE) {
+#endif
+                /* allocate cbuf and copy buf to xbuf, before byte-swap */
+                xbuf = NCI_Malloc((size_t)nbytes);
+                memcpy(xbuf, buf, nbytes);
+            }
+
+            /* perform array in-place byte-swap on xbuf */
+            ncmpii_in_swapn(xbuf, bnelems, ncmpix_len_nctype(varp->type));
+
+            if (xbuf == buf) need_swap_back_buf = 1;
+            /* user buf needs to be swapped back to its original contents */
+        }
+        /* cbuf is no longer needed */
+        if (cbuf != buf && cbuf != xbuf) NCI_Free(cbuf);
+    }
+    else { /* rw_flag == READ_REQ */
+        /* allocate xbuf for reading */
+        if (buftype_is_contig && imaptype == MPI_DATATYPE_NULL && !need_convert)
+            xbuf = buf;
+        else
+            xbuf = NCI_Malloc((size_t)nbytes);
+    }
+    /* xbuf is the buffer whose data has been converted into the external
+     * data type, ready to be written to the netCDF file. For read,
+     * after read from file, the contents of xbuf are in external type
+     */
+
+mpi_io:
+    if (io_method == COLL_IO)
+        fh = ncp->nciop->collective_fh;
+    else
+        fh = ncp->nciop->independent_fh;
+
+    /* MPI_File_set_view is collective */
+    err = ncmpii_file_set_view(ncp, fh, &offset, filetype);
+    if (err != NC_NOERR) {
+        nbytes = 0; /* skip this request */
+        if (status == NC_NOERR) status = err;
+    }
+    if (filetype != MPI_BYTE) MPI_Type_free(&filetype);
+
+    if (rw_flag == WRITE_REQ) {
+        if (io_method == COLL_IO) {
+            TRACE_IO(MPI_File_write_at_all)(fh, offset, xbuf, (int)nbytes,
+                                            MPI_BYTE, &mpistatus);
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn, "MPI_File_write_at_all");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) {
+                    status = (err == NC_EFILE) ? NC_EWRITE : err;
+                    DEBUG_ASSIGN_ERROR(status, status)
+                }
+            }
+        }
+        else { /* io_method == INDEP_IO */
+            TRACE_IO(MPI_File_write_at)(fh, offset, xbuf, (int)nbytes,
+                                        MPI_BYTE,  &mpistatus);
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn, "MPI_File_write_at");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) {
+                    status = (err == NC_EFILE) ? NC_EWRITE : err;
+                    DEBUG_ASSIGN_ERROR(status, status)
+                }
+            }
+        }
+        int put_size;
+        MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
+        ncp->nciop->put_size += put_size;
+    }
+    else {  /* rw_flag == READ_REQ */
+        if (io_method == COLL_IO) {
+            TRACE_IO(MPI_File_read_at_all)(fh, offset, xbuf, (int)nbytes,
+                                           MPI_BYTE, &mpistatus);
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn, "MPI_File_read_at_all");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) {
+                    status = (err == NC_EFILE) ? NC_EREAD : err;
+                    DEBUG_ASSIGN_ERROR(status, status)
+                }
+            }
+        }
+        else { /* io_method == INDEP_IO */
+            TRACE_IO(MPI_File_read_at)(fh, offset, xbuf, (int)nbytes,
+                                       MPI_BYTE, &mpistatus);
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn, "MPI_File_read_at");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) {
+                    status = (err == NC_EFILE) ? NC_EREAD : err;
+                    DEBUG_ASSIGN_ERROR(status, status)
+                }
+            }
+        }
+        int get_size;
+        MPI_Get_count(&mpistatus, MPI_BYTE, &get_size);
+        ncp->nciop->get_size += get_size;
+    }
+
+    /* No longer need to reset the file view, as the root's fileview includes
+     * the whole file header.
+     TRACE_IO(MPI_File_set_view)(fh, 0, MPI_BYTE, MPI_BYTE, "native",
+                                 MPI_INFO_NULL);
+     */
+
+    if (rw_flag == READ_REQ && nbytes > 0) {
+        /* xbuf contains the data read from file.
+         * Check if it needs to be type-converted + byte-swapped
+         */
+        int position;
+        MPI_Offset insize=bnelems*el_size;
+        if (insize != (int)insize && status == NC_NOERR)
+            DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+
+        if (need_convert) {
+            /* xbuf cannot be buf, but cbuf can */
+            if (buftype_is_contig && imaptype == MPI_DATATYPE_NULL)
+                cbuf = buf; /* vars call and buftype is contiguous */
+            else
+                cbuf = NCI_Malloc((size_t)insize);
+
+            /* type conversion + byte-swap from xbuf to cbuf */
+            DATATYPE_GET_CONVERT(varp->type, xbuf, cbuf, bnelems, ptype, err)
+            /* retain the first error status */
+            if (status == NC_NOERR) status = err;
+            NCI_Free(xbuf);
+        } else {
+            if (need_swap) /* perform array in-place byte-swap on xbuf */
+                ncmpii_in_swapn(xbuf, bnelems, ncmpix_len_nctype(varp->type));
+            cbuf = xbuf;
+        }
+        /* done with xbuf */
+
+        /* varm && noncontig: cbuf -> lbuf -> buf
+           vars && noncontig: cbuf == lbuf -> buf
+           varm && contig:    cbuf -> lbuf == buf
+           vars && contig:    cbuf == lbuf == buf
+        */
+        if (imaptype != MPI_DATATYPE_NULL && !buftype_is_contig)
+            /* a true varm and buftype is not contiguous: we need a separate
+             * buffer, lbuf, to unpack cbuf to lbuf using imaptype, and later
+             * unpack lbuf to buf using buftype.
+             * In this case, cbuf cannot be buf and lbuf cannot be buf.
+             */
+            lbuf = NCI_Malloc((size_t)insize);
+        else if (imaptype == MPI_DATATYPE_NULL) /* not varm */
+            lbuf = cbuf;
+        else /* varm and buftype is contiguous */
+            lbuf = buf;
+
+        if (imaptype != MPI_DATATYPE_NULL) {
+            /* unpack cbuf to lbuf based on imaptype */
+            position = 0;
+            MPI_Unpack(cbuf, (int)insize, &position, lbuf, 1, imaptype,
+                       MPI_COMM_SELF);
+            MPI_Type_free(&imaptype);
+        }
+        /* done with cbuf */
+        if (cbuf != lbuf) NCI_Free(cbuf);
+
+        if (!buftype_is_contig) {
+            /* unpack lbuf to buf based on buftype */
+            position = 0;
+            MPI_Unpack(lbuf, (int)insize, &position, buf, (int)bufcount,
+                       buftype, MPI_COMM_SELF);
+        }
+        /* done with lbuf */
+        if (lbuf != buf) NCI_Free(lbuf);
+    }
+    else if (rw_flag == WRITE_REQ) {
+        if (xbuf != NULL && xbuf != buf) NCI_Free(xbuf);
+
+        if (need_swap_back_buf) /* byte-swap back to buf's original contents */
+            ncmpii_in_swapn(buf, bnelems, ncmpix_len_nctype(varp->type));
+
+        if (IS_RECVAR(varp)) {
+            /* update header's number of records in memory */
+            MPI_Offset new_numrecs = ncp->numrecs;
+
+            /* calculate the max record ID written by this request */
+            if (status == NC_NOERR) { /* do this only if no error */
+                if (stride == NULL)
+                    new_numrecs = start[0] + count[0];
+                else
+                    new_numrecs = start[0] + (count[0] - 1) * stride[0] + 1;
+
+                /* note new_numrecs can be smaller than ncp->numrecs */
+            }
+
+            if (io_method == INDEP_IO) {
+                /* For independent put, we delay the sync for numrecs until
+                 * the next collective call, such as end_indep(), sync(),
+                 * enddef(), or close(). This is because if we update numrecs
+                 * to file now, race condition can happen. Note numrecs in
+                 * memory may be inconsistent and obsolete till then.
+                 */
+                if (ncp->numrecs < new_numrecs) {
+                    ncp->numrecs = new_numrecs;
+                    set_NC_ndirty(ncp);
+                }
+            }
+            else { /* COLL_IO: sync numrecs in memory and file */
+                /* In ncmpii_sync_numrecs(), new_numrecs is checked against
+                 * ncp->numrecs.
+                 */
+                err = ncmpii_sync_numrecs(ncp, new_numrecs);
+                if (status == NC_NOERR) status = err;
+            }
+        }
+
+        if (NC_doFsync(ncp)) { /* NC_SHARE is set */
+            TRACE_IO(MPI_File_sync)(fh);
+            if (io_method == COLL_IO)
+                TRACE_COMM(MPI_Barrier)(ncp->nciop->comm);
+        }
+    }
+
+    return ((warning != NC_NOERR) ? warning : status);
+}
+
+
+define(`CollIndep', `ifelse(`$1', `_all', `COLL_IO', `INDEP_IO')')dnl
+define(`ReadWrite', `ifelse(`$1', `get',  `READ_REQ', `WRITE_REQ')')dnl
+define(`BufConst',  `ifelse(`$1', `put',  `const')')dnl
+
+dnl
+dnl VAR_FLEXIBLE
+dnl
+define(`VAR_FLEXIBLE',dnl
+`dnl
+/*----< ncmpi_$1_var$2() >---------------------------------------------------*/
+int
+ncmpi_$1_var$2(int                ncid,
+               int                varid,
+               BufConst($1) void *buf,
+               MPI_Offset         bufcount,
+               MPI_Datatype       buftype)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    MPI_Offset *start, *count;
+
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VAR,
+                                 1, 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    GET_FULL_DIMENSIONS(start, count)
+
+    /* $1_var is a special case of $1_varm */
+    status = ncmpii_getput_varm(ncp, varp, start, count, NULL, NULL, (void*)buf,
+                                bufcount, buftype, ReadWrite($1),
+                                CollIndep($2));
+    if (varp->ndims > 0) NCI_Free(start);
+    return status;
+}
+')dnl
+
+dnl PnetCDF flexible APIs
+VAR_FLEXIBLE(put)
+VAR_FLEXIBLE(get)
+VAR_FLEXIBLE(put, _all)
+VAR_FLEXIBLE(get, _all)
+
+dnl
+dnl VAR(ncid, varid, op)
+dnl
+define(`VAR',dnl
+`dnl
+/*----< ncmpi_$1_var_$3$2() >------------------------------------------------*/
+int
+ncmpi_$1_var_$3$2(int              ncid,
+                  int              varid,
+                  BufConst($1) $4 *op)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    MPI_Offset *start, *count;
+
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, 0, API_VAR,
+                                 1, 0, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    GET_FULL_DIMENSIONS(start, count)
+
+    /* $1_var is a special case of $1_varm */
+    status = ncmpii_getput_varm(ncp, varp, start, count, NULL, NULL, (void*)op,
+                                -1, $5, ReadWrite($1), CollIndep($2));
+    if (varp->ndims > 0) NCI_Free(start);
+    return status;
+}
+')dnl
+
+VAR(put,     , text,      char,               MPI_CHAR)
+VAR(put,     , schar,     schar,              MPI_SIGNED_CHAR)
+VAR(put,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VAR(put,     , short,     short,              MPI_SHORT)
+VAR(put,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VAR(put,     , int,       int,                MPI_INT)
+VAR(put,     , uint,      uint,               MPI_UNSIGNED)
+VAR(put,     , long,      long,               MPI_LONG)
+VAR(put,     , float,     float,              MPI_FLOAT)
+VAR(put,     , double,    double,             MPI_DOUBLE)
+VAR(put,     , longlong,  long long,          MPI_LONG_LONG_INT)
+VAR(put,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VAR(put, _all, text,      char,               MPI_CHAR)
+VAR(put, _all, schar,     schar,              MPI_SIGNED_CHAR)
+VAR(put, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VAR(put, _all, short,     short,              MPI_SHORT)
+VAR(put, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VAR(put, _all, int,       int,                MPI_INT)
+VAR(put, _all, uint,      uint,               MPI_UNSIGNED)
+VAR(put, _all, long,      long,               MPI_LONG)
+VAR(put, _all, float,     float,              MPI_FLOAT)
+VAR(put, _all, double,    double,             MPI_DOUBLE)
+VAR(put, _all, longlong,  long long,          MPI_LONG_LONG_INT)
+VAR(put, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VAR(get,     , text,      char,               MPI_CHAR)
+VAR(get,     , schar,     schar,              MPI_SIGNED_CHAR)
+VAR(get,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VAR(get,     , short,     short,              MPI_SHORT)
+VAR(get,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VAR(get,     , int,       int,                MPI_INT)
+VAR(get,     , uint,      uint,               MPI_UNSIGNED)
+VAR(get,     , long,      long,               MPI_LONG)
+VAR(get,     , float,     float,              MPI_FLOAT)
+VAR(get,     , double,    double,             MPI_DOUBLE)
+VAR(get,     , longlong,  long long,          MPI_LONG_LONG_INT)
+VAR(get,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VAR(get, _all, text,      char,               MPI_CHAR)
+VAR(get, _all, schar,     schar,              MPI_SIGNED_CHAR)
+VAR(get, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VAR(get, _all, short,     short,              MPI_SHORT)
+VAR(get, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VAR(get, _all, int,       int,                MPI_INT)
+VAR(get, _all, uint,      uint,               MPI_UNSIGNED)
+VAR(get, _all, long,      long,               MPI_LONG)
+VAR(get, _all, float,     float,              MPI_FLOAT)
+VAR(get, _all, double,    double,             MPI_DOUBLE)
+VAR(get, _all, longlong,  long long,          MPI_LONG_LONG_INT)
+VAR(get, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+dnl
+dnl VAR1_FLEXIBLE
+dnl
+define(`VAR1_FLEXIBLE',dnl
+`dnl
+/*----< ncmpi_$1_var1$2() >--------------------------------------------------*/
+int
+ncmpi_$1_var1$2(int                ncid,
+                int                varid,
+                const MPI_Offset   start[],
+                BufConst($1) void *buf,
+                MPI_Offset         bufcount,
+                MPI_Datatype       buftype)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    MPI_Offset *count;
+
+    status = ncmpii_sanity_check(ncid, varid, start, NULL, bufcount, API_VAR1,
+                                 1, 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    GET_ONE_COUNT(count)
+
+    status = ncmpii_getput_varm(ncp, varp, start, count, NULL, NULL, (void*)buf,
+                                bufcount, buftype, ReadWrite($1),
+                                CollIndep($2));
+    if (varp->ndims > 0) NCI_Free(count);
+    return status;
+}
+')dnl
+
+VAR1_FLEXIBLE(put)
+VAR1_FLEXIBLE(get)
+VAR1_FLEXIBLE(put, _all)
+VAR1_FLEXIBLE(get, _all)
+
+dnl
+dnl VAR1
+dnl
+define(`VAR1',dnl
+`dnl
+/*----< ncmpi_$1_var1_$3$2() >-----------------------------------------------*/
+int
+ncmpi_$1_var1_$3$2(int               ncid,
+                   int               varid,
+                   const MPI_Offset  start[],
+                   BufConst($1) $4  *op)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    MPI_Offset *count;
+
+    status = ncmpii_sanity_check(ncid, varid, start, NULL, 0, API_VAR1,
+                                 1, 0, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    GET_ONE_COUNT(count)
+
+    /* $1_var1 is a special case of $1_varm */
+    status = ncmpii_getput_varm(ncp, varp, start, count, NULL, NULL, (void*)op,
+                                -1, $5, ReadWrite($1), CollIndep($2));
+    if (varp->ndims > 0) NCI_Free(count);
+    return status;
+}
+')dnl
+
+VAR1(put,     , text,      char,               MPI_CHAR)
+VAR1(put,     , schar,     schar,              MPI_SIGNED_CHAR)
+VAR1(put,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VAR1(put,     , short,     short,              MPI_SHORT)
+VAR1(put,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VAR1(put,     , int,       int,                MPI_INT)
+VAR1(put,     , uint,      uint,               MPI_UNSIGNED)
+VAR1(put,     , long,      long,               MPI_LONG)
+VAR1(put,     , float,     float,              MPI_FLOAT)
+VAR1(put,     , double,    double,             MPI_DOUBLE)
+VAR1(put,     , longlong,  long long,          MPI_LONG_LONG_INT)
+VAR1(put,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VAR1(put, _all, text,      char,               MPI_CHAR)
+VAR1(put, _all, schar,     schar,              MPI_SIGNED_CHAR)
+VAR1(put, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VAR1(put, _all, short,     short,              MPI_SHORT)
+VAR1(put, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VAR1(put, _all, int,       int,                MPI_INT)
+VAR1(put, _all, uint,      uint,               MPI_UNSIGNED)
+VAR1(put, _all, long,      long,               MPI_LONG)
+VAR1(put, _all, float,     float,              MPI_FLOAT)
+VAR1(put, _all, double,    double,             MPI_DOUBLE)
+VAR1(put, _all, longlong,  long long,          MPI_LONG_LONG_INT)
+VAR1(put, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VAR1(get,     , text,      char,               MPI_CHAR)
+VAR1(get,     , schar,     schar,              MPI_SIGNED_CHAR)
+VAR1(get,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VAR1(get,     , short,     short,              MPI_SHORT)
+VAR1(get,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VAR1(get,     , int,       int,                MPI_INT)
+VAR1(get,     , uint,      uint,               MPI_UNSIGNED)
+VAR1(get,     , long,      long,               MPI_LONG)
+VAR1(get,     , float,     float,              MPI_FLOAT)
+VAR1(get,     , double,    double,             MPI_DOUBLE)
+VAR1(get,     , longlong,  long long,          MPI_LONG_LONG_INT)
+VAR1(get,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VAR1(get, _all, text,      char,               MPI_CHAR)
+VAR1(get, _all, schar,     schar,              MPI_SIGNED_CHAR)
+VAR1(get, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VAR1(get, _all, short,     short,              MPI_SHORT)
+VAR1(get, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VAR1(get, _all, int,       int,                MPI_INT)
+VAR1(get, _all, uint,      uint,               MPI_UNSIGNED)
+VAR1(get, _all, long,      long,               MPI_LONG)
+VAR1(get, _all, float,     float,              MPI_FLOAT)
+VAR1(get, _all, double,    double,             MPI_DOUBLE)
+VAR1(get, _all, longlong,  long long,          MPI_LONG_LONG_INT)
+VAR1(get, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+dnl
+dnl VARA_FLEXIBLE
+dnl
+define(`VARA_FLEXIBLE',dnl
+`dnl
+/*----< ncmpi_$1_vara$2() >--------------------------------------------------*/
+int
+ncmpi_$1_vara$2(int                ncid,
+                int                varid,
+                const MPI_Offset   start[],
+                const MPI_Offset   count[],
+                BufConst($1) void *buf,
+                MPI_Offset         bufcount,
+                MPI_Datatype       buftype)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARA,
+                                 1, 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    /* $1_vara is a special case of $1_varm */
+    return ncmpii_getput_varm(ncp, varp, start, count, NULL, NULL, (void*)buf,
+                              bufcount, buftype, ReadWrite($1), CollIndep($2));
+}
+')dnl
+
+dnl PnetCDF flexible APIs
+VARA_FLEXIBLE(put)
+VARA_FLEXIBLE(get)
+VARA_FLEXIBLE(put, _all)
+VARA_FLEXIBLE(get, _all)
+
+dnl
+dnl VARA
+dnl
+define(`VARA',dnl
+`dnl
+/*----< ncmpi_$1_vara_$3$2() >-----------------------------------------------*/
+int
+ncmpi_$1_vara_$3$2(int               ncid,
+                   int               varid,
+                   const MPI_Offset  start[],
+                   const MPI_Offset  count[],
+                   BufConst($1) $4  *op)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARA,
+                                 1, 0, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    /* $1_vara is a special case of $1_varm */
+    return ncmpii_getput_varm(ncp, varp, start, count, NULL, NULL, (void*)op,
+                              -1, $5, ReadWrite($1), CollIndep($2));
+}
+')dnl
+
+VARA(put,     , text,      char,               MPI_CHAR)
+VARA(put,     , schar,     schar,              MPI_SIGNED_CHAR)
+VARA(put,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARA(put,     , short,     short,              MPI_SHORT)
+VARA(put,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARA(put,     , int,       int,                MPI_INT)
+VARA(put,     , uint,      uint,               MPI_UNSIGNED)
+VARA(put,     , long,      long,               MPI_LONG)
+VARA(put,     , float,     float,              MPI_FLOAT)
+VARA(put,     , double,    double,             MPI_DOUBLE)
+VARA(put,     , longlong,  long long,          MPI_LONG_LONG_INT)
+VARA(put,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARA(put, _all, text,      char,               MPI_CHAR)
+VARA(put, _all, schar,     schar,              MPI_SIGNED_CHAR)
+VARA(put, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARA(put, _all, short,     short,              MPI_SHORT)
+VARA(put, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARA(put, _all, int,       int,                MPI_INT)
+VARA(put, _all, uint,      uint,               MPI_UNSIGNED)
+VARA(put, _all, long,      long,               MPI_LONG)
+VARA(put, _all, float,     float,              MPI_FLOAT)
+VARA(put, _all, double,    double,             MPI_DOUBLE)
+VARA(put, _all, longlong,  long long,          MPI_LONG_LONG_INT)
+VARA(put, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARA(get,     , text,      char,               MPI_CHAR)
+VARA(get,     , schar,     schar,              MPI_SIGNED_CHAR)
+VARA(get,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARA(get,     , short,     short,              MPI_SHORT)
+VARA(get,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARA(get,     , int,       int,                MPI_INT)
+VARA(get,     , uint,      uint,               MPI_UNSIGNED)
+VARA(get,     , long,      long,               MPI_LONG)
+VARA(get,     , float,     float,              MPI_FLOAT)
+VARA(get,     , double,    double,             MPI_DOUBLE)
+VARA(get,     , longlong,  long long,          MPI_LONG_LONG_INT)
+VARA(get,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARA(get, _all, text,      char,               MPI_CHAR)
+VARA(get, _all, schar,     schar,              MPI_SIGNED_CHAR)
+VARA(get, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARA(get, _all, short,     short,              MPI_SHORT)
+VARA(get, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARA(get, _all, int,       int,                MPI_INT)
+VARA(get, _all, uint,      uint,               MPI_UNSIGNED)
+VARA(get, _all, long,      long,               MPI_LONG)
+VARA(get, _all, float,     float,              MPI_FLOAT)
+VARA(get, _all, double,    double,             MPI_DOUBLE)
+VARA(get, _all, longlong,  long long,          MPI_LONG_LONG_INT)
+VARA(get, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+dnl
+dnl VARS_FLEXIBLE
+dnl
+define(`VARS_FLEXIBLE',dnl
+`dnl
+/*----< ncmpi_$1_vars$2() >--------------------------------------------------*/
+int
+ncmpi_$1_vars$2(int                ncid,
+                int                varid,
+                const MPI_Offset   start[],
+                const MPI_Offset   count[],
+                const MPI_Offset   stride[],
+                BufConst($1) void *buf,
+                MPI_Offset         bufcount,
+                MPI_Datatype       buftype)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARS,
+                                 1, 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_getput_varm(ncp, varp, start, count, stride, NULL, (void*)buf,
+                              bufcount, buftype, ReadWrite($1), CollIndep($2));
+}
+')dnl
+
+dnl PnetCDF flexible APIs
+VARS_FLEXIBLE(put)
+VARS_FLEXIBLE(get)
+VARS_FLEXIBLE(put, _all)
+VARS_FLEXIBLE(get, _all)
+
+dnl
+dnl VARS
+dnl
+define(`VARS',dnl
+`dnl
+/*----< ncmpi_$1_vars_$3$2() >-----------------------------------------------*/
+int
+ncmpi_$1_vars_$3$2(int               ncid,
+                   int               varid,
+                   const MPI_Offset  start[],
+                   const MPI_Offset  count[],
+                   const MPI_Offset  stride[],
+                   BufConst($1) $4  *op)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARS,
+                                 1, 0, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_getput_varm(ncp, varp, start, count, stride, NULL, (void*)op,
+                              -1, $5, ReadWrite($1), CollIndep($2));
+}
+')dnl
+
+VARS(put,     , text,      char,               MPI_CHAR)
+VARS(put,     , schar,     schar,              MPI_SIGNED_CHAR)
+VARS(put,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARS(put,     , short,     short,              MPI_SHORT)
+VARS(put,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARS(put,     , int,       int,                MPI_INT)
+VARS(put,     , uint,      uint,               MPI_UNSIGNED)
+VARS(put,     , long,      long,               MPI_LONG)
+VARS(put,     , float,     float,              MPI_FLOAT)
+VARS(put,     , double,    double,             MPI_DOUBLE)
+VARS(put,     , longlong,  long long,          MPI_LONG_LONG_INT)
+VARS(put,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARS(put, _all, text,      char,               MPI_CHAR)
+VARS(put, _all, schar,     schar,              MPI_SIGNED_CHAR)
+VARS(put, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARS(put, _all, short,     short,              MPI_SHORT)
+VARS(put, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARS(put, _all, int,       int,                MPI_INT)
+VARS(put, _all, uint,      uint,               MPI_UNSIGNED)
+VARS(put, _all, long,      long,               MPI_LONG)
+VARS(put, _all, float,     float,              MPI_FLOAT)
+VARS(put, _all, double,    double,             MPI_DOUBLE)
+VARS(put, _all, longlong,  long long,          MPI_LONG_LONG_INT)
+VARS(put, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARS(get,     , text,      char,               MPI_CHAR)
+VARS(get,     , schar,     schar,              MPI_SIGNED_CHAR)
+VARS(get,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARS(get,     , short,     short,              MPI_SHORT)
+VARS(get,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARS(get,     , int,       int,                MPI_INT)
+VARS(get,     , uint,      uint,               MPI_UNSIGNED)
+VARS(get,     , long,      long,               MPI_LONG)
+VARS(get,     , float,     float,              MPI_FLOAT)
+VARS(get,     , double,    double,             MPI_DOUBLE)
+VARS(get,     , longlong,  long long,          MPI_LONG_LONG_INT)
+VARS(get,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARS(get, _all, text,      char,               MPI_CHAR)
+VARS(get, _all, schar,     schar,              MPI_SIGNED_CHAR)
+VARS(get, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARS(get, _all, short,     short,              MPI_SHORT)
+VARS(get, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARS(get, _all, int,       int,                MPI_INT)
+VARS(get, _all, uint,      uint,               MPI_UNSIGNED)
+VARS(get, _all, long,      long,               MPI_LONG)
+VARS(get, _all, float,     float,              MPI_FLOAT)
+VARS(get, _all, double,    double,             MPI_DOUBLE)
+VARS(get, _all, longlong,  long long,          MPI_LONG_LONG_INT)
+VARS(get, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+dnl
+dnl VARM_FLEXIBLE
+dnl
+define(`VARM_FLEXIBLE',dnl
+`dnl
+/*----< ncmpi_$1_varm$2() >--------------------------------------------------*/
+int
+ncmpi_$1_varm$2(int                ncid,
+                int                varid,
+                const MPI_Offset   start[],
+                const MPI_Offset   count[],
+                const MPI_Offset   stride[],
+                const MPI_Offset   imap[],
+                BufConst($1) void *buf,
+                MPI_Offset         bufcount,
+                MPI_Datatype       buftype)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARM,
+                                 1, 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_getput_varm(ncp, varp, start, count, stride, imap,
+                              (void*)buf, bufcount, buftype, ReadWrite($1),
+                              CollIndep($2));
+}
+')dnl
+
+dnl PnetCDF flexible APIs
+VARM_FLEXIBLE(put)
+VARM_FLEXIBLE(get)
+VARM_FLEXIBLE(put, _all)
+VARM_FLEXIBLE(get, _all)
+
+dnl
+dnl VARM
+dnl
+define(`VARM',dnl
+`dnl
+/*----< ncmpi_$1_varm_$3$2() >------------------------------------------------*/
+int
+ncmpi_$1_varm_$3$2(int               ncid,
+                   int               varid,
+                   const MPI_Offset  start[],
+                   const MPI_Offset  count[],
+                   const MPI_Offset  stride[],
+                   const MPI_Offset  imap[],
+                   BufConst($1) $4  *op)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARM,
+                                 1, 0, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_getput_varm(ncp, varp, start, count, stride, imap, (void*)op,
+                              -1, $5, ReadWrite($1), CollIndep($2));
+}
+')dnl
+
+VARM(put,     , text,      char,               MPI_CHAR)
+VARM(put,     , schar,     schar,              MPI_SIGNED_CHAR)
+VARM(put,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARM(put,     , short,     short,              MPI_SHORT)
+VARM(put,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARM(put,     , int,       int,                MPI_INT)
+VARM(put,     , uint,      uint,               MPI_UNSIGNED)
+VARM(put,     , long,      long,               MPI_LONG)
+VARM(put,     , float,     float,              MPI_FLOAT)
+VARM(put,     , double,    double,             MPI_DOUBLE)
+VARM(put,     , longlong,  long long,          MPI_LONG_LONG_INT)
+VARM(put,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARM(put, _all, text,      char,               MPI_CHAR)
+VARM(put, _all, schar,     schar,              MPI_SIGNED_CHAR)
+VARM(put, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARM(put, _all, short,     short,              MPI_SHORT)
+VARM(put, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARM(put, _all, int,       int,                MPI_INT)
+VARM(put, _all, uint,      uint,               MPI_UNSIGNED)
+VARM(put, _all, long,      long,               MPI_LONG)
+VARM(put, _all, float,     float,              MPI_FLOAT)
+VARM(put, _all, double,    double,             MPI_DOUBLE)
+VARM(put, _all, longlong,  long long,          MPI_LONG_LONG_INT)
+VARM(put, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARM(get,     , text,      char,               MPI_CHAR)
+VARM(get,     , schar,     schar,              MPI_SIGNED_CHAR)
+VARM(get,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARM(get,     , short,     short,              MPI_SHORT)
+VARM(get,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARM(get,     , int,       int,                MPI_INT)
+VARM(get,     , uint,      uint,               MPI_UNSIGNED)
+VARM(get,     , long,      long,               MPI_LONG)
+VARM(get,     , float,     float,              MPI_FLOAT)
+VARM(get,     , double,    double,             MPI_DOUBLE)
+VARM(get,     , longlong,  long long,          MPI_LONG_LONG_INT)
+VARM(get,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARM(get, _all, text,      char,               MPI_CHAR)
+VARM(get, _all, schar,     schar,              MPI_SIGNED_CHAR)
+VARM(get, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARM(get, _all, short,     short,              MPI_SHORT)
+VARM(get, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARM(get, _all, int,       int,                MPI_INT)
+VARM(get, _all, uint,      uint,               MPI_UNSIGNED)
+VARM(get, _all, long,      long,               MPI_LONG)
+VARM(get, _all, float,     float,              MPI_FLOAT)
+VARM(get, _all, double,    double,             MPI_DOUBLE)
+VARM(get, _all, longlong,  long long,          MPI_LONG_LONG_INT)
+VARM(get, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+
diff --git a/src/lib/header.c b/src/lib/header.c
new file mode 100644
index 0000000..0f0f4c0
--- /dev/null
+++ b/src/lib/header.c
@@ -0,0 +1,2530 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: header.c 2299 2016-01-09 06:14:37Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <assert.h>
+#include <string.h>  /* memcpy(), memcmp() */
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "macro.h"
+
+#ifdef SIZEOF_INT
+# if SIZEOF_INT == 4
+#  define lld(x) (x)
+# elif  SIZEOF_INT == 8
+#  define lld(x) (long long)(x)
+# endif
+#endif
+
+/* Prototypes for functions used only in this file */
+static MPI_Offset hdr_len_NC_name(const NC_string *ncstrp, int sizeof_t);
+static MPI_Offset hdr_len_NC_dim(const NC_dim *dimp, int sizeof_t);
+static MPI_Offset hdr_len_NC_dimarray(const NC_dimarray *ncap, int sizeof_t);
+static MPI_Offset hdr_len_NC_attr(const NC_attr *attrp, int sizeof_t);
+static MPI_Offset hdr_len_NC_attrarray(const NC_attrarray *ncap, int sizeof_t);
+static MPI_Offset hdr_len_NC_var(const NC_var *varp, int sizeof_off_t, int sizeof_t);
+static MPI_Offset hdr_len_NC_vararray(const NC_vararray *ncap, int sizeof_t, int sizeof_off_t);
+static int hdr_put_NC_name(bufferinfo *pbp, const NC_string *ncstrp);
+static int hdr_put_NC_attrV(bufferinfo *pbp, const NC_attr *attrp);
+static int hdr_put_NC_dim(bufferinfo *pbp, const NC_dim *dimp);
+static int hdr_put_NC_attr(bufferinfo *pbp, const NC_attr *attrp);
+static int hdr_put_NC_var(bufferinfo *pbp, const NC_var *varp);
+static int hdr_put_NC_dimarray(bufferinfo *pbp, const NC_dimarray *ncap);
+static int hdr_put_NC_attrarray(bufferinfo *pbp, const NC_attrarray *ncap);
+static int hdr_put_NC_vararray(bufferinfo *pbp, const NC_vararray *ncap);
+static int hdr_fetch(bufferinfo *gbp);
+static int hdr_check_buffer(bufferinfo *gbp, MPI_Offset nextread);
+static int hdr_get_NCtype(bufferinfo *gbp, NCtype *typep);
+static int hdr_get_NC_name(bufferinfo *gbp, NC_string **ncstrpp);
+static int hdr_get_NC_dim(bufferinfo *gbp, NC_dim **dimpp);
+static int hdr_get_NC_dimarray(bufferinfo *gbp, NC_dimarray *ncap);
+static int hdr_get_nc_type(bufferinfo *gbp, nc_type *typep);
+static int hdr_get_NC_attrV(bufferinfo *gbp, NC_attr *attrp);
+static int hdr_get_NC_attr(bufferinfo *gbp, NC_attr **attrpp);
+static int hdr_get_NC_attrarray(bufferinfo *gbp, NC_attrarray *ncap);
+static int hdr_get_NC_var(bufferinfo *gbp, NC_var **varpp);
+static int hdr_get_NC_vararray(bufferinfo *gbp, NC_vararray *ncap);
+
+/*
+ * "magic number" at beginning of file: 0x43444601 (big endian)
+ */
+static const schar ncmagic1[] = {'C', 'D', 'F', 0x01};
+static const schar ncmagic2[] = {'C', 'D', 'F', 0x02};
+static const schar ncmagic5[] = {'C', 'D', 'F', 0x05};
+
+/*
+ * Recompute the shapes of all variables
+ * Sets ncp->begin_var to start of first variable.
+ * Sets ncp->begin_rec to start of first record variable.
+ * Returns -1 on error. The only possible error is an reference
+ * to a non existent dimension, which would occur for a corrupt
+ * netcdf file.
+ */
+int
+ncmpii_NC_computeshapes(NC *ncp)
+{
+    NC_var **vpp = (NC_var **)ncp->vars.value;
+    NC_var *const *const end = &vpp[ncp->vars.ndefined];
+    NC_var *first_var = NULL;       /* first "non-record" var */
+    NC_var *first_rec = NULL;       /* first "record" var */
+    int status;
+
+    ncp->begin_var = (MPI_Offset) ncp->xsz;
+    ncp->begin_rec = (MPI_Offset) ncp->xsz;
+    ncp->recsize = 0;
+
+    if (ncp->vars.ndefined == 0) return NC_NOERR;
+
+    for ( /*NADA*/; vpp < end; vpp++) {
+        /* (*vpp)->len is recomputed from dimensions in ncmpii_NC_var_shape64() */
+        status = ncmpii_NC_var_shape64(ncp, *vpp, &ncp->dims);
+
+        if (status != NC_NOERR) return status ;
+
+        if (IS_RECVAR(*vpp)) {
+            if (first_rec == NULL)
+                first_rec = *vpp;
+            ncp->recsize += (*vpp)->len;
+        }
+        else {
+            if (first_var == NULL)
+            first_var = *vpp;
+            /*
+             * Overwritten each time thru.
+             * Usually overwritten in first_rec != NULL clause.
+             */
+            ncp->begin_rec = (*vpp)->begin + (MPI_Offset)(*vpp)->len;
+        }
+    }
+
+    if (first_rec != NULL) {
+        if (ncp->begin_rec > first_rec->begin)
+            DEBUG_RETURN_ERROR(NC_ENOTNC) /* not a netCDF file or corrupted */
+
+        ncp->begin_rec = first_rec->begin;
+        /*
+         * for special case of exactly one record variable, pack value
+         */
+        if (ncp->recsize == first_rec->len)
+            ncp->recsize = *first_rec->dsizes * first_rec->xsz;
+    }
+
+    if (first_var != NULL)
+        ncp->begin_var = first_var->begin;
+    else
+        ncp->begin_var = ncp->begin_rec;
+
+    if (ncp->begin_var <= 0 ||
+        ncp->xsz > ncp->begin_var ||
+        ncp->begin_rec <= 0 ||
+        ncp->begin_var > ncp->begin_rec)
+        DEBUG_RETURN_ERROR(NC_ENOTNC) /* not a netCDF file or corrupted */
+
+    return NC_NOERR;
+}
+
+/*
+ * To compute how much space will the xdr'd header take
+ */
+
+#define X_SIZEOF_NC_TYPE X_SIZEOF_INT
+#define X_SIZEOF_NCTYPE X_SIZEOF_INT
+
+/*----< hdr_len_NC_name() >--------------------------------------------------*/
+inline static MPI_Offset
+hdr_len_NC_name(const NC_string *ncstrp,
+                int              sizeof_t)     /* NON_NEG */
+{
+    /* netCDF file format:
+     * name       = nelems  namestring
+     * nelems     = NON_NEG
+     * namestring = ID1 [IDN ...] padding
+     * ID1        = alphanumeric | '_'
+     * IDN        = alphanumeric | special1 | special2
+     * padding    = <0, 1, 2, or 3 bytes to next 4-byte boundary>
+     * NON_NEG    = <non-negative INT> |  // CDF-1 and CDF-2
+     *              <non-negative INT64>  // CDF-5
+     */
+    MPI_Offset sz = sizeof_t; /* nelems */
+
+    assert(ncstrp != NULL);
+
+    if (ncstrp->nchars != 0)  /* namestring */
+        sz += _RNDUP(ncstrp->nchars, X_ALIGN);
+
+    return sz;
+}
+
+/*----< hdr_len_NC_dim() >---------------------------------------------------*/
+inline static MPI_Offset
+hdr_len_NC_dim(const NC_dim *dimp,
+               int           sizeof_t)     /* NON_NEG */
+{
+    /* netCDF file format:
+     *  ...
+     * dim        = name  dim_length
+     * dim_length = NON_NEG
+     * NON_NEG    = <non-negative INT> |  // CDF-1 and CDF-2
+     *              <non-negative INT64>  // CDF-5
+     */
+    MPI_Offset sz;
+
+    assert(dimp != NULL);
+
+    sz = hdr_len_NC_name(dimp->name, sizeof_t); /* name */
+    sz += sizeof_t;                             /* dim_length */
+
+    return sz;
+}
+
+/*----< hdr_len_NC_dimarray() >----------------------------------------------*/
+inline static MPI_Offset
+hdr_len_NC_dimarray(const NC_dimarray *ncap,
+                    int                sizeof_t)     /* NON_NEG */
+{
+    /* netCDF file format:
+     *  ...
+     * dim_list     = ABSENT | NC_DIMENSION  nelems  [dim ...]
+     * ABSENT       = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *                ZERO  ZERO64  // for CDF-5
+     * ZERO         = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64       = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_DIMENSION = \x00 \x00 \x00 \x0A         // tag for list of dimensions
+     * nelems       = NON_NEG       // number of elements in following sequence
+     * NON_NEG      = <non-negative INT> |        // CDF-1 and CDF-2
+     *                <non-negative INT64>        // CDF-5
+     */
+    int i;
+    MPI_Offset xlen;
+
+    xlen = X_SIZEOF_NCTYPE;           /* NC_DIMENSION */
+    xlen += sizeof_t;                 /* nelems */
+
+    if (ncap == NULL) /* ABSENT: no dimension is defined */
+        return xlen;
+
+    /* [dim ...] */
+    for (i=0; i<ncap->ndefined; i++)
+        xlen += hdr_len_NC_dim(ncap->value[i], sizeof_t);
+
+    return xlen;
+}
+
+/*----< hdr_len_NC_attr() >--------------------------------------------------*/
+inline static MPI_Offset
+hdr_len_NC_attr(const NC_attr *attrp,
+                int            sizeof_t)     /* NON_NEG */
+{
+    /* netCDF file format:
+     *  ...
+     * attr    = name  nc_type  nelems  [values ...]
+     * nc_type = NC_BYTE | NC_CHAR | NC_SHORT | ...
+     * nelems  = NON_NEG       // number of elements in following sequence
+     * values  = bytes | chars | shorts | ints | floats | doubles
+     * bytes   = [BYTE ...]  padding
+     * chars   = [CHAR ...]  padding
+     * shorts  = [SHORT ...]  padding
+     * ints    = [INT ...]
+     * floats  = [FLOAT ...]
+     * doubles = [DOUBLE ...]
+     * padding = <0, 1, 2, or 3 bytes to next 4-byte boundary>
+     * NON_NEG = <non-negative INT> |  // CDF-1 and CDF-2
+     *           <non-negative INT64>  // CDF-5
+     */
+    MPI_Offset sz;
+
+    assert(attrp != NULL);
+
+    sz  = hdr_len_NC_name(attrp->name, sizeof_t); /* name */
+    sz += X_SIZEOF_NC_TYPE;                       /* nc_type */
+    sz += sizeof_t;                               /* nelems */
+    sz += attrp->xsz;                             /* [values ...] */
+
+    return sz;
+}
+
+/*----< hdr_len_NC_attrarray() >---------------------------------------------*/
+inline static MPI_Offset
+hdr_len_NC_attrarray(const NC_attrarray *ncap,
+                     int                 sizeof_t)     /* NON_NEG */
+{
+    /* netCDF file format:
+     *  ...
+     * att_list     = ABSENT | NC_ATTRIBUTE  nelems  [attr ...]
+     * ABSENT       = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *                ZERO  ZERO64  // for CDF-5
+     * ZERO         = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64       = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_ATTRIBUTE = \x00 \x00 \x00 \x0C         // tag for list of attributes
+     * nelems       = NON_NEG       // number of elements in following sequence
+     * NON_NEG      = <non-negative INT> |        // CDF-1 and CDF-2
+     *                <non-negative INT64>        // CDF-5
+     */
+    int i;
+    MPI_Offset xlen;
+
+    xlen = X_SIZEOF_NCTYPE;        /* NC_ATTRIBUTE */
+    xlen += sizeof_t;              /* nelems */
+
+    if (ncap == NULL) /* ABSENT: no attribute is defined */
+        return xlen;
+
+    for (i=0; i<ncap->ndefined; i++) /* [attr ...] */
+        xlen += hdr_len_NC_attr(ncap->value[i], sizeof_t);
+
+    return xlen;
+}
+
+/*----< hdr_len_NC_var() >---------------------------------------------------*/
+inline static MPI_Offset
+hdr_len_NC_var(const NC_var *varp,
+               int           sizeof_off_t, /* OFFSET */
+               int           sizeof_t)     /* NON_NEG */
+{
+    /* netCDF file format:
+     * netcdf_file = header data
+     * header      = magic numrecs dim_list gatt_list var_list
+     *  ...
+     * var         = name nelems [dimid ...] vatt_list nc_type vsize begin
+     * nelems      = NON_NEG
+     * dimid       = NON_NEG
+     * vatt_list   = att_list
+     * nc_type     = NC_BYTE | NC_CHAR | NC_SHORT | ...
+     * vsize       = NON_NEG
+     * begin       = OFFSET        // Variable start location.
+     * OFFSET      = <non-negative INT> |  // CDF-1
+     *               <non-negative INT64>  // CDF-2 and CDF-5
+     * NON_NEG     = <non-negative INT> |  // CDF-1 and CDF-2
+     *               <non-negative INT64>  // CDF-5
+     */
+    MPI_Offset sz;
+
+    assert(varp != NULL);
+
+    /* for CDF-1, sizeof_off_t == 4 && sizeof_t == 4
+     * for CDF-2, sizeof_off_t == 8 && sizeof_t == 4
+     * for CDF-5, sizeof_off_t == 8 && sizeof_t == 8
+     */
+    sz = hdr_len_NC_name(varp->name, sizeof_t);         /* name */
+    sz += sizeof_t;                                     /* nelems */
+    sz += sizeof_t * varp->ndims;                       /* [dimid ...] */
+    sz += hdr_len_NC_attrarray(&varp->attrs, sizeof_t); /* vatt_list */
+    sz += X_SIZEOF_NC_TYPE;                             /* nc_type */
+    sz += sizeof_t;                                     /* vsize */
+    sz += sizeof_off_t;                                 /* begin */
+
+    return sz;
+}
+
+/*----< hdr_len_NC_vararray() >----------------------------------------------*/
+inline static MPI_Offset
+hdr_len_NC_vararray(const NC_vararray *ncap,
+                    int                sizeof_t,     /* NON_NEG */
+                    int                sizeof_off_t) /* OFFSET */
+{
+    /* netCDF file format:
+     * netcdf_file = header  data
+     * header      = magic  numrecs  dim_list  gatt_list  var_list
+     *  ...
+     * var_list    = ABSENT | NC_VARIABLE   nelems  [var ...]
+     * ABSENT      = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *               ZERO  ZERO64  // for CDF-5
+     * ZERO        = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64      = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_VARIABLE = \x00 \x00 \x00 \x0B         // tag for list of variables
+     * nelems      = NON_NEG       // number of elements in following sequence
+     * NON_NEG     = <non-negative INT> |        // CDF-1 and CDF-2
+     *               <non-negative INT64>        // CDF-5
+     */
+    int i;
+    MPI_Offset xlen;
+
+    xlen = X_SIZEOF_NCTYPE;           /* NC_VARIABLE */
+    xlen += sizeof_t;                 /* nelems */
+
+    if (ncap == NULL) /* ABSENT: no variable is defined */
+        return xlen;
+
+    /* for CDF-1, sizeof_off_t == 4 && sizeof_t == 4
+     * for CDF-2, sizeof_off_t == 8 && sizeof_t == 4
+     * for CDF-5, sizeof_off_t == 8 && sizeof_t == 8
+     */
+    for (i=0; i<ncap->ndefined; i++)  /* [var ...] */
+        xlen += hdr_len_NC_var(ncap->value[i], sizeof_off_t, sizeof_t);
+
+    return xlen;
+}
+
+/*----< ncmpii_hdr_len_NC() >------------------------------------------------*/
+MPI_Offset
+ncmpii_hdr_len_NC(const NC *ncp)
+{
+    /* netCDF file format:
+     * netcdf_file = header  data
+     * header      = magic  numrecs  dim_list  gatt_list  var_list
+     *  ...
+     * numrecs     = NON_NEG | STREAMING   // length of record dimension
+     * NON_NEG     = <non-negative INT> |  // CDF-1 and CDF-2
+     *               <non-negative INT64>  // CDF-5
+     */
+
+    int sizeof_t, sizeof_off_t;
+    MPI_Offset xlen;
+
+    assert(ncp != NULL);
+
+    if (fIsSet(ncp->flags, NC_64BIT_DATA)) {        /* CDF-5 */
+        sizeof_t     = X_SIZEOF_INT64; /* 8-byte integer for all integers */
+        sizeof_off_t = X_SIZEOF_INT64; /* 8-byte integer for var begin */
+    }
+    else if (fIsSet(ncp->flags, NC_64BIT_OFFSET)) { /* CDF-2 */
+        sizeof_t     = X_SIZEOF_INT; /* 4-byte integer in CDF-1 */
+        sizeof_off_t = X_SIZEOF_INT64; /* 8-byte integer for var begin */
+    }
+    else { /* CDF-1 */
+        sizeof_t     = X_SIZEOF_INT; /* 4-byte integer in CDF-1 */
+        sizeof_off_t = X_SIZEOF_INT; /* 4-byte integer in CDF-1 */
+    }
+
+    xlen  = sizeof(ncmagic1);                                          /* magic */
+    xlen += sizeof_t;                                                  /* numrecs */
+    xlen += hdr_len_NC_dimarray(&ncp->dims,   sizeof_t);               /* dim_list */
+    xlen += hdr_len_NC_attrarray(&ncp->attrs, sizeof_t);               /* gatt_list */
+    xlen += hdr_len_NC_vararray(&ncp->vars,   sizeof_t, sizeof_off_t); /* var_list */
+
+    return xlen; /* return the header size (not yet aligned) */
+}
+
+/* Begin Of put NC */
+
+/*----< hdr_put_NC_name() >--------------------------------------------------*/
+inline static int
+hdr_put_NC_name(bufferinfo      *pbp,
+                const NC_string *ncstrp)
+{
+    /* netCDF file format:
+     *  ...
+     * name       = nelems  namestring
+     * nelems     = NON_NEG
+     * namestring = ID1 [IDN ...] padding
+     * ID1        = alphanumeric | '_'
+     * IDN        = alphanumeric | special1 | special2
+     * padding    = <0, 1, 2, or 3 bytes to next 4-byte boundary>
+     * NON_NEG    = <non-negative INT> |  // CDF-1 and CDF-2
+     *              <non-negative INT64>  // CDF-5
+     */
+    int status;
+
+    /* copy nelems */
+    if (pbp->version == 5)
+        status = ncmpix_put_uint64((void**)(&pbp->pos), ncstrp->nchars);
+    else {
+        if (ncstrp->nchars != (uint)ncstrp->nchars) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)ncstrp->nchars);
+    }
+    if (status != NC_NOERR) return status;
+
+    /* copy namestring */
+    status = ncmpix_pad_putn_text(&pbp->pos, ncstrp->nchars, ncstrp->cp);
+    if (status != NC_NOERR) return status;
+
+    return NC_NOERR;
+}
+
+/*----< hdr_put_NC_attrV() >-------------------------------------------------*/
+/*
+ * Put the values of an attribute
+ */
+inline static int
+hdr_put_NC_attrV(bufferinfo    *pbp,
+                 const NC_attr *attrp)
+{
+    /* netCDF file format:
+     *  ...
+     * attr    = name  nc_type  nelems  [values ...]
+     *  ...
+     * values  = bytes | chars | shorts | ints | floats | doubles
+     * bytes   = [BYTE ...]  padding
+     * chars   = [CHAR ...]  padding
+     * shorts  = [SHORT ...]  padding
+     * ints    = [INT ...]
+     * floats  = [FLOAT ...]
+     * doubles = [DOUBLE ...]
+     * padding = <0, 1, 2, or 3 bytes to next 4-byte boundary>
+     */
+    MPI_Offset padding, sz;
+
+    /* ncmpix_len_nctype() returns the element size (unaligned) of attrp->type
+       attrp->xsz is the aligned total size of attribute values
+     */
+    sz = ncmpix_len_nctype(attrp->type);
+    sz *= attrp->nelems;
+    padding = attrp->xsz - sz;
+
+    if (sz != (size_t) sz) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    memcpy(pbp->pos, attrp->xvalue, (size_t)sz);
+    pbp->pos = (void *)((char *)pbp->pos + sz);
+
+    /* zero-padding is per buffer, not per element */
+    memset(pbp->pos, 0, (size_t)padding);
+    pbp->pos = (void *)((char *)pbp->pos + padding);
+
+    return NC_NOERR;
+}
+
+/*----< hdr_put_NC_dim() >---------------------------------------------------*/
+inline static int
+hdr_put_NC_dim(bufferinfo   *pbp,
+               const NC_dim *dimp)
+{
+    /* netCDF file format:
+     *  ...
+     * dim        = name  dim_length
+     * dim_length = NON_NEG
+     * NON_NEG    = <non-negative INT> |  // CDF-1 and CDF-2
+     *              <non-negative INT64>  // CDF-5
+     */
+    int status;
+
+    /* copy name */
+    status = hdr_put_NC_name(pbp, dimp->name);
+    if (status != NC_NOERR) return status;
+
+    /* copy dim_length */
+    if (pbp->version == 5)
+        status = ncmpix_put_uint64((void**)(&pbp->pos), dimp->size);
+    else {
+        /* TODO: Isn't checking dimension size already done in def_dim()? */
+        if (dimp->size != (uint)dimp->size) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)dimp->size);
+    }
+    if (status != NC_NOERR) return status;
+
+    return NC_NOERR;
+}
+
+/*----< hdr_put_NC_dimarray() >----------------------------------------------*/
+inline static int
+hdr_put_NC_dimarray(bufferinfo        *pbp,
+                    const NC_dimarray *ncap)
+{
+    /* netCDF file format:
+     *  ...
+     * dim_list     = ABSENT | NC_DIMENSION  nelems  [dim ...]
+     * ABSENT       = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *                ZERO  ZERO64  // for CDF-5
+     * ZERO         = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64       = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_DIMENSION = \x00 \x00 \x00 \x0A         // tag for list of dimensions
+     * nelems       = NON_NEG       // number of elements in following sequence
+     * NON_NEG      = <non-negative INT> |        // CDF-1 and CDF-2
+     *                <non-negative INT64>        // CDF-5
+     */
+    int i, status;
+
+    assert(pbp != NULL);
+
+    if (ncap == NULL || ncap->ndefined == 0) { /* ABSENT */
+        status = ncmpix_put_uint32((void**)(&pbp->pos), NC_UNSPECIFIED);
+        if (status != NC_NOERR) return status;
+
+        /* put a ZERO or ZERO64 depending on which CDF format */
+        if (pbp->version == 5)
+            status = ncmpix_put_uint64((void**)(&pbp->pos), 0);
+        else
+            status = ncmpix_put_uint32((void**)(&pbp->pos), 0);
+        if (status != NC_NOERR) return status;
+    }
+    else {
+        /* copy NC_DIMENSION */
+        status = ncmpix_put_uint32((void**)(&pbp->pos), NC_DIMENSION);
+        if (status != NC_NOERR) return status;
+
+        /* copy nelems */
+        if (pbp->version == 5)
+            status = ncmpix_put_uint64((void**)(&pbp->pos), ncap->ndefined);
+        else
+            status = ncmpix_put_uint32((void**)(&pbp->pos), ncap->ndefined);
+        if (status != NC_NOERR) return status;
+
+        /* copy [dim ...] */
+        for (i=0; i<ncap->ndefined; i++) {
+            status = hdr_put_NC_dim(pbp, ncap->value[i]);
+            if (status != NC_NOERR) return status;
+        }
+    }
+
+    return NC_NOERR;
+}
+
+/*----< hdr_put_NC_attr() >--------------------------------------------------*/
+inline static int
+hdr_put_NC_attr(bufferinfo    *pbp,
+                const NC_attr *attrp)
+{
+    /* netCDF file format:
+     *  ...
+     * attr    = name  nc_type  nelems  [values ...]
+     * nc_type = NC_BYTE | NC_CHAR | NC_SHORT | ...
+     * nelems  = NON_NEG       // number of elements in following sequence
+     * NON_NEG = <non-negative INT> |  // CDF-1 and CDF-2
+     *           <non-negative INT64>  // CDF-5
+     */
+    int status;
+
+    /* copy name */
+    status = hdr_put_NC_name(pbp, attrp->name);
+    if (status != NC_NOERR) return status;
+
+    /* copy nc_type */
+    status = ncmpix_put_uint32((void**)(&pbp->pos), attrp->type);
+    if (status != NC_NOERR) return status;
+
+    /* copy nelems */
+    if (pbp->version == 5)
+        status = ncmpix_put_uint64((void**)(&pbp->pos), attrp->nelems);
+    else {
+        if (attrp->nelems != (uint)attrp->nelems) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)attrp->nelems);
+    }
+    if (status != NC_NOERR) return status;
+
+    /* copy [values ...] */
+    status = hdr_put_NC_attrV(pbp, attrp);
+    if (status != NC_NOERR) return status;
+
+    return NC_NOERR;
+}
+
+/*----< hdr_put_NC_attrarray() >---------------------------------------------*/
+inline static int
+hdr_put_NC_attrarray(bufferinfo         *pbp,
+                     const NC_attrarray *ncap)
+{
+    /* netCDF file format:
+     *  ...
+     * att_list     = ABSENT | NC_ATTRIBUTE  nelems  [attr ...]
+     * ABSENT       = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *                ZERO  ZERO64  // for CDF-5
+     * ZERO         = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64       = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_ATTRIBUTE = \x00 \x00 \x00 \x0C         // tag for list of attributes
+     * nelems       = NON_NEG       // number of elements in following sequence
+     * NON_NEG      = <non-negative INT> |        // CDF-1 and CDF-2
+     *                <non-negative INT64>        // CDF-5
+     */
+    int i, status;
+
+    assert(pbp != NULL);
+
+    if (ncap == NULL || ncap->ndefined == 0) { /* ABSENT */
+        status = ncmpix_put_uint32((void**)(&pbp->pos), NC_UNSPECIFIED);
+        if (status != NC_NOERR) return status;
+
+        /* put a ZERO or ZERO64 depending on which CDF format */
+        if (pbp->version == 5)
+            status = ncmpix_put_uint64((void**)(&pbp->pos), 0);
+        else
+            status = ncmpix_put_uint32((void**)(&pbp->pos), 0);
+        if (status != NC_NOERR) return status;
+    }
+    else {
+        /* copy NC_ATTRIBUTE */
+        status = ncmpix_put_uint32((void**)(&pbp->pos), NC_ATTRIBUTE);
+        if (status != NC_NOERR) return status;
+
+        /* copy nelems */
+        if (pbp->version == 5)
+            status = ncmpix_put_uint64((void**)(&pbp->pos), ncap->ndefined);
+        else
+            status = ncmpix_put_uint32((void**)(&pbp->pos), ncap->ndefined);
+        if (status != NC_NOERR) return status;
+
+        /* copy [attr ...] */
+        for (i=0; i<ncap->ndefined; i++) {
+            status = hdr_put_NC_attr(pbp, ncap->value[i]);
+            if (status != NC_NOERR) return status;
+        }
+    }
+
+    return NC_NOERR;
+}
+
+/*----< hdr_put_NC_var() >---------------------------------------------------*/
+static int
+hdr_put_NC_var(bufferinfo   *pbp,
+               const NC_var *varp)
+{
+    /* netCDF file format:
+     * netcdf_file = header data
+     * header      = magic numrecs dim_list gatt_list var_list
+     *  ...
+     * var         = name nelems [dimid ...] vatt_list nc_type vsize begin
+     * nelems      = NON_NEG
+     * dimid       = NON_NEG
+     * vatt_list   = att_list
+     * nc_type     = NC_BYTE | NC_CHAR | NC_SHORT | ...
+     * vsize       = NON_NEG
+     * begin       = OFFSET        // Variable start location.
+     * OFFSET      = <non-negative INT> |  // CDF-1
+     *               <non-negative INT64>  // CDF-2 and CDF-5
+     * NON_NEG     = <non-negative INT> |  // CDF-1 and CDF-2
+     *               <non-negative INT64>  // CDF-5
+     */
+    int i, status;
+
+    /* copy name */
+    status = hdr_put_NC_name(pbp, varp->name);
+    if (status != NC_NOERR) return status;
+
+    /* copy nelems */
+    if (pbp->version == 5)
+        status = ncmpix_put_uint64((void**)(&pbp->pos), varp->ndims);
+    else
+        status = ncmpix_put_uint32((void**)(&pbp->pos), varp->ndims);
+    if (status != NC_NOERR) return status;
+
+    /* copy [dimid ...] */
+    for (i=0; i<varp->ndims; i++) {
+        if (pbp->version == 5)
+            status = ncmpix_put_uint64((void**)(&pbp->pos), varp->dimids[i]);
+        else
+            status = ncmpix_put_uint32((void**)(&pbp->pos), varp->dimids[i]);
+        if (status != NC_NOERR) return status;
+    }
+
+    /* copy vatt_list */
+    status = hdr_put_NC_attrarray(pbp, &varp->attrs);
+    if (status != NC_NOERR) return status;
+
+    /* copy nc_type */
+    status = ncmpix_put_uint32((void**)(&pbp->pos), varp->type);
+    if (status != NC_NOERR) return status;
+
+    /* copy vsize */
+    /* in CDF-1 and CDF-2, a variable's size in the header is a 32-bit integer
+     * in CDF-5, it is a 64-bit integer
+     */
+    if (pbp->version == 5)
+        status = ncmpix_put_uint64((void**)(&pbp->pos), varp->len);
+    else {
+        /* Special case, when there is no record variable, the last fixed-size
+         * variable can be larger than 2 GiB if its file starting offset is
+         * less than 2 GiB. This checking has already been done in the call
+         * to ncmpii_NC_check_vlens() in ncmpii_NC_enddef().
+         *
+         * if (varp->len != (int)varp->len) DEBUG_RETURN_ERROR(NC_EVARSIZE)
+         */
+        status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)varp->len);
+    }
+    if (status != NC_NOERR) return status;
+
+    /* copy begin */
+    /* in CDF-1 header, a variable's starting file offset is a 32-bit integer
+     * in CDF-2 and CDF-5, it is a 64-bit integer
+     */
+    if (pbp->version == 1) {
+        if (varp->begin != (uint)varp->begin) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        status = ncmpix_put_uint32((void**)(&pbp->pos), (uint)varp->begin);
+    }
+    else
+        status = ncmpix_put_uint64((void**)(&pbp->pos), varp->begin);
+    if (status != NC_NOERR) return status;
+
+    return NC_NOERR;
+}
+
+/*----< hdr_put_NC_vararray() >----------------------------------------------*/
+static int
+hdr_put_NC_vararray(bufferinfo        *pbp,
+                    const NC_vararray *ncap)
+{
+    /* netCDF file format:
+     * netcdf_file = header  data
+     * header      = magic  numrecs  dim_list  gatt_list  var_list
+     *  ...
+     * var_list    = ABSENT | NC_VARIABLE   nelems  [var ...]
+     * ABSENT      = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *               ZERO  ZERO64  // for CDF-5
+     * ZERO        = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64      = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_VARIABLE = \x00 \x00 \x00 \x0B         // tag for list of variables
+     * nelems      = NON_NEG       // number of elements in following sequence
+     * NON_NEG     = <non-negative INT> |        // CDF-1 and CDF-2
+     *               <non-negative INT64>        // CDF-5
+     */
+    int i, status;
+
+    assert(pbp != NULL);
+
+    if (ncap == NULL || ncap->ndefined == 0) { /* ABSENT */
+        status = ncmpix_put_uint32((void**)(&pbp->pos), NC_UNSPECIFIED);
+        if (status != NC_NOERR) return status;
+
+        /* put a ZERO or ZERO64 depending on which CDF format */
+        if (pbp->version == 5)
+            status = ncmpix_put_uint64((void**)(&pbp->pos), 0);
+        else
+            status = ncmpix_put_uint32((void**)(&pbp->pos), 0);
+        if (status != NC_NOERR) return status;
+    }
+    else {
+        /* copy NC_VARIABLE */
+        status = ncmpix_put_uint32((void**)(&pbp->pos), NC_VARIABLE);
+        if (status != NC_NOERR) return status;
+
+        /* copy nelems */
+        if (pbp->version == 5)
+            status = ncmpix_put_uint64((void**)(&pbp->pos), ncap->ndefined);
+        else
+            status = ncmpix_put_uint32((void**)(&pbp->pos), ncap->ndefined);
+        if (status != NC_NOERR) return status;
+
+        /* copy [var ...] */
+        for (i=0; i<ncap->ndefined; i++) {
+            status = hdr_put_NC_var(pbp, ncap->value[i]);
+            if (status != NC_NOERR) return status;
+        }
+    }
+
+    return NC_NOERR;
+}
+
+/*----< ncmpii_hdr_put_NC() >------------------------------------------------*/
+/* fill the file header into the I/O buffer, buf
+ * this function is collective */
+int
+ncmpii_hdr_put_NC(NC   *ncp,
+                  void *buf) {
+    int status;
+    bufferinfo putbuf;
+    MPI_Offset nrecs=0;
+
+    putbuf.nciop     = NULL;
+    putbuf.offset    = 0;
+    putbuf.pos       = buf;
+    putbuf.base      = buf;
+    putbuf.size      = ncp->xsz;
+    putbuf.put_size  = 0;
+    putbuf.get_size  = 0;
+    putbuf.safe_mode = ncp->safe_mode;
+
+    /* netCDF file format:
+     * netcdf_file  = header  data
+     * header       = magic  numrecs  dim_list  gatt_list  var_list
+     */
+
+    /* copy "magic", 4 characters */
+    if (ncp->flags & NC_64BIT_DATA) {
+        putbuf.version = 5;
+        status = ncmpix_putn_schar_schar(&putbuf.pos, sizeof(ncmagic5), ncmagic5);
+    }
+    else if (ncp->flags & NC_64BIT_OFFSET) {
+        putbuf.version = 2;
+        status = ncmpix_putn_schar_schar(&putbuf.pos, sizeof(ncmagic2), ncmagic2);
+    }
+    else {
+        putbuf.version = 1;
+        status = ncmpix_putn_schar_schar(&putbuf.pos, sizeof(ncmagic1), ncmagic1);
+    }
+    if (status != NC_NOERR) return status;
+
+    /* copy numrecs, number of records */
+    nrecs = ncp->numrecs;
+    if (ncp->flags & NC_64BIT_DATA)
+        status = ncmpix_put_uint64((void**)(&putbuf.pos), nrecs);
+    else {
+        if (nrecs != (uint)nrecs) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        status = ncmpix_put_uint32((void**)(&putbuf.pos), (uint)nrecs);
+    }
+    if (status != NC_NOERR) return status;
+
+    /* copy dim_list */
+    status = hdr_put_NC_dimarray(&putbuf, &ncp->dims);
+    if (status != NC_NOERR) return status;
+
+    /* copy gatt_list */
+    status = hdr_put_NC_attrarray(&putbuf, &ncp->attrs);
+    if (status != NC_NOERR) return status;
+
+    /* copy var_list */
+    status = hdr_put_NC_vararray(&putbuf, &ncp->vars);
+    if (status != NC_NOERR) return status;
+
+    ncp->nciop->put_size += putbuf.put_size;
+    ncp->nciop->get_size += putbuf.get_size;
+
+    return NC_NOERR;
+}
+
+/* End Of put NC */
+
+/* Begin Of get NC */
+
+/*
+ * Fetch the next header chunk.  the chunk is 'gbp->size' bytes big
+ * Takes care to not overwrite leftover (unused) data in the buffer before
+ * fetching a new chunk: the current approach is to re-read the extra data.
+ *
+ * NOTE: An alternate approach (which we do not do) would be to save the old
+ *       data, read the next chunk and then copy the old data into the new
+ *       chunk.  This alternate approach might help if it is important for reads
+ *       to be aligned.
+ */
+static int
+hdr_fetch(bufferinfo *gbp) {
+    int rank, err=NC_NOERR, mpireturn;
+    MPI_Offset slack;        /* any leftover data in the buffer */
+    MPI_Aint pos_addr, base_addr;
+
+    assert(gbp->base != NULL);
+
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(gbp->pos,  &pos_addr);
+    MPI_Get_address(gbp->base, &base_addr);
+#else
+    MPI_Address(gbp->pos,  &pos_addr);
+    MPI_Address(gbp->base, &base_addr);
+#endif
+    slack = gbp->size - (pos_addr - base_addr);
+    /* . if gbp->pos and gbp->base are the same, there is no leftover buffer
+     *   data to worry about.
+     * In the other extreme, where gbp->size == (gbp->pos - gbp->base), then
+     * all data in the buffer has been consumed */
+    if (slack == gbp->size) slack = 0;
+
+    if (gbp->size != (size_t)gbp->size) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    if (gbp->size != (int)gbp->size) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+
+    memset(gbp->base, 0, (size_t)gbp->size);
+    gbp->pos = gbp->base;
+    gbp->index = 0;
+
+    MPI_Comm_rank(gbp->nciop->comm, &rank);
+    if (rank == 0) {
+        MPI_Status mpistatus;
+        /* fileview is already entire file visible and MPI_File_read_at does
+           not change the file pointer */
+        TRACE_IO(MPI_File_read_at)(gbp->nciop->collective_fh,
+                                   (gbp->offset)-slack, gbp->base,
+                                   (int)gbp->size, MPI_BYTE, &mpistatus);
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_File_read_at");
+            if (err == NC_EFILE) DEBUG_ASSIGN_ERROR(err, NC_EREAD)
+        }
+        else {
+            int get_size;
+            MPI_Get_count(&mpistatus, MPI_BYTE, &get_size);
+            gbp->get_size += get_size;
+        }
+    }
+    /* we might have had to backtrack */
+    gbp->offset += (gbp->size - slack);
+
+    if (gbp->safe_mode == 1) {
+        TRACE_COMM(MPI_Bcast)(&err, 1, MPI_INT, 0, gbp->nciop->comm);
+        if (err != NC_NOERR) return err;
+    }
+
+    /* broadcast root's read to other processes */
+    TRACE_COMM(MPI_Bcast)(gbp->base, (int)gbp->size, MPI_BYTE, 0, gbp->nciop->comm);
+
+    return err;
+}
+
+/*----< hdr_check_buffer() >--------------------------------------------------*/
+/* Ensure that 'nextread' bytes are available.  */
+inline static int
+hdr_check_buffer(bufferinfo *gbp,
+                 MPI_Offset  nextread)
+{
+    MPI_Aint pos_addr, base_addr;
+
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(gbp->pos,  &pos_addr);
+    MPI_Get_address(gbp->base, &base_addr);
+#else
+    MPI_Address(gbp->pos,  &pos_addr);
+    MPI_Address(gbp->base, &base_addr);
+#endif
+    if (pos_addr + nextread <= base_addr + gbp->size)
+        return NC_NOERR;
+
+    return hdr_fetch(gbp);
+}
+
+/*----< hdr_get_NCtype() >----------------------------------------------------*/
+inline static int
+hdr_get_NCtype(bufferinfo *gbp,
+               NCtype     *typep)
+{
+    /* NCtype is 4-byte integer */
+    uint type = 0;
+    int status = hdr_check_buffer(gbp, 4);
+    if (status != NC_NOERR) return status;
+
+    /* get an external unsigned 4-byte integer from the file */
+    status = ncmpix_get_uint32((const void**)(&gbp->pos), &type);
+    gbp->index += X_SIZEOF_INT;
+    if (status != NC_NOERR) return status;
+
+    *typep = (NCtype) type;
+    return NC_NOERR;
+}
+
+/*----< hdr_get_uint32() >---------------------------------------------------*/
+inline static int
+hdr_get_uint32(bufferinfo *gbp,
+               uint        *xp)
+{
+    /* in CDF-1 format, all integers are 32-bit
+     * in CDF-2 format, only variable begin (starting file offset) is 64-bit
+     * in CDF-5 format, both variable's begin and size are 64-bit
+     */
+    int status = hdr_check_buffer(gbp, 4); /* size of int32 == 4 */
+    if (status != NC_NOERR) return status;
+    gbp->index += 4;
+
+    status = ncmpix_get_uint32((const void **)(&gbp->pos), xp);
+    return status;
+}
+
+/*----< hdr_get_uint64() >---------------------------------------------------*/
+inline static int
+hdr_get_uint64(bufferinfo *gbp,
+               uint64     *xp)
+{
+    /* in CDF-1 format, all integers are 32-bit
+     * in CDF-2 format, only variable begin (starting file offset) is 64-bit
+     * in CDF-5 format, both variable's begin and size are 64-bit
+     */
+    int status = hdr_check_buffer(gbp, 8); /* size of int64 == 8 */
+    if (status != NC_NOERR) return status;
+    gbp->index += 8;
+
+    status = ncmpix_get_uint64((const void **)(&gbp->pos), xp);
+    return status;
+}
+
+/*----< hdr_get_nc_type() >---------------------------------------------------*/
+inline static int
+hdr_get_nc_type(bufferinfo *gbp,
+                nc_type    *typep)
+{
+    /* nc_type is 4-byte integer, X_SIZEOF_INT */
+    int status;
+    uint type;
+
+    status = hdr_check_buffer(gbp, X_SIZEOF_INT);
+    if (status != NC_NOERR) return status;
+
+    status = ncmpix_get_uint32((const void**)(&gbp->pos), &type);
+    gbp->index += X_SIZEOF_INT;
+    if (status != NC_NOERR) return status;
+
+    if (type != NC_BYTE    &&
+        type != NC_CHAR    &&
+        type != NC_UBYTE   &&
+        type != NC_SHORT   &&
+        type != NC_USHORT  &&
+        type != NC_INT     &&
+        type != NC_UINT    &&
+        type != NC_FLOAT   &&
+        type != NC_DOUBLE  &&
+        type != NC_INT64   &&
+        type != NC_UINT64
+       )
+        DEBUG_RETURN_ERROR(NC_EINVAL)
+
+    *typep = (nc_type) type;
+    return NC_NOERR;
+}
+
+/*----< ncmpix_len_nctype() >------------------------------------------------*/
+int
+ncmpix_len_nctype(nc_type type) {
+    switch(type) {
+        case NC_BYTE:
+        case NC_CHAR:
+        case NC_UBYTE:  return X_SIZEOF_CHAR;
+        case NC_SHORT:
+        case NC_USHORT: return X_SIZEOF_SHORT;
+        case NC_INT:
+        case NC_UINT:   return X_SIZEOF_INT;
+        case NC_FLOAT:  return X_SIZEOF_FLOAT;
+        case NC_DOUBLE: return X_SIZEOF_DOUBLE;
+        case NC_INT64:
+        case NC_UINT64: return X_SIZEOF_INT64;
+        default: assert("ncmpix_len_nctype bad type" == 0);
+    }
+    return 0;
+}
+
+/*----< hdr_get_NC_name() >---------------------------------------------------*/
+static int
+hdr_get_NC_name(bufferinfo  *gbp,
+                NC_string  **ncstrpp)
+{
+    /* netCDF file format:
+     *  ...
+     * name       = nelems  namestring
+     * nelems     = NON_NEG
+     * namestring = ID1 [IDN ...] padding
+     * ID1        = alphanumeric | '_'
+     * IDN        = alphanumeric | special1 | special2
+     * padding    = <0, 1, 2, or 3 bytes to next 4-byte boundary>
+     * NON_NEG    = <non-negative INT> |  // CDF-1 and CDF-2
+     *              <non-negative INT64>  // CDF-5
+     */
+    int status;
+    MPI_Offset  nchars, nbytes, padding, bufremain, strcount;
+    NC_string *ncstrp;
+    char *cpos, pad[X_ALIGN-1];
+    MPI_Aint pos_addr, base_addr;
+
+    /* get nelems */
+    if (gbp->version == 5) {
+        uint64 tmp;
+        status = hdr_get_uint64(gbp, &tmp);
+        nchars = (MPI_Offset)tmp;
+    }
+    else {
+        uint tmp;
+        status = hdr_get_uint32(gbp, &tmp);
+        nchars = (MPI_Offset)tmp;
+    }
+    if (status != NC_NOERR) return status;
+
+    /* Allocate a NC_string structure large enough to hold nchars characters */
+    ncstrp = ncmpii_new_NC_string((size_t)nchars, NULL);
+    if (ncstrp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    nbytes = nchars * X_SIZEOF_CHAR;
+    padding = _RNDUP(X_SIZEOF_CHAR * ncstrp->nchars, X_ALIGN)
+            - X_SIZEOF_CHAR * ncstrp->nchars;
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(gbp->pos,  &pos_addr);
+    MPI_Get_address(gbp->base, &base_addr);
+#else
+    MPI_Address(gbp->pos,  &pos_addr);
+    MPI_Address(gbp->base, &base_addr);
+#endif
+    bufremain = gbp->size - (pos_addr - base_addr);
+    cpos = ncstrp->cp;
+
+    /* get namestring with padding */
+    while (nbytes > 0) {
+        if (bufremain > 0) {
+            strcount = MIN(bufremain, nbytes);
+            if (strcount != (size_t)strcount) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+            memcpy(cpos, gbp->pos, (size_t)strcount);
+            nbytes -= strcount;
+            gbp->pos = (void *)((char *)gbp->pos + strcount);
+            gbp->index += strcount;
+            cpos += strcount;
+            bufremain -= strcount;
+        } else {
+            status = hdr_fetch(gbp);
+            if (status != NC_NOERR) {
+                ncmpii_free_NC_string(ncstrp);
+                return status;
+            }
+            bufremain = gbp->size;
+        }
+    }
+
+    /* handle the padding */
+    if (padding > 0) {
+        memset(pad, 0, X_ALIGN-1);
+        if (memcmp(gbp->pos, pad, (size_t)padding) != 0) {
+            ncmpii_free_NC_string(ncstrp);
+            DEBUG_RETURN_ERROR(NC_EINVAL)
+        }
+        gbp->pos = (void *)((char *)gbp->pos + padding);
+        gbp->index += padding;
+    }
+
+    *ncstrpp = ncstrp;
+
+    return NC_NOERR;
+}
+
+/*----< hdr_get_NC_dim() >----------------------------------------------------*/
+inline static int
+hdr_get_NC_dim(bufferinfo  *gbp,
+               NC_dim     **dimpp)
+{
+    /* netCDF file format:
+     *  ...
+     * dim        = name  dim_length
+     * dim_length = NON_NEG
+     * NON_NEG    = <non-negative INT> |  // CDF-1 and CDF-2
+     *              <non-negative INT64>  // CDF-5
+     */
+    int status;
+    NC_string *ncstrp;
+    NC_dim *dimp;
+
+    /* get name */
+    status = hdr_get_NC_name(gbp, &ncstrp);
+    if (status != NC_NOERR) return status;
+
+    dimp = ncmpii_new_x_NC_dim(ncstrp);
+    if (dimp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    /* get dim_length */
+    if (gbp->version == 5) {
+        uint64 tmp;
+        status = hdr_get_uint64(gbp, &tmp);
+        dimp->size = (MPI_Offset)tmp;
+    }
+    else {
+        uint tmp;
+        status = hdr_get_uint32(gbp, &tmp);
+        dimp->size = (MPI_Offset)tmp;
+    }
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_dim(dimp); /* frees name */
+        return status;
+    }
+
+    *dimpp = dimp;
+    return NC_NOERR;
+}
+
+/*----< hdr_get_NC_dimarray() >-----------------------------------------------*/
+static int
+hdr_get_NC_dimarray(bufferinfo  *gbp,
+                    NC_dimarray *ncap)
+{
+    /* netCDF file format:
+     *  ...
+     * dim_list     = ABSENT | NC_DIMENSION  nelems  [dim ...]
+     * ABSENT       = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *                ZERO  ZERO64  // for CDF-5
+     * ZERO         = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64       = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_DIMENSION = \x00 \x00 \x00 \x0A         // tag for list of dimensions
+     * nelems       = NON_NEG       // number of elements in following sequence
+     * NON_NEG      = <non-negative INT> |        // CDF-1 and CDF-2
+     *                <non-negative INT64>        // CDF-5
+     */
+    int i, status;
+    NCtype type = NC_UNSPECIFIED;
+    MPI_Offset ndefined;
+
+    assert(gbp != NULL && gbp->pos != NULL);
+    assert(ncap != NULL);
+    assert(ncap->value == NULL);
+
+    /* get NCtype (NC_DIMENSION) */
+    status = hdr_get_NCtype(gbp, &type);
+    if (status != NC_NOERR) return status;
+
+    /* get nelems */
+    if (gbp->version == 5) {
+        uint64 tmp;
+        status = hdr_get_uint64(gbp, &tmp);
+        ndefined = (MPI_Offset)tmp;
+    }
+    else {
+        uint tmp;
+        status = hdr_get_uint32(gbp, &tmp);
+        ndefined = (MPI_Offset)tmp;
+    }
+    if (status != NC_NOERR) return status;
+    if (ndefined != (int)ndefined) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    ncap->ndefined = (int)ndefined;
+    /* TODO: we should allow ndefined > 2^32, considering change the data type
+     * of ndefined from int to MPI_Offset */
+
+    if (ndefined == 0) {
+        if (type != NC_DIMENSION && type != NC_UNSPECIFIED)
+            DEBUG_RETURN_ERROR(NC_EINVAL)
+    } else {
+        if (type != NC_DIMENSION) DEBUG_RETURN_ERROR(NC_EINVAL)
+
+        ncap->value = (NC_dim **) NCI_Malloc((size_t)ndefined * sizeof(NC_dim*));
+        if (ncap->value == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+        ncap->nalloc = (int)ndefined;
+        /* TODO: we should allow nalloc > 2^32, considering change the data
+         * type of nalloc from int to MPI_Offset */
+
+        for (i=0; i<ndefined; i++) {
+            status = hdr_get_NC_dim(gbp, ncap->value + i);
+            if (status != NC_NOERR) { /* error: fail to get the next dim */
+                ncap->ndefined = i;
+                ncmpii_free_NC_dimarray(ncap);
+                return status;
+            }
+        }
+    }
+
+    return NC_NOERR;
+}
+
+/*----< hdr_get_NC_attrV() >--------------------------------------------------*/
+static int
+hdr_get_NC_attrV(bufferinfo *gbp,
+                 NC_attr    *attrp)
+{
+    /* netCDF file format:
+     *  ...
+     * attr    = name  nc_type  nelems  [values ...]
+     *  ...
+     * values  = bytes | chars | shorts | ints | floats | doubles
+     * bytes   = [BYTE ...]  padding
+     * chars   = [CHAR ...]  padding
+     * shorts  = [SHORT ...]  padding
+     * ints    = [INT ...]
+     * floats  = [FLOAT ...]
+     * doubles = [DOUBLE ...]
+     * padding = <0, 1, 2, or 3 bytes to next 4-byte boundary>
+     */
+    int status;
+    void *value = attrp->xvalue;
+    char pad[X_ALIGN-1];
+    MPI_Offset nbytes, padding, bufremain, attcount;
+    MPI_Aint pos_addr, base_addr;
+
+    nbytes = attrp->nelems * ncmpix_len_nctype(attrp->type);
+    padding = attrp->xsz - nbytes;
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(gbp->pos,  &pos_addr);
+    MPI_Get_address(gbp->base, &base_addr);
+#else
+    MPI_Address(gbp->pos,  &pos_addr);
+    MPI_Address(gbp->base, &base_addr);
+#endif
+    bufremain = gbp->size - (pos_addr - base_addr);
+
+    /* get values */
+    while (nbytes > 0) {
+        if (bufremain > 0) {
+            attcount = MIN(bufremain, nbytes);
+            if (attcount != (size_t)attcount) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+            memcpy(value, gbp->pos, (size_t)attcount);
+            nbytes -= attcount;
+            gbp->pos = (void *)((char *)gbp->pos + attcount);
+            gbp->index += attcount;
+            value = (void *)((char *)value + attcount);
+            bufremain -= attcount;
+        } else {
+            status = hdr_fetch(gbp);
+            if (status != NC_NOERR) return status;
+            bufremain = gbp->size;
+        }
+    }
+
+    /* handle the padding */
+    if (padding > 0) {
+        memset(pad, 0, X_ALIGN-1);
+        if (memcmp(gbp->pos, pad, (size_t)padding) != 0) DEBUG_RETURN_ERROR(NC_EINVAL)
+        gbp->pos = (void *)((char *)gbp->pos + padding);
+        gbp->index += padding;
+    }
+
+    return NC_NOERR;
+}
+
+/*----< hdr_get_NC_attr() >---------------------------------------------------*/
+static int
+hdr_get_NC_attr(bufferinfo  *gbp,
+                NC_attr    **attrpp)
+{
+    /* netCDF file format:
+     *  ...
+     * attr    = name  nc_type  nelems  [values ...]
+     * nc_type = NC_BYTE | NC_CHAR | NC_SHORT | ...
+     * nelems  = NON_NEG       // number of elements in following sequence
+     * NON_NEG = <non-negative INT> |  // CDF-1 and CDF-2
+     *           <non-negative INT64>  // CDF-5
+     */
+    int status;
+    NC_string *strp;
+    nc_type type;
+    MPI_Offset nelems;
+    NC_attr *attrp;
+
+    /* get name */
+    status = hdr_get_NC_name(gbp, &strp);
+    if (status != NC_NOERR) return status;
+
+    /* get nc_type */
+    status = hdr_get_nc_type(gbp, &type);
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_string(strp);
+        return status;
+    }
+
+    /* get nelems */
+    if (gbp->version == 5) {
+        uint64 tmp;
+        status = hdr_get_uint64(gbp, &tmp);
+        nelems = (MPI_Offset)tmp;
+    }
+    else {
+        uint tmp;
+        status = hdr_get_uint32(gbp, &tmp);
+        nelems = (MPI_Offset)tmp;
+    }
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_string(strp);
+        return status;
+    }
+
+    /* allocate space for attribute object */
+    attrp = ncmpii_new_x_NC_attr(strp, type, nelems);
+    if (attrp == NULL) {
+        ncmpii_free_NC_string(strp);
+        return status;
+    }
+
+    /* get [values ...] */
+    status = hdr_get_NC_attrV(gbp, attrp);
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_attr(attrp); /* frees strp */
+        return status;
+    }
+
+    *attrpp = attrp;
+    return NC_NOERR;
+}
+
+/*----< hdr_get_NC_attrarray() >----------------------------------------------*/
+static int
+hdr_get_NC_attrarray(bufferinfo   *gbp,
+                     NC_attrarray *ncap)
+{
+    /* netCDF file format:
+     *  ...
+     * att_list     = ABSENT | NC_ATTRIBUTE  nelems  [attr ...]
+     * ABSENT       = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *                ZERO  ZERO64  // for CDF-5
+     * ZERO         = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64       = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_ATTRIBUTE = \x00 \x00 \x00 \x0C         // tag for list of attributes
+     * nelems       = NON_NEG       // number of elements in following sequence
+     * NON_NEG      = <non-negative INT> |        // CDF-1 and CDF-2
+     *                <non-negative INT64>        // CDF-5
+     */
+    int i, status;
+    NCtype type = NC_UNSPECIFIED;
+    MPI_Offset ndefined;
+
+    assert(gbp != NULL && gbp->pos != NULL);
+    assert(ncap != NULL);
+    assert(ncap->value == NULL);
+
+    /* get NCtype (NC_ATTRIBUTE) */
+    status = hdr_get_NCtype(gbp, &type);
+    if (status != NC_NOERR) return status;
+
+    /* get nelems */
+    if (gbp->version == 5) {
+        uint64 tmp;
+        status = hdr_get_uint64(gbp, &tmp);
+        ndefined = (MPI_Offset)tmp;
+    }
+    else {
+        uint tmp;
+        status = hdr_get_uint32(gbp, &tmp);
+        ndefined = (MPI_Offset)tmp;
+    }
+    if (status != NC_NOERR) return status;
+    if (ndefined != (int)ndefined) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    ncap->ndefined = (int)ndefined;
+
+    if (ndefined == 0) {
+        if (type != NC_ATTRIBUTE && type != NC_UNSPECIFIED)
+            DEBUG_RETURN_ERROR(NC_EINVAL)
+    } else {
+        if (type != NC_ATTRIBUTE) DEBUG_RETURN_ERROR(NC_EINVAL)
+
+        ncap->value = (NC_attr **)NCI_Malloc((size_t)ndefined * sizeof(NC_attr*));
+        if (ncap->value == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+        ncap->nalloc = (int)ndefined;
+
+        /* get [attr ...] */
+        for (i=0; i<ndefined; i++) {
+            status = hdr_get_NC_attr(gbp, ncap->value + i);
+            if (status != NC_NOERR) { /* Error: fail to get the next att */
+                ncap->ndefined = i;
+                ncmpii_free_NC_attrarray(ncap);
+                return status;
+            }
+        }
+    }
+
+    return NC_NOERR;
+}
+
+/*----< hdr_get_NC_var() >---------------------------------------------------*/
+static int
+hdr_get_NC_var(bufferinfo  *gbp,
+               NC_var     **varpp)
+{
+    /* netCDF file format:
+     * netcdf_file = header data
+     * header      = magic numrecs dim_list gatt_list var_list
+     *  ...
+     * var         = name nelems [dimid ...] vatt_list nc_type vsize begin
+     * nelems      = NON_NEG
+     * dimid       = NON_NEG
+     * vatt_list   = att_list
+     * nc_type     = NC_BYTE | NC_CHAR | NC_SHORT | ...
+     * vsize       = NON_NEG
+     * begin       = OFFSET        // Variable start location.
+     * OFFSET      = <non-negative INT> |  // CDF-1
+     *               <non-negative INT64>  // CDF-2 and CDF-5
+     * NON_NEG     = <non-negative INT> |  // CDF-1 and CDF-2
+     *               <non-negative INT64>  // CDF-5
+     */
+    int status;
+    NC_string *strp;
+    MPI_Offset ndims=0, dim;
+    MPI_Offset tmp_dimids=0;
+    NC_var *varp;
+
+    /* get name */
+    status = hdr_get_NC_name(gbp, &strp);
+    if (status != NC_NOERR) return status;
+
+    /* nelems */
+    if (gbp->version == 5) {
+        uint64 tmp;
+        status = hdr_get_uint64(gbp, &tmp);
+        ndims = (MPI_Offset)tmp;
+    }
+    else {
+        uint tmp;
+        status = hdr_get_uint32(gbp, &tmp);
+        ndims = (MPI_Offset)tmp;
+    }
+    if (status != NC_NOERR) {
+         ncmpii_free_NC_string(strp);
+         return status;
+    }
+    if (ndims != (int)ndims) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+
+    /* allocate space for var object */
+    varp = ncmpii_new_x_NC_var(strp, (int)ndims);
+    if (varp == NULL) {
+        ncmpii_free_NC_string(strp);
+        DEBUG_RETURN_ERROR(NC_ENOMEM)
+    }
+
+    /* get [dimid ...] */
+    for (dim=0; dim<ndims; dim++) {
+        status = hdr_check_buffer(gbp, (gbp->version == 5 ? 8 : 4));
+        if (status != NC_NOERR) {
+            ncmpii_free_NC_var(varp);
+            return status;
+        }
+        if (gbp->version == 5) {
+            uint64 tmp;
+            status = hdr_get_uint64(gbp, &tmp);
+            tmp_dimids = (MPI_Offset)tmp;
+        }
+        else {
+            uint tmp;
+            status = hdr_get_uint32(gbp, &tmp);
+            tmp_dimids = (MPI_Offset)tmp;
+        }
+        /* TODO: consider change the data type of dimids from int to
+         * MPI_Offset */
+        varp->dimids[dim] = (int)tmp_dimids;
+        if (status != NC_NOERR) {
+           return status;
+        }
+    }
+
+    /* get vatt_list */
+    status = hdr_get_NC_attrarray(gbp, &varp->attrs);
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_var(varp);
+        return status;
+    }
+
+    /* get nc_type */
+    status = hdr_get_nc_type(gbp, &varp->type);
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_var(varp);
+        return status;
+    }
+
+    /* get vsize */
+    if (gbp->version == 5) {
+        uint64 tmp;
+        status = hdr_get_uint64(gbp, &tmp);
+        varp->len = (MPI_Offset)tmp;
+    }
+    else {
+        uint tmp;
+        status = hdr_get_uint32(gbp, &tmp);
+        varp->len = (MPI_Offset)tmp;
+    }
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_var(varp);
+        return status;
+    }
+    /* As described in CDF-2 format specification, vsize is redundant.
+       Its value may be computed from the product of dimension lengths.
+       In CDF-2, vsize is a 4-byte integer. So, if we define a variable of
+       less than 2^32 elements but size > 2^32-4 bytes, then vsize in CDF-2
+       will overflow. Recompute varp->len can ignore an overflowed value in
+       vsize stored in the file and hence bypass the limitation of CDF-2 on
+       variable size of 2^32-4 bytes.
+
+       Later on, back to ncmpii_hdr_get_NC(), ncmpii_NC_computeshapes() is
+       called which recomputes varp->len using the dimension values and hence
+       overwrites the value read from file above.
+
+       In summary, PnetCDF now ignores the value of vsize stored in the file
+       header.
+     */
+
+    /* next element is 'begin' */
+    status = hdr_check_buffer(gbp, (gbp->version == 1 ? 4 : 8));
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_var(varp);
+        return status;
+    }
+
+    /* get begin */
+    if (gbp->version == 1) {
+        uint tmp=0;
+        status = ncmpix_get_uint32((const void **)(&gbp->pos), &tmp);
+        varp->begin = (MPI_Offset)tmp;
+    }
+    else {
+        uint64 tmp=0;
+        status = ncmpix_get_uint64((const void **)(&gbp->pos), &tmp);
+        varp->begin = (MPI_Offset)tmp;
+    }
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_var(varp);
+        return status;
+    }
+
+    *varpp = varp;
+    return NC_NOERR;
+}
+
+/*----< hdr_get_NC_vararray() >----------------------------------------------*/
+static int
+hdr_get_NC_vararray(bufferinfo  *gbp,
+                    NC_vararray *ncap)
+{
+    /* netCDF file format:
+     * netcdf_file = header  data
+     * header      = magic  numrecs  dim_list  gatt_list  var_list
+     *  ...
+     * var_list    = ABSENT | NC_VARIABLE   nelems  [var ...]
+     * ABSENT      = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *               ZERO  ZERO64  // for CDF-5
+     * ZERO        = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64      = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_VARIABLE = \x00 \x00 \x00 \x0B         // tag for list of variables
+     * nelems      = NON_NEG       // number of elements in following sequence
+     * NON_NEG     = <non-negative INT> |        // CDF-1 and CDF-2
+     *               <non-negative INT64>        // CDF-5
+     */
+    int i, status;
+    NCtype type = NC_UNSPECIFIED;
+    MPI_Offset ndefined;
+
+    assert(gbp != NULL && gbp->pos != NULL);
+    assert(ncap != NULL);
+    assert(ncap->value == NULL);
+
+    /* get NCtype (NC_VARIABLE) from gbp buffer */
+    status = hdr_get_NCtype(gbp, &type);
+    if (status != NC_NOERR) return status;
+
+    /* get nelems (number of variables) from gbp buffer */
+    if (gbp->version == 5) {
+        uint64 tmp;
+        status = hdr_get_uint64(gbp, &tmp);
+        ndefined = (MPI_Offset)tmp;
+    }
+    else {
+        uint tmp;
+        status = hdr_get_uint32(gbp, &tmp);
+        ndefined = (MPI_Offset)tmp;
+    }
+    if (status != NC_NOERR) return status;
+    if (ndefined != (int)ndefined) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    ncap->ndefined = (int)ndefined;
+    /* TODO: we should allow ndefined > 2^32, considering change the data type
+     * of ndefined from int to MPI_Offset */
+
+    if (ndefined == 0) { /* no variable defined */
+        if (type != NC_VARIABLE && type != NC_UNSPECIFIED)
+            DEBUG_RETURN_ERROR(NC_EINVAL)
+    } else {
+        if (type != NC_VARIABLE) DEBUG_RETURN_ERROR(NC_EINVAL)
+
+        ncap->value = (NC_var **) NCI_Malloc((size_t)ndefined * sizeof(NC_var*));
+        if (ncap->value == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+        ncap->nalloc = (int)ndefined;
+
+        /* get [var ...] */
+        for (i=0; i<ndefined; i++) {
+            status = hdr_get_NC_var(gbp, ncap->value + i);
+            if (status != NC_NOERR) { /* Error: fail to get the next var */
+                ncap->ndefined = i;
+                ncmpii_free_NC_vararray(ncap);
+                return status;
+            }
+        }
+    }
+
+    return NC_NOERR;
+}
+
+/*----< ncmpii_hdr_get_NC() >------------------------------------------------*/
+/*  CDF format specification
+ *      netcdf_file  = header  data
+ *      header       = magic  numrecs  dim_list  gatt_list  var_list
+ *      magic        = 'C'  'D'  'F'  VERSION
+ *      VERSION      = \x01 |                      // classic format
+ *                     \x02 |                      // 64-bit offset format
+ *                     \x05                        // 64-bit data format
+ *      numrecs      = NON_NEG | STREAMING         // length of record dimension
+ *      dim_list     = ABSENT | NC_DIMENSION  nelems  [dim ...]
+ *      gatt_list    = att_list                    // global attributes
+ *      att_list     = ABSENT | NC_ATTRIBUTE  nelems  [attr ...]
+ *      var_list     = ABSENT | NC_VARIABLE   nelems  [var ...]
+ */
+int
+ncmpii_hdr_get_NC(NC *ncp)
+{
+    int status;
+    bufferinfo getbuf;
+    schar magic[sizeof(ncmagic1)];
+    MPI_Offset nrecs = 0;
+    MPI_Aint pos_addr, base_addr;
+
+    assert(ncp != NULL);
+
+    /* Initialize the get buffer that stores the header read from the file */
+    getbuf.nciop     = ncp->nciop;
+    getbuf.offset    = 0;   /* read from start of the file */
+    getbuf.put_size  = 0;   /* amount of writes so far in bytes */
+    getbuf.get_size  = 0;   /* amount of reads  so far in bytes */
+    getbuf.safe_mode = ncp->safe_mode;
+
+    /* CDF-5's minimum header size is 4 bytes more than CDF-1 and CDF-2's */
+    getbuf.size = _RNDUP( MAX(MIN_NC_XSZ+4, ncp->chunk), X_ALIGN );
+    if (getbuf.size > NC_DEFAULT_CHUNKSIZE)
+        getbuf.size = NC_DEFAULT_CHUNKSIZE;
+
+    if (getbuf.size != (size_t)getbuf.size) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    getbuf.pos = getbuf.base = (void *)NCI_Malloc((size_t)getbuf.size);
+    getbuf.index = 0;
+
+    /* Fetch the next header chunk. The chunk is 'gbp->size' bytes big */
+    status = hdr_fetch(&getbuf);
+    if (status != NC_NOERR) return status;
+
+    /* processing the header from getbuf, the get buffer */
+
+    /* First get the file format information, magic */
+    memset(magic, 0, sizeof(magic));
+    status = ncmpix_getn_schar_schar((const void **)(&getbuf.pos),
+                                     sizeof(magic), magic);
+    if (status != NC_NOERR) return status;
+    getbuf.index += (MPI_Offset)sizeof(magic);
+
+    /* don't need to worry about CDF-1 or CDF-2
+     * if the first bits are not 'CDF'
+     */
+    if (memcmp(magic, ncmagic1, sizeof(ncmagic1)-1) != 0) {
+        NCI_Free(getbuf.base);
+        DEBUG_RETURN_ERROR(NC_ENOTNC)
+    }
+
+    /* check version number in last byte of magic */
+    if (magic[sizeof(ncmagic1)-1] == 0x1) {
+        getbuf.version = 1;
+        fSet(ncp->flags, NC_32BIT);
+    } else if (magic[sizeof(ncmagic1)-1] == 0x2) {
+        getbuf.version = 2;
+        fSet(ncp->flags, NC_64BIT_OFFSET);
+        if (SIZEOF_MPI_OFFSET != 8) {
+            /* take the easy way out: if we can't support all CDF-2
+             * files, return immediately */
+            NCI_Free(getbuf.base);
+            DEBUG_RETURN_ERROR(NC_ESMALL)
+        }
+    } else if (magic[sizeof(ncmagic1)-1] == 0x5) {
+        getbuf.version = 5;
+        fSet(ncp->flags, NC_64BIT_DATA);
+        if (SIZEOF_MPI_OFFSET != 8) {
+            NCI_Free(getbuf.base);
+            DEBUG_RETURN_ERROR(NC_ESMALL)
+        }
+    } else {
+        NCI_Free(getbuf.base);
+        DEBUG_RETURN_ERROR(NC_ENOTNC) /* not an netCDF file */
+    }
+
+    /** Ensure that 'nextread' bytes (numrecs) are available. */
+    status = hdr_check_buffer(&getbuf, (getbuf.version == 5) ? 8 : 4);
+    if(status != NC_NOERR) {
+        NCI_Free(getbuf.base);
+        return status;
+    }
+
+    /* get numrecs from getbuf into ncp */
+    if (getbuf.version == 5) {
+        uint64 tmp=0;
+        status = ncmpix_get_uint64((const void **)(&getbuf.pos), &tmp);
+        nrecs = (MPI_Offset)tmp;
+    }
+    else {
+        uint tmp=0;
+        status = ncmpix_get_uint32((const void **)(&getbuf.pos), &tmp);
+        nrecs = (MPI_Offset)tmp;
+    }
+    if (status != NC_NOERR) {
+        NCI_Free(getbuf.base);
+        return status;
+    }
+
+    if (getbuf.version == 5)
+        getbuf.index += X_SIZEOF_INT64;
+    else
+        getbuf.index += X_SIZEOF_SIZE_T;
+
+    ncp->numrecs = nrecs;
+
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(getbuf.pos,  &pos_addr);
+    MPI_Get_address(getbuf.base, &base_addr);
+#else
+    MPI_Address(getbuf.pos,  &pos_addr);
+    MPI_Address(getbuf.base, &base_addr);
+#endif
+    assert(pos_addr < base_addr + getbuf.size);
+
+    /* get dim_list from getbuf into ncp */
+    status = hdr_get_NC_dimarray(&getbuf, &ncp->dims);
+    if (status != NC_NOERR) {
+        NCI_Free(getbuf.base);
+        return status;
+    }
+
+    /* get gatt_list from getbuf into ncp */
+    status = hdr_get_NC_attrarray(&getbuf, &ncp->attrs);
+    if (status != NC_NOERR) {
+        NCI_Free(getbuf.base);
+        return status;
+    }
+
+    /* get var_list from getbuf into ncp */
+    status = hdr_get_NC_vararray(&getbuf, &ncp->vars);
+    if (status != NC_NOERR) {
+        NCI_Free(getbuf.base);
+        return status;
+    }
+
+    /* get the un-aligned size occupied by the file header */
+    ncp->xsz = ncmpii_hdr_len_NC(ncp);
+
+    /* Recompute the shapes of all variables
+     * Sets ncp->begin_var to start of first variable.
+     * Sets ncp->begin_rec to start of first record variable.
+     */
+    status = ncmpii_NC_computeshapes(ncp);
+
+    NCI_Free(getbuf.base);
+
+    ncp->nciop->put_size += getbuf.put_size;
+    ncp->nciop->get_size += getbuf.get_size;
+
+    return status;
+}
+
+/* End Of get NC */
+
+#define WARN_STR "Warning (inconsistent metadata):"
+
+/*----< ncmpii_comp_dims() >--------------------------------------------------*/
+/* compare the local copy of dim_list against root's
+ * If inconsistency is detected, overwrite local's with root's
+ * this function is collective.
+ */
+static int
+ncmpii_comp_dims(int          safe_mode,
+                 NC_dimarray *root_dim,
+                 NC_dimarray *local_dim)
+{
+    int i, err, status=NC_NOERR;
+
+    if (root_dim->ndefined != local_dim->ndefined) {
+        if (safe_mode)
+            printf("%s number of dimensions (local=%d, root=%d)\n",
+                   WARN_STR, local_dim->ndefined, root_dim->ndefined);
+        DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_DIM_NUM)
+    }
+
+    for (i=0; i<root_dim->ndefined; i++) {
+
+        if (i >= local_dim->ndefined) { /* if local list is shorter */
+            /* copy root's dim to local */
+            NC_dim *new_dim = dup_NC_dim(root_dim->value[i]);
+            err = incr_NC_dimarray(local_dim, new_dim);
+            if (err != NC_NOERR) return err; /* this is a fatal error */
+            continue;
+        }
+
+        /* check dimension name */
+        NC_string *root_name, *local_name;
+         root_name =  root_dim->value[i]->name;
+        local_name = local_dim->value[i]->name;
+
+        err = NC_NOERR;
+        if (root_name->nchars != local_name->nchars) {
+            if (safe_mode)
+                printf("%s dimension name length (local=%lld, root=%lld)\n",
+                       WARN_STR, local_name->nchars, root_name->nchars);
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_DIM_NAME)
+        }
+        else if (memcmp(root_name->cp, local_name->cp, (size_t)root_name->nchars) != 0) {
+            if (safe_mode)
+                printf("%s dimension name (local=%s, root=%s)\n",
+                       WARN_STR, local_name->cp, root_name->cp);
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_DIM_NAME)
+        }
+        else if (root_dim->value[i]->size != local_dim->value[i]->size) {
+            /* check dimension size */
+            if (safe_mode)
+                printf("%s dimension %s's size (local=%lld, root=%lld)\n",
+                       WARN_STR, root_dim->value[i]->name->cp,
+                       root_dim->value[i]->size, local_dim->value[i]->size);
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_DIM_SIZE)
+        }
+        if (status == NC_NOERR) status = err;
+
+        /* overwrite local's dim with root's */
+        if (err != NC_NOERR) {
+            ncmpii_free_NC_dim(local_dim->value[i]);
+            local_dim->value[i] = dup_NC_dim(root_dim->value[i]);
+        }
+    }
+
+    /* delete extra dimensions defined only in local copy */
+    for (; i<local_dim->ndefined; i++)
+        ncmpii_free_NC_dim(local_dim->value[i]);
+
+    local_dim->ndefined = root_dim->ndefined;
+
+    return status;
+}
+
+/*----< ncmpii_comp_attrs() >-------------------------------------------------*/
+/* compare the local copy of attr_list against root's
+ * If inconsistency is detected, overwrite local's with root's
+ */
+static int
+ncmpii_comp_attrs(int           safe_mode,
+                  NC_attrarray *root_attr,
+                  NC_attrarray *local_attr)
+{
+    int i, j, err, status=NC_NOERR;
+    char *msg;
+
+    /* check if the numbers of attributes are the same */
+    if (root_attr->ndefined != local_attr->ndefined) {
+        if (safe_mode)
+            printf("%s number of attributes (root=%d, local=%d)\n",
+                   WARN_STR, root_attr->ndefined, local_attr->ndefined);
+        DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_ATTR_NUM)
+    }
+
+    for (i=0; i<root_attr->ndefined; i++) {
+
+        if (i >= local_attr->ndefined) { /* if local list is shorter */
+            /* copy root's attr to local */
+            NC_attr *new_attr = dup_NC_attr(root_attr->value[i]);
+            err = incr_NC_attrarray(local_attr, new_attr);
+            if (err != NC_NOERR) return err; /* a fatal error */
+            continue;
+        }
+
+        NC_attr *v1 = root_attr->value[i];
+        NC_attr *v2 = local_attr->value[i];
+        char *name = v1->name->cp;
+
+#define ATTR_WARN(msg, attr, root, local) \
+    if (safe_mode) printf(msg, WARN_STR, attr, root, local);
+
+#define ATTR_WARN_J(msg, attr, j, root, local) \
+    if (safe_mode) printf(msg, WARN_STR, attr, j, root, local);
+
+        err = NC_NOERR;
+        if (v1->name->nchars != v2->name->nchars ||
+            memcmp(name, v2->name->cp, (size_t)v1->name->nchars) != 0) {
+            msg ="%s attribute %s (root=%s, local=%s)\n";
+            ATTR_WARN(msg, "name", name, v2->name->cp)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_NAME)
+        }
+        else if (v1->type != v2->type) {
+            msg = "%s attribute \"%s\" type (root=%d, local=%d)\n";
+            ATTR_WARN(msg, name, v1->type, v2->type)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_TYPE)
+        }
+        else if (v1->nelems != v2->nelems) {
+            msg = "%s attribute \"%s\" length (root=%lld, local=%lld)\n";
+            ATTR_WARN(msg, name, lld(v1->nelems), lld(v2->nelems))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_LEN)
+        }
+        else if (v1->xsz != v2->xsz) { /* internal check */
+            msg = "%s attribute \"%s\" size (root=%lld, local=%lld)\n";
+            ATTR_WARN(msg, name, lld(v1->xsz), lld(v2->xsz))
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_SIZE)
+        }
+        /* hereinafter, we have v1->nelems == v2->nelems */
+        else if (v1->type == NC_CHAR) {
+            if (memcmp(v1->xvalue, v2->xvalue, (size_t)v1->nelems)) {
+                msg = "%s attribute \"%s\" CHAR (root=%s, local=%s)\n";
+                ATTR_WARN(msg, name, (char*)v1->xvalue, (char*)v2->xvalue);
+                DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
+            }
+        }
+        else if (v1->type == NC_BYTE) {
+            schar *sba = (schar*) v1->xvalue;
+            schar *sbb = (schar*) v2->xvalue;
+            for (j=0; j<v1->nelems; j++) {
+                if (sba[j] != sbb[j]) {
+                    msg = "%s attribute \"%s\"[%d] BYTE (root=%hhdb, local=%hhdb)\n";
+                    ATTR_WARN_J(msg, name, j, sba[j], sbb[j])
+                    DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
+                    break;
+                }
+            }
+        }
+        else if (v1->type == NC_UBYTE) {
+            uchar *uba = (uchar*) v1->xvalue;
+            uchar *ubb = (uchar*) v2->xvalue;
+            for (j=0; j<v1->nelems; j++) {
+                if (uba[j] != ubb[j]) {
+                    msg = "%s attribute \"%s\"[%d] UBYTE (root=%hhuub, local=%hhuub)\n";
+                    ATTR_WARN_J(msg, name, j, uba[j], ubb[j])
+                    DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
+                    break;
+                }
+            }
+        }
+        else if (v1->type == NC_SHORT) {
+            short *ssa = (short*) v1->xvalue;
+            short *ssb = (short*) v2->xvalue;
+            for (j=0; j<v1->nelems; j++) {
+                if (ssa[j] != ssb[j]) {
+                    msg = "%s attribute \"%s\"[%d] SHORT (root=%hds, local=%hds)\n";
+                    ATTR_WARN_J(msg, name, j, ssa[j], ssb[j])
+                    DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
+                    break;
+                }
+            }
+        }
+        else if (v1->type == NC_USHORT) {
+            ushort *usa = (ushort*) v1->xvalue;
+            ushort *usb = (ushort*) v2->xvalue;
+            for (j=0; j<v1->nelems; j++) {
+                if (usa[j] != usb[j]) {
+                    msg = "%s attribute \"%s\"[%d] USHORT (root=%huus, local=%huus)\n";
+                    ATTR_WARN_J(msg, name, j, usa[j], usb[j])
+                    DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
+                    break;
+                }
+            }
+        }
+        else if (v1->type == NC_INT) {
+            int *sia = (int*) v1->xvalue;
+            int *sib = (int*) v2->xvalue;
+            for (j=0; j<v1->nelems; j++) {
+                if (sia[j] != sib[j]) {
+                    msg = "%s attribute \"%s\"[%d] INT (root=%d, local=%d)\n";
+                    ATTR_WARN_J(msg, name, j, sia[j], sib[j])
+                    DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
+                    break;
+                }
+            }
+        }
+        else if (v1->type == NC_UINT) {
+            uint *uia = (uint*) v1->xvalue;
+            uint *uib = (uint*) v2->xvalue;
+            for (j=0; j<v1->nelems; j++) {
+                if (uia[j] != uib[j]) {
+                    msg = "%s attribute \"%s\"[%d] UINT (root=%uu, local=%uu)\n";
+                    ATTR_WARN_J(msg, name, j, uia[j], uib[j])
+                    DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
+                    break;
+                }
+            }
+        }
+        else if (v1->type == NC_FLOAT) {
+            float *fa = (float*) v1->xvalue;
+            float *fb = (float*) v2->xvalue;
+            for (j=0; j<v1->nelems; j++) {
+                /* floating-point inequality here but we genuinely do
+                 * expect all processors to set bit-for-bit identical
+                 * headers */
+                if (fa[j] != fb[j]) {
+                    msg = "%s attribute \"%s\"[%d] FLOAT (root=%f, local=%f)\n";
+                    ATTR_WARN_J(msg, name, j, fa[j], fb[j])
+                    DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
+                    break;
+                }
+            }
+        }
+        else if (v1->type == NC_DOUBLE) {
+            double *da = (double*) v1->xvalue;
+            double *db = (double*) v2->xvalue;
+            for (j=0; j<v1->nelems; j++) {
+                /* floating-point inequality here but we genuinely do
+                 * expect all processors to set bit-for-bit identical
+                 * headers */
+                if (da[j] != db[j]) {
+                    msg = "%s attribute \"%s\"[%d] DOUBLE (root=%f, local=%f)\n";
+                    ATTR_WARN_J(msg, name, j, da[j], db[j])
+                    DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
+                    break;
+                }
+            }
+        }
+        else if (v1->type == NC_INT64) {
+            long long *slla = (long long*) v1->xvalue;
+            long long *sllb = (long long*) v2->xvalue;
+            for (j=0; j<v1->nelems; j++) {
+                if (slla[j] != sllb[j]) {
+                    msg = "%s attribute \"%s\"[%d] INT64 (root=%lldll, local=%lldll)\n";
+                    ATTR_WARN_J(msg, name, j, slla[j], sllb[j])
+                    DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
+                    break;
+                }
+            }
+        }
+        else if (v1->type == NC_UINT64) {
+            unsigned long long *ulla = (unsigned long long*) v1->xvalue;
+            unsigned long long *ullb = (unsigned long long*) v2->xvalue;
+            for (j=0; j<v1->nelems; j++) {
+                if (ulla[j] != ullb[j]) {
+                    msg = "%s attribute \"%s\"[%d] UINT64 (root=%llull, local=%llull)\n";
+                    ATTR_WARN_J(msg, name, j, ulla[j], ullb[j])
+                    DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_ATTR_VAL)
+                    break;
+                }
+            }
+        }
+        if (status == NC_NOERR) status = err;
+
+        /* overwrite local's attr with root's */
+        if (ErrIsHeaderDiff(err)) {
+            ncmpii_free_NC_attr(local_attr->value[i]);
+            local_attr->value[i] = dup_NC_attr(root_attr->value[i]);
+        }
+    }
+
+    /* delete extra attributes defined only in local copy */
+    for (; i<local_attr->ndefined; i++)
+        ncmpii_free_NC_attr(local_attr->value[i]);
+
+    local_attr->ndefined = root_attr->ndefined;
+
+    return status;
+}
+
+/*----< ncmpii_comp_vars() >--------------------------------------------------*/
+/* compare the local copy of var_list against root's
+ * If inconsistency is detected, overwrite local's with root's
+ */
+static int
+ncmpii_comp_vars(int          safe_mode,
+                 NC_vararray *root_var,
+                 NC_vararray *local_var)
+{
+    int i, j, err, status=NC_NOERR, no_fill;
+    char *msg;
+
+    /* check if the numbers of variables are the same */
+    if (root_var->ndefined != local_var->ndefined) {
+        if (safe_mode)
+            printf("%s number of variables (root=%d, local=%d)\n",
+                   WARN_STR, root_var->ndefined, local_var->ndefined);
+        DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_VAR_NUM)
+    }
+
+    for (i=0; i<root_var->ndefined; i++) {
+
+        if (i >= local_var->ndefined) { /* if local list is shorter */
+            /* copy root's variable to local */
+            NC_var *new_var = dup_NC_var(root_var->value[i]);
+            err = incr_NC_vararray(local_var, new_var);
+            if (err != NC_NOERR) return err; /* a fatal error */
+            /* local_var->ndefined is increased by 1 in incr_NC_vararray() */
+            continue;
+        }
+
+        NC_var *v1 = root_var->value[i];
+        NC_var *v2 = local_var->value[i];
+        char name[128];
+        /* in PnetCDF, name->cp is always NULL character terminated */
+        strcpy(name, v1->name->cp);
+
+        /* preserve original local variable's no_fill setting */
+        no_fill = v2->no_fill;
+
+#define VAR_WARN(msg, var, root, local) \
+    if (safe_mode) printf(msg, WARN_STR, var, root, local);
+
+#define VAR_WARN_J(msg, var, j, root, local) \
+    if (safe_mode) printf(msg, WARN_STR, var, j, root, local);
+
+        err = NC_NOERR;
+        if (v1->name->nchars != v2->name->nchars ||
+            strncmp(v1->name->cp, v2->name->cp, (size_t)v1->name->nchars) != 0) {
+            msg = "%s variable %s (root=%s, local=%s)\n";
+            VAR_WARN(msg, "name", name, v2->name->cp)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_VAR_NAME)
+        }
+        else if (v1->ndims != v2->ndims) {
+            msg = "%s variable %s's ndims (root=%d, local=%d)\n";
+            VAR_WARN(msg, name, v1->ndims, v2->ndims)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_VAR_NDIMS)
+        }
+        else if (v1->type != v2->type) {
+            msg = "%s variable %s's type (root=%d, local=%d)\n";
+            VAR_WARN(msg, name, v1->type, v2->type)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_VAR_TYPE)
+        }
+        else if (v1->len != v2->len) {
+            msg = "%s variable %s's len (root=%lld, local=%lld)\n";
+            VAR_WARN(msg, name, v1->len, v2->len)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_VAR_LEN)
+        }
+        else if (v1->begin != v2->begin) {
+            msg = "%s variable %s's begin (root=%lld, local=%lld)\n";
+            VAR_WARN(msg, name, v1->begin, v2->begin)
+            DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_VAR_BEGIN)
+        }
+        else {
+            for (j=0; j<v1->ndims; j++) {
+                if (v1->dimids[j] != v2->dimids[j]) {
+                    msg = "%s variable %s's %dth dim ID (root=%d, local=%ld)\n";
+                    VAR_WARN_J(msg, name, j, v1->dimids[j], v2->dimids[j])
+                    DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_VAR_DIMIDS)
+                    break;
+                }
+            }
+        }
+        /* compare variable's attributes if by far no inconsistency is found */
+        if (err == NC_NOERR) {
+            err = ncmpii_comp_attrs(safe_mode, &(v1->attrs), &(v2->attrs));
+            if (err != NC_NOERR && !ErrIsHeaderDiff(err))
+                return err; /* a fatal error */
+        }
+
+        if (status == NC_NOERR) status = err;
+
+        /* if there is any inconsistency, overwrite local's var with root's */
+        if (ErrIsHeaderDiff(err)) {
+            ncmpii_free_NC_var(local_var->value[i]);
+            local_var->value[i] = dup_NC_var(root_var->value[i]);
+            /* restore original local variable's no_fill setting */
+            local_var->value[i]->no_fill = no_fill;
+            /* note once a new var is created, one must call
+             * ncmpii_NC_computeshapes() to recalculate the shape */
+        }
+    }
+
+    /* delete extra variables defined only in local copy */
+    for (; i<local_var->ndefined; i++)
+        ncmpii_free_NC_var(local_var->value[i]);
+
+    local_var->ndefined = root_var->ndefined;
+
+    return status;
+}
+
+/*----< ncmpii_hdr_check_NC() >-----------------------------------------------*/
+/* This function is only called by NC_check_header()
+ * It checks the header of local copy against root's and overwrites local's
+ * header object, ncp, with root's header if any inconsistency is detected.
+ * This function is called independently and should not contain any MPI
+ * communication calls.
+ */
+int
+ncmpii_hdr_check_NC(bufferinfo *getbuf, /* header from root */
+                    NC         *ncp)
+{
+    int rank, err, status=NC_NOERR;
+    schar magic[sizeof(ncmagic1)];
+    MPI_Offset nrecs=0, chunksize=NC_DEFAULT_CHUNKSIZE;
+    MPI_Aint pos_addr, base_addr;
+    NC *root_ncp;
+
+    assert(ncp != NULL);
+    assert(getbuf != NULL);
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    /* check header's magic */
+    memset(magic, 0, sizeof(magic));
+    err = ncmpix_getn_schar_schar((const void **)(&getbuf->pos),
+                                  sizeof(magic), magic);
+    if (err != NC_NOERR) {
+        /* Fatal error, as root's header is significant */
+        if (ncp->safe_mode) fprintf(stderr,"Error: CDF magic number from root's header\n");
+        return err;
+    }
+    getbuf->index += (MPI_Offset)sizeof(magic);
+
+    /* check if the first 3 letters are "CDF" */
+    if (memcmp(magic, ncmagic1, sizeof(ncmagic1)-1) != 0) {
+        /* Fatal error, as root's header is significant */
+        if (ncp->safe_mode)
+            fprintf(stderr,"Error: root's header indicates not a CDF file\n");
+        DEBUG_RETURN_ERROR(NC_ENOTNC) /* should not continue */
+    }
+
+    /* allocate a header object and fill it with root's header */
+    root_ncp = ncmpii_new_NC(&chunksize);
+
+    /* consistency of magic numbers should have already been checked during
+     * ncmpi_create()
+     */
+    if (magic[sizeof(ncmagic1)-1] == 0x5) {
+        fSet(root_ncp->flags, NC_64BIT_DATA);
+    }
+    else if (magic[sizeof(ncmagic1)-1] == 0x2) {
+        fSet(root_ncp->flags, NC_64BIT_OFFSET);
+    }
+    else if (magic[sizeof(ncmagic1)-1] != 0x1) {
+        /* Fatal error, as root's header is significant */
+        if (ncp->safe_mode)
+            fprintf(stderr,"Error: root's header indicates not CDF 1/2/5 format\n");
+        DEBUG_RETURN_ERROR(NC_ENOTNC) /* should not continue */
+    }
+
+    /* check version number in last byte of magic */
+    int local_ver, root_ver;
+         if (ncp->flags & NC_64BIT_DATA)   local_ver = 0x5;
+    else if (ncp->flags & NC_64BIT_OFFSET) local_ver = 0x2;
+    else                                   local_ver = 0x1;
+
+    root_ver = magic[sizeof(ncmagic1)-1];
+    if (local_ver != root_ver) {
+        if (ncp->safe_mode)
+            printf("%s CDF file format (local=CDF-%d, root=CDF-%d)\n",
+                   WARN_STR, local_ver, root_ver);
+
+        /* overwrite the local header object with root's */
+             if (local_ver == 0x5) fClr(ncp->flags, NC_64BIT_DATA);
+        else if (local_ver == 0x2) fClr(ncp->flags, NC_64BIT_OFFSET);
+
+             if (root_ver  == 0x5) fSet(ncp->flags, NC_64BIT_DATA);
+        else if (root_ver  == 0x2) fSet(ncp->flags, NC_64BIT_OFFSET);
+
+        /* this inconsistency is not fatal */
+        DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_OMODE)
+    }
+    getbuf->version = root_ver; /* getbuf's version has not been set before */
+
+#if SIZEOF_MPI_OFFSET < 8
+    if (root_ver > 1) {
+        /* for NC_64BIT_DATA or NC_64BIT_OFFSET, MPI_Offset must be 8 bytes */
+        if (ncp->safe_mode) fprintf(stderr,"Error: cannot support CDF-2 and CDF-5 on this machine\n");
+        DEBUG_RETURN_ERROR(NC_ESMALL) /* should not continue */
+    }
+#endif
+
+    /* since getbuf contains the entire root's header, we do not need to check
+     * for any next element in the buffer. Similarly, for all possible calls
+     * to hdr_check_buffer() from this subroutine, hdr_fetch() will never be
+     * called.
+     * (move on to the next element in header: number of records)
+     err = hdr_check_buffer(getbuf, (getbuf->version == 5) ? 8 : 4);
+     if (err != NC_NOERR) {
+         if (ncp->safe_mode)
+             fprintf(stderr,"Error: root's header is too short\n");
+         return err;
+     }
+     */
+
+    if (getbuf->version == 5) {
+        uint64 tmp=0;
+        err = ncmpix_get_uint64((const void **)(&getbuf->pos), &tmp);
+        nrecs = (MPI_Offset)tmp;
+    }
+    else {
+        uint tmp=0;
+        err = ncmpix_get_uint32((const void **)(&getbuf->pos), &tmp);
+        nrecs = (MPI_Offset)tmp;
+    }
+    if (err != NC_NOERR) {
+        if (ncp->safe_mode)
+            fprintf(stderr,"Error: failed to read numrecs from root's header\n");
+        return err; /* should not continue */
+    }
+
+    /* move the buffer point forward */
+    if (getbuf->version == 5)
+        getbuf->index += X_SIZEOF_INT64;
+    else
+        getbuf->index += X_SIZEOF_SIZE_T;
+
+    root_ncp->numrecs = nrecs;
+    if (root_ncp->numrecs != ncp->numrecs) {
+        if (ncp->safe_mode)
+            printf("%s number of records (local=%lld, root=%lld)\n",
+                   WARN_STR, ncp->numrecs, root_ncp->numrecs);
+        /* overwrite the local header's numrecs */
+        ncp->numrecs = root_ncp->numrecs;
+        if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(err, NC_EMULTIDEFINE_NUMRECS)
+    }
+
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(getbuf->pos,  &pos_addr);
+    MPI_Get_address(getbuf->base, &base_addr);
+#else
+    MPI_Address(getbuf->pos,  &pos_addr);
+    MPI_Address(getbuf->base, &base_addr);
+#endif
+    assert(pos_addr < base_addr + getbuf->size);
+
+    /* get the next header element dim_list from getbuf to root_ncp */
+    err = hdr_get_NC_dimarray(getbuf, &root_ncp->dims);
+    if (err != NC_NOERR) return err; /* fatal error */
+
+    /* compare local's and root's dim_list */
+    err = ncmpii_comp_dims(ncp->safe_mode, &root_ncp->dims, &ncp->dims);
+    if (err != NC_NOERR && !ErrIsHeaderDiff(err))
+        return err; /* a fatal error */
+    if (status == NC_NOERR) status = err;
+
+    /* get the next header element gatt_list from getbuf to root_ncp */
+    err = hdr_get_NC_attrarray(getbuf, &root_ncp->attrs);
+    if (err != NC_NOERR) return err; /* fatal error */
+
+    /* get the next header element att_list from getbuf to root_ncp */
+    err = ncmpii_comp_attrs(ncp->safe_mode, &root_ncp->attrs, &ncp->attrs);
+    if (err != NC_NOERR && !ErrIsHeaderDiff(err))
+        return err; /* a fatal error */
+    if (status == NC_NOERR) status = err;
+
+    /* get the next header element var_list from getbuf to root_ncp */
+    err = hdr_get_NC_vararray(getbuf, &root_ncp->vars);
+    if (err != NC_NOERR) return err; /* fatal error */
+
+    /* compare local's and root's var_list */
+    err = ncmpii_comp_vars(ncp->safe_mode, &root_ncp->vars, &ncp->vars);
+    if (err != NC_NOERR && !ErrIsHeaderDiff(err))
+        return err; /* a fatal error */
+    if (status == NC_NOERR) status = err;
+
+    if (err != NC_NOERR) { /* header has been sync-ed with root */
+        /* recompute shape is required for every new variable created */
+        err = ncmpii_NC_computeshapes(ncp);
+        if (err != NC_NOERR) return err; /* a fatal error */
+    }
+    /* now, the local header object has been sync-ed with root */
+
+    if (ncp->safe_mode && ErrIsHeaderDiff(status)) {
+        /* recompute header size */
+        MPI_Offset root_xsz, local_xsz;
+         root_xsz = ncmpii_hdr_len_NC(root_ncp);
+        local_xsz = ncmpii_hdr_len_NC(ncp);
+        /* root's header size is getbuf->size */
+        assert( ncp->xsz == getbuf->size &&
+                root_xsz == local_xsz    &&
+               local_xsz == getbuf->size);
+    }
+    ncmpii_free_NC(root_ncp);
+    return status;
+}
+
+/*----< ncmpii_write_header() >-----------------------------------------------*/
+/* This function is called only in data mode (collective or independent) and by
+ * 1. ncmpi_rename_att()
+ * 2. ncmpi_copy_att()
+ * 3. ncmpii_put_att()
+ * 4. ncmpi_rename_dim()
+ * 5. ncmpi_rename_var()
+ *
+ * This function is collective (even in independent data mode) */
+int ncmpii_write_header(NC *ncp)
+{
+    int rank, status=NC_NOERR, mpireturn, err;
+    MPI_File fh;
+
+    /* Write the entire header to the file. This function may be called from
+     * a rename API. In that case, we cannot just change the variable name in
+     * the file header, because if the file space occupied by the name shrinks,
+     * all metadata following the new name must be moved ahead.
+     */
+
+    fh = ncp->nciop->collective_fh;
+    if (NC_indep(ncp))
+        fh = ncp->nciop->independent_fh;
+
+    MPI_Comm_rank(ncp->nciop->comm, &rank);
+    if (rank == 0) {
+        MPI_Status mpistatus;
+        void *buf = NCI_Malloc((size_t)ncp->xsz); /* header's write buffer */
+
+        /* copy header object to write buffer */
+        status = ncmpii_hdr_put_NC(ncp, buf);
+
+        if (ncp->xsz != (int)ncp->xsz) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        TRACE_IO(MPI_File_write_at)(fh, 0, buf, (int)ncp->xsz, MPI_BYTE, &mpistatus);
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_File_write_at");
+            if (status == NC_NOERR) {
+                status = (err == NC_EFILE) ? NC_EWRITE : err;
+                DEBUG_ASSIGN_ERROR(status, status)
+            }
+        }
+        else {
+            int put_size;
+            MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
+            ncp->nciop->put_size += put_size;
+        }
+        NCI_Free(buf);
+    }
+
+    if (ncp->safe_mode == 1) {
+        /* broadcast root's status, because only root writes to the file */
+        int root_status = status;
+        TRACE_COMM(MPI_Bcast)(&root_status, 1, MPI_INT, 0, ncp->nciop->comm);
+        /* root's write has failed, which is serious */
+        if (root_status == NC_EWRITE) DEBUG_ASSIGN_ERROR(status, NC_EWRITE)
+    }
+
+    /* update file header size */
+    ncp->xsz = ncmpii_hdr_len_NC(ncp);
+
+    if (NC_doFsync(ncp)) { /* NC_SHARE is set */
+        TRACE_IO(MPI_File_sync)(fh);
+        TRACE_COMM(MPI_Barrier)(ncp->nciop->comm);
+    }
+
+    return status;
+}
+
diff --git a/src/lib/i_getput.m4 b/src/lib/i_getput.m4
new file mode 100644
index 0000000..6bf1a26
--- /dev/null
+++ b/src/lib/i_getput.m4
@@ -0,0 +1,939 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: i_getput.m4 2290 2016-01-02 18:37:46Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <assert.h>
+
+#include <string.h> /* memcpy() */
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "ncmpidtype.h"
+#include "macro.h"
+
+
+define(`CollIndep',   `ifelse(`$1',`_all', `COLL_IO', `INDEP_IO')')dnl
+define(`ReadWrite',   `ifelse(`$1', `get', `READ_REQ', `WRITE_REQ')')dnl
+define(`BufConst',    `ifelse(`$1', `put', `const')')dnl
+
+dnl
+dnl VAR_FLEXIBLE
+dnl
+define(`VAR_FLEXIBLE',dnl
+`dnl
+/*----< ncmpi_i$1_var() >----------------------------------------------------*/
+int
+ncmpi_i$1_var(int                ncid,
+              int                varid,
+              BufConst($1) void *buf,
+              MPI_Offset         bufcount,
+              MPI_Datatype       buftype,
+              int               *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    MPI_Offset *start, *count;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VAR,
+                                 0, 1, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    GET_FULL_DIMENSIONS(start, count)
+
+    /* i$1_var is a special case of i$1_varm */
+    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                                 (void*)buf, bufcount, buftype, reqid,
+                                 ReadWrite($1), 0, 0);
+    if (varp->ndims > 0) NCI_Free(start);
+    return status;
+}
+')dnl
+
+VAR_FLEXIBLE(put)
+VAR_FLEXIBLE(get)
+
+dnl
+dnl VAR
+dnl
+define(`VAR',dnl
+`dnl
+/*----< ncmpi_i$1_var_$2() >-------------------------------------------------*/
+int
+ncmpi_i$1_var_$2(int              ncid,
+                 int              varid,
+                 BufConst($1) $3 *buf,
+                 int             *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    MPI_Offset *start, *count;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, 0, API_VAR,
+                                 0, 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    GET_FULL_DIMENSIONS(start, count)
+
+    /* i$1_var is a special case of i$1_varm */
+    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                                 (void*)buf, -1, $4, reqid,
+                                 ReadWrite($1), 0, 0);
+    if (varp->ndims > 0) NCI_Free(start);
+    return status;
+}
+')dnl
+
+VAR(put, text,      char,               MPI_CHAR)
+VAR(put, schar,     schar,              MPI_SIGNED_CHAR)
+VAR(put, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VAR(put, short,     short,              MPI_SHORT)
+VAR(put, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VAR(put, int,       int,                MPI_INT)
+VAR(put, uint,      uint,               MPI_UNSIGNED)
+VAR(put, long,      long,               MPI_LONG)
+VAR(put, float,     float,              MPI_FLOAT)
+VAR(put, double,    double,             MPI_DOUBLE)
+VAR(put, longlong,  long long,          MPI_LONG_LONG_INT)
+VAR(put, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VAR(get, text,      char,               MPI_CHAR)
+VAR(get, schar,     schar,              MPI_SIGNED_CHAR)
+VAR(get, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VAR(get, short,     short,              MPI_SHORT)
+VAR(get, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VAR(get, int,       int,                MPI_INT)
+VAR(get, uint,      uint,               MPI_UNSIGNED)
+VAR(get, long,      long,               MPI_LONG)
+VAR(get, float,     float,              MPI_FLOAT)
+VAR(get, double,    double,             MPI_DOUBLE)
+VAR(get, longlong,  long long,          MPI_LONG_LONG_INT)
+VAR(get, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+
+dnl
+dnl VAR1_FLEXIBLE
+dnl
+define(`VAR1_FLEXIBLE',dnl
+`dnl
+/*----< ncmpi_i$1_var1() >---------------------------------------------------*/
+int
+ncmpi_i$1_var1(int                ncid,
+               int                varid,
+               const MPI_Offset  *start,
+               BufConst($1) void *buf,
+               MPI_Offset         bufcount,
+               MPI_Datatype       buftype,
+               int               *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    MPI_Offset *count;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, NULL, bufcount, API_VAR1,
+                                 0, 1, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    GET_ONE_COUNT(count)
+
+    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                                 (void*)buf, bufcount, buftype, reqid,
+                                 ReadWrite($1), 0, 0);
+    if (varp->ndims > 0) NCI_Free(count);
+    return status;
+}
+')dnl
+
+VAR1_FLEXIBLE(put)
+VAR1_FLEXIBLE(get)
+
+dnl
+dnl VAR1
+dnl
+define(`VAR1',dnl
+`dnl
+/*----< ncmpi_i$1_var1_$2() >------------------------------------------------*/
+int
+ncmpi_i$1_var1_$2(int               ncid,
+                  int               varid,
+                  const MPI_Offset  start[],
+                  BufConst($1) $3  *buf,
+                  int              *reqid)
+{
+    int         status;
+    NC         *ncp;
+    NC_var     *varp=NULL;
+    MPI_Offset *count;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, NULL, 0, API_VAR1,
+                                 0, 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    GET_ONE_COUNT(count)
+
+    status = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                                 (void*)buf, -1, $4, reqid, ReadWrite($1), 0,
+                                 0);
+    if (varp->ndims > 0) NCI_Free(count);
+    return status;
+}
+')dnl
+
+VAR1(put, text,      char,               MPI_CHAR)
+VAR1(put, schar,     schar,              MPI_SIGNED_CHAR)
+VAR1(put, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VAR1(put, short,     short,              MPI_SHORT)
+VAR1(put, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VAR1(put, int,       int,                MPI_INT)
+VAR1(put, uint,      uint,               MPI_UNSIGNED)
+VAR1(put, long,      long,               MPI_LONG)
+VAR1(put, float,     float,              MPI_FLOAT)
+VAR1(put, double,    double,             MPI_DOUBLE)
+VAR1(put, longlong,  long long,          MPI_LONG_LONG_INT)
+VAR1(put, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VAR1(get, text,      char,               MPI_CHAR)
+VAR1(get, schar,     schar,              MPI_SIGNED_CHAR)
+VAR1(get, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VAR1(get, short,     short,              MPI_SHORT)
+VAR1(get, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VAR1(get, int,       int,                MPI_INT)
+VAR1(get, uint,      uint,               MPI_UNSIGNED)
+VAR1(get, long,      long,               MPI_LONG)
+VAR1(get, float,     float,              MPI_FLOAT)
+VAR1(get, double,    double,             MPI_DOUBLE)
+VAR1(get, longlong,  long long,          MPI_LONG_LONG_INT)
+VAR1(get, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+
+dnl
+dnl VARA_FLEXIBLE
+dnl
+define(`VARA_FLEXIBLE',dnl
+`dnl
+/*----< ncmpi_i$1_vara() >---------------------------------------------------*/
+int
+ncmpi_i$1_vara(int                ncid,
+               int                varid,
+               const MPI_Offset  *start,
+               const MPI_Offset  *count,
+               BufConst($1) void *buf,
+               MPI_Offset         bufcount,
+               MPI_Datatype       buftype,
+               int               *reqid)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARA,
+                                 0, 1, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                               (void*)buf, bufcount, buftype, reqid,
+                               ReadWrite($1), 0, 0);
+}
+')dnl
+
+VARA_FLEXIBLE(put)
+VARA_FLEXIBLE(get)
+
+dnl
+dnl VARA
+dnl
+define(`VARA',dnl
+`dnl
+/*----< ncmpi_i$1_vara_$1() >------------------------------------------------*/
+int
+ncmpi_i$1_vara_$2(int               ncid,
+                  int               varid,
+                  const MPI_Offset  start[],
+                  const MPI_Offset  count[],
+                  BufConst($1) $3  *buf,
+                  int              *reqid)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARA,
+                                 0, 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                               (void*)buf, -1, $4, reqid, ReadWrite($1), 0, 0);
+}
+')dnl
+
+VARA(put, text,      char,               MPI_CHAR)
+VARA(put, schar,     schar,              MPI_SIGNED_CHAR)
+VARA(put, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARA(put, short,     short,              MPI_SHORT)
+VARA(put, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARA(put, int,       int,                MPI_INT)
+VARA(put, uint,      uint,               MPI_UNSIGNED)
+VARA(put, long,      long,               MPI_LONG)
+VARA(put, float,     float,              MPI_FLOAT)
+VARA(put, double,    double,             MPI_DOUBLE)
+VARA(put, longlong,  long long,          MPI_LONG_LONG_INT)
+VARA(put, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARA(get, text,      char,               MPI_CHAR)
+VARA(get, schar,     schar,              MPI_SIGNED_CHAR)
+VARA(get, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARA(get, short,     short,              MPI_SHORT)
+VARA(get, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARA(get, int,       int,                MPI_INT)
+VARA(get, uint,      uint,               MPI_UNSIGNED)
+VARA(get, long,      long,               MPI_LONG)
+VARA(get, float,     float,              MPI_FLOAT)
+VARA(get, double,    double,             MPI_DOUBLE)
+VARA(get, longlong,  long long,          MPI_LONG_LONG_INT)
+VARA(get, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+
+dnl
+dnl VARS_FLEXIBLE
+dnl
+define(`VARS_FLEXIBLE',dnl
+`dnl
+/*----< ncmpi_i$1_vars() >---------------------------------------------------*/
+int
+ncmpi_i$1_vars(int                ncid,
+               int                varid,
+               const MPI_Offset   start[],
+               const MPI_Offset   count[],
+               const MPI_Offset   stride[],
+               BufConst($1) void *buf,
+               MPI_Offset         bufcount,
+               MPI_Datatype       buftype,
+               int               *reqid)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARS,
+                                 0, 1, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_igetput_varm(ncp, varp, start, count, stride, NULL,
+                               (void*)buf, bufcount, buftype, reqid,
+                               ReadWrite($1), 0, 0);
+}
+')dnl
+
+VARS_FLEXIBLE(put)
+VARS_FLEXIBLE(get)
+
+dnl
+dnl VARS
+dnl
+define(`VARS',dnl
+`dnl
+/*----< ncmpi_i$1_vars_$2() >------------------------------------------------*/
+int
+ncmpi_i$1_vars_$2(int               ncid,
+                  int               varid,
+                  const MPI_Offset  start[],
+                  const MPI_Offset  count[],
+                  const MPI_Offset  stride[],
+                  BufConst($1) $3  *buf,
+                  int              *reqid)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARS,
+                                 0, 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_igetput_varm(ncp, varp, start, count, stride, NULL,
+                               (void*)buf, -1, $4, reqid, ReadWrite($1), 0, 0);
+}
+')dnl
+
+VARS(put, text,      char,               MPI_CHAR)
+VARS(put, schar,     schar,              MPI_SIGNED_CHAR)
+VARS(put, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARS(put, short,     short,              MPI_SHORT)
+VARS(put, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARS(put, int,       int,                MPI_INT)
+VARS(put, uint,      uint,               MPI_UNSIGNED)
+VARS(put, long,      long,               MPI_LONG)
+VARS(put, float,     float,              MPI_FLOAT)
+VARS(put, double,    double,             MPI_DOUBLE)
+VARS(put, longlong,  long long,          MPI_LONG_LONG_INT)
+VARS(put, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARS(get, text,      char,               MPI_CHAR)
+VARS(get, schar,     schar,              MPI_SIGNED_CHAR)
+VARS(get, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARS(get, short,     short,              MPI_SHORT)
+VARS(get, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARS(get, int,       int,                MPI_INT)
+VARS(get, uint,      uint,               MPI_UNSIGNED)
+VARS(get, long,      long,               MPI_LONG)
+VARS(get, float,     float,              MPI_FLOAT)
+VARS(get, double,    double,             MPI_DOUBLE)
+VARS(get, longlong,  long long,          MPI_LONG_LONG_INT)
+VARS(get, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+
+/* buffer layers:
+
+        User Level              buf     (user defined buffer of MPI_Datatype)
+        MPI Datatype Level      cbuf    (contiguous buffer of ptype)
+        NetCDF XDR Level        xbuf    (XDR I/O buffer)
+*/
+
+static int
+pack_request(NC *ncp, NC_var *varp, NC_req *req,
+             const MPI_Offset start[], const MPI_Offset count[],
+             const MPI_Offset stride[]);
+
+dnl
+dnl VARM_FLEXIBLE
+dnl
+define(`VARM_FLEXIBLE',dnl
+`dnl
+/*----< ncmpi_i$1_varm() >---------------------------------------------------*/
+int
+ncmpi_i$1_varm(int                ncid,
+               int                varid,
+               const MPI_Offset   start[],
+               const MPI_Offset   count[],
+               const MPI_Offset   stride[],
+               const MPI_Offset   imap[],
+               BufConst($1) void *buf,
+               MPI_Offset         bufcount,
+               MPI_Datatype       buftype,
+               int               *reqid)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, count, bufcount, API_VARM,
+                                 0, 1, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_igetput_varm(ncp, varp, start, count, stride, imap,
+                               (void*)buf, bufcount, buftype, reqid,
+                               ReadWrite($1), 0, 0);
+}
+')dnl
+
+VARM_FLEXIBLE(put)
+VARM_FLEXIBLE(get)
+
+dnl
+dnl VARM
+dnl
+define(`VARM',dnl
+`dnl
+/*----< ncmpi_i$1_varm_$2() >------------------------------------------------*/
+int
+ncmpi_i$1_varm_$2(int               ncid,
+                  int               varid,
+                  const MPI_Offset  start[],
+                  const MPI_Offset  count[],
+                  const MPI_Offset  stride[],
+                  const MPI_Offset  imap[],
+                  BufConst($1) $3  *buf,
+                  int              *reqid)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+    status = ncmpii_sanity_check(ncid, varid, start, count, 0, API_VARM,
+                                 0, 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_igetput_varm(ncp, varp, start, count, stride, imap,
+                               (void*)buf, -1, $4, reqid, ReadWrite($1), 0, 0);
+}
+')dnl
+
+VARM(put, text,      char,               MPI_CHAR)
+VARM(put, schar,     schar,              MPI_SIGNED_CHAR)
+VARM(put, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARM(put, short,     short,              MPI_SHORT)
+VARM(put, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARM(put, int,       int,                MPI_INT)
+VARM(put, uint,      uint,               MPI_UNSIGNED)
+VARM(put, long,      long,               MPI_LONG)
+VARM(put, float,     float,              MPI_FLOAT)
+VARM(put, double,    double,             MPI_DOUBLE)
+VARM(put, longlong,  long long,          MPI_LONG_LONG_INT)
+VARM(put, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARM(get, text,      char,               MPI_CHAR)
+VARM(get, schar,     schar,              MPI_SIGNED_CHAR)
+VARM(get, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARM(get, short,     short,              MPI_SHORT)
+VARM(get, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARM(get, int,       int,                MPI_INT)
+VARM(get, uint,      uint,               MPI_UNSIGNED)
+VARM(get, long,      long,               MPI_LONG)
+VARM(get, float,     float,              MPI_FLOAT)
+VARM(get, double,    double,             MPI_DOUBLE)
+VARM(get, longlong,  long long,          MPI_LONG_LONG_INT)
+VARM(get, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+/*----< ncmpii_abuf_malloc() >------------------------------------------------*/
+/* allocate memory space from the attached buffer pool */
+static int
+ncmpii_abuf_malloc(NC *ncp, MPI_Offset nbytes, void **buf, int *abuf_index)
+{
+    /* extend the table size if more entries are needed */
+    if (ncp->abuf->tail + 1 == ncp->abuf->table_size) {
+        ncp->abuf->table_size += NC_ABUF_DEFAULT_TABLE_SIZE;
+        ncp->abuf->occupy_table = (NC_buf_status*)
+                   NCI_Realloc(ncp->abuf->occupy_table,
+                               (size_t)ncp->abuf->table_size * sizeof(NC_buf_status));
+    }
+    /* mark the new entry is used and store the requested buffer size */
+    ncp->abuf->occupy_table[ncp->abuf->tail].is_used  = 1;
+    ncp->abuf->occupy_table[ncp->abuf->tail].req_size = nbytes;
+    *abuf_index = ncp->abuf->tail;
+
+    *buf = (char*)ncp->abuf->buf + ncp->abuf->size_used;
+    ncp->abuf->size_used += nbytes;
+    ncp->abuf->tail++;
+
+    return NC_NOERR;
+}
+
+/*----< ncmpii_igetput_varm() >-----------------------------------------------*/
+int
+ncmpii_igetput_varm(NC               *ncp,
+                    NC_var           *varp,
+                    const MPI_Offset  start[],
+                    const MPI_Offset  count[],
+                    const MPI_Offset  stride[],
+                    const MPI_Offset  imap[],
+                    void             *buf,      /* user buffer */
+                    MPI_Offset        bufcount,
+                    MPI_Datatype      buftype,
+                    int              *reqid,    /* out, can be NULL */
+                    int               rw_flag,
+                    int               use_abuf,    /* if use attached buffer */
+                    int               isSameGroup) /* if part of a varn group */
+{
+    void *xbuf=NULL, *cbuf=NULL, *lbuf=NULL;
+    int err=NC_NOERR, status=NC_NOERR, warning=NC_NOERR;
+    int i, abuf_index=-1, el_size, buftype_is_contig;
+    int need_convert, need_swap, need_swap_back_buf=0;
+    MPI_Offset bnelems=0, nbytes;
+    MPI_Datatype ptype, imaptype=MPI_DATATYPE_NULL;
+    NC_req *req;
+
+    /* check NC_ECHAR error and calculate the followings:
+     * ptype: element data type (MPI primitive type) in buftype
+     * bufcount: If it is -1, then this is called from a high-level API and in
+     * this case buftype will be an MPI primitive data type. If not, then this
+     * is called from a flexible API. In that case, we recalculate bufcount to
+     * match with count[].
+     * bnelems: number of ptypes in user buffer
+     * nbytes: number of bytes (in external data representation) to read/write
+     * from/to the file
+     * el_size: size of ptype
+     * buftype_is_contig: whether buftype is contiguous
+     */
+    err = ncmpii_calc_datatype_elems(ncp, varp, start, count, stride, rw_flag,
+                                     buftype, &ptype, &bufcount, &bnelems,
+                                     &nbytes, &el_size, &buftype_is_contig);
+    if (err == NC_EIOMISMATCH) DEBUG_ASSIGN_ERROR(warning, err)
+    else if (err != NC_NOERR) return err;
+
+    if (bnelems == 0) {
+        /* zero-length request, mark this as a NULL request */
+        if (!isSameGroup && reqid != NULL)
+            /* only if this is not part of a group request */
+            *reqid = NC_REQ_NULL;
+        return ((warning != NC_NOERR) ? warning : NC_NOERR);
+    }
+
+    /* for bput call, check if the remaining buffer space is sufficient
+     * to accommodate this request
+     */
+    if (rw_flag == WRITE_REQ && use_abuf &&
+        ncp->abuf->size_allocated - ncp->abuf->size_used < nbytes)
+        DEBUG_RETURN_ERROR(NC_EINSUFFBUF)
+
+    /* check if type conversion and Endianness byte swap is needed */
+    need_convert = ncmpii_need_convert(varp->type, ptype);
+    need_swap    = ncmpii_need_swap(varp->type, ptype);
+
+    /* check whether this is a true varm call, if yes, imaptype will be a
+     * newly created MPI derived data type, otherwise MPI_DATATYPE_NULL
+     */
+    err = ncmpii_create_imaptype(varp, count, imap, bnelems, el_size, ptype,
+                                 &imaptype);
+    if (err != NC_NOERR) return err;
+
+    if (rw_flag == WRITE_REQ) { /* pack request to xbuf */
+        int position, abuf_allocated=0;
+        MPI_Offset outsize=bnelems*el_size;
+        /* assert(bnelems > 0); */
+        if (outsize != (int)outsize) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+
+        /* attached buffer allocation logic
+         * if (use_abuf)
+         *     if contig && no imap && no convert
+         *         buf   ==   lbuf   ==   cbuf    ==     xbuf memcpy-> abuf
+         *                                               abuf
+         *     if contig && no imap &&    convert
+         *         buf   ==   lbuf   ==   cbuf convert-> xbuf == abuf
+         *                                               abuf
+         *     if contig &&    imap && no convert
+         *         buf   ==   lbuf pack-> cbuf    ==     xbuf == abuf
+         *                                abuf
+         *     if contig &&    imap &&    convert
+         *         buf   ==   lbuf pack-> cbuf convert-> xbuf == abuf
+         *                                               abuf
+         *  if noncontig && no imap && no convert
+         *         buf pack-> lbuf   ==   cbuf    ==     xbuf == abuf
+         *                    abuf
+         *  if noncontig && no imap &&    convert
+         *         buf pack-> lbuf   ==   cbuf convert-> xbuf == abuf
+         *                                               abuf
+         *  if noncontig &&    imap && no convert
+         *         buf pack-> lbuf pack-> cbuf    ==     xbuf == abuf
+         *                                abuf
+         *  if noncontig &&    imap &&    convert
+         *         buf pack-> lbuf pack-> cbuf convert-> xbuf == abuf
+         *                                               abuf
+         */
+
+        /* Step 1: pack buf into a contiguous buffer, lbuf, if buftype is
+         * not contiguous
+         */
+        if (!buftype_is_contig) { /* buftype is not contiguous */
+            /* allocate lbuf */
+            if (use_abuf && imaptype == MPI_DATATYPE_NULL && !need_convert) {
+                status = ncmpii_abuf_malloc(ncp, nbytes, &lbuf, &abuf_index);
+                if (status != NC_NOERR) return status;
+                abuf_allocated = 1;
+            }
+            else lbuf = NCI_Malloc((size_t)outsize);
+
+            if (bufcount != (int)bufcount) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+
+            /* pack buf into lbuf using buftype */
+            position = 0;
+            MPI_Pack(buf, (int)bufcount, buftype, lbuf, (int)outsize,
+                     &position, MPI_COMM_SELF);
+        }
+        else /* for contiguous case, we reuse buf */
+            lbuf = buf;
+
+        /* Step 2: pack lbuf to cbuf if imap is non-contiguous */
+        if (imaptype != MPI_DATATYPE_NULL) { /* true varm */
+            /* allocate cbuf */
+            if (use_abuf && !need_convert) {
+                assert(abuf_allocated == 0);
+                status = ncmpii_abuf_malloc(ncp, nbytes, &cbuf, &abuf_index);
+                if (status != NC_NOERR) {
+                    if (lbuf != buf) NCI_Free(lbuf);
+                    return status;
+                }
+                abuf_allocated = 1;
+            }
+            else cbuf = NCI_Malloc((size_t)outsize);
+
+            /* pack lbuf to cbuf using imaptype */
+            position = 0;
+            MPI_Pack(lbuf, 1, imaptype, cbuf, (int)outsize, &position,
+                     MPI_COMM_SELF);
+            MPI_Type_free(&imaptype);
+        }
+        else /* not a true varm call: reuse lbuf */
+            cbuf = lbuf;
+
+        /* lbuf is no longer needed */
+        if (lbuf != buf && lbuf != cbuf) NCI_Free(lbuf);
+
+        /* Step 3: type-convert and byte-swap cbuf to xbuf, and xbuf will be
+         * used in MPI write function to write to file
+         */
+
+        /* when user buf type != nc var type defined in file */
+        if (need_convert) {
+            if (use_abuf) { /* use attached buffer to allocate xbuf */
+                assert(abuf_allocated == 0);
+                status = ncmpii_abuf_malloc(ncp, nbytes, &xbuf, &abuf_index);
+                if (status != NC_NOERR) {
+                    if (cbuf != buf) NCI_Free(cbuf);
+                    return status;
+                }
+                abuf_allocated = 1;
+            }
+            else xbuf = NCI_Malloc((size_t)nbytes);
+
+            /* datatype conversion + byte-swap from cbuf to xbuf */
+            DATATYPE_PUT_CONVERT(varp->type, xbuf, cbuf, bnelems, ptype, status)
+            /* NC_ERANGE can be caused by a subset of buf that is out of range
+             * of the external data type, it is not considered a fatal error.
+             * The request must continue to finish.
+             */
+            if (status != NC_NOERR && status != NC_ERANGE) {
+                if (cbuf != buf)  NCI_Free(cbuf);
+                if (xbuf != NULL) NCI_Free(xbuf);
+                return status;
+            }
+        }
+        else {
+            if (use_abuf && buftype_is_contig && imaptype == MPI_DATATYPE_NULL){
+                assert(abuf_allocated == 0);
+                status = ncmpii_abuf_malloc(ncp, nbytes, &xbuf, &abuf_index);
+                if (status != NC_NOERR) {
+                    if (cbuf != buf) NCI_Free(cbuf);
+                    return status;
+                }
+                memcpy(xbuf, cbuf, (size_t)nbytes);
+            }
+            else xbuf = cbuf;
+
+            if (need_swap) {
+#ifdef DISABLE_IN_PLACE_SWAP
+                if (xbuf == buf) {
+#else
+                if (xbuf == buf && nbytes <= NC_BYTE_SWAP_BUFFER_SIZE) {
+#endif
+                    /* allocate xbuf and copy buf to xbuf, before byte-swap */
+                    xbuf = NCI_Malloc((size_t)nbytes);
+                    memcpy(xbuf, buf, (size_t)nbytes);
+                }
+                /* perform array in-place byte swap on xbuf */
+                ncmpii_in_swapn(xbuf, bnelems, ncmpix_len_nctype(varp->type));
+
+                if (xbuf == buf) need_swap_back_buf = 1;
+                /* user buf needs to be swapped back to its original contents */
+            }
+        }
+        /* cbuf is no longer needed */
+        if (cbuf != buf && cbuf != xbuf) NCI_Free(cbuf);
+    }
+    else { /* rw_flag == READ_REQ */
+        /* Type conversion and byte swap for read are done at wait call, we
+         * need bnelems to reverse the steps as done in write case
+         */
+        if (buftype_is_contig && imaptype == MPI_DATATYPE_NULL && !need_convert)
+            xbuf = buf;  /* there is no buffered read (bget_var, etc.) */
+        else
+            xbuf = NCI_Malloc((size_t)nbytes);
+    }
+
+    /* allocate a new request object to store the write info */
+    req = (NC_req*) NCI_Malloc(sizeof(NC_req));
+
+    req->buf                = buf;
+    req->xbuf               = xbuf;
+    req->bnelems            = bnelems;
+    req->bufcount           = bufcount;
+    req->ptype              = ptype;
+    req->buftype_is_contig  = buftype_is_contig;
+    req->need_swap_back_buf = need_swap_back_buf;
+    req->imaptype           = imaptype;
+    req->rw_flag            = rw_flag;
+    req->abuf_index         = abuf_index;
+    req->tmpBuf             = NULL;
+    req->userBuf            = NULL;
+
+    /* only when read and buftype is not contiguous, we duplicate buftype for
+     * later in the wait call to unpack buffer based on buftype
+     */
+    if (rw_flag == READ_REQ && !buftype_is_contig)
+        MPI_Type_dup(buftype, &req->buftype);
+    else
+        req->buftype = MPI_DATATYPE_NULL;
+
+    pack_request(ncp, varp, req, start, count, stride);
+
+    /* add the new request to the internal request array (or linked list) */
+    if (ncp->head == NULL) {
+        req->id   = 0;
+        ncp->head = req;
+        ncp->tail = ncp->head;
+    }
+    else { /* add to the tail */
+        if (!isSameGroup)
+            req->id = ncp->tail->id + 1;
+        else if (reqid != NULL)
+            req->id = *reqid;
+        ncp->tail->next = req;
+        ncp->tail = req;
+    }
+    for (i=0; i<req->num_subreqs; i++)
+        req->subreqs[i].id = req->id;
+
+    /* return the request ID */
+    if (reqid != NULL) *reqid = req->id;
+
+    return ((warning != NC_NOERR) ? warning : status);
+}
+
+/*----< pack_request() >------------------------------------------------------*/
+/* if this request is for a record variable, then we break this request into
+ * sub-requests, each for a record
+ */
+static int
+pack_request(NC               *ncp,
+             NC_var           *varp,
+             NC_req           *req,
+             const MPI_Offset  start[],
+             const MPI_Offset  count[],
+             const MPI_Offset  stride[])
+{
+    int     i, j;
+    size_t  dims_chunk;
+    NC_req *subreqs;
+
+    dims_chunk       = (size_t)varp->ndims * SIZEOF_MPI_OFFSET;
+
+    req->varp        = varp;
+    req->next        = NULL;
+    req->subreqs     = NULL;
+    req->num_subreqs = 0;
+
+    if (stride != NULL)
+        req->start = (MPI_Offset*) NCI_Malloc(dims_chunk*3);
+    else
+        req->start = (MPI_Offset*) NCI_Malloc(dims_chunk*2);
+
+    req->count = req->start + varp->ndims;
+
+    if (stride != NULL)
+        req->stride = req->count + varp->ndims;
+    else
+        req->stride = NULL;
+
+    for (i=0; i<varp->ndims; i++) {
+        req->start[i] = start[i];
+        req->count[i] = count[i];
+        if (stride != NULL)
+            req->stride[i] = stride[i];
+    }
+
+#ifdef _DISALLOW_POST_NONBLOCKING_API_IN_DEFINE_MODE
+    /* move the offset calculation to wait time (ncmpii_wait_getput),
+     * such that posting a nonblocking request can be done in define
+     * mode
+     */
+
+    /* get the starting file offset for this request */
+    ncmpii_get_offset(ncp, varp, start, NULL, NULL, req->rw_flag,
+                      &req->offset_start);
+
+    /* get the ending file offset for this request */
+    ncmpii_get_offset(ncp, varp, start, count, stride, req->rw_flag,
+                      &req->offset_end);
+    req->offset_end += varp->xsz - 1;
+#endif
+
+    /* check if this is a record variable. if yes, split the request into
+     * subrequests, one subrequest for a record access. Hereinafter,
+     * treat each request as a non-record variable request
+     */
+
+    /* check if this access is within one record, if yes, no need to create
+       subrequests */
+    if (IS_RECVAR(varp) && req->count[0] > 1) {
+        MPI_Offset rec_bufcount = 1;
+        for (i=1; i<varp->ndims; i++)
+            rec_bufcount *= req->count[i];
+
+        subreqs = (NC_req*) NCI_Malloc((size_t)req->count[0]*sizeof(NC_req));
+        for (i=0; i<req->count[0]; i++) {
+            MPI_Offset span;
+            subreqs[i] = *req; /* inherit most attributes from req */
+
+            /* each sub-request contains <= one record size */
+            if (stride != NULL)
+                subreqs[i].start = (MPI_Offset*) NCI_Malloc(dims_chunk*3);
+            else
+                subreqs[i].start = (MPI_Offset*) NCI_Malloc(dims_chunk*2);
+
+            subreqs[i].count = subreqs[i].start + varp->ndims;
+
+            if (stride != NULL) {
+                subreqs[i].stride = subreqs[i].count + varp->ndims;
+                subreqs[i].start[0] = req->start[0] + stride[0] * i;
+                subreqs[i].stride[0] = req->stride[0];
+            } else {
+                subreqs[i].stride = NULL;
+                subreqs[i].start[0] = req->start[0] + i;
+            }
+
+            subreqs[i].count[0] = 1;
+            subreqs[i].bnelems = 1;
+            for (j=1; j<varp->ndims; j++) {
+                subreqs[i].start[j]  = req->start[j];
+                subreqs[i].count[j]  = req->count[j];
+                subreqs[i].bnelems  *= subreqs[i].count[j];
+                if (stride != NULL)
+                    subreqs[i].stride[j] = req->stride[j];
+            }
+
+#ifdef _DISALLOW_POST_NONBLOCKING_API_IN_DEFINE_MODE
+            /* move the offset calculation to wait time (ncmpii_wait_getput),
+             * such that posting a nonblocking request can be done in define
+             * mode
+             */
+            ncmpii_get_offset(ncp, varp, subreqs[i].start, NULL, NULL,
+                              subreqs[i].rw_flag, &subreqs[i].offset_start);
+            ncmpii_get_offset(ncp, varp, subreqs[i].start,
+                              subreqs[i].count, subreqs[i].stride,
+                              subreqs[i].rw_flag, &subreqs[i].offset_end);
+            subreqs[i].offset_end += varp->xsz - 1;
+#endif
+            span                = i*rec_bufcount*varp->xsz;
+            subreqs[i].buf      = (char*)(req->buf)  + span;
+            /* xbuf cannot be NULL    assert(req->xbuf != NULL); */
+            subreqs[i].xbuf     = (char*)(req->xbuf) + span;
+            subreqs[i].bufcount = rec_bufcount;
+        }
+        req->num_subreqs = (int)req->count[0];
+        req->subreqs     = subreqs;
+
+        if (req->count[0] != (int)req->count[0])
+            DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    }
+
+    return NC_NOERR;
+}
+
diff --git a/src/lib/i_varn.m4 b/src/lib/i_varn.m4
new file mode 100644
index 0000000..f3fa832
--- /dev/null
+++ b/src/lib/i_varn.m4
@@ -0,0 +1,336 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: i_varn.m4 2290 2016-01-02 18:37:46Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "ncmpidtype.h"
+#include "macro.h"
+
+/* ncmpi_iget/iput_varn_<type>_<mode> API:
+ *    type:   data type of I/O buffer, buf
+ *    mode:   indpendent (<nond>) or collective (_all)
+ *
+ * arguments:
+ *    num:    number of start and count pairs
+ *    starts: an 2D array of size [num][ndims]. Each starts[i][*] indicates
+ *            the starting array indices for a subarray request. ndims is
+ *            the number of dimensions of the defined netCDF variable.
+ *    counts: an 2D array of size [num][ndims]. Each counts[i][*] indicates
+ *            the number of array elements to be accessed. This argument
+ *            can be NULL, equivalent to counts with all 1s.
+ *    bufcount and buftype: these 2 arguments are only available for flexible
+ *            APIs, indicating the I/O buffer memory layout. When buftype is
+ *            MPI_DATATYPE_NULL, bufcount is ignored and the data type of buf
+ *            is considered matched the variable data type defined in the file.
+ *    reqid:  request ID returned to user
+ */
+
+static int
+ncmpii_igetput_varn(NC               *ncp,
+                    NC_var           *varp,
+                    int               num,
+                    MPI_Offset* const starts[],  /* [num][varp->ndims] */
+                    MPI_Offset* const counts[],  /* [num][varp->ndims] */
+                    void             *buf,
+                    MPI_Offset        bufcount,
+                    MPI_Datatype      buftype,   /* data type of the bufer */
+                    int              *reqid,
+                    int               rw_flag,
+                    int               use_abuf);
+
+dnl
+define(`IsBput',    `ifelse(`$1',`bput', `1', `0')')dnl
+define(`ReadWrite', `ifelse(`$1',`iget', `READ_REQ', `WRITE_REQ')')dnl
+define(`BufConst',  `ifelse(`$1',`iget', , `const')')dnl
+dnl
+dnl VARN_FLEXIBLE()
+dnl
+define(`VARN_FLEXIBLE',dnl
+`dnl
+/*----< ncmpi_$1_varn() >-----------------------------------------------------*/
+int
+ncmpi_$1_varn(int                 ncid,
+              int                 varid,
+              int                 num,
+              MPI_Offset* const   starts[],
+              MPI_Offset* const   counts[],
+              BufConst($1) void  *buf,
+              MPI_Offset          bufcount,
+              MPI_Datatype        buftype,
+              int                *reqid)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+
+    /* check for zero-size request */
+    if (num == 0 || bufcount == 0) return NC_NOERR;
+
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VARN,
+                                 0, 1, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_igetput_varn(ncp, varp, num, starts, counts, (void*)buf,
+                               bufcount, buftype, reqid, ReadWrite($1),
+                               IsBput($1));
+}
+')dnl
+
+dnl PnetCDF flexible APIs
+VARN_FLEXIBLE(iput)
+VARN_FLEXIBLE(iget)
+VARN_FLEXIBLE(bput)
+
+dnl
+dnl VARN()
+dnl
+define(`VARN',dnl
+`dnl
+/*----< ncmpi_$1_varn_$2() >--------------------------------------------------*/
+int
+ncmpi_$1_varn_$2(int                ncid,
+                 int                varid,
+                 int                num,
+                 MPI_Offset* const  starts[],
+                 MPI_Offset* const  counts[],
+                 BufConst($1) $3   *buf,
+                 int               *reqid)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    if (reqid != NULL) *reqid = NC_REQ_NULL;
+
+    /* check for zero request */
+    if (num == 0) return NC_NOERR;
+
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, 0, API_VARN,
+                                 0, 0, ReadWrite($1), NONBLOCKING_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    /* set bufcount to -1 indicating non-flexible API */
+    return ncmpii_igetput_varn(ncp, varp, num, starts, counts, (void*)buf,
+                               -1, $4, reqid, ReadWrite($1), IsBput($1));
+}
+')dnl
+
+VARN(iput, text,      char,               MPI_CHAR)
+VARN(iput, schar,     schar,              MPI_SIGNED_CHAR)
+VARN(iput, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARN(iput, short,     short,              MPI_SHORT)
+VARN(iput, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARN(iput, int,       int,                MPI_INT)
+VARN(iput, uint,      uint,               MPI_UNSIGNED)
+VARN(iput, long,      long,               MPI_LONG)
+VARN(iput, float,     float,              MPI_FLOAT)
+VARN(iput, double,    double,             MPI_DOUBLE)
+VARN(iput, longlong,  long long,          MPI_LONG_LONG_INT)
+VARN(iput, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARN(iget, text,      char,               MPI_CHAR)
+VARN(iget, schar,     schar,              MPI_SIGNED_CHAR)
+VARN(iget, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARN(iget, short,     short,              MPI_SHORT)
+VARN(iget, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARN(iget, int,       int,                MPI_INT)
+VARN(iget, uint,      uint,               MPI_UNSIGNED)
+VARN(iget, long,      long,               MPI_LONG)
+VARN(iget, float,     float,              MPI_FLOAT)
+VARN(iget, double,    double,             MPI_DOUBLE)
+VARN(iget, longlong,  long long,          MPI_LONG_LONG_INT)
+VARN(iget, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARN(bput, text,      char,               MPI_CHAR)
+VARN(bput, schar,     schar,              MPI_SIGNED_CHAR)
+VARN(bput, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARN(bput, short,     short,              MPI_SHORT)
+VARN(bput, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARN(bput, int,       int,                MPI_INT)
+VARN(bput, uint,      uint,               MPI_UNSIGNED)
+VARN(bput, long,      long,               MPI_LONG)
+VARN(bput, float,     float,              MPI_FLOAT)
+VARN(bput, double,    double,             MPI_DOUBLE)
+VARN(bput, longlong,  long long,          MPI_LONG_LONG_INT)
+VARN(bput, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+
+/*----< ncmpii_igetput_varn() >-----------------------------------------------*/
+static int
+ncmpii_igetput_varn(NC               *ncp,
+                    NC_var           *varp,
+                    int               num,
+                    MPI_Offset* const starts[],  /* [num][varp->ndims] */
+                    MPI_Offset* const counts[],  /* [num][varp->ndims] */
+                    void             *buf,
+                    MPI_Offset        bufcount,
+                    MPI_Datatype      buftype,   /* data type of the bufer */
+                    int              *reqidp,    /* OUT: request ID */
+                    int               rw_flag,   /* WRITE_REQ or READ_REQ */
+                    int               use_abuf)  /* if use attached buffer */
+{
+    int i, j, el_size, status=NC_NOERR, free_cbuf=0, isSameGroup, reqid;
+    void *cbuf=NULL;
+    char *bufp;
+    MPI_Offset **_counts=NULL;
+    MPI_Datatype ptype;
+
+    if (use_abuf && ncp->abuf == NULL) DEBUG_RETURN_ERROR(NC_ENULLABUF)
+
+    /* it is illegal for starts to be NULL */
+    if (starts == NULL) DEBUG_RETURN_ERROR(NC_ENULLSTART)
+
+    if (counts != NULL) {
+        for (j=0; j<num; j++) {
+            for (i=0; i<varp->ndims; i++) {
+                if (counts[j][i] < 0) /* no negative counts[][] */
+                    DEBUG_RETURN_ERROR(NC_ENEGATIVECNT)
+            }
+        }
+    }
+
+    cbuf = buf;
+    if (buftype == MPI_DATATYPE_NULL) {
+        /* In this case, we make ptype match the variable data type defined
+         * in file - no data conversion will be done. Also, it means buf is
+         * contiguous. buftype will no longer be used.
+         */
+        ptype = ncmpii_nc2mpitype(varp->type);
+        MPI_Type_size(ptype, &el_size); /* buffer element size */
+    }
+    else if (bufcount == -1) { /* if (IsPrimityMPIType(buftype)) */
+        /* this subroutine is called from a high-level API
+         * Also, it means the user buf is contiguous.
+         * Assign ptype to buftype, and buftype will no longer be used.
+         */
+        ptype = buftype;
+        MPI_Type_size(ptype, &el_size); /* buffer element size */
+    }
+    else { /* (bufcount > 0) flexible API is used */
+        /* pack buf into cbuf, a contiguous buffer */
+        int isderived, iscontig_of_ptypes;
+        MPI_Offset bnelems;
+
+        /* ptype (primitive MPI data type) from buftype
+         * el_size is the element size of ptype
+         * bnelems is the total number of ptype elements in buftype
+         */
+        status = ncmpii_dtype_decode(buftype, &ptype, &el_size, &bnelems,
+                                     &isderived, &iscontig_of_ptypes);
+
+        if (status != NC_NOERR) return status;
+
+        if (bufcount != (int)bufcount) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+
+        /* check if buftype is contiguous, if not, pack to one, cbuf */
+        if (! iscontig_of_ptypes && bnelems > 0) {
+            int position = 0;
+            MPI_Offset packsize = bnelems*el_size;
+            if (packsize != (int)packsize) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+
+            cbuf = NCI_Malloc((size_t)packsize);
+            free_cbuf = 1;
+            /* if not use_abuf, need a callback to free cbuf */
+
+            if (rw_flag == WRITE_REQ)
+                MPI_Pack(buf, (int)bufcount, buftype, cbuf, (int)packsize,
+                         &position, MPI_COMM_SELF);
+        }
+    }
+
+    /* We allow counts == NULL and treat this the same as all 1s */
+    if (counts == NULL) {
+        _counts    = (MPI_Offset**) NCI_Malloc((size_t)num * sizeof(MPI_Offset*));
+        _counts[0] = (MPI_Offset*)  NCI_Malloc((size_t)(num * varp->ndims *
+                                                        SIZEOF_MPI_OFFSET));
+        for (i=1; i<num; i++)
+            _counts[i] = _counts[i-1] + varp->ndims;
+        for (i=0; i<num; i++)
+            for (j=0; j<varp->ndims; j++)
+                _counts[i][j] = 1;
+    }
+    else
+        _counts = (MPI_Offset**) counts;
+
+    /* break buf into num pieces */
+    isSameGroup=0;
+    bufp = (char*)cbuf;
+    for (i=0; i<num; i++) {
+        MPI_Offset buflen;
+
+        /* check whether start, count, and stride are valid */
+        status = NC_start_count_stride_ck(ncp, varp, starts[i], _counts[i], NULL, rw_flag);
+        if (status != NC_NOERR) goto err_check;
+
+        for (buflen=1, j=0; j<varp->ndims; j++)
+            buflen *= _counts[i][j];
+
+        if (buflen == 0) continue;
+        status = ncmpii_igetput_varm(ncp, varp, starts[i], _counts[i], NULL,
+                                     NULL, bufp, buflen, ptype, &reqid,
+                                     rw_flag, use_abuf, isSameGroup);
+        if (status != NC_NOERR) goto err_check;
+
+        /* use isSamegroup so we end up with one nonblocking request (only the
+         * first request gets a request ID back, the rest reuse the same ID.
+         * This single ID represents num nonblocking requests */
+        isSameGroup=1;
+        bufp += buflen * el_size;
+    }
+
+    /* add callback if buftype is noncontiguous */
+    if (free_cbuf) { /* cbuf != buf, cbuf is temp allocated */
+        if (rw_flag == READ_REQ) {
+            /* tell wait() to unpack cbuf to buf and free cbuf */
+            status = ncmpii_set_iget_callback(ncp, reqid, cbuf, buf,
+                                              (int)bufcount, buftype);
+        }
+        else { /* WRITE_REQ */
+            if (use_abuf)
+                /* cbuf has been copied to the attached buffer, so it is safe
+                 * to free cbuf now */
+                NCI_Free(cbuf);
+            else
+                /* tell wait() to free cbuf once done */
+                status = ncmpii_set_iput_callback(ncp, reqid, cbuf);
+        }
+    }
+
+err_check:
+    if (_counts != NULL && _counts != counts) {
+        NCI_Free(_counts[0]);
+        NCI_Free(_counts);
+    }
+
+    if (status != NC_NOERR) {
+        if (reqid != NC_REQ_NULL) /* cancel pending nonblocking request */
+            ncmpii_cancel(ncp, 1, &reqid, NULL);
+        if (free_cbuf) NCI_Free(cbuf);
+    }
+    if (reqidp != NULL) *reqidp = reqid;
+
+    return status;
+}
diff --git a/src/lib/m_getput_varx.m4 b/src/lib/m_getput_varx.m4
new file mode 100644
index 0000000..96575d9
--- /dev/null
+++ b/src/lib/m_getput_varx.m4
@@ -0,0 +1,1090 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: m_getput_varx.m4 2290 2016-01-02 18:37:46Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "ncmpidtype.h"
+#include "macro.h"
+
+
+/* buffer layers:
+
+        User Level              buf     (user defined buffer of MPI_Datatype)
+        MPI Datatype Level      cbuf    (contiguous buffer of ptype)
+        NetCDF XDR Level        xbuf    (XDR I/O buffer)
+*/
+
+static int
+ncmpii_mgetput_varm(int                ncid,
+                    int                num,
+                    int                varids[],    /* [num] */
+                    MPI_Offset* const  starts[],    /* [num] */
+                    MPI_Offset* const  counts[],    /* [num] */
+                    MPI_Offset* const  strides[],   /* [num] */
+                    MPI_Offset* const  imaps[],     /* [num] */
+                    void              *bufs[],      /* [num] */
+                    MPI_Offset         bufcounts[], /* [num] */
+                    MPI_Datatype       datatypes[], /* [num] */
+                    int                rw_flag,     /* WRITE_REQ or READ_REQ */
+                    int                io_method);  /* COLL_IO or INDEP_IO */
+
+/*----< ncmpi_mput_var() >---------------------------------------------------*/
+int
+ncmpi_mput_var(int           ncid,
+               int           num,
+               int           varids[],    /* [num] */
+               void         *bufs[],      /* [num] */
+               MPI_Offset    bufcounts[], /* [num] */
+               MPI_Datatype  datatypes[]) /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, NULL, NULL, NULL,
+                               NULL, bufs, bufcounts, datatypes,
+                               WRITE_REQ, INDEP_IO);
+}
+
+/*----< ncmpi_mput_var_all() >-----------------------------------------------*/
+int
+ncmpi_mput_var_all(int           ncid,
+                   int           num,
+                   int           varids[],    /* [num] */
+                   void         *bufs[],      /* [num] */
+                   MPI_Offset    bufcounts[], /* [num] */
+                   MPI_Datatype  datatypes[]) /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, NULL, NULL, NULL,
+                               NULL, bufs, bufcounts, datatypes,
+                               WRITE_REQ, COLL_IO);
+}
+
+dnl
+dnl MPUT_VAR(btype_name, btype, mpi_type, mode, mode_name)
+dnl
+define(`MPUT_VAR',dnl
+`dnl
+/*----< ncmpi_mput_var_$1$5() >-----------------------------------------------*/
+int
+ncmpi_mput_var_$1$5(int ncid,
+                    int num,
+                    int varids[],
+                    $2 *bufs[])
+{
+    int i, err;
+    MPI_Datatype *datatypes;
+
+    datatypes = (MPI_Datatype*) NCI_Malloc((size_t)num * sizeof(MPI_Datatype));
+    for (i=0; i<num; i++)
+        datatypes[i] = $3;
+
+    err = ncmpii_mgetput_varm(ncid, num, varids, NULL, NULL, NULL,
+                              NULL, (void**)bufs, NULL, datatypes,
+                              WRITE_REQ, $4);
+    NCI_Free(datatypes);
+    return err;
+}
+')dnl
+
+MPUT_VAR(text,      char,               MPI_CHAR,               INDEP_IO)
+MPUT_VAR(schar,     signed char,        MPI_SIGNED_CHAR,        INDEP_IO)
+MPUT_VAR(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      INDEP_IO)
+MPUT_VAR(short,     short,              MPI_SHORT,              INDEP_IO)
+MPUT_VAR(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     INDEP_IO)
+MPUT_VAR(int,       int,                MPI_INT,                INDEP_IO)
+MPUT_VAR(uint,      unsigned int,       MPI_UNSIGNED,           INDEP_IO)
+MPUT_VAR(long,      long,               MPI_LONG,               INDEP_IO)
+MPUT_VAR(float,     float,              MPI_FLOAT,              INDEP_IO)
+MPUT_VAR(double,    double,             MPI_DOUBLE,             INDEP_IO)
+MPUT_VAR(longlong,  long long,          MPI_LONG_LONG_INT,      INDEP_IO)
+MPUT_VAR(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, INDEP_IO)
+
+MPUT_VAR(text,      char,               MPI_CHAR,               COLL_IO, _all)
+MPUT_VAR(schar,     signed char,        MPI_SIGNED_CHAR,        COLL_IO, _all)
+MPUT_VAR(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      COLL_IO, _all)
+MPUT_VAR(short,     short,              MPI_SHORT,              COLL_IO, _all)
+MPUT_VAR(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     COLL_IO, _all)
+MPUT_VAR(int,       int,                MPI_INT,                COLL_IO, _all)
+MPUT_VAR(uint,      unsigned int,       MPI_UNSIGNED,           COLL_IO, _all)
+MPUT_VAR(long,      long,               MPI_LONG,               COLL_IO, _all)
+MPUT_VAR(float,     float,              MPI_FLOAT,              COLL_IO, _all)
+MPUT_VAR(double,    double,             MPI_DOUBLE,             COLL_IO, _all)
+MPUT_VAR(longlong,  long long,          MPI_LONG_LONG_INT,      COLL_IO, _all)
+MPUT_VAR(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, COLL_IO, _all)
+
+/*----< ncmpi_mput_var1() >--------------------------------------------------*/
+int
+ncmpi_mput_var1(int                ncid,
+                int                num,
+                int                varids[],    /* [num] */
+                MPI_Offset* const  starts[],    /* [num] */
+                void              *bufs[],      /* [num] */
+                MPI_Offset         bufcounts[], /* [num] */
+                MPI_Datatype       datatypes[]) /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, NULL, NULL,
+                               NULL, bufs, bufcounts, datatypes,
+                               WRITE_REQ, INDEP_IO);
+}
+
+/*----< ncmpi_mput_var1_all() >----------------------------------------------*/
+int
+ncmpi_mput_var1_all(int                ncid,
+                    int                num,
+                    int                varids[],    /* [num] */
+                    MPI_Offset* const  starts[],    /* [num] */
+                    void              *bufs[],      /* [num] */
+                    MPI_Offset         bufcounts[], /* [num] */
+                    MPI_Datatype       datatypes[]) /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, NULL, NULL,
+                               NULL, bufs, bufcounts, datatypes,
+                               WRITE_REQ, COLL_IO);
+}
+
+dnl
+dnl MPUT_VAR1(btype_name, btype, mpi_type, mode, mode_name)
+dnl
+define(`MPUT_VAR1',dnl
+`dnl
+/*----< ncmpi_mput_var1_$1$5() >----------------------------------------------*/
+int
+ncmpi_mput_var1_$1$5(int                ncid,
+                     int                num,
+                     int                varids[],
+                     MPI_Offset* const  starts[],    /* [num] */
+                     $2                *bufs[])
+{
+    int i, err;
+    MPI_Datatype *datatypes;
+
+    datatypes = (MPI_Datatype*) NCI_Malloc((size_t)num * sizeof(MPI_Datatype));
+    for (i=0; i<num; i++)
+        datatypes[i] = $3;
+
+    err = ncmpii_mgetput_varm(ncid, num, varids, starts, NULL, NULL,
+                              NULL, (void**)bufs, NULL, datatypes,
+                              WRITE_REQ, $4);
+    NCI_Free(datatypes);
+    return err;
+}
+')dnl
+
+MPUT_VAR1(text,      char,               MPI_CHAR,               INDEP_IO)
+MPUT_VAR1(schar,     signed char,        MPI_SIGNED_CHAR,        INDEP_IO)
+MPUT_VAR1(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      INDEP_IO)
+MPUT_VAR1(short,     short,              MPI_SHORT,              INDEP_IO)
+MPUT_VAR1(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     INDEP_IO)
+MPUT_VAR1(int,       int,                MPI_INT,                INDEP_IO)
+MPUT_VAR1(uint,      unsigned int,       MPI_UNSIGNED,           INDEP_IO)
+MPUT_VAR1(long,      long,               MPI_LONG,               INDEP_IO)
+MPUT_VAR1(float,     float,              MPI_FLOAT,              INDEP_IO)
+MPUT_VAR1(double,    double,             MPI_DOUBLE,             INDEP_IO)
+MPUT_VAR1(longlong,  long long,          MPI_LONG_LONG_INT,      INDEP_IO)
+MPUT_VAR1(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, INDEP_IO)
+
+MPUT_VAR1(text,      char,               MPI_CHAR,               COLL_IO, _all)
+MPUT_VAR1(schar,     signed char,        MPI_SIGNED_CHAR,        COLL_IO, _all)
+MPUT_VAR1(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      COLL_IO, _all)
+MPUT_VAR1(short,     short,              MPI_SHORT,              COLL_IO, _all)
+MPUT_VAR1(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     COLL_IO, _all)
+MPUT_VAR1(int,       int,                MPI_INT,                COLL_IO, _all)
+MPUT_VAR1(uint,      unsigned int,       MPI_UNSIGNED,           COLL_IO, _all)
+MPUT_VAR1(long,      long,               MPI_LONG,               COLL_IO, _all)
+MPUT_VAR1(float,     float,              MPI_FLOAT,              COLL_IO, _all)
+MPUT_VAR1(double,    double,             MPI_DOUBLE,             COLL_IO, _all)
+MPUT_VAR1(longlong,  long long,          MPI_LONG_LONG_INT,      COLL_IO, _all)
+MPUT_VAR1(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, COLL_IO, _all)
+
+/*----< ncmpi_mput_vara() >--------------------------------------------------*/
+int
+ncmpi_mput_vara(int                ncid,
+                int                num,
+                int                varids[],    /* [num] */
+                MPI_Offset* const  starts[],    /* [num] */
+                MPI_Offset* const  counts[],    /* [num] */
+                void              *bufs[],      /* [num] */
+                MPI_Offset         bufcounts[], /* [num] */
+                MPI_Datatype       datatypes[]) /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, counts, NULL,
+                               NULL, bufs, bufcounts, datatypes,
+                               WRITE_REQ, INDEP_IO);
+}
+
+/*----< ncmpi_mput_vara_all() >----------------------------------------------*/
+int
+ncmpi_mput_vara_all(int                ncid,
+                    int                num,
+                    int                varids[],    /* [num] */
+                    MPI_Offset* const  starts[],    /* [num] */
+                    MPI_Offset* const  counts[],    /* [num] */
+                    void              *bufs[],      /* [num] */
+                    MPI_Offset         bufcounts[], /* [num] */
+                    MPI_Datatype       datatypes[]) /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, counts, NULL,
+                               NULL, bufs, bufcounts, datatypes,
+                               WRITE_REQ, COLL_IO);
+}
+
+dnl
+dnl MPUT_VARA(btype_name, btype, mpi_type, mode, mode_name)
+dnl
+define(`MPUT_VARA',dnl
+`dnl
+/*----< ncmpi_mput_vara_$1$5() >----------------------------------------------*/
+int
+ncmpi_mput_vara_$1$5(int                ncid,
+                     int                num,
+                     int                varids[],
+                     MPI_Offset* const  starts[],    /* [num] */
+                     MPI_Offset* const  counts[],    /* [num] */
+                     $2                *bufs[])
+{
+    int i, err;
+    MPI_Datatype *datatypes;
+
+    datatypes = (MPI_Datatype*) NCI_Malloc((size_t)num * sizeof(MPI_Datatype));
+    for (i=0; i<num; i++)
+        datatypes[i] = $3;
+
+    err = ncmpii_mgetput_varm(ncid, num, varids, starts, counts, NULL,
+                              NULL, (void**)bufs, NULL, datatypes,
+                              WRITE_REQ, $4);
+    NCI_Free(datatypes);
+    return err;
+}
+')dnl
+
+MPUT_VARA(text,      char,               MPI_CHAR,               INDEP_IO)
+MPUT_VARA(schar,     signed char,        MPI_SIGNED_CHAR,        INDEP_IO)
+MPUT_VARA(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      INDEP_IO)
+MPUT_VARA(short,     short,              MPI_SHORT,              INDEP_IO)
+MPUT_VARA(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     INDEP_IO)
+MPUT_VARA(int,       int,                MPI_INT,                INDEP_IO)
+MPUT_VARA(uint,      unsigned int,       MPI_UNSIGNED,           INDEP_IO)
+MPUT_VARA(long,      long,               MPI_LONG,               INDEP_IO)
+MPUT_VARA(float,     float,              MPI_FLOAT,              INDEP_IO)
+MPUT_VARA(double,    double,             MPI_DOUBLE,             INDEP_IO)
+MPUT_VARA(longlong,  long long,          MPI_LONG_LONG_INT,      INDEP_IO)
+MPUT_VARA(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, INDEP_IO)
+
+MPUT_VARA(text,      char,               MPI_CHAR,               COLL_IO, _all)
+MPUT_VARA(schar,     signed char,        MPI_SIGNED_CHAR,        COLL_IO, _all)
+MPUT_VARA(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      COLL_IO, _all)
+MPUT_VARA(short,     short,              MPI_SHORT,              COLL_IO, _all)
+MPUT_VARA(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     COLL_IO, _all)
+MPUT_VARA(int,       int,                MPI_INT,                COLL_IO, _all)
+MPUT_VARA(uint,      unsigned int,       MPI_UNSIGNED,           COLL_IO, _all)
+MPUT_VARA(long,      long,               MPI_LONG,               COLL_IO, _all)
+MPUT_VARA(float,     float,              MPI_FLOAT,              COLL_IO, _all)
+MPUT_VARA(double,    double,             MPI_DOUBLE,             COLL_IO, _all)
+MPUT_VARA(longlong,  long long,          MPI_LONG_LONG_INT,      COLL_IO, _all)
+MPUT_VARA(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, COLL_IO, _all)
+
+/*----< ncmpi_mput_vars() >--------------------------------------------------*/
+int
+ncmpi_mput_vars(int                ncid,
+                int                num,
+                int                varids[],    /* [num] */
+                MPI_Offset* const  starts[],    /* [num] */
+                MPI_Offset* const  counts[],    /* [num] */
+                MPI_Offset* const  strides[],   /* [num] */
+                void              *bufs[],      /* [num] */
+                MPI_Offset         bufcounts[], /* [num] */
+                MPI_Datatype       datatypes[]) /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, counts, strides,
+                               NULL, bufs, bufcounts, datatypes,
+                               WRITE_REQ, INDEP_IO);
+}
+
+/*----< ncmpi_mput_vars_all() >----------------------------------------------*/
+int
+ncmpi_mput_vars_all(int                ncid,
+                    int                num,
+                    int                varids[],    /* [num] */
+                    MPI_Offset* const  starts[],    /* [num] */
+                    MPI_Offset* const  counts[],    /* [num] */
+                    MPI_Offset* const  strides[],   /* [num] */
+                    void              *bufs[],      /* [num] */
+                    MPI_Offset         bufcounts[], /* [num] */
+                    MPI_Datatype       datatypes[]) /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, counts, strides,
+                               NULL, bufs, bufcounts, datatypes,
+                               WRITE_REQ, COLL_IO);
+}
+
+dnl
+dnl MPUT_VARS(btype_name, btype, mpi_type, mode, mode_name)
+dnl
+define(`MPUT_VARS',dnl
+`dnl
+/*----< ncmpi_mput_vars_$1$5() >----------------------------------------------*/
+int
+ncmpi_mput_vars_$1$5(int                ncid,
+                     int                num,
+                     int                varids[],
+                     MPI_Offset* const  starts[],    /* [num] */
+                     MPI_Offset* const  counts[],    /* [num] */
+                     MPI_Offset* const  strides[],   /* [num] */
+                     $2                *bufs[])
+{
+    int i, err;
+    MPI_Datatype *datatypes;
+
+    datatypes = (MPI_Datatype*) NCI_Malloc((size_t)num * sizeof(MPI_Datatype));
+    for (i=0; i<num; i++)
+        datatypes[i] = $3;
+
+    err = ncmpii_mgetput_varm(ncid, num, varids, starts, counts, strides,
+                              NULL, (void**)bufs, NULL, datatypes,
+                              WRITE_REQ, $4);
+    NCI_Free(datatypes);
+    return err;
+}
+')dnl
+
+MPUT_VARS(text,      char,               MPI_CHAR,               INDEP_IO)
+MPUT_VARS(schar,     signed char,        MPI_SIGNED_CHAR,        INDEP_IO)
+MPUT_VARS(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      INDEP_IO)
+MPUT_VARS(short,     short,              MPI_SHORT,              INDEP_IO)
+MPUT_VARS(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     INDEP_IO)
+MPUT_VARS(int,       int,                MPI_INT,                INDEP_IO)
+MPUT_VARS(uint,      unsigned int,       MPI_UNSIGNED,           INDEP_IO)
+MPUT_VARS(long,      long,               MPI_LONG,               INDEP_IO)
+MPUT_VARS(float,     float,              MPI_FLOAT,              INDEP_IO)
+MPUT_VARS(double,    double,             MPI_DOUBLE,             INDEP_IO)
+MPUT_VARS(longlong,  long long,          MPI_LONG_LONG_INT,      INDEP_IO)
+MPUT_VARS(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, INDEP_IO)
+
+MPUT_VARS(text,      char,               MPI_CHAR,               COLL_IO, _all)
+MPUT_VARS(schar,     signed char,        MPI_SIGNED_CHAR,        COLL_IO, _all)
+MPUT_VARS(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      COLL_IO, _all)
+MPUT_VARS(short,     short,              MPI_SHORT,              COLL_IO, _all)
+MPUT_VARS(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     COLL_IO, _all)
+MPUT_VARS(int,       int,                MPI_INT,                COLL_IO, _all)
+MPUT_VARS(uint,      unsigned int,       MPI_UNSIGNED,           COLL_IO, _all)
+MPUT_VARS(long,      long,               MPI_LONG,               COLL_IO, _all)
+MPUT_VARS(float,     float,              MPI_FLOAT,              COLL_IO, _all)
+MPUT_VARS(double,    double,             MPI_DOUBLE,             COLL_IO, _all)
+MPUT_VARS(longlong,  long long,          MPI_LONG_LONG_INT,      COLL_IO, _all)
+MPUT_VARS(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, COLL_IO, _all)
+
+/*----< ncmpi_mput_varm() >--------------------------------------------------*/
+int
+ncmpi_mput_varm(int                ncid,
+                int                num,
+                int                varids[],    /* [num] */
+                MPI_Offset* const  starts[],    /* [num] */
+                MPI_Offset* const  counts[],    /* [num] */
+                MPI_Offset* const  strides[],   /* [num] */
+                MPI_Offset* const  imaps[],     /* [num] */
+                void              *bufs[],      /* [num] */
+                MPI_Offset         bufcounts[], /* [num] */
+                MPI_Datatype       datatypes[]) /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, counts, strides,
+                               imaps, bufs, bufcounts, datatypes,
+                               WRITE_REQ, INDEP_IO);
+}
+
+/*----< ncmpi_mput_varm_all() >----------------------------------------------*/
+int
+ncmpi_mput_varm_all(int                ncid,
+                    int                num,
+                    int                varids[],    /* [num] */
+                    MPI_Offset* const  starts[],    /* [num] */
+                    MPI_Offset* const  counts[],    /* [num] */
+                    MPI_Offset* const  strides[],   /* [num] */
+                    MPI_Offset* const  imaps[],     /* [num] */
+                    void              *bufs[],      /* [num] */
+                    MPI_Offset         bufcounts[], /* [num] */
+                    MPI_Datatype       datatypes[]) /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, counts, strides,
+                               imaps, bufs, bufcounts, datatypes,
+                               WRITE_REQ, COLL_IO);
+}
+
+dnl
+dnl MPUT_VARM(btype_name, btype, mpi_type, mode, mode_name)
+dnl
+define(`MPUT_VARM',dnl
+`dnl
+/*----< ncmpi_mput_varm_$1$5() >----------------------------------------------*/
+int
+ncmpi_mput_varm_$1$5(int                ncid,
+                     int                num,
+                     int                varids[],
+                     MPI_Offset* const  starts[],    /* [num] */
+                     MPI_Offset* const  counts[],    /* [num] */
+                     MPI_Offset* const  strides[],   /* [num] */
+                     MPI_Offset* const  imaps[],     /* [num] */
+                     $2                *bufs[])
+{
+    int i, err;
+    MPI_Datatype *datatypes;
+
+    datatypes = (MPI_Datatype*) NCI_Malloc((size_t)num * sizeof(MPI_Datatype));
+    for (i=0; i<num; i++)
+        datatypes[i] = $3;
+
+    err = ncmpii_mgetput_varm(ncid, num, varids, starts, counts, strides,
+                              imaps, (void**)bufs, NULL, datatypes,
+                              WRITE_REQ, $4);
+    NCI_Free(datatypes);
+    return err;
+}
+')dnl
+
+MPUT_VARM(text,      char,               MPI_CHAR,               INDEP_IO)
+MPUT_VARM(schar,     signed char,        MPI_SIGNED_CHAR,        INDEP_IO)
+MPUT_VARM(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      INDEP_IO)
+MPUT_VARM(short,     short,              MPI_SHORT,              INDEP_IO)
+MPUT_VARM(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     INDEP_IO)
+MPUT_VARM(int,       int,                MPI_INT,                INDEP_IO)
+MPUT_VARM(uint,      unsigned int,       MPI_UNSIGNED,           INDEP_IO)
+MPUT_VARM(long,      long,               MPI_LONG,               INDEP_IO)
+MPUT_VARM(float,     float,              MPI_FLOAT,              INDEP_IO)
+MPUT_VARM(double,    double,             MPI_DOUBLE,             INDEP_IO)
+MPUT_VARM(longlong,  long long,          MPI_LONG_LONG_INT,      INDEP_IO)
+MPUT_VARM(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, INDEP_IO)
+
+MPUT_VARM(text,      char,               MPI_CHAR,               COLL_IO, _all)
+MPUT_VARM(schar,     signed char,        MPI_SIGNED_CHAR,        COLL_IO, _all)
+MPUT_VARM(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      COLL_IO, _all)
+MPUT_VARM(short,     short,              MPI_SHORT,              COLL_IO, _all)
+MPUT_VARM(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     COLL_IO, _all)
+MPUT_VARM(int,       int,                MPI_INT,                COLL_IO, _all)
+MPUT_VARM(uint,      unsigned int,       MPI_UNSIGNED,           COLL_IO, _all)
+MPUT_VARM(long,      long,               MPI_LONG,               COLL_IO, _all)
+MPUT_VARM(float,     float,              MPI_FLOAT,              COLL_IO, _all)
+MPUT_VARM(double,    double,             MPI_DOUBLE,             COLL_IO, _all)
+MPUT_VARM(longlong,  long long,          MPI_LONG_LONG_INT,      COLL_IO, _all)
+MPUT_VARM(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, COLL_IO, _all)
+
+/*----< ncmpi_mget_var() >---------------------------------------------------*/
+int
+ncmpi_mget_var(int           ncid,
+               int           num,
+               int           varids[],     /* [num] */
+               void         *bufs[],       /* [num] */
+               MPI_Offset    bufcounts[],  /* [num] */
+               MPI_Datatype  datatypes[])  /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, NULL, NULL, NULL,
+                               NULL, bufs, bufcounts, datatypes,
+                               READ_REQ, INDEP_IO);
+}
+
+/*----< ncmpi_mget_var_all() >-----------------------------------------------*/
+int
+ncmpi_mget_var_all(int           ncid,
+                   int           num,
+                   int           varids[],     /* [num] */
+                   void         *bufs[],       /* [num] */
+                   MPI_Offset    bufcounts[],  /* [num] */
+                   MPI_Datatype  datatypes[])  /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, NULL, NULL, NULL,
+                               NULL, bufs, bufcounts, datatypes,
+                               READ_REQ, COLL_IO);
+}
+
+dnl
+dnl MGET_VAR(btype_name, btype, mpi_type, mode, mode_name)
+dnl
+define(`MGET_VAR',dnl
+`dnl
+/*----< ncmpi_mget_var_$1$5() >-----------------------------------------------*/
+int
+ncmpi_mget_var_$1$5(int ncid,
+                    int num,
+                    int varids[],
+                    $2 *bufs[])
+{
+    int i, err;
+    MPI_Datatype *datatypes;
+
+    datatypes = (MPI_Datatype*) NCI_Malloc((size_t)num * sizeof(MPI_Datatype));
+    for (i=0; i<num; i++)
+        datatypes[i] = $3;
+
+    err = ncmpii_mgetput_varm(ncid, num, varids, NULL, NULL, NULL,
+                              NULL, (void**)bufs, NULL, datatypes,
+                              READ_REQ, $4);
+    NCI_Free(datatypes);
+    return err;
+}
+')dnl
+
+MGET_VAR(text,      char,               MPI_CHAR,               INDEP_IO)
+MGET_VAR(schar,     signed char,        MPI_SIGNED_CHAR,        INDEP_IO)
+MGET_VAR(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      INDEP_IO)
+MGET_VAR(short,     short,              MPI_SHORT,              INDEP_IO)
+MGET_VAR(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     INDEP_IO)
+MGET_VAR(int,       int,                MPI_INT,                INDEP_IO)
+MGET_VAR(uint,      unsigned int,       MPI_UNSIGNED,           INDEP_IO)
+MGET_VAR(long,      long,               MPI_LONG,               INDEP_IO)
+MGET_VAR(float,     float,              MPI_FLOAT,              INDEP_IO)
+MGET_VAR(double,    double,             MPI_DOUBLE,             INDEP_IO)
+MGET_VAR(longlong,  long long,          MPI_LONG_LONG_INT,      INDEP_IO)
+MGET_VAR(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, INDEP_IO)
+
+MGET_VAR(text,      char,               MPI_CHAR,               COLL_IO, _all)
+MGET_VAR(schar,     signed char,        MPI_SIGNED_CHAR,        COLL_IO, _all)
+MGET_VAR(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      COLL_IO, _all)
+MGET_VAR(short,     short,              MPI_SHORT,              COLL_IO, _all)
+MGET_VAR(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     COLL_IO, _all)
+MGET_VAR(int,       int,                MPI_INT,                COLL_IO, _all)
+MGET_VAR(uint,      unsigned int,       MPI_UNSIGNED,           COLL_IO, _all)
+MGET_VAR(long,      long,               MPI_LONG,               COLL_IO, _all)
+MGET_VAR(float,     float,              MPI_FLOAT,              COLL_IO, _all)
+MGET_VAR(double,    double,             MPI_DOUBLE,             COLL_IO, _all)
+MGET_VAR(longlong,  long long,          MPI_LONG_LONG_INT,      COLL_IO, _all)
+MGET_VAR(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, COLL_IO, _all)
+
+/*----< ncmpi_mget_var1() >--------------------------------------------------*/
+int
+ncmpi_mget_var1(int                ncid,
+                int                num,
+                int                varids[],     /* [num] */
+                MPI_Offset* const  starts[],     /* [num] */
+                void              *bufs[],       /* [num] */
+                MPI_Offset         bufcounts[],  /* [num] */
+                MPI_Datatype       datatypes[])  /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, NULL, NULL,
+                               NULL, bufs, bufcounts, datatypes,
+                               READ_REQ, INDEP_IO);
+}
+
+/*----< ncmpi_mget_var1_all() >----------------------------------------------*/
+int
+ncmpi_mget_var1_all(int                ncid,
+                    int                num,
+                    int                varids[],     /* [num] */
+                    MPI_Offset* const  starts[],     /* [num] */
+                    void              *bufs[],       /* [num] */
+                    MPI_Offset         bufcounts[],  /* [num] */
+                    MPI_Datatype       datatypes[])  /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, NULL, NULL,
+                               NULL, bufs, bufcounts, datatypes,
+                               READ_REQ, COLL_IO);
+}
+
+dnl
+dnl MGET_VAR1(btype_name, btype, mpi_type, mode, mode_name)
+dnl
+define(`MGET_VAR1',dnl
+`dnl
+/*----< ncmpi_mget_var1_$1$5() >----------------------------------------------*/
+int
+ncmpi_mget_var1_$1$5(int                ncid,
+                     int                num,
+                     int                varids[],
+                     MPI_Offset* const  starts[],    /* [num] */
+                     $2                *bufs[])
+{
+    int i, err;
+    MPI_Datatype *datatypes;
+
+    datatypes = (MPI_Datatype*) NCI_Malloc((size_t)num * sizeof(MPI_Datatype));
+    for (i=0; i<num; i++)
+        datatypes[i] = $3;
+
+    err = ncmpii_mgetput_varm(ncid, num, varids, starts, NULL, NULL,
+                              NULL, (void**)bufs, NULL, datatypes,
+                              READ_REQ, $4);
+    NCI_Free(datatypes);
+    return err;
+}
+')dnl
+
+MGET_VAR1(text,      char,               MPI_CHAR,               INDEP_IO)
+MGET_VAR1(schar,     signed char,        MPI_SIGNED_CHAR,        INDEP_IO)
+MGET_VAR1(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      INDEP_IO)
+MGET_VAR1(short,     short,              MPI_SHORT,              INDEP_IO)
+MGET_VAR1(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     INDEP_IO)
+MGET_VAR1(int,       int,                MPI_INT,                INDEP_IO)
+MGET_VAR1(uint,      unsigned int,       MPI_UNSIGNED,           INDEP_IO)
+MGET_VAR1(long,      long,               MPI_LONG,               INDEP_IO)
+MGET_VAR1(float,     float,              MPI_FLOAT,              INDEP_IO)
+MGET_VAR1(double,    double,             MPI_DOUBLE,             INDEP_IO)
+MGET_VAR1(longlong,  long long,          MPI_LONG_LONG_INT,      INDEP_IO)
+MGET_VAR1(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, INDEP_IO)
+
+MGET_VAR1(text,      char,               MPI_CHAR,               COLL_IO, _all)
+MGET_VAR1(schar,     signed char,        MPI_SIGNED_CHAR,        COLL_IO, _all)
+MGET_VAR1(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      COLL_IO, _all)
+MGET_VAR1(short,     short,              MPI_SHORT,              COLL_IO, _all)
+MGET_VAR1(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     COLL_IO, _all)
+MGET_VAR1(int,       int,                MPI_INT,                COLL_IO, _all)
+MGET_VAR1(uint,      unsigned int,       MPI_UNSIGNED,           COLL_IO, _all)
+MGET_VAR1(long,      long,               MPI_LONG,               COLL_IO, _all)
+MGET_VAR1(float,     float,              MPI_FLOAT,              COLL_IO, _all)
+MGET_VAR1(double,    double,             MPI_DOUBLE,             COLL_IO, _all)
+MGET_VAR1(longlong,  long long,          MPI_LONG_LONG_INT,      COLL_IO, _all)
+MGET_VAR1(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, COLL_IO, _all)
+
+/*----< ncmpi_mget_vara() >--------------------------------------------------*/
+int
+ncmpi_mget_vara(int                ncid,
+                int                num,
+                int                varids[],     /* [num] */
+                MPI_Offset* const  starts[],     /* [num] */
+                MPI_Offset* const  counts[],     /* [num] */
+                void              *bufs[],       /* [num] */
+                MPI_Offset         bufcounts[],  /* [num] */
+                MPI_Datatype       datatypes[])  /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, counts, NULL,
+                               NULL, bufs, bufcounts, datatypes,
+                               READ_REQ, INDEP_IO);
+}
+
+/*----< ncmpi_mget_vara_all() >----------------------------------------------*/
+int
+ncmpi_mget_vara_all(int                ncid,
+                    int                num,
+                    int                varids[],     /* [num] */
+                    MPI_Offset* const  starts[],     /* [num] */
+                    MPI_Offset* const  counts[],     /* [num] */
+                    void              *bufs[],       /* [num] */
+                    MPI_Offset         bufcounts[],  /* [num] */
+                    MPI_Datatype       datatypes[])  /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, counts, NULL,
+                               NULL, bufs, bufcounts, datatypes,
+                               READ_REQ, COLL_IO);
+}
+
+dnl
+dnl MGET_VARA(btype_name, btype, mpi_type, mode, mode_name)
+dnl
+define(`MGET_VARA',dnl
+`dnl
+/*----< ncmpi_mget_vara_$1$5() >----------------------------------------------*/
+int
+ncmpi_mget_vara_$1$5(int                ncid,
+                     int                num,
+                     int                varids[],
+                     MPI_Offset* const  starts[],    /* [num] */
+                     MPI_Offset* const  counts[],    /* [num] */
+                     $2                *bufs[])
+{
+    int i, err;
+    MPI_Datatype *datatypes;
+
+    datatypes = (MPI_Datatype*) NCI_Malloc((size_t)num * sizeof(MPI_Datatype));
+    for (i=0; i<num; i++)
+        datatypes[i] = $3;
+
+    err = ncmpii_mgetput_varm(ncid, num, varids, starts, counts, NULL,
+                              NULL, (void**)bufs, NULL, datatypes,
+                              READ_REQ, $4);
+    NCI_Free(datatypes);
+    return err;
+}
+')dnl
+
+MGET_VARA(text,      char,               MPI_CHAR,               INDEP_IO)
+MGET_VARA(schar,     signed char,        MPI_SIGNED_CHAR,        INDEP_IO)
+MGET_VARA(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      INDEP_IO)
+MGET_VARA(short,     short,              MPI_SHORT,              INDEP_IO)
+MGET_VARA(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     INDEP_IO)
+MGET_VARA(int,       int,                MPI_INT,                INDEP_IO)
+MGET_VARA(uint,      unsigned int,       MPI_UNSIGNED,           INDEP_IO)
+MGET_VARA(long,      long,               MPI_LONG,               INDEP_IO)
+MGET_VARA(float,     float,              MPI_FLOAT,              INDEP_IO)
+MGET_VARA(double,    double,             MPI_DOUBLE,             INDEP_IO)
+MGET_VARA(longlong,  long long,          MPI_LONG_LONG_INT,      INDEP_IO)
+MGET_VARA(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, INDEP_IO)
+
+MGET_VARA(text,      char,               MPI_CHAR,               COLL_IO, _all)
+MGET_VARA(schar,     signed char,        MPI_SIGNED_CHAR,        COLL_IO, _all)
+MGET_VARA(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      COLL_IO, _all)
+MGET_VARA(short,     short,              MPI_SHORT,              COLL_IO, _all)
+MGET_VARA(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     COLL_IO, _all)
+MGET_VARA(int,       int,                MPI_INT,                COLL_IO, _all)
+MGET_VARA(uint,      unsigned int,       MPI_UNSIGNED,           COLL_IO, _all)
+MGET_VARA(long,      long,               MPI_LONG,               COLL_IO, _all)
+MGET_VARA(float,     float,              MPI_FLOAT,              COLL_IO, _all)
+MGET_VARA(double,    double,             MPI_DOUBLE,             COLL_IO, _all)
+MGET_VARA(longlong,  long long,          MPI_LONG_LONG_INT,      COLL_IO, _all)
+MGET_VARA(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, COLL_IO, _all)
+
+/*----< ncmpi_mget_vars() >--------------------------------------------------*/
+int
+ncmpi_mget_vars(int                ncid,
+                int                num,
+                int                varids[],     /* [num] */
+                MPI_Offset* const  starts[],     /* [num] */
+                MPI_Offset* const  counts[],     /* [num] */
+                MPI_Offset* const  strides[],    /* [num] */
+                void              *bufs[],       /* [num] */
+                MPI_Offset         bufcounts[],  /* [num] */
+                MPI_Datatype       datatypes[])  /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, counts, strides,
+                               NULL, bufs, bufcounts, datatypes,
+                               READ_REQ, INDEP_IO);
+}
+
+/*----< ncmpi_mget_vars_all() >----------------------------------------------*/
+int
+ncmpi_mget_vars_all(int                ncid,
+                    int                num,
+                    int                varids[],     /* [num] */
+                    MPI_Offset* const  starts[],     /* [num] */
+                    MPI_Offset* const  counts[],     /* [num] */
+                    MPI_Offset* const  strides[],    /* [num] */
+                    void              *bufs[],       /* [num] */
+                    MPI_Offset         bufcounts[],  /* [num] */
+                    MPI_Datatype       datatypes[])  /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, counts, strides,
+                               NULL, bufs, bufcounts, datatypes,
+                               READ_REQ, COLL_IO);
+}
+
+dnl
+dnl MGET_VARS(btype_name, btype, mpi_type, mode, mode_name)
+dnl
+define(`MGET_VARS',dnl
+`dnl
+/*----< ncmpi_mget_vars_$1$5() >----------------------------------------------*/
+int
+ncmpi_mget_vars_$1$5(int                ncid,
+                     int                num,
+                     int                varids[],
+                     MPI_Offset* const  starts[],    /* [num] */
+                     MPI_Offset* const  counts[],    /* [num] */
+                     MPI_Offset* const  strides[],   /* [num] */
+                     $2                *bufs[])
+{
+    int i, err;
+    MPI_Datatype *datatypes;
+
+    datatypes = (MPI_Datatype*) NCI_Malloc((size_t)num * sizeof(MPI_Datatype));
+    for (i=0; i<num; i++)
+        datatypes[i] = $3;
+
+    err = ncmpii_mgetput_varm(ncid, num, varids, starts, counts, strides,
+                              NULL, (void**)bufs, NULL, datatypes,
+                              READ_REQ, $4);
+    NCI_Free(datatypes);
+    return err;
+}
+')dnl
+
+MGET_VARS(text,      char,               MPI_CHAR,               INDEP_IO)
+MGET_VARS(schar,     signed char,        MPI_SIGNED_CHAR,        INDEP_IO)
+MGET_VARS(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      INDEP_IO)
+MGET_VARS(short,     short,              MPI_SHORT,              INDEP_IO)
+MGET_VARS(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     INDEP_IO)
+MGET_VARS(int,       int,                MPI_INT,                INDEP_IO)
+MGET_VARS(uint,      unsigned int,       MPI_UNSIGNED,           INDEP_IO)
+MGET_VARS(long,      long,               MPI_LONG,               INDEP_IO)
+MGET_VARS(float,     float,              MPI_FLOAT,              INDEP_IO)
+MGET_VARS(double,    double,             MPI_DOUBLE,             INDEP_IO)
+MGET_VARS(longlong,  long long,          MPI_LONG_LONG_INT,      INDEP_IO)
+MGET_VARS(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, INDEP_IO)
+
+MGET_VARS(text,      char,               MPI_CHAR,               COLL_IO, _all)
+MGET_VARS(schar,     signed char,        MPI_SIGNED_CHAR,        COLL_IO, _all)
+MGET_VARS(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      COLL_IO, _all)
+MGET_VARS(short,     short,              MPI_SHORT,              COLL_IO, _all)
+MGET_VARS(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     COLL_IO, _all)
+MGET_VARS(int,       int,                MPI_INT,                COLL_IO, _all)
+MGET_VARS(uint,      unsigned int,       MPI_UNSIGNED,           COLL_IO, _all)
+MGET_VARS(long,      long,               MPI_LONG,               COLL_IO, _all)
+MGET_VARS(float,     float,              MPI_FLOAT,              COLL_IO, _all)
+MGET_VARS(double,    double,             MPI_DOUBLE,             COLL_IO, _all)
+MGET_VARS(longlong,  long long,          MPI_LONG_LONG_INT,      COLL_IO, _all)
+MGET_VARS(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, COLL_IO, _all)
+
+/*----< ncmpi_mget_varm() >--------------------------------------------------*/
+int
+ncmpi_mget_varm(int                ncid,
+                int                num,
+                int                varids[],     /* [num] */
+                MPI_Offset* const  starts[],     /* [num] */
+                MPI_Offset* const  counts[],     /* [num] */
+                MPI_Offset* const  strides[],    /* [num] */
+                MPI_Offset* const  imaps[],      /* [num] */
+                void              *bufs[],       /* [num] */
+                MPI_Offset         bufcounts[],  /* [num] */
+                MPI_Datatype       datatypes[])  /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, counts, strides,
+                               imaps, bufs, bufcounts, datatypes,
+                               READ_REQ, INDEP_IO);
+}
+
+/*----< ncmpi_mget_varm_all() >----------------------------------------------*/
+int
+ncmpi_mget_varm_all(int                ncid,
+                    int                num,
+                    int                varids[],     /* [num] */
+                    MPI_Offset* const  starts[],     /* [num] */
+                    MPI_Offset* const  counts[],     /* [num] */
+                    MPI_Offset* const  strides[],    /* [num] */
+                    MPI_Offset* const  imaps[],      /* [num] */
+                    void              *bufs[],       /* [num] */
+                    MPI_Offset         bufcounts[],  /* [num] */
+                    MPI_Datatype       datatypes[])  /* [num] */
+{
+    return ncmpii_mgetput_varm(ncid, num, varids, starts, counts, strides,
+                               imaps, bufs, bufcounts, datatypes,
+                               READ_REQ, COLL_IO);
+}
+
+dnl
+dnl MGET_VARM(btype_name, btype, mpi_type, mode, mode_name)
+dnl
+define(`MGET_VARM',dnl
+`dnl
+/*----< ncmpi_mget_varm_$1$5() >----------------------------------------------*/
+int
+ncmpi_mget_varm_$1$5(int                ncid,
+                     int                num,
+                     int                varids[],
+                     MPI_Offset* const  starts[],    /* [num] */
+                     MPI_Offset* const  counts[],    /* [num] */
+                     MPI_Offset* const  strides[],   /* [num] */
+                     MPI_Offset* const  imaps[],     /* [num] */
+                     $2                *bufs[])
+{
+    int i, err;
+    MPI_Datatype *datatypes;
+
+    datatypes = (MPI_Datatype*) NCI_Malloc((size_t)num * sizeof(MPI_Datatype));
+    for (i=0; i<num; i++)
+        datatypes[i] = $3;
+
+    err = ncmpii_mgetput_varm(ncid, num, varids, starts, counts, strides,
+                              imaps, (void**)bufs, NULL, datatypes,
+                              READ_REQ, $4);
+    NCI_Free(datatypes);
+    return err;
+}
+')dnl
+
+MGET_VARM(text,      char,               MPI_CHAR,               INDEP_IO)
+MGET_VARM(schar,     signed char,        MPI_SIGNED_CHAR,        INDEP_IO)
+MGET_VARM(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      INDEP_IO)
+MGET_VARM(short,     short,              MPI_SHORT,              INDEP_IO)
+MGET_VARM(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     INDEP_IO)
+MGET_VARM(int,       int,                MPI_INT,                INDEP_IO)
+MGET_VARM(uint,      unsigned int,       MPI_UNSIGNED,           INDEP_IO)
+MGET_VARM(long,      long,               MPI_LONG,               INDEP_IO)
+MGET_VARM(float,     float,              MPI_FLOAT,              INDEP_IO)
+MGET_VARM(double,    double,             MPI_DOUBLE,             INDEP_IO)
+MGET_VARM(longlong,  long long,          MPI_LONG_LONG_INT,      INDEP_IO)
+MGET_VARM(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, INDEP_IO)
+
+MGET_VARM(text,      char,               MPI_CHAR,               COLL_IO, _all)
+MGET_VARM(schar,     signed char,        MPI_SIGNED_CHAR,        COLL_IO, _all)
+MGET_VARM(uchar,     unsigned char,      MPI_UNSIGNED_CHAR,      COLL_IO, _all)
+MGET_VARM(short,     short,              MPI_SHORT,              COLL_IO, _all)
+MGET_VARM(ushort,    unsigned short,     MPI_UNSIGNED_SHORT,     COLL_IO, _all)
+MGET_VARM(int,       int,                MPI_INT,                COLL_IO, _all)
+MGET_VARM(uint,      unsigned int,       MPI_UNSIGNED,           COLL_IO, _all)
+MGET_VARM(long,      long,               MPI_LONG,               COLL_IO, _all)
+MGET_VARM(float,     float,              MPI_FLOAT,              COLL_IO, _all)
+MGET_VARM(double,    double,             MPI_DOUBLE,             COLL_IO, _all)
+MGET_VARM(longlong,  long long,          MPI_LONG_LONG_INT,      COLL_IO, _all)
+MGET_VARM(ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG, COLL_IO, _all)
+
+/*----< ncmpii_mgetput_varm() >-----------------------------------------------*/
+int
+ncmpii_mgetput_varm(int                ncid,
+                    int                num,
+                    int                varids[],    /* [num] */
+                    MPI_Offset* const  starts[],    /* [num] */
+                    MPI_Offset* const  counts[],    /* [num] */
+                    MPI_Offset* const  strides[],   /* [num] */
+                    MPI_Offset* const  imaps[],     /* [num] */
+                    void              *bufs[],      /* [num] */
+                    MPI_Offset         bufcounts[], /* [num] */
+                    MPI_Datatype       datatypes[], /* [num] */
+                    int                rw_flag,     /* WRITE_REQ or READ_REQ */
+                    int                io_method)   /* COLL_IO or INDEP_IO */
+{
+    int i, j, err, status=NC_NOERR, *req_ids=NULL, *statuses=NULL;
+    NC *ncp=NULL;
+
+    /* check if ncid is valid */
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+    /* if ncid is invalid, we must return the error now. However, the program
+     * might hang when only a subset or processes have this error.
+     */
+
+    /* check if it is in define mode. This must be called in data mode */
+    if (NC_indef(ncp)) {
+        DEBUG_ASSIGN_ERROR(status, NC_EINDEFINE)
+        goto err_check;
+    }
+
+    /* check file write permission if this is write request */
+    if (rw_flag == WRITE_REQ && NC_readonly(ncp)) {
+        DEBUG_ASSIGN_ERROR(status, NC_EPERM)
+        goto err_check;
+    }
+
+err_check:
+    /* at this point, if status is not NC_NOERR, it is a fatal error */
+    if (ncp->safe_mode == 1 && io_method == COLL_IO) {
+        int mpireturn, min_st;
+        TRACE_COMM(MPI_Allreduce)(&status, &min_st, 1, MPI_INT, MPI_MIN,
+                                  ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce"); 
+        if (min_st != NC_NOERR) return status;
+    }
+
+    if (io_method == INDEP_IO && status != NC_NOERR)
+        return status;
+
+    if (status != NC_NOERR)
+        /* this can only be reached for COLL_IO and safe_mode == 0, set num=0
+         * just so this process can participate the collective calls in
+         * wait_all */
+        num = 0;
+
+    if (num > 0) {
+        req_ids  = (int*) NCI_Malloc((size_t)(2 * num * SIZEOF_INT));
+        statuses = req_ids + num;
+    }
+
+    /* for each request call ncmpi_igetput_varm() */
+    for (i=0; i<num; i++) {
+        NC_var *varp;
+        MPI_Offset *start, *count, buflen=0;
+
+        req_ids[i] = NC_REQ_NULL;
+
+        err = ncmpii_NC_lookupvar(ncp, varids[i], &varp);
+        if (err != NC_NOERR) {
+            if (status == NC_NOERR) status = err;
+            continue; /* invalid varid, skip this request */
+        }
+
+        if (bufcounts != NULL) buflen = bufcounts[i];
+
+        if (starts == NULL) {         /* var */
+            GET_FULL_DIMENSIONS(start, count)
+            /* when bufcounts == NULL, it means the same as counts[] */
+            if (bufcounts == NULL) {
+                for (buflen=1, j=0; j<varp->ndims; j++)
+                    buflen *= count[j];
+            }
+            err = ncmpii_igetput_varm(ncp, varp, start, count, NULL, NULL,
+                                      bufs[i], buflen, datatypes[i],
+                                      &req_ids[i], rw_flag, 0, 0);
+            if (status == NC_NOERR) status = err;
+            if (varp->ndims > 0) NCI_Free(start);
+        } else if (counts == NULL) {  /* var1 */
+            /* check whether starts[i] is valid */
+            err = NC_start_count_stride_ck(ncp, varp, starts[i], NULL, NULL, rw_flag);
+            if (status == NC_NOERR) status = err;
+            if (err != NC_NOERR) continue; /* skip this request */
+            GET_ONE_COUNT(count)
+            /* when bufcounts == NULL, it means the same as counts[] */
+            if (bufcounts == NULL) buflen = 1;
+
+            err = ncmpii_igetput_varm(ncp, varp, starts[i], count, NULL, NULL,
+                                      bufs[i], buflen, datatypes[i],
+                                      &req_ids[i], rw_flag, 0, 0);
+            if (status == NC_NOERR) status = err;
+            if (varp->ndims > 0) NCI_Free(count);
+        } else if (strides == NULL) { /* vara */
+            /* check whether starts[i] and counts[i] are valid */
+            err = NC_start_count_stride_ck(ncp, varp, starts[i], counts[i], NULL, rw_flag);
+            if (status == NC_NOERR) status = err;
+            if (err != NC_NOERR) continue; /* skip this request */
+            /* when bufcounts == NULL, it means the same as counts[] */
+            if (bufcounts == NULL) {
+                for (buflen=1, j=0; j<varp->ndims; j++)
+                    buflen *= counts[i][j];
+            }
+            err = ncmpii_igetput_varm(ncp, varp, starts[i], counts[i], NULL,
+                                      NULL, bufs[i], buflen, datatypes[i],
+                                      &req_ids[i], rw_flag, 0, 0);
+            if (status == NC_NOERR) status = err;
+        } else if (imaps == NULL) {   /* vars */
+            /* check whether starts[i], counts[i], and strides[i] are valid */
+            err = NC_start_count_stride_ck(ncp, varp, starts[i], counts[i], strides[i], rw_flag);
+            if (status == NC_NOERR) status = err;
+            if (err != NC_NOERR) continue; /* skip this request */
+            /* when bufcounts == NULL, it means the same as counts[] */
+            if (bufcounts == NULL) {
+                for (buflen=1, j=0; j<varp->ndims; j++)
+                    buflen *= counts[i][j];
+            }
+            err = ncmpii_igetput_varm(ncp, varp, starts[i], counts[i],
+                                      strides[i], NULL, bufs[i], buflen,
+                                      datatypes[i], &req_ids[i],
+                                      rw_flag, 0, 0);
+            if (status == NC_NOERR) status = err;
+        } else {                      /* varm */
+            /* check whether starts[i], counts[i], and strides[i] are valid */
+            err = NC_start_count_stride_ck(ncp, varp, starts[i], counts[i], strides[i], rw_flag);
+            if (status == NC_NOERR) status = err;
+            if (err != NC_NOERR) continue; /* skip this request */
+            /* when bufcounts == NULL, it means the same as counts[] */
+            if (bufcounts == NULL) {
+                for (buflen=1, j=0; j<varp->ndims; j++)
+                    buflen *= counts[i][j];
+            }
+            err = ncmpii_igetput_varm(ncp, varp, starts[i], counts[i],
+                                      strides[i], imaps[i], bufs[i],
+                                      buflen, datatypes[i],
+                                      &req_ids[i], rw_flag, 0, 0);
+            if (status == NC_NOERR) status = err;
+        }
+    }
+
+    if (io_method == COLL_IO)
+        err = ncmpi_wait_all(ncid, num, req_ids, statuses);
+    else
+        err = ncmpi_wait(ncid, num, req_ids, statuses);
+
+    /* return the first error if there is one */
+    if (status == NC_NOERR) status = err;
+    if (status == NC_NOERR) {
+        for (i=0; i<num; i++)
+            if (statuses[i] != NC_NOERR) {
+                status = statuses[i];
+                break;
+            }
+    }
+
+    if (num > 0) NCI_Free(req_ids);
+
+    return status;
+}
diff --git a/src/lib/macro.h b/src/lib/macro.h
new file mode 100644
index 0000000..5dedec8
--- /dev/null
+++ b/src/lib/macro.h
@@ -0,0 +1,188 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: macro.h 2196 2015-11-27 22:31:05Z wkliao $ */
+
+#ifndef _H_MACRO
+#define _H_MACRO
+
+#ifndef MAX
+#define MAX(mm,nn) (((mm) > (nn)) ? (mm) : (nn))
+#endif
+#ifndef MIN
+#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
+#endif
+
+void *NCI_Malloc_fn(size_t size, int lineno, const char *func, const char *fname);
+void *NCI_Calloc_fn(size_t nelem, size_t elsize, int lineno, const char *func, const char *fname);
+void *NCI_Realloc_fn(void *ptr, size_t size, int lineno, const char *func, const char *fname);
+void  NCI_Free_fn(void *ptr, int lineno, const char *func, const char *fname);
+
+#define NCI_Malloc(a)    NCI_Malloc_fn(a,__LINE__,__func__,__FILE__)
+#define NCI_Calloc(a,b)  NCI_Calloc_fn(a,b,__LINE__,__func__,__FILE__)
+#define NCI_Realloc(a,b) NCI_Realloc_fn(a,b,__LINE__,__func__,__FILE__)
+#define NCI_Free(a)      NCI_Free_fn(a,__LINE__,__func__,__FILE__)
+
+
+#define CHECK_MPI_ERROR(mpi_errorcode, err_msg, nc_err) {                     \
+    if (mpi_errorcode != MPI_SUCCESS) {                                       \
+        char errorString[MPI_MAX_ERROR_STRING];                               \
+        int rank, errorStringLen;                                             \
+        MPI_Comm_rank(ncp->nciop->comm, &rank);                               \
+        MPI_Error_string(mpi_errorcode, errorString, &errorStringLen);        \
+        printf("%2d: MPI Failure at line %d of %s (%s : %s)\n",               \
+               rank, __LINE__, __FILE__, err_msg, errorString);               \
+        mpi_err = nc_err;                                                     \
+    }                                                                         \
+}
+
+#ifdef PNC_DEBUG
+#define DEBUG_RETURN_ERROR(err) {                                       \
+    int _rank;                                                          \
+    char *env_str = getenv("PNETCDF_VERBOSE_DEBUG_MODE");               \
+    MPI_Comm_rank(MPI_COMM_WORLD, &_rank);                              \
+    if (env_str != NULL && *env_str != '0')                             \
+        fprintf(stderr, "Rank %d: %s error at line %d of %s in %s\n",   \
+        _rank,ncmpii_err_code_name(err),__LINE__,__func__,__FILE__);    \
+    return err;                                                         \
+}
+#define DEBUG_ASSIGN_ERROR(status, err) {                               \
+    int _rank;                                                          \
+    char *env_str = getenv("PNETCDF_VERBOSE_DEBUG_MODE");               \
+    MPI_Comm_rank(MPI_COMM_WORLD, &_rank);                              \
+    if (env_str != NULL && *env_str != '0')                             \
+        fprintf(stderr, "Rank %d: %s error at line %d of %s in %s\n",   \
+        _rank,ncmpii_err_code_name(err),__LINE__,__func__,__FILE__);    \
+    status = err;                                                       \
+}
+#else
+#define DEBUG_RETURN_ERROR(err) return err;
+#define DEBUG_ASSIGN_ERROR(status, err) status = err;
+#endif
+
+#define GET_ONE_COUNT(count) {                                                \
+    int _i;                                                                   \
+    count = (MPI_Offset*) NCI_Malloc((size_t)varp->ndims * SIZEOF_MPI_OFFSET);\
+    for (_i=0; _i<varp->ndims; _i++)                                          \
+        count[_i] = 1;                                                        \
+}
+
+#ifdef ENABLE_SUBFILING
+#define GET_FULL_DIMENSIONS(start, count) {                                   \
+    int _i;                                                                   \
+    int _ndims = (varp->num_subfiles>1?varp->ndims_org:varp->ndims);          \
+    start = (MPI_Offset*) NCI_Malloc((size_t)_ndims*2*SIZEOF_MPI_OFFSET);     \
+    count = start + _ndims;                                                   \
+                                                                              \
+    for (_i=0; _i<_ndims; _i++) {                                             \
+        NC_dim *dimp;                                                         \
+        int _dimid;                                                           \
+        _dimid = (varp->num_subfiles>1)?varp->dimids_org[_i]:varp->dimids[_i];\
+        dimp = ncmpii_elem_NC_dimarray(&ncp->dims, _dimid);                   \
+        if (dimp->size == NC_UNLIMITED)                                       \
+            count[_i] = NC_get_numrecs(ncp);                                  \
+        else                                                                  \
+            count[_i] = dimp->size;                                           \
+        start[_i] = 0;                                                        \
+    }                                                                         \
+}
+#else /* without subfiling */
+#define GET_FULL_DIMENSIONS(start, count) {                                   \
+    int _i=0;                                                                 \
+    start = (MPI_Offset*) NCI_Malloc((size_t)varp->ndims*2*SIZEOF_MPI_OFFSET);\
+    count = start + varp->ndims;                                              \
+                                                                              \
+    if (IS_RECVAR(varp)) { /* find current numrec if varp is record var */    \
+        count[0] = NC_get_numrecs(ncp);                                       \
+        start[0] = 0;                                                         \
+        _i = 1;                                                               \
+    }                                                                         \
+    for (; _i<varp->ndims; _i++) {                                            \
+        count[_i] = varp->shape[_i];                                          \
+        start[_i] = 0;                                                        \
+    }                                                                         \
+}
+#endif
+
+#define DATATYPE_GET_CONVERT(vartype, inbuf, outbuf, cnelems, memtype, err) { \
+    /* vartype is the variable's data type defined in the nc file             \
+     * memtype is the I/O buffers data type (MPI_Datatype)  */                \
+    switch(vartype) {                                                         \
+        case NC_BYTE:                                                         \
+            err = ncmpii_x_getn_schar(inbuf, outbuf, cnelems, memtype);       \
+            break;                                                            \
+        case NC_UBYTE:                                                        \
+            err = ncmpii_x_getn_uchar(inbuf, outbuf, cnelems, memtype);       \
+            break;                                                            \
+        case NC_SHORT:                                                        \
+            err = ncmpii_x_getn_short(inbuf, outbuf, cnelems, memtype);       \
+            break;                                                            \
+        case NC_USHORT:                                                       \
+            err = ncmpii_x_getn_ushort(inbuf, outbuf, cnelems, memtype);      \
+            break;                                                            \
+        case NC_INT:                                                          \
+            err = ncmpii_x_getn_int(inbuf, outbuf, cnelems, memtype);         \
+            break;                                                            \
+        case NC_UINT:                                                         \
+            err = ncmpii_x_getn_uint(inbuf, outbuf, cnelems, memtype);        \
+            break;                                                            \
+        case NC_FLOAT:                                                        \
+            err = ncmpii_x_getn_float(inbuf, outbuf, cnelems, memtype);       \
+            break;                                                            \
+        case NC_DOUBLE:                                                       \
+            err = ncmpii_x_getn_double(inbuf, outbuf, cnelems, memtype);      \
+            break;                                                            \
+        case NC_INT64:                                                        \
+            err = ncmpii_x_getn_int64(inbuf, outbuf, cnelems, memtype);       \
+            break;                                                            \
+        case NC_UINT64:                                                       \
+            err = ncmpii_x_getn_uint64(inbuf, outbuf, cnelems, memtype);      \
+            break;                                                            \
+        default:                                                              \
+            err = NC_EBADTYPE;                                                \
+            break;                                                            \
+    }                                                                         \
+}
+
+#define DATATYPE_PUT_CONVERT(vartype, outbuf, inbuf, cnelems, memtype, err) { \
+    /* vartype is the variable's data type defined in the nc file             \
+     * memtype is the I/O buffers data type (MPI_Datatype)  */                \
+    switch(vartype) {                                                         \
+        case NC_BYTE:                                                         \
+            err = ncmpii_x_putn_schar(outbuf, inbuf, cnelems, memtype);       \
+            break;                                                            \
+        case NC_UBYTE:                                                        \
+            err = ncmpii_x_putn_uchar(outbuf, inbuf, cnelems, memtype);       \
+            break;                                                            \
+        case NC_SHORT:                                                        \
+            err = ncmpii_x_putn_short(outbuf, inbuf, cnelems, memtype);       \
+            break;                                                            \
+        case NC_USHORT:                                                       \
+            err = ncmpii_x_putn_ushort(outbuf, inbuf, cnelems, memtype);      \
+            break;                                                            \
+        case NC_INT:                                                          \
+            err = ncmpii_x_putn_int(outbuf, inbuf, cnelems, memtype);         \
+            break;                                                            \
+        case NC_UINT:                                                         \
+            err = ncmpii_x_putn_uint(outbuf, inbuf, cnelems, memtype);        \
+            break;                                                            \
+        case NC_FLOAT:                                                        \
+            err = ncmpii_x_putn_float(outbuf, inbuf, cnelems, memtype);       \
+            break;                                                            \
+        case NC_DOUBLE:                                                       \
+            err = ncmpii_x_putn_double(outbuf, inbuf, cnelems, memtype);      \
+            break;                                                            \
+        case NC_INT64:                                                        \
+            err = ncmpii_x_putn_int64(outbuf, inbuf, cnelems, memtype);       \
+            break;                                                            \
+        case NC_UINT64:                                                       \
+            err = ncmpii_x_putn_uint64(outbuf, inbuf, cnelems, memtype);      \
+            break;                                                            \
+        default:                                                              \
+            err = NC_EBADTYPE;                                                \
+            break;                                                            \
+    }                                                                         \
+}
+
+#endif
diff --git a/src/lib/malloc.c b/src/lib/malloc.c
new file mode 100644
index 0000000..0ec953f
--- /dev/null
+++ b/src/lib/malloc.c
@@ -0,0 +1,275 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: malloc.c 2244 2015-12-19 22:41:28Z wkliao $ */
+
+/* These are routines for allocating and deallocating memory.
+   They should be called as NCI_Malloc(size) and
+   NCI_Free(ptr). In macro.h, they are macro-replaced to
+   NCI_Malloc_fn(size,__LINE__,__FILE__) and
+   NCI_Free_fn(ptr,__LINE__,__FILE__).
+ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h> /* strcpy(), strlen() */
+
+#include <mpi.h>
+#include "nc.h"
+
+#ifdef PNC_MALLOC_TRACE
+
+#ifdef HAVE_SEARCH_H
+#include <search.h> /* tfind(), tsearch() and tdelete() */
+#endif
+
+/* global variables for malloc tracing */
+static void       *ncmpii_mem_root;
+static MPI_Offset  ncmpii_mem_alloc;
+static MPI_Offset  ncmpii_max_mem_alloc;
+
+/*----< ncmpii_init_malloc_tracing() >----------------------------------------*/
+void ncmpii_init_malloc_tracing(void)
+{
+    ncmpii_mem_alloc     = 0;
+    ncmpii_max_mem_alloc = 0;
+    ncmpii_mem_root      = NULL;
+}
+#endif
+
+/*----< ncmpii_inq_malloc_size() >--------------------------------------------*/
+/* get the current aggregate size allocated by malloc */
+int ncmpii_inq_malloc_size(MPI_Offset *size)
+{
+#ifdef PNC_MALLOC_TRACE
+    *size = ncmpii_mem_alloc;
+    return 1;
+#else
+    return 0;
+#endif
+}
+
+/*----< ncmpii_inq_malloc_max_size() >----------------------------------------*/
+/* get the max watermark ever researched by malloc */
+int ncmpii_inq_malloc_max_size(MPI_Offset *size)
+{
+#ifdef PNC_MALLOC_TRACE
+    *size = ncmpii_max_mem_alloc;
+    return 1;
+#else
+    return 0;
+#endif
+}
+
+#ifdef PNC_MALLOC_TRACE
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+typedef struct {
+    void   *self;
+    void   *buf;
+    size_t  size;
+    int     lineno;
+    char   *func;
+    char   *filename;
+} ncmpii_mem_entry;
+
+inline static
+int ncmpii_cmp(const void *a, const void *b) {
+    ncmpii_mem_entry *fa = (ncmpii_mem_entry*)a;
+    ncmpii_mem_entry *fb = (ncmpii_mem_entry*)b;
+
+    if (fa->buf > fb->buf) return  1;
+    if (fa->buf < fb->buf) return -1;
+    return 0;
+}
+
+inline static
+void walker(const void *node, const VISIT which, const int depth) {
+    ncmpii_mem_entry *f;
+    f = *(ncmpii_mem_entry **)node;
+    if (which == preorder || which == leaf)
+        printf("Warning: malloc yet to be freed (buf=%p size=%zd filename=%s func=%s line=%d)\n", f->buf, f->size, f->filename, f->func, f->lineno);
+}
+#endif
+
+/* check if there is any malloc residue */
+int ncmpii_inq_malloc_list(void)
+{
+#ifdef PNC_MALLOC_TRACE
+    /* check if malloc tree is empty */
+    if (ncmpii_mem_root != NULL)
+        twalk(ncmpii_mem_root, walker);
+    return 1;
+#else
+    return 0;
+#endif
+}
+
+#ifdef PNC_MALLOC_TRACE
+/*----< ncmpii_add_mem_entry() >----------------------------------------------*/
+/* add a new malloc entry to the table */
+static
+void ncmpii_add_mem_entry(void       *buf,
+                          size_t      size,
+                          const int   lineno,
+                          const char *func,
+                          const char *filename)
+{
+    /* use C tsearch utility */
+    ncmpii_mem_entry *node = (ncmpii_mem_entry*) malloc(sizeof(ncmpii_mem_entry));
+    node->self     = node;
+    node->buf      = buf;
+    node->size     = size;
+    node->lineno   = lineno;
+    node->func     = (char*)malloc(strlen(func)+1);
+    node->filename = (char*)malloc(strlen(filename)+1);
+    strcpy(node->func, func);
+    node->func[strlen(func)] = '\0';
+    strcpy(node->filename, filename);
+    node->filename[strlen(filename)] = '\0';
+
+    /* search and add a new item */
+    void *ret = tsearch(node, &ncmpii_mem_root, ncmpii_cmp);
+    if (ret == NULL) {
+        printf("Error: tsearch()\n");
+        return;
+    }
+    ncmpii_mem_alloc += (MPI_Offset)size;
+    ncmpii_max_mem_alloc = MAX(ncmpii_max_mem_alloc, ncmpii_mem_alloc);
+}
+
+/*----< ncmpii_del_mem_entry() >----------------------------------------------*/
+/* delete a malloc entry from the table */
+static
+void ncmpii_del_mem_entry(void *buf)
+{
+    /* use C tsearch utility */
+    if (ncmpii_mem_root != NULL) {
+        ncmpii_mem_entry node;
+        node.buf  = buf;
+        void *ret = tfind(&node, &ncmpii_mem_root, ncmpii_cmp);
+        ncmpii_mem_entry **found = (ncmpii_mem_entry**) ret;
+        if (ret == NULL) {
+            printf("Error: tfind() buf=%p\n", buf);
+            return;
+        }
+        /* free space for func and filename */
+        free((*found)->func);
+        free((*found)->filename);
+
+        /* subtract the space amount to be freed */
+        ncmpii_mem_alloc -= (MPI_Offset)((*found)->size);
+        void *tmp = (*found)->self;
+        ret = tdelete(&node, &ncmpii_mem_root, ncmpii_cmp);
+        if (ret == NULL) {
+            printf("Error: tdelete() buf=%p\n", buf);
+            return;
+        }
+        free(tmp);
+    }
+}
+#endif
+
+/*----< NCI_Malloc_fn() >-----------------------------------------------------*/
+void *NCI_Malloc_fn(size_t      size,
+                    const int   lineno,
+                    const char *func,
+                    const char *filename)
+{
+#ifdef NC_DEBUG
+    if (size == 0)
+        fprintf(stderr, "Attempt to malloc zero-size in file %s, line %d\n", filename, lineno);
+#endif
+    if (size == 0) return NULL;
+    void *buf = malloc(size);
+    if (!buf) {
+	fprintf(stderr, "malloc(%zd) failed in file %s, line %d\n", size, filename, lineno);
+	MPI_Abort(MPI_COMM_WORLD, 1);
+    }
+#ifdef PNC_MALLOC_TRACE
+    ncmpii_add_mem_entry(buf, size, lineno, func, filename);
+#endif
+    return buf;
+}
+
+
+/*----< NCI_Calloc_fn() >-----------------------------------------------------*/
+void *NCI_Calloc_fn(size_t      nelem,
+                    size_t      elsize,
+                    const int   lineno,
+                    const char *func,
+                    const char *filename)
+{
+#ifdef NC_DEBUG
+    if (nelem == 0 || elsize == 0)
+        fprintf(stderr, "Attempt to calloc zero-size in file %s, line %d\n", filename, lineno);
+#endif
+    if (nelem == 0 || elsize == 0) return NULL;
+    void *buf =calloc(nelem, elsize);
+    if (!buf) {
+	fprintf(stderr, "calloc(%zd, %zd) failed in file %s, line %d\n", nelem, elsize, filename, lineno);
+	MPI_Abort(MPI_COMM_WORLD, 1);
+    }
+#ifdef PNC_MALLOC_TRACE
+    ncmpii_add_mem_entry(buf, nelem * elsize, lineno, func, filename);
+#endif
+    return buf;
+}
+
+
+/*----< NCI_Realloc_fn() >----------------------------------------------------*/
+void *NCI_Realloc_fn(void       *ptr,
+                     size_t      size,
+                     const int   lineno,
+                     const char *func,
+                     const char *filename)
+{
+#ifdef NC_DEBUG
+    if (size == 0)
+        fprintf(stderr, "Attempt to realloc zero-size in file %s, line %d\n", filename, lineno);
+#endif
+#ifdef PNC_MALLOC_TRACE
+    if (ptr != NULL) ncmpii_del_mem_entry(ptr);
+#endif
+    if (size == 0) return NULL;
+    void *buf = (void *) realloc(ptr, size);
+    if (!buf) {
+	fprintf(stderr, "realloc failed in file %s, line %d\n", filename, lineno);
+	MPI_Abort(MPI_COMM_WORLD, 1);
+    }
+#ifdef PNC_MALLOC_TRACE
+    ncmpii_add_mem_entry(buf, size, lineno, func, filename);
+#endif
+    return buf;
+}
+
+
+/*----< NCI_Free_fn() >-------------------------------------------------------*/
+void NCI_Free_fn(void       *ptr,
+                 const int   lineno,
+                 const char *func,
+                 const char *filename)
+{
+#ifdef NC_DEBUG
+    if (ptr == NULL)
+	fprintf(stderr, "Attempt to free null pointer in file %s, line %d\n", filename, lineno);
+#endif
+    if (ptr == NULL) return;
+#ifdef PNC_MALLOC_TRACE
+    ncmpii_del_mem_entry(ptr);
+#endif
+    free(ptr);
+}
+
+
diff --git a/src/lib/mpincio.c b/src/lib/mpincio.c
new file mode 100644
index 0000000..9ee5fce
--- /dev/null
+++ b/src/lib/mpincio.c
@@ -0,0 +1,592 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: mpincio.c 2196 2015-11-27 22:31:05Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#ifdef HAVE_ACCESS
+#include <unistd.h>  /* access() */
+#endif
+#include <assert.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>  /* strchr() */
+#ifdef _MSC_VER /* Microsoft Compilers */
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+/* #define INSTRUMENT 1 */
+#ifdef INSTRUMENT /* debugging */
+#undef NDEBUG
+#include <stdio.h>
+#include "instr.h"
+#endif
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncio.h"
+#include "fbits.h"
+#include "rnd.h"
+#include "macro.h"
+
+#if !defined(NDEBUG) && !defined(X_INT_MAX)
+#define  X_INT_MAX INT_MAX
+#endif
+
+#if 0 /* !defined(NDEBUG) && !defined(X_ALIGN) */
+#define  X_ALIGN 4
+#else
+#undef X_ALIGN
+#endif
+
+#define MAX_NC_ID 1024
+
+static unsigned char IDalloc[MAX_NC_ID];
+
+inline void
+ncmpiio_free(ncio *nciop) {
+    if (nciop != NULL) {
+#ifdef HAVE_MPI_INFO_FREE
+        if (nciop->mpiinfo != MPI_INFO_NULL)
+            MPI_Info_free(&(nciop->mpiinfo));
+#endif
+        if (nciop->comm != MPI_COMM_NULL)
+            MPI_Comm_free(&(nciop->comm));
+
+        NCI_Free(nciop);
+    }
+}
+
+inline ncio *
+ncmpiio_new(const char *path, int ioflags)
+{
+    size_t sz_ncio = M_RNDUP(sizeof(ncio));
+    size_t sz_path = M_RNDUP(strlen(path) +1);
+    ncio *nciop;
+
+    nciop = (ncio *) NCI_Malloc(sz_ncio + sz_path);
+    if (nciop == NULL) return NULL;
+
+    nciop->ioflags  = ioflags;
+    nciop->comm     = MPI_COMM_NULL;
+    nciop->mpiinfo  = MPI_INFO_NULL;
+    nciop->put_size = 0;
+    nciop->get_size = 0;
+
+    nciop->path = (char *) ((char *)nciop + sz_ncio);
+    (void) strcpy((char *)nciop->path, path);
+
+    return nciop;
+}
+
+/*----< ncmpiio_extract_hints() >--------------------------------------------*/
+/* this is where the I/O hints designated to pnetcdf are extracted */
+static
+void ncmpiio_extract_hints(ncio     *nciop,
+                           MPI_Info  info)
+{
+    /* value 0 indicates the hint is not set */
+    nciop->hints.h_align                = 0;
+    nciop->hints.v_align                = 0;
+    nciop->hints.r_align                = 0;
+    nciop->hints.header_read_chunk_size = 0;
+#ifdef ENABLE_SUBFILING
+    nciop->hints.subfile_mode           = 1;
+    nciop->hints.num_subfiles           = 0;
+#endif
+
+    /* extract NC hints */
+    if (info != MPI_INFO_NULL) {
+        char value[MPI_MAX_INFO_VAL];
+        int  flag;
+
+        MPI_Info_get(info, "nc_header_align_size", MPI_MAX_INFO_VAL-1, value,
+                     &flag);
+        if (flag) nciop->hints.h_align = atoll(value);
+
+        MPI_Info_get(info, "nc_var_align_size",    MPI_MAX_INFO_VAL-1, value,
+                     &flag);
+        if (flag) nciop->hints.v_align = atoll(value);
+
+        MPI_Info_get(info, "nc_record_align_size", MPI_MAX_INFO_VAL-1,
+                     value, &flag);
+        if (flag) nciop->hints.r_align = atoll(value);
+
+        MPI_Info_get(info, "nc_header_read_chunk_size", MPI_MAX_INFO_VAL-1,
+                     value, &flag);
+        if (flag) nciop->hints.header_read_chunk_size = atoll(value);
+
+#ifdef ENABLE_SUBFILING
+        MPI_Info_get(info, "pnetcdf_subfiling", MPI_MAX_INFO_VAL-1,
+                     value, &flag);
+        if (flag && strcasecmp(value, "disable") == 0)
+            nciop->hints.subfile_mode = 0;
+
+        MPI_Info_get(info, "nc_num_subfiles", MPI_MAX_INFO_VAL-1,
+                     value, &flag);
+        if (flag) nciop->hints.num_subfiles = atoi(value);
+#endif
+
+        /* nc_header_align_size, nc_var_align_size, and nciop->hints.r_align
+         * take effect when a file is created or opened and later adding more
+         * header or variable data */
+
+        if (nciop->hints.h_align < 0)
+            nciop->hints.h_align = 0;
+        if (nciop->hints.v_align < 0)
+            nciop->hints.v_align = 0;
+        if (nciop->hints.r_align < 0)
+            nciop->hints.r_align = 0;
+        if (nciop->hints.header_read_chunk_size < 0)
+            nciop->hints.header_read_chunk_size = 0;
+#ifdef ENABLE_SUBFILING
+        if (nciop->hints.num_subfiles < 0)
+            nciop->hints.num_subfiles = 0;
+        /* override subfile hints if env var is set */
+        char *num_sf_env;
+        num_sf_env = getenv("NC_NUM_SUBFILES");
+        if (num_sf_env != NULL)
+            nciop->hints.num_subfiles = atoi(num_sf_env);
+        if (nciop->hints.subfile_mode == 0)
+            nciop->hints.num_subfiles = 0;
+#endif
+    }
+}
+
+/*----< ncmpiio_create() >---------------------------------------------------*/
+int
+ncmpiio_create(MPI_Comm     comm,
+               const char  *path,
+               int          ioflags,
+               MPI_Info     info,
+               NC          *ncp)
+{
+    ncio *nciop;
+    int i, rank, mpireturn, err;
+    int mpiomode = MPI_MODE_RDWR | MPI_MODE_CREATE;
+
+    /* TODO: check whether path are the same across all processes */
+    if (ncp->safe_mode) {
+        int isPathValid=1;
+        if (path == NULL || *path == 0) isPathValid = 0;
+        TRACE_COMM(MPI_Allreduce)(&isPathValid, &err, 1, MPI_INT, MPI_LAND, comm);
+        if (err == 0) DEBUG_RETURN_ERROR(NC_EINVAL)
+    }
+
+    MPI_Comm_rank(comm, &rank);
+
+    /* NC_CLOBBER is the default mode, even if it is not used in cmode */
+    if (fIsSet(ioflags, NC_NOCLOBBER)) {
+        /* check if file exists: NetCDF requires NC_EEXIST returned if the file
+         * already exists and NC_NOCLOBBER mode is used in create
+         */
+#ifdef HAVE_ACCESS
+        int file_exist;
+        /* if access() is available, use it to check whether file already exists
+         * rank 0 calls access() and broadcasts file_exist */
+        if (rank == 0) {
+            /* remove the file system type prefix name if there is any.
+             * For example, path=="lustre:/home/foo/testfile.nc",
+             * use "/home/foo/testfile.nc" when calling access()
+             */
+            char *filename = strchr(path, ':');
+            if (filename == NULL) /* no prefix */
+                filename = (char*)path;
+            else
+                filename++;
+
+            if (access(filename, F_OK) == 0) file_exist = 1;
+            else                             file_exist = 0;
+        }
+        TRACE_COMM(MPI_Bcast)(&file_exist, 1, MPI_INT, 0, comm);
+        if (file_exist) DEBUG_RETURN_ERROR(NC_EEXIST)
+#else
+        /* use MPI_MODE_EXCL mode in MPI_File_open and check returned error */
+        fSet(mpiomode, MPI_MODE_EXCL);
+#endif
+    }
+    else { /* NC_CLOBBER is the default mode in create */
+        /* rank 0 deletes the file and ignores error code for file not exist
+         * Note calling MPI_File_set_size is expensive as it calls truncate()
+         */
+        if (rank == 0) {
+#ifdef HAVE_UNLINK
+            err = unlink(path);
+            if (err < 0 && errno != ENOENT) /* ignore ENOENT: file not exist */
+                DEBUG_ASSIGN_ERROR(err, NC_EFILE) /* other error */
+            else
+                err = NC_NOERR;
+#else
+            err = NC_NOERR;
+            TRACE_IO(MPI_File_delete)((char*)path, MPI_INFO_NULL);
+            if (mpireturn != MPI_SUCCESS) {
+                int errorclass;
+                MPI_Error_class(mpireturn, &errorclass);
+                if (errorclass != MPI_ERR_NO_SUCH_FILE) /* ignore this error */
+                    err = ncmpii_handle_error(mpireturn, "MPI_File_delete");
+            }
+#endif
+        }
+        /* all processes must wait here until file deletion is completed */
+        TRACE_COMM(MPI_Bcast)(&err, 1, MPI_INT, 0, comm);
+        if (err != NC_NOERR) return err;
+    }
+
+    /* ignore if NC_NOWRITE set by user */
+    fSet(ioflags, NC_WRITE);
+
+    nciop = ncmpiio_new(path, ioflags); /* allocate buffer */
+    if (nciop == NULL)
+        DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    nciop->mpiomode  = MPI_MODE_RDWR;
+    nciop->mpioflags = 0;
+
+    /* extract MPI-IO hints */
+    ncmpiio_extract_hints(nciop, info);
+
+    TRACE_IO(MPI_File_open)(comm, (char *)path, mpiomode, info,
+                            &nciop->collective_fh);
+    if (mpireturn != MPI_SUCCESS) {
+        ncmpiio_free(nciop);
+#ifndef HAVE_ACCESS
+        if (fIsSet(ioflags, NC_NOCLOBBER)) {
+            /* This is the case when NC_NOCLOBBER is used in file creation and
+             * function access() is not available. MPI_MODE_EXCL is set in open
+             * mode. When MPI_MODE_EXCL is used and the file already exists,
+             * MPI-IO should return error class MPI_ERR_FILE_EXISTS. But, some
+             * MPI-IO implementations (older ROMIO) do not correctly return
+             * this error class. In this case, we can do the followings: check
+             * errno to see if it set to EEXIST. Note usually rank 0 makes the
+             * file open call and can be the only one having errno set.
+             */
+            TRACE_COMM(MPI_Bcast)(&errno, 1, MPI_INT, 0, comm);
+            if (errno == EEXIST) DEBUG_RETURN_ERROR(NC_EEXIST)
+        }
+#endif
+        return ncmpii_handle_error(mpireturn, "MPI_File_open");
+        /* for NC_NOCLOBBER, MPI_MODE_EXCL was added to mpiomode. If the file
+         * already exists, MPI-IO should return error class MPI_ERR_FILE_EXISTS
+         * which PnetCDF will return error code NC_EEXIST. This is checked
+         * inside of ncmpii_handle_error()
+         */
+    }
+
+    for (i=0; i<MAX_NC_ID; i++)
+        if (IDalloc[i] == 0)
+            break;
+
+    if (i == MAX_NC_ID) {
+        ncmpiio_free(nciop);
+        DEBUG_RETURN_ERROR(NC_ENFILE)
+    }
+
+    *((int *)&nciop->fd) = i;
+    IDalloc[i] = 1;
+
+    /* collective I/O mode is the default mode */
+    set_NC_collectiveFh(nciop);
+
+    /* duplicate communicator as user may free it later */
+    mpireturn = MPI_Comm_dup(comm, &(nciop->comm));
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_Comm_dup");
+
+    /* get the file info actually used by MPI-IO (maybe alter user's info) */
+    MPI_File_get_info(nciop->collective_fh, &nciop->mpiinfo);
+
+    ncp->nciop = nciop;
+    return NC_NOERR;
+}
+
+/*----< ncmpiio_open() >-----------------------------------------------------*/
+int
+ncmpiio_open(MPI_Comm     comm,
+             const char  *path,
+             int          ioflags,
+             MPI_Info     info,
+             NC          *ncp)
+{
+    ncio *nciop;
+    int i, mpireturn;
+    int mpiomode = fIsSet(ioflags, NC_WRITE) ? MPI_MODE_RDWR : MPI_MODE_RDONLY;
+
+    /* TODO: check whether path are the same across all processes */
+    if (ncp->safe_mode) {
+        int isPathValid=1, err;
+        if (path == NULL || *path == 0) isPathValid = 0;
+        TRACE_COMM(MPI_Allreduce)(&isPathValid, &err, 1, MPI_INT, MPI_LAND, comm);
+        if (err == 0) DEBUG_RETURN_ERROR(NC_EINVAL)
+    }
+
+    /* When open an non-existing file for read, we can either call access() to
+     * check and return error code NC_ENOENT, or call MPI_File_open and expect
+     * error class MPI_ERR_NO_SUCH_FILE. For now, we let MPI-IO to check.
+     */
+#if 0 && defined(HAVE_ACCESS)
+    if (mpiomode == MPI_MODE_RDONLY) { /* file should already exit */
+        int rank, file_exist;
+        MPI_Comm_rank(comm, &rank);
+        if (rank == 0) {
+            if (access(path, F_OK) == 0) file_exist = 1;
+            else                         file_exist = 0;
+        }
+        TRACE_COMM(MPI_Bcast)(&file_exist, 1, MPI_INT, 0, comm);
+        if (!file_exist) DEBUG_RETURN_ERROR(NC_ENOENT)
+    }
+#endif
+
+    nciop = ncmpiio_new(path, ioflags);
+    if (nciop == NULL)
+        DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    nciop->mpiomode  = mpiomode;
+    nciop->mpioflags = 0;
+
+    /* extract MPI-IO hints */
+    ncmpiio_extract_hints(nciop, info);
+
+    TRACE_IO(MPI_File_open)(comm, (char *)path, mpiomode,
+                            info, &nciop->collective_fh);
+    if (mpireturn != MPI_SUCCESS) {
+        ncmpiio_free(nciop);
+        return ncmpii_handle_error(mpireturn, "MPI_File_open");
+    }
+
+    for (i=0; i<MAX_NC_ID && IDalloc[i] != 0; i++);
+    if (i == MAX_NC_ID) {
+        ncmpiio_free(nciop);
+        DEBUG_RETURN_ERROR(NC_ENFILE)
+    }
+    *((int *)&nciop->fd) = i;
+    IDalloc[i] = 1;
+
+    set_NC_collectiveFh(nciop);
+
+    /* duplicate communicator as user may free it later */
+    mpireturn = MPI_Comm_dup(comm, &(nciop->comm));
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_Comm_dup");
+
+    /* get the file info used by MPI-IO */
+    MPI_File_get_info(nciop->collective_fh, &nciop->mpiinfo);
+
+    ncp->nciop = nciop;
+    return NC_NOERR;
+}
+
+/*----< ncmpiio_sync() >-----------------------------------------------------*/
+/* This function must be called collectively, no matter if it is in collective
+ * or independent data mode.
+ */
+inline int
+ncmpiio_sync(ncio *nciop) {
+#ifndef DISABLE_FILE_SYNC
+    int mpireturn;
+
+    if (NC_independentFhOpened(nciop)) {
+        TRACE_IO(MPI_File_sync)(nciop->independent_fh);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_File_sync");
+    }
+    if (NC_collectiveFhOpened(nciop)) {
+        TRACE_IO(MPI_File_sync)(nciop->collective_fh);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_File_sync");
+    }
+    TRACE_COMM(MPI_Barrier)(nciop->comm);
+#endif
+    return NC_NOERR;
+}
+
+/*----< ncmpiio_close() >----------------------------------------------------*/
+int
+ncmpiio_close(ncio *nciop, int doUnlink) {
+    int mpireturn;
+
+    if (nciop == NULL) /* this should never occur */
+        DEBUG_RETURN_ERROR(NC_EINVAL)
+
+    if (NC_independentFhOpened(nciop)) {
+        TRACE_IO(MPI_File_close)(&(nciop->independent_fh));
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_File_close");
+    }
+
+    if (NC_collectiveFhOpened(nciop)) {
+        TRACE_IO(MPI_File_close)(&(nciop->collective_fh));
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_File_close");
+    }
+    IDalloc[*((int *)&nciop->fd)] = 0;
+
+    if (doUnlink) {
+        TRACE_IO(MPI_File_delete)((char *)nciop->path, nciop->mpiinfo);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_File_delete");
+    }
+    ncmpiio_free(nciop);
+
+    return NC_NOERR;
+}
+
+/*----< ncmpiio_move() >-----------------------------------------------------*/
+int
+ncmpiio_move(ncio *const nciop,
+             MPI_Offset  to,
+             MPI_Offset  from,
+             MPI_Offset  nbytes)
+{
+    int rank, nprocs, bufcount, mpireturn, err, status=NC_NOERR, min_st;
+    void *buf;
+    int chunk_size = 1048576; /* move 1 MB per process at a time */
+    MPI_Status mpistatus;
+
+    MPI_Comm_size(nciop->comm, &nprocs);
+    MPI_Comm_rank(nciop->comm, &rank);
+
+    /* if the file striping unit size is known (obtained from MPI-IO), then
+     * we use that instead of 1 MB */
+    if (nciop->striping_unit > 0) chunk_size = nciop->striping_unit;
+
+    buf = NCI_Malloc((size_t)chunk_size);
+    if (buf == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    /* make fileview entire file visible */
+    TRACE_IO(MPI_File_set_view)(nciop->collective_fh, 0, MPI_BYTE, MPI_BYTE,
+                                "native", MPI_INFO_NULL);
+
+    /* move the variable starting from its tail toward its beginning */
+    while (nbytes > 0) {
+        /* calculate how much to move at each time */
+        bufcount = chunk_size;
+        if (nbytes < nprocs * chunk_size) {
+            /* handle the last group of chunks */
+            MPI_Offset rem_chunks = nbytes / chunk_size;
+            if (rank > rem_chunks) /* these processes do not read/write */
+                bufcount = 0;
+            else if (rank == rem_chunks) /* this process reads/writes less */
+                bufcount = (int)(nbytes % chunk_size);
+            nbytes = 0;
+        }
+        else {
+            nbytes -= chunk_size*nprocs;
+        }
+
+        /* read the original data @ from+nbytes+rank*chunk_size */
+        TRACE_IO(MPI_File_read_at_all)(nciop->collective_fh,
+                                       from+nbytes+rank*chunk_size,
+                                       buf, bufcount, MPI_BYTE, &mpistatus);
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_File_read_at_all");
+            if (err == NC_EFILE) DEBUG_ASSIGN_ERROR(status, NC_EREAD)
+        }
+        else {
+            int get_size;
+            MPI_Get_count(&mpistatus, MPI_BYTE, &get_size);
+            nciop->get_size += get_size;
+        }
+
+        /* MPI_Barrier(nciop->comm); */
+        /* important, in case new region overlaps old region */
+        TRACE_COMM(MPI_Allreduce)(&status, &min_st, 1, MPI_INT, MPI_MIN, nciop->comm);
+        status = min_st;
+        if (status != NC_NOERR) break;
+
+        /* write to new location @ to+nbytes+rank*chunk_size */
+        TRACE_IO(MPI_File_write_at_all)(nciop->collective_fh,
+                                        to+nbytes+rank*chunk_size,
+                                        buf, bufcount, MPI_BYTE, &mpistatus);
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_File_write_at_all");
+            if (err == NC_EFILE) DEBUG_ASSIGN_ERROR(status, NC_EWRITE)
+        }
+        else {
+            int put_size;
+            MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
+            nciop->put_size += put_size;
+        }
+        TRACE_COMM(MPI_Allreduce)(&status, &min_st, 1, MPI_INT, MPI_MIN, nciop->comm);
+        status = min_st;
+        if (status != NC_NOERR) break;
+    }
+    NCI_Free(buf);
+    return status;
+}
+
+/*----< ncmpiio_move_fixed_vars() >-------------------------------------------*/
+/* move one fixed variable at a time, only when the new begin > old begin */
+int
+ncmpiio_move_fixed_vars(NC *ncp,
+                        NC *old)
+{
+    int i, err, status=NC_NOERR;
+
+    /* move starting from the last fixed variable */
+    for (i=old->vars.ndefined-1; i>=0; i--) {
+        if (IS_RECVAR(old->vars.value[i])) continue;
+
+        MPI_Offset from = old->vars.value[i]->begin;
+        MPI_Offset to   = ncp->vars.value[i]->begin;
+        if (to > from) {
+            err = ncmpiio_move(ncp->nciop, to, from, ncp->vars.value[i]->len);
+            if (status == NC_NOERR) status = err;
+        }
+    }
+    return status;
+}
+
+int ncmpiio_get_hint(NC *ncp, char *key, char *value, int *flag)
+{
+    MPI_Info info;
+
+    /* info hints can come from the file system but can also come from
+     * user-specified hints.  the MPI implementation probably should
+     * merge the two, but some implementations not only ignore hints
+     * they don't understand, but also fail to incorporate those hints
+     * into the info struct (this is unfortunate for us, but entirely
+     * standards compliant).
+     *
+     * Our policy will be to use the implementation's info first
+     * (perhaps the implementation knows something about the underlying
+     * file system), and then consult user-supplied hints should we not
+     * find the hint in the info associated with the MPI file descriptor
+     */
+
+    /* first check the hint from the MPI library ... */
+    MPI_File_get_info(ncp->nciop->collective_fh, &info);
+    if (info != MPI_INFO_NULL)
+        MPI_Info_get(info, key, MPI_MAX_INFO_VAL-1, value, flag);
+    if (*flag == 0)  {
+        /* ... then check the hint passed in through ncmpi_create */
+        if (ncp->nciop->mpiinfo != MPI_INFO_NULL) {
+            MPI_Info_get(ncp->nciop->mpiinfo, key,
+                    MPI_MAX_INFO_VAL-1, value, flag);
+        }
+    }
+#ifdef HAVE_MPI_INFO_FREE
+    if (info != MPI_INFO_NULL)
+        MPI_Info_free(&info);
+#endif
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
diff --git a/src/lib/mpinetcdf.c b/src/lib/mpinetcdf.c
new file mode 100644
index 0000000..e0ac0f5
--- /dev/null
+++ b/src/lib/mpinetcdf.c
@@ -0,0 +1,1183 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: mpinetcdf.c 2282 2015-12-26 17:44:27Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <assert.h>
+#include <string.h>  /* strtok(), strcpy(), strchr() */
+#include <strings.h> /* strcasecmp() */
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "macro.h"
+#ifdef ENABLE_SUBFILING
+#include "subfile.h"
+#endif
+
+/* The const string below is for the RCS ident(1) command to find a string like
+ * "\044Id: \100(#) PnetCDF library version 1.4.0 of 16 Nov 2013 $"
+ * in the library file (libpnetcdf.a).
+ */
+static char const pnetcdf_libvers[] =
+        "\044Id: \100(#) PnetCDF library version "PNETCDF_VERSION" of "PNETCDF_RELEASE_DATE" $";
+
+/* pnetcdf_libvers is slightly different from the one returned from
+ * ncmpi_inq_libvers(). The string pnetcdf_libvers is for command "ident" to
+ * use. People can run command ident libpnetcdf.a to obtain the version of a
+ * library (or an executable built from that library). In PnetCDF case, the
+ * command will print the string of pnetcdf_libvers. Command "ident' looks for
+ * a specific keyword pattern and print it. See man page of ident.
+ *
+ * The API ncmpi_inq_libvers() below on the other hand returns a string to be
+ * used by the utility tools like ncmpidump, ncmpigen, etc. Check the last line
+ * of output from command "ncmpidump -v".
+ */
+
+/*----< ncmpi_inq_libvers() >------------------------------------------------*/
+inline const char*
+ncmpi_inq_libvers(void) {
+
+    /* match the style used by netCDF API nc_inq_libvers()
+     * for example, "4.3.0 of Jun 16 2013 12:11:30 $" */
+    /* we need some silly operation so the compiler will emit the otherwise
+     * unused pnetcdf_libvers */
+    if ((void *)pnetcdf_libvers != (void *)ncmpi_inq_libvers) {
+	; /* do nothing */
+    }
+    return PNETCDF_VERSION " of " PNETCDF_RELEASE_DATE;
+}
+
+/* Begin Of Dataset Functions */
+
+/*----< ncmpi_create() >-----------------------------------------------------*/
+/**  \ingroup datasets
+Create a new netCDF file.
+
+This function creates a new netCDF dataset, returning a netCDF ID that can
+subsequently be used to refer to the netCDF dataset in other PnetCDF function
+calls. The new netCDF dataset opened for write access and placed in define
+mode, ready for you to add dimensions, variables, and attributes.
+
+\param comm The MPI communicator. This API is a collective routine: all
+processes must provide the same value for cmode, and all processes must provide
+filenames that reference the same file. (Values for info may vary.) comm must
+be an MPI intracommunicator.
+
+\param path The file name of the new netCDF dataset.
+
+\param cmode The creation mode flag. The following flags are available:
+NC_NOCLOBBER, NC_SHARE, NC_64BIT_OFFSET, and NC_64BIT_DATA.
+
+\param info MPI info object. It is used to provide file access hints,including
+existing MPI hints as well as PnetCDF hints.  For MPI hints, users are referred
+to MPI user guide for further information. For PnetCDF hints see below.
+
+\param ncidp Pointer to location where returned netCDF ID is to be stored.
+
+<h2>The cmode Flag</h2>
+
+The cmode flag is used to control the type of file created, and some aspects of
+how it may be used.
+
+Setting NC_NOCLOBBER means you do not want to clobber (overwrite) an existing
+dataset; an error (NC_EEXIST) is returned if the specified dataset already
+exists.
+
+The NC_SHARE flag in PnetCDF does not mean sharing the file with the processes
+in this MPI program. Instead, it means the file will be concurrently shared
+by a different MPI program. Hence, PnetCDF calls MPI_File_sync() right after
+every time an MPI_File_write() call is made. This includes writing to metadata
+(file header) as well as array data.
+
+Setting NC_64BIT_OFFSET causes PnetCDF to create a 64-bit offset format file
+(CDF-2), instead of a netCDF classic format file.  The 64-bit offset format
+imposes far fewer restrictions on large (i.e. over 2 GB) data files.  See Large
+File Support (The PnetCDF Users Guide).
+
+Setting NC_64BIT_DATA causes PnetCDF to create a 64-bit data format file
+(CDF-5). The 64-bit data format allows define variables with more than 4
+billion array elements. See Large File Support (The PnetCDF Users Guide).
+
+A zero value (defined for convenience as NC_CLOBBER) specifies the default
+behavior: overwrite any existing dataset with the same file name.
+
+<h2>The info object Flag</h2>
+
+Starting from version 1.3.1, the following PnetCDF hints are available:
+
+- nc_header_align_size: This hint allows some extra space between the end of
+the header describing the entire file and the first variable. If you have an
+application that periodically wishes to add more variables to an already
+existing file, expanding the file header size may result in an expensive move
+of the entire data file to make room for the definition of the new variables.
+Hence, setting this hint to a value that is big enough to accommodate any
+additional variables means you may leave your application code as-is and yet
+still see tremendous performance improvements.
+
+- nc_var_align_size: If you are writing to a block-based parallel file system,
+such as IBM's GPFS or Lustre, then an application write becomes a block write
+at the file system layer. If a write straddles two blocks, then locks must be
+acquired for both blocks. Aligning the start of a variable to a block boundary,
+combined with collective I/O optimization in the MPI-IO library can often
+eliminate all unaligned file system accesses.
+
+- nc_record_align_size: This hint aligns the starting file offset of the
+record variable section.
+
+- nc_header_read_chunk_size: PnetCDF reads the file headers in chunks. This
+hint indicates the chunk size (in bytes). The default is 256 KB.
+
+\returns ::NC_NOERR No error.
+\returns ::NC_ENOMEM System out of memory.
+\returns ::NC_EEXIST Specified file name exists when using NC_NOCLOBBER.
+Can be use to check if the file exists.
+\returns ::NC_EMULTIDEFINE_OMODE Bad file create/open mode or modes are
+inconsistent across processes
+\returns ::NC_EOFILE: Can not open/create file (MPI-IO errors)
+\returns ::NC_EFILE: Unknown error in file operation
+
+<h1>Examples</h1>
+
+In this example we create a netCDF dataset named foo.nc; we want the dataset to
+be created in the current directory only if a dataset with that name does not
+already exist:
+
+ at code
+     #include <mpi.h>
+     #include <pnetcdf.h>
+        ...
+     int status;
+     int ncid;
+     MPI_Info info;
+        ...
+     MPI_Info_create (&info);
+     MPI_Info_set (info, "romio_no_indep_rw",    "true");
+     MPI_Info_set (info, "nc_header_align_size", "4194304");
+     MPI_Info_set (info, "nc_var_align_size",    "1048576");
+     MPI_Info_set (info, "nc_record_align_size", "1048576");
+
+     status = ncmpi_create(MPI_COMM_WORLD, "foo.nc", NC_NOCLOBBER, info, &ncid);
+     if (status != NC_NOERR) handle_error(status);
+     MPI_Info_free(&info);
+ at endcode
+
+In this example we create a netCDF dataset named foo.nc. It will
+be in the CDF-5 format.
+
+ at code
+     #include <mpi.h>
+     #include <pnetcdf.h>
+        ...
+     int status;
+     int ncid;
+     int cmode = NC_NOCLOBBER | NC_64BIT_DATA;
+     MPI_Info info = MPI_INFO_NULL;
+        ...
+     status = ncmpi_create(MPI_COMM_WORLD, "foo.nc", cmode, info, &ncid);
+     if (status != NC_NOERR) handle_error(status);
+ at endcode
+*/
+int
+ncmpi_create(MPI_Comm    comm,
+             const char *path,
+             int         cmode,
+             MPI_Info    info,
+             int        *ncidp)
+{
+    int flag, err, status=NC_NOERR, safe_mode=0, mpireturn;
+    char *env_str=NULL, *hint_str, value[MPI_MAX_INFO_VAL];
+    MPI_Info   env_info;
+    MPI_Offset chunksize=NC_DEFAULT_CHUNKSIZE;
+    NC *ncp;
+
+#ifdef PNC_DEBUG
+    safe_mode = 1;
+    /* this configure time setting will be overwritten by the run-time
+     * environment variable PNETCDF_SAFE_MODE */
+#endif
+    /* get environment variable PNETCDF_SAFE_MODE
+     * if it is set to 1, then we perform a strict parameter consistent test
+     */
+    env_str = getenv("PNETCDF_SAFE_MODE");
+    if (env_str != NULL) {
+        if (*env_str == '0') safe_mode = 0;
+        else                 safe_mode = 1;
+        /* if PNETCDF_SAFE_MODE is set but without a value, *env_str can
+         * be '\0' (null character). In this case, safe_mode is enabled */
+    }
+
+    if (safe_mode) {
+        /* check if cmode is consistent with root's */
+        int root_cmode=cmode;
+
+        TRACE_COMM(MPI_Bcast)(&root_cmode, 1, MPI_INT, 0, comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+
+        if (root_cmode != cmode) {
+            int rank;
+            MPI_Comm_rank(comm, &rank);
+            /* cmodes are inconsistent, overwrite local cmode with root's */
+            printf("rank %d: Warning - inconsistent file create mode, overwrite with root's\n",rank);
+            cmode = root_cmode;
+            DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_OMODE)
+        }
+        TRACE_COMM(MPI_Allreduce)(&status, &err, 1, MPI_INT, MPI_MIN, comm);
+        if (err != NC_NOERR) return status;
+
+        /* when safe_mode is disabled, NC_EMULTIDEFINE_OMODE will be reported at
+         * the time ncmpi_enddef() returns */
+    }
+
+    /* It is illegal to have both NC_64BIT_OFFSET & NC_64BIT_DATA */
+    if ((cmode & (NC_64BIT_OFFSET|NC_64BIT_DATA)) ==
+                 (NC_64BIT_OFFSET|NC_64BIT_DATA))
+        DEBUG_ASSIGN_ERROR(status, NC_EINVAL_CMODE)
+    /* In safe_mode, cmodes are sync-ed, so all processes can return the same
+     * error code. But, when not in safe mode, if cmode is not consistent
+     * among processes, then some processes might not violate this above rule
+     * which can cause the program to hang (because MPI_File_open is a
+     * collective call). We use MPI_Allreduce below to check the error
+     * code, but it is costly.
+     */
+    if (safe_mode) {
+        TRACE_COMM(MPI_Allreduce)(&status, &err, 1, MPI_INT, MPI_MIN, comm);
+        status = err;
+    }
+    if (status != NC_NOERR) return status;
+
+    /* take hints from the environment variable PNETCDF_HINTS
+     * a string of hints separated by ";" and each hint is in the
+     * form of hint=value. E.g. cb_nodes=16;cb_config_list=*:6
+     * If this environment variable is set, it  overrides any values that
+     * were set by using calls to MPI_Info_set in the application code.
+     */
+    env_str = getenv("PNETCDF_HINTS");
+    env_info = info;
+    if (env_str != NULL) {
+        if (info == MPI_INFO_NULL)
+            MPI_Info_create(&env_info); /* ignore error */
+
+        hint_str = strtok(env_str, ";");
+        while (hint_str != NULL && env_info != MPI_INFO_NULL) {
+            char key[128], *val;
+            strcpy(key, hint_str);
+            val = strchr(key, '=');
+            *val = '\0';
+            val++;
+            /* printf("env hint: key=%s val=%s\n",key,val); */
+            MPI_Info_set(env_info, key, val); /* override */
+            hint_str = strtok(NULL, ";");
+        }
+    }
+
+    /* get header chunk size from user info */
+    if (env_info != MPI_INFO_NULL) {
+        MPI_Info_get(env_info, "nc_header_read_chunk_size", MPI_MAX_INFO_VAL-1,
+                     value, &flag);
+        if (flag) chunksize = atoll(value);
+    }
+
+    /* allocate buffer for header object NC */
+    if ((ncp = ncmpii_new_NC(&chunksize)) == NULL)
+        DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    ncp->safe_mode = safe_mode;
+    ncp->abuf      = NULL;
+    ncp->old       = NULL;
+#ifdef ENABLE_SUBFILING
+    ncp->subfile_mode = 1;
+    if (env_info != MPI_INFO_NULL) {
+        MPI_Info_get(env_info, "pnetcdf_subfiling", MPI_MAX_INFO_VAL-1,
+                     value, &flag);
+        if (flag && strcasecmp(value, "disable") == 0)
+            ncp->subfile_mode = 0;
+    }
+    ncp->ncid_sf = -1; /* subfile ncid; init to -1 */
+    ncp->nc_num_subfiles = 0; /* num_subfiles; init to 0 */
+#endif
+    assert(ncp->flags == 0);
+
+    /* set the file format version based on the create mode, cmode */
+    if (fIsSet(cmode, NC_64BIT_DATA)) {
+        if (SIZEOF_MPI_OFFSET <  8) DEBUG_RETURN_ERROR(NC_ESMALL)
+        fSet(ncp->flags, NC_64BIT_DATA);
+    } else if (fIsSet(cmode, NC_64BIT_OFFSET)) {
+        /* unlike serial netcdf, we will not bother to support
+         * NC_64BIT_OFFSET on systems with off_t smaller than 8 bytes.
+         * serial netcdf has proven it's possible if datasets are small, but
+         * that's a hassle we don't want to worry about */
+        if (SIZEOF_OFF_T < 8) DEBUG_RETURN_ERROR(NC_ESMALL)
+        fSet(ncp->flags, NC_64BIT_OFFSET);
+    } else {
+        /* check default format */
+        int default_format;
+        ncmpi_inq_default_format(&default_format);
+        if (default_format == NC_FORMAT_CDF5) {
+            if (SIZEOF_MPI_OFFSET <  8) DEBUG_RETURN_ERROR(NC_ESMALL)
+            fSet(ncp->flags, NC_64BIT_DATA);
+        }
+        else if (default_format == NC_FORMAT_CDF2) {
+            if (SIZEOF_OFF_T < 8) DEBUG_RETURN_ERROR(NC_ESMALL)
+            fSet(ncp->flags, NC_64BIT_OFFSET);
+        }
+        else
+            fSet(ncp->flags, NC_32BIT);
+    }
+
+    /* find the true header size (not-yet aligned) */
+    ncp->xsz = ncmpii_hdr_len_NC(ncp);
+
+    fSet(ncp->flags, NC_NOFILL);
+
+    err = ncmpiio_create(comm, path, cmode, env_info, ncp);
+    if (err != NC_NOERR) { /* fatal error */
+        ncmpii_free_NC(ncp);
+        return err;
+    }
+
+    fSet(ncp->flags, NC_CREAT);
+
+    /* the linked list storing the outstanding non-blocking requests */
+    ncp->head = NULL;
+    ncp->tail = NULL;
+
+    /* add to the linked list of opened files */
+    ncmpii_add_to_NCList(ncp);
+    *ncidp = ncp->nciop->fd;
+
+    if (env_info != info) MPI_Info_free(&env_info);
+
+    return status;
+}
+
+/*----< ncmpi_open() >-------------------------------------------------------*/
+int
+ncmpi_open(MPI_Comm    comm,
+           const char *path,
+           int         omode,
+           MPI_Info    info,
+           int        *ncidp)
+{
+    int i, flag, err, status=NC_NOERR, safe_mode=0, mpireturn;
+    char *env_str=NULL, *hint_str, value[MPI_MAX_INFO_VAL];
+    MPI_Info   env_info;
+    MPI_Offset chunksize=NC_DEFAULT_CHUNKSIZE;
+    NC *ncp;
+
+#ifdef PNC_DEBUG
+    safe_mode = 1;
+    /* this configure time setting will be overwritten by the run-time
+     * environment variable PNETCDF_SAFE_MODE */
+#endif
+    /* get environment variable PNETCDF_SAFE_MODE
+     * if it is set to 1, then we perform a strict parameter consistent test
+     */
+    env_str = getenv("PNETCDF_SAFE_MODE");
+    if (env_str != NULL) {
+        if (*env_str == '0') safe_mode = 0;
+        else                 safe_mode = 1;
+        /* if PNETCDF_SAFE_MODE is set but without a value, *env_str can
+         * be '\0' (null character). In this case, safe_mode is enabled */
+    }
+
+    if (safe_mode) {
+        /* check if omode is consistent with root's */
+        int root_omode=omode;
+
+        /* Note if omode contains NC_NOWRITE, it is equivalent to NC_CLOBBER.
+           In pnetcdf.h, they both are defined the same value, 0.
+         */
+
+        TRACE_COMM(MPI_Bcast)(&root_omode, 1, MPI_INT, 0, comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+
+        if (root_omode != omode) {
+            int rank;
+            MPI_Comm_rank(comm, &rank);
+            /* omodes are inconsistent, overwrite local omode with root's */
+            printf("rank %d: Warning - inconsistent file open mode, overwrite with root's\n",rank);
+            omode = root_omode;
+            DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_OMODE)
+        }
+    }
+
+    /* take hints from the environment variable PNETCDF_HINTS
+     * a string of hints separated by ";" and each hint is in the
+     * form of hint=value. E.g. cb_nodes=16;cb_config_list=*:6
+     * If this environment variable is set, it  overrides any values that
+     * were set by using calls to MPI_Info_set in the application code.
+     */
+    env_str = getenv("PNETCDF_HINTS");
+    env_info = info;
+    if (env_str != NULL) {
+        if (info == MPI_INFO_NULL)
+            MPI_Info_create(&env_info); /* ignore error */
+
+        hint_str = strtok(env_str, ";");
+        while (hint_str != NULL && env_info != MPI_INFO_NULL) {
+            char key[128], *val;
+            strcpy(key, hint_str);
+            val = strchr(key, '=');
+            *val = '\0';
+            val++;
+            /* printf("env hint: key=%s val=%s\n",key,val); */
+            MPI_Info_set(env_info, key, val); /* override */
+            hint_str = strtok(NULL, ";");
+        }
+    }
+
+    /* get header chunk size from user info, if provided */
+    if (env_info != MPI_INFO_NULL) {
+        MPI_Info_get(env_info, "nc_header_read_chunk_size", MPI_MAX_INFO_VAL-1,
+                     value, &flag);
+        if (flag) chunksize = atoll(value);
+    }
+
+    ncp = ncmpii_new_NC(&chunksize);
+    if (ncp == NULL)
+        DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    ncp->safe_mode = safe_mode;
+    ncp->old       = NULL;
+#ifdef ENABLE_SUBFILING
+    ncp->subfile_mode = 1;
+    if (env_info != MPI_INFO_NULL) {
+        MPI_Info_get(env_info, "pnetcdf_subfiling", MPI_MAX_INFO_VAL-1,
+                     value, &flag);
+        if (flag && strcasecmp(value, "disable") == 0)
+            ncp->subfile_mode = 0;
+    }
+    ncp->ncid_sf   = -1;
+    ncp->nc_num_subfiles = 0;
+#endif
+
+    err = ncmpiio_open(comm, path, omode, env_info, ncp);
+    if (err != NC_NOERR) { /* fatal error */
+        ncmpii_free_NC(ncp);
+        return err;
+    }
+
+    assert(ncp->flags == 0);
+    fSet(ncp->flags, NC_NOFILL);
+
+    err = ncmpii_hdr_get_NC(ncp); /* read header from file */
+    if (err != NC_NOERR) { /* fatal error */
+        ncmpiio_close(ncp->nciop, 0);
+        ncmpii_free_NC(ncp);
+        return err;
+    }
+    ncp->head = NULL;
+    ncp->tail = NULL;
+
+    ncmpii_add_to_NCList(ncp);
+    *ncidp = ncp->nciop->fd;
+
+#ifdef ENABLE_SUBFILING
+    if (ncp->subfile_mode) {
+        /* check attr for subfiles */
+        err = ncmpi_get_att_int(ncp->nciop->fd, NC_GLOBAL, "num_subfiles",
+                                &ncp->nc_num_subfiles);
+        if (err == NC_NOERR && ncp->nc_num_subfiles > 1) {
+            /* ignore error NC_ENOTATT if this attribute is not defined */
+            int nvars;
+
+            err = ncmpi_inq_nvars(ncp->nciop->fd, &nvars);
+            if (status == NC_NOERR) status = err;
+
+            for (i=0; i<nvars; i++) {
+                err = ncmpi_get_att_int(ncp->nciop->fd, i, "num_subfiles",
+                                        &ncp->vars.value[i]->num_subfiles);
+                if (err == NC_ENOTATT) continue;
+                if (err != NC_NOERR && status == NC_NOERR) { /* other error */
+                    status = err;
+                    continue;
+                }
+
+                if (ncp->vars.value[i]->num_subfiles > 1) {
+                    err = ncmpi_get_att_int(ncp->nciop->fd, i, "ndims_org",
+                                            &ncp->vars.value[i]->ndims_org);
+                    if (status == NC_NOERR) status = err;
+                }
+            }
+
+            if (ncp->nc_num_subfiles > 1) {
+                err = ncmpii_subfile_open(ncp, &ncp->ncid_sf);
+                if (status == NC_NOERR) status = err;
+            }
+        }
+    }
+    else
+        ncp->nc_num_subfiles = 0;
+#endif
+
+    if (env_info != info) MPI_Info_free(&env_info);
+
+    /* update the total number of record variables */
+    ncp->vars.num_rec_vars = 0;
+    for (i=0; i<ncp->vars.ndefined; i++)
+        ncp->vars.num_rec_vars += IS_RECVAR(ncp->vars.value[i]);
+
+    return status;
+}
+
+/*----< ncmpi_inq_format() >-------------------------------------------------*/
+int
+ncmpi_inq_format(int  ncid,
+                 int *formatp) /* out */
+{
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        return status;
+
+    if (fIsSet(ncp->flags, NC_64BIT_DATA)) {
+        *formatp = NC_FORMAT_CDF5;
+    } else if (fIsSet(ncp->flags, NC_64BIT_OFFSET)) {
+        *formatp = NC_FORMAT_CDF2;
+    } else if (fIsSet(ncp->flags, NC_32BIT)){
+        *formatp = NC_FORMAT_CLASSIC;
+    } else {
+        /* this should not happen, because if ncid is valid, checking for
+         * valid CDF format should have already been done already */
+        *formatp = NC_FORMAT_UNKNOWN;
+    }
+    return status;
+}
+
+/*----< ncmpi_inq_file_format() >--------------------------------------------*/
+int
+ncmpi_inq_file_format(char *filename,
+                      int  *formatp) /* out */
+{
+    int ncid, status;
+    NC *ncp;
+
+    /* open file for reading its header */
+    status = ncmpi_open(MPI_COMM_SELF, filename, NC_NOWRITE, MPI_INFO_NULL,
+                        &ncid);
+    if (status == NC_ENOTNC)
+        DEBUG_ASSIGN_ERROR(*formatp, NC_FORMAT_UNKNOWN)
+    if (status != NC_NOERR)
+        return status;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+         return status;
+
+    if (fIsSet(ncp->flags, NC_64BIT_DATA)) {
+        *formatp = NC_FORMAT_CDF5;
+    } else if (fIsSet(ncp->flags, NC_64BIT_OFFSET)) {
+        *formatp = NC_FORMAT_CDF2;
+    } else if (fIsSet(ncp->flags, NC_32BIT)){
+        *formatp = NC_FORMAT_CLASSIC;
+    } else {
+        /* this should not happen, because if ncid is valid, checking for
+         * valid CDF format should have already been done already */
+        *formatp = NC_FORMAT_UNKNOWN;
+    }
+    status = ncmpi_close(ncid);
+
+    return status;
+}
+
+/*----< ncmpi_inq_file_info() >-----------------------------------------------*/
+int
+ncmpi_inq_file_info(int       ncid,
+                    MPI_Info *info_used)
+{
+    int mpireturn, status=NC_NOERR;
+    char value[MPI_MAX_INFO_VAL];
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        return status;
+
+#ifdef HAVE_MPI_INFO_DUP
+    mpireturn = MPI_Info_dup(ncp->nciop->mpiinfo, info_used);
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_Info_dup");
+#else
+    mpireturn = MPI_File_get_info(ncp->nciop->collective_fh, info_used);
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_File_get_info");
+#endif
+
+    sprintf(value, "%lld", ncp->nciop->hints.h_align);
+    MPI_Info_set(*info_used, "nc_header_align_size", value);
+
+    sprintf(value, "%lld", ncp->nciop->hints.v_align);
+    MPI_Info_set(*info_used, "nc_var_align_size", value);
+
+    sprintf(value, "%lld", ncp->nciop->hints.r_align);
+    MPI_Info_set(*info_used, "nc_record_align_size", value);
+
+    sprintf(value, "%lld", ncp->nciop->hints.header_read_chunk_size);
+    MPI_Info_set(*info_used, "nc_header_read_chunk_size", value);
+
+#ifdef ENABLE_SUBFILING
+    sprintf(value, "%d", ncp->nciop->hints.subfile_mode);
+    MPI_Info_set(*info_used, "pnetcdf_subfiling", value);
+    sprintf(value, "%d", ncp->nciop->hints.num_subfiles);
+    MPI_Info_set(*info_used, "nc_num_subfiles", value);
+#endif
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_get_file_info() >-----------------------------------------------*/
+int
+ncmpi_get_file_info(int       ncid,
+                    MPI_Info *info_used)
+{
+    return ncmpi_inq_file_info(ncid, info_used);
+}
+
+/*----< ncmpi_redef() >------------------------------------------------------*/
+int
+ncmpi_redef(int ncid) {
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        return status;
+
+    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM) /* read-only */
+    /* if open mode is inconsistent, then this return might cause parallel
+     * program to hang */
+
+    /* cannot be in define mode */
+    if (NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_EINDEFINE)
+
+    /* sync all metadata, including numrecs, if changed in independent mode.
+     * also ensure exiting define mode always entering collective data mode
+     */
+    if (NC_indep(ncp))
+        ncmpii_end_indep_data(ncp);
+
+    if (NC_doFsync(ncp)) { /* re-read the header from file */
+        status = ncmpii_read_NC(ncp);
+        if (status != NC_NOERR) return status;
+    }
+
+    /* duplicate a header to be uses in enddef() for checking if header grows */
+    ncp->old = ncmpii_dup_NC(ncp);
+    if (ncp->old == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    /* we are now entering define mode */
+    fSet(ncp->flags, NC_INDEF);
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_begin_indep_data() >-------------------------------------------*/
+int
+ncmpi_begin_indep_data(int ncid)
+{
+    int status=NC_NOERR;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (NC_indef(ncp))  /* must not be in define mode */
+        DEBUG_RETURN_ERROR(NC_EINDEFINE)
+
+    if (NC_indep(ncp))  /* already in indep data mode */
+        return NC_NOERR;
+
+    /* we need no MPI_File_sync() here. If users want a stronger data
+     * consistency, they can either use NC_SHARE or call ncmpi_sync()
+     */
+#if 0 && !defined(DISABLE_FILE_SYNC)
+    if (!NC_readonly(ncp) && NC_collectiveFhOpened(ncp->nciop)) {
+        /* calling file sync for those already open the file */
+        int err, mpireturn;
+        /* MPI_File_sync() is collective */
+        TRACE_IO(MPI_File_sync)(ncp->nciop->collective_fh);
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_File_sync");
+            if (status == NC_NOERR) status = err;
+        }
+        TRACE_COMM(MPI_Barrier)(ncp->nciop->comm);
+    }
+#endif
+
+    fSet(ncp->flags, NC_INDEP);
+
+    status = ncmpii_check_mpifh(ncp, 0);
+
+    return status;
+}
+
+/*----< ncmpi_end_indep_data() >---------------------------------------------*/
+int
+ncmpi_end_indep_data(int ncid) {
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (!NC_indep(ncp)) /* must be in independent data mode */
+        DEBUG_RETURN_ERROR(NC_ENOTINDEP)
+
+    return ncmpii_end_indep_data(ncp);
+}
+
+/*----< ncmpii_end_indep_data() >--------------------------------------------*/
+/* this function is called when:
+ * 1. ncmpi_end_indep_data()
+ * 2. ncmpi_redef() from independent data mode entering to define more
+ * 3. ncmpii_close() when closing the file
+ * This function is collective.
+ */
+int
+ncmpii_end_indep_data(NC *ncp)
+{
+    int status=NC_NOERR;
+
+    if (!NC_readonly(ncp)) {
+        if (ncp->vars.num_rec_vars > 0) {
+            /* numrecs dirty bit may not be the same across all processes.
+             * force sync in memory no matter if dirty or not.
+             */
+            set_NC_ndirty(ncp);
+            status = ncmpii_sync_numrecs(ncp, ncp->numrecs);
+            /* the only possible dirty part of the header is numrecs */
+        }
+
+#ifndef DISABLE_FILE_SYNC
+        /* calling file sync for those already open the file */
+        if (NC_doFsync(ncp) && NC_independentFhOpened(ncp->nciop)) {
+            int mpireturn;
+            /* MPI_File_sync() is collective */
+            TRACE_IO(MPI_File_sync)(ncp->nciop->independent_fh);
+            if (mpireturn != MPI_SUCCESS) {
+                int err = ncmpii_handle_error(mpireturn, "MPI_File_sync");
+                if (status == NC_NOERR) status = err;
+            }
+            TRACE_COMM(MPI_Barrier)(ncp->nciop->comm);
+        }
+#endif
+    }
+
+    fClr(ncp->flags, NC_INDEP);
+
+    return status;
+}
+
+/*----< ncmpi_enddef() >-----------------------------------------------------*/
+int
+ncmpi_enddef(int ncid) {
+    int status;
+    NC *ncp;
+
+    /* check if file ID ncid is valid */
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (!NC_indef(ncp)) /* must currently in define mode */
+        DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+
+    return ncmpii_enddef(ncp);
+}
+
+/*----< ncmpi__enddef() >-----------------------------------------------------*/
+int
+ncmpi__enddef(int        ncid,
+              MPI_Offset h_minfree,
+              MPI_Offset v_align,
+              MPI_Offset v_minfree,
+              MPI_Offset r_align)
+{
+    int status;
+    NC *ncp;
+
+    /* check if file ID ncid is valid */
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (!NC_indef(ncp)) /* must currently in define mode */
+        DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+
+    return ncmpii__enddef(ncp, h_minfree, v_align, v_minfree, r_align);
+}
+
+/*----< ncmpi_sync_numrecs() >------------------------------------------------*/
+/* this API is collective, but can be called in independent data mode.
+ * Note numrecs is always sync-ed in memory and update in file in collective
+ * data mode.
+ */
+int
+ncmpi_sync_numrecs(int ncid) {
+    int status = NC_NOERR;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* cannot be in define mode */
+    if (NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_EINDEFINE)
+
+    /* check if we have defined record variables */
+    if (ncp->vars.num_rec_vars == 0) return NC_NOERR;
+
+    if (!NC_indep(ncp)) /* in collective data mode, numrecs is always sync-ed */
+        return NC_NOERR;
+    else /* if called in independent mode, we force sync in memory */
+        set_NC_ndirty(ncp);
+
+    /* sync numrecs in memory and file */
+    status = ncmpii_sync_numrecs(ncp, ncp->numrecs);
+
+#ifndef DISABLE_FILE_SYNC
+    if (NC_doFsync(ncp)) { /* NC_SHARE is set */
+        int err, mpireturn;
+        if (NC_indep(ncp)) {
+            TRACE_IO(MPI_File_sync)(ncp->nciop->independent_fh);
+        }
+        else {
+            TRACE_IO(MPI_File_sync)(ncp->nciop->collective_fh);
+        }
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_File_sync");
+            if (status == NC_NOERR) status = err;
+        }
+        TRACE_COMM(MPI_Barrier)(ncp->nciop->comm);
+    }
+#endif
+    return status;
+}
+
+/*----< ncmpi_sync() >--------------------------------------------------------*/
+/* This API must be called collectively, no matter if it is in collective
+ * or independent data mode.
+ */
+int
+ncmpi_sync(int ncid) {
+    int status = NC_NOERR;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_EINDEFINE)
+
+    if (NC_readonly(ncp))
+        /* calling sync for file opened for read only means re-read header */
+        return ncmpii_read_NC(ncp);
+
+    /* the only part of header that can be dirty is numrecs (caused only by
+     * independent APIs) */
+    if (ncp->vars.num_rec_vars > 0 && NC_indep(ncp)) {
+        /* sync numrecs in memory among processes and in file */
+        set_NC_ndirty(ncp);
+        status = ncmpii_sync_numrecs(ncp, ncp->numrecs);
+        if (status != NC_NOERR) return status;
+    }
+
+    /* calling MPI_File_sync() on both collective and independent handlers */
+    return ncmpiio_sync(ncp->nciop);
+}
+
+/*----< ncmpi_abort() >------------------------------------------------------*/
+int
+ncmpi_abort(int ncid) {
+   /*
+    * In data mode, same as ncmpiio_close.
+    * In define mode, descard new definition.
+    * In create, remove the file.
+    */
+    int status, err, doUnlink = 0;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* delete the file if it is newly created by ncmpi_create() */
+    doUnlink = NC_IsNew(ncp);
+
+    if (ncp->old != NULL) {
+        /* a plain redef, not a create */
+        assert(!NC_IsNew(ncp));
+        assert(fIsSet(ncp->flags, NC_INDEF));
+        ncmpii_free_NC(ncp->old);
+        ncp->old = NULL;
+        fClr(ncp->flags, NC_INDEF);
+    }
+
+    if (!doUnlink) {
+        if (!NC_readonly(ncp) &&  /* file is open for write */
+             NC_indep(ncp)) {     /* in independent data mode */
+            status = ncmpii_end_indep_data(ncp); /* sync header */
+        }
+
+        if (NC_doFsync(ncp)) {
+            err = ncmpiio_sync(ncp->nciop); /* calling MPI_File_sync() */
+            if (status == NC_NOERR ) status = err;
+        }
+    }
+
+    /* close the file */
+    err = ncmpiio_close(ncp->nciop, doUnlink);
+    if (status == NC_NOERR ) status = err;
+
+    ncp->nciop = NULL;
+
+    /* remove this file from the list of opened files */
+    ncmpii_del_from_NCList(ncp);
+
+    /* free up space occupied by the header metadata */
+    ncmpii_free_NC(ncp);
+
+    return status;
+}
+
+/*----< ncmpi_close() >------------------------------------------------------*/
+int
+ncmpi_close(int ncid) {
+    int status = NC_NOERR;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        return status;
+
+    /* calling the implementation of ncmpi_close() */
+    return ncmpii_close(ncp);
+}
+
+/*----< ncmpi_delete() >-----------------------------------------------------*/
+/* ncmpi_delete:
+ * doesn't do anything to release resources, so call ncmpi_close before calling
+ * this function.
+ *
+ * filename: the name of the
+ * file we will remove.  info: mpi info, in case underlying file system needs
+ * hints.
+ */
+int
+ncmpi_delete(char     *filename,
+             MPI_Info  info)
+{
+    int err=NC_NOERR, mpireturn;
+
+    TRACE_IO(MPI_File_delete)(filename, info);
+    if (mpireturn != MPI_SUCCESS)
+        err = ncmpii_handle_error(mpireturn, "MPI_File_delete");
+    return err;
+}
+
+/* End Of Dataset Functions */
+
+/*----< ncmpii_check_mpifh() >-----------------------------------------------*/
+int
+ncmpii_check_mpifh(NC  *ncp,
+                   int  collective)
+{
+    int mpireturn;
+
+    if (collective && NC_indep(ncp)) /* collective handle but in indep mode */
+        DEBUG_RETURN_ERROR(NC_EINDEP)
+
+    if (!collective && !NC_indep(ncp)) /* indep handle but in collective mode */
+        DEBUG_RETURN_ERROR(NC_ENOTINDEP)
+
+    if (collective && !NC_collectiveFhOpened(ncp->nciop)) {
+        TRACE_IO(MPI_File_open)(ncp->nciop->comm, (char*)ncp->nciop->path,
+                                ncp->nciop->mpiomode, ncp->nciop->mpiinfo,
+                                &ncp->nciop->collective_fh);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_File_open");
+
+        set_NC_collectiveFh(ncp->nciop);
+    }
+    else if (!collective && !NC_independentFhOpened(ncp->nciop)) {
+        TRACE_IO(MPI_File_open)(MPI_COMM_SELF, (char*)ncp->nciop->path,
+                                ncp->nciop->mpiomode, ncp->nciop->mpiinfo,
+                                &ncp->nciop->independent_fh);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_File_open");
+
+        set_NC_independentFh(ncp->nciop);
+    }
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_put_size() >------------------------------------------------*/
+/* returns the amount of writes, in bytes, committed to file system so far */
+int
+ncmpi_inq_put_size(int         ncid,
+                   MPI_Offset *size)
+{
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        return status;
+
+    *size = ncp->nciop->put_size;
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_get_size() >------------------------------------------------*/
+/* returns the amount of reads, in bytes, obtained from file system so far */
+int
+ncmpi_inq_get_size(int         ncid,
+                   MPI_Offset *size)
+{
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        return status;
+
+    *size = ncp->nciop->get_size;
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_striping() >------------------------------------------------*/
+/* return file (system) striping settings, striping size and count, if they are
+ * available from MPI-IO hint. Otherwise, 0s are returned.
+ */
+int
+ncmpi_inq_striping(int  ncid,
+                   int *striping_size,
+                   int *striping_count)
+{
+    int flag, status=NC_NOERR;
+    char value[MPI_MAX_INFO_VAL];
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        return status;
+
+    if (striping_size != NULL) {
+        MPI_Info_get(ncp->nciop->mpiinfo, "striping_unit", MPI_MAX_INFO_VAL-1,
+                     value, &flag);
+        *striping_size = 0;
+        if (flag) *striping_size = atoi(value);
+    }
+
+    if (striping_count != NULL) {
+        MPI_Info_get(ncp->nciop->mpiinfo, "striping_factor", MPI_MAX_INFO_VAL-1,
+                     value, &flag);
+        *striping_count = 0;
+        if (flag) *striping_count = atoi(value);
+    }
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_malloc_size() >--------------------------------------------*/
+/* report the current aggregate size allocated by malloc, yet to be freed */
+int ncmpi_inq_malloc_size(MPI_Offset *size)
+{
+#ifdef PNC_MALLOC_TRACE
+    ncmpii_inq_malloc_size(size);
+    return NC_NOERR;
+#else
+    DEBUG_RETURN_ERROR(NC_ENOTENABLED)
+#endif
+}
+
+/*----< ncmpi_inq_malloc_max_size() >----------------------------------------*/
+/* get the max watermark ever researched by malloc (aggregated amount) */
+int ncmpi_inq_malloc_max_size(MPI_Offset *size)
+{
+#ifdef PNC_MALLOC_TRACE
+    ncmpii_inq_malloc_max_size(size);
+    return NC_NOERR;
+#else
+    DEBUG_RETURN_ERROR(NC_ENOTENABLED)
+#endif
+}
+
+/*----< ncmpi_inq_malloc_list() >--------------------------------------------*/
+/* walk the malloc tree and print yet-to-be-freed malloc residues */
+int ncmpi_inq_malloc_list(void)
+{
+#ifdef PNC_MALLOC_TRACE
+    ncmpii_inq_malloc_list();
+    return NC_NOERR;
+#else
+    DEBUG_RETURN_ERROR(NC_ENOTENABLED)
+#endif
+}
+
+/*----< ncmpi_inq_files_opened() >-------------------------------------------*/
+int
+ncmpi_inq_files_opened(int *num, int *ncids)
+{
+    return ncmpii_inq_files_opened(num, ncids);
+}
+
+/*----< ncmpi_inq_recsize() >------------------------------------------------*/
+int
+ncmpi_inq_recsize(int         ncid,
+                  MPI_Offset *recsize)
+{
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        return status;
+
+    *recsize = ncp->recsize;
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_header_extent() >-------------------------------------------*/
+int
+ncmpi_inq_header_extent(int         ncid,
+                        MPI_Offset *extent)
+{
+    int err;
+    NC *ncp;
+
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) return err;
+
+    *extent = ncp->begin_var;
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_header_size() >---------------------------------------------*/
+int
+ncmpi_inq_header_size(int         ncid,
+                      MPI_Offset *size)
+{
+    int err;
+    NC *ncp;
+
+    err = ncmpii_NC_check_id(ncid, &ncp);
+    if (err != NC_NOERR) return err;
+
+    *size = ncp->xsz;
+
+    return NC_NOERR;
+}
+
diff --git a/src/lib/nc.c b/src/lib/nc.c
new file mode 100644
index 0000000..b2f06ce
--- /dev/null
+++ b/src/lib/nc.c
@@ -0,0 +1,1635 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: nc.c 2299 2016-01-09 06:14:37Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "rnd.h"
+#include "ncx.h"
+#include "macro.h"
+#ifdef ENABLE_SUBFILING
+#include "subfile.h"
+#endif
+
+/* list of open netcdf's */
+static NC *NClist = NULL;
+
+/* This is the default create format for ncmpi_create and nc__create. */
+static int default_create_format = NC_FORMAT_CLASSIC;
+
+/* These have to do with version numbers. */
+#define MAGIC_NUM_LEN 4
+#define VER_CLASSIC 1
+#define VER_64BIT_OFFSET 2
+#define VER_HDF5 3
+#define VER_64BIT_DATA 5
+
+/* Prototypes for functions used only in this file */
+#if 0
+static int move_data_r(NC *ncp, NC *old);
+static int move_vars_r(NC *ncp, NC *old);
+static int NC_check_def(MPI_Comm comm, void *buf, MPI_Offset nn);
+static int nc_set_fill(int ncid, int fillmode, int *old_mode_ptr);
+#endif
+
+/*----< ncmpii_add_to_NCList() >---------------------------------------------*/
+void
+ncmpii_add_to_NCList(NC *ncp)
+{
+    assert(ncp != NULL);
+
+    /* add the newly created NC object to the head of linked list */
+    ncp->prev = NULL;
+    if (NClist != NULL)
+        NClist->prev = ncp;
+    ncp->next = NClist;
+    NClist = ncp;
+}
+
+/*----< ncmpii_del_from_NCList() >-------------------------------------------*/
+void
+ncmpii_del_from_NCList(NC *ncp)
+{
+    assert(ncp != NULL);
+
+    if (NClist == ncp) {
+        assert(ncp->prev == NULL);
+        NClist = ncp->next;
+    }
+    else {
+        assert(ncp->prev != NULL);
+        ncp->prev->next = ncp->next;
+    }
+
+    if (ncp->next != NULL)
+        ncp->next->prev = ncp->prev;
+
+    ncp->next = NULL;
+    ncp->prev = NULL;
+}
+
+/*----< NC_check_header() >--------------------------------------------------*/
+/*
+ * Check the consistency of defined header metadata across all processes and
+ * overwrite the local header objects with root's if inconsistency is found.
+ * This function is collective.
+ */
+static int
+NC_check_header(NC         *ncp,
+                void       *buf,
+                MPI_Offset  local_xsz) /* size of buf */
+{
+    void *cmpbuf;
+    int rank, g_status, status=NC_NOERR, mpireturn;
+    bufferinfo gbp;
+
+    MPI_Comm_rank(ncp->nciop->comm, &rank);
+
+    /* root's header size has been broadcasted in NC_begin() and saved in
+     * ncp->xsz.
+     */
+    if (rank == 0)
+        cmpbuf = buf;
+    else
+        cmpbuf = (void*) NCI_Malloc((size_t)ncp->xsz);
+
+    /* process 0 broadcasts its header
+     * TODO: currently the header size cannot be larger than 2^31 bytes,
+     * due to the 2nd argument, count, of MPI_Bcast being of type int.
+     * Possible solution is to broadcast in chunks of 2^31 bytes.
+     */
+    if (ncp->xsz != (int)ncp->xsz) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    TRACE_COMM(MPI_Bcast)(cmpbuf, (int)ncp->xsz, MPI_BYTE, 0, ncp->nciop->comm);
+
+    if (rank > 0 && (ncp->xsz != local_xsz || memcmp(buf, cmpbuf, (size_t)ncp->xsz))) {
+        /* now part of this process's header is not consistent with root's
+         * check and report the inconsistent part
+         */
+
+        gbp.nciop  = ncp->nciop; /* will not be used in ncmpii_hdr_check_NC() */
+        gbp.offset = 0;          /* will not be used in ncmpii_hdr_check_NC() */
+        gbp.size   = ncp->xsz;   /* entire header is in the buffer, cmpbuf */
+        gbp.index  = 0;
+        gbp.pos    = gbp.base = cmpbuf;
+
+        /* find the inconsistent part of the header, report the difference, and
+         * overwrite the local header object with root's. ncmpii_hdr_check_NC()
+         * should not have any MPI communication calls.
+         */
+        status = ncmpii_hdr_check_NC(&gbp, ncp);
+
+        /* header consistency is only checked on non-root processes. The
+         * returned status can be a fatal error or header inconsistency error,
+         * (fatal errors are due to object allocation), but never NC_NOERR.
+         */
+    }
+
+    if (ncp->safe_mode) {
+        TRACE_COMM(MPI_Allreduce)(&status, &g_status, 1, MPI_INT, MPI_MIN,
+                                  ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce"); 
+
+        if (g_status != NC_NOERR) { /* some headers are inconsistent */
+            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE)
+        }
+    }
+
+    if (rank > 0) NCI_Free(cmpbuf);
+
+    return status;
+}
+
+
+#if 0
+/* 'defined but not used': seems like a useful function though. why did we
+ * write it?  should we be using it? */
+
+static int
+NC_check_def(MPI_Comm comm, void *buf, MPI_Offset nn) {
+  int rank;
+  int errcheck;
+  MPI_Offset compare = 0;
+  void *cmpbuf;
+  MPI_Offset max_size;
+
+  MPI_Comm_rank(comm, &rank);
+
+  if (rank == 0)
+    max_size = nn;
+  MPI_Bcast(&max_size, 1, MPI_OFFSET, 0, comm);
+
+  compare = max_size - nn;
+
+  MPI_Allreduce(&compare, &errcheck, 1, MPI_OFFSET, MPI_LOR, comm);
+
+  if (errcheck)
+    DEBUG_RETURN_ERROR(NC_EMULTIDEFINE)
+
+  if (rank == 0)
+    cmpbuf = buf;
+  else
+    cmpbuf = (void *)NCI_Malloc(nn);
+
+  MPI_Bcast(cmpbuf, nn, MPI_BYTE, 0, comm);
+
+  if (rank != 0) {
+    compare = memcmp(buf, cmpbuf, nn);
+    NCI_Free(cmpbuf);
+  }
+
+  MPI_Allreduce(&compare, &errcheck, 1, MPI_OFFSET, MPI_LOR, comm);
+
+  if (errcheck){
+    DEBUG_RETURN_ERROR(NC_EMULTIDEFINE)
+  }else{
+    return NC_NOERR;
+  }
+}
+#endif
+
+/*----< ncmpii_NC_check_id() >-----------------------------------------------*/
+int
+ncmpii_NC_check_id(int   ncid,
+                   NC  **ncpp)
+{
+    NC *ncp;
+
+    if (ncid >= 0) {
+        for (ncp = NClist; ncp != NULL; ncp = ncp->next) {
+            if (ncp->nciop->fd == ncid) {
+                *ncpp = ncp;
+                return NC_NOERR; /* normal return */
+            }
+        }
+    }
+
+    /* else, not found */
+    DEBUG_RETURN_ERROR(NC_EBADID)
+}
+
+
+/*----< ncmpii_inq_files_opened() >------------------------------------------*/
+int
+ncmpii_inq_files_opened(int *num, int *ncids)
+{
+    NC *ncp;
+
+/*
+    for (ncp=NClist; ncp!=NULL; ncp=ncp->next)
+        printf("still open %s\n",ncp->nciop->path);
+*/
+    if (num == NULL) DEBUG_RETURN_ERROR(NC_EINVAL)
+
+    *num = 0;
+    for (ncp=NClist; ncp!=NULL; ncp=ncp->next)
+        (*num)++;
+
+    if (*num > 0 && ncids != NULL) {
+        /* when ncids is NULL, we skip getting the values */
+        int i=0;
+        for (ncp=NClist; ncp!=NULL; ncp=ncp->next)
+            ncids[i] = ncp->nciop->fd;
+    }
+    return NC_NOERR;
+}
+
+
+/*----< ncmpii_free_NC() >----------------------------------------------------*/
+inline void
+ncmpii_free_NC(NC *ncp)
+{
+    if (ncp == NULL) return;
+    ncmpii_free_NC_dimarray(&ncp->dims);
+    ncmpii_free_NC_attrarray(&ncp->attrs);
+    ncmpii_free_NC_vararray(&ncp->vars);
+    NCI_Free(ncp);
+}
+
+
+/*----< ncmpii_new_NC() >----------------------------------------------------*/
+inline NC *
+ncmpii_new_NC(const MPI_Offset *chunkp)
+{
+    NC *ncp = (NC *) NCI_Calloc(1, sizeof(NC));
+
+    if (ncp == NULL) return NULL;
+
+    ncp->chunk = (chunkp != NULL) ? *chunkp : NC_SIZEHINT_DEFAULT;
+
+    return ncp;
+}
+
+/*----< ncmpi_set_default_format() >-----------------------------------------*/
+/* This function sets a default create file format.
+ * Valid formats are NC_FORMAT_CLASSIC, NC_FORMAT_CDF2, and NC_FORMAT_CDF5
+ * This API is collective.
+ */
+int
+ncmpi_set_default_format(int format, int *old_formatp)
+{
+    int safe_mode=0, mpireturn, status=NC_NOERR;
+    char *env_str;
+
+    /* Return existing format if desired. */
+    if (old_formatp)
+        *old_formatp = default_create_format;
+
+    env_str = getenv("PNETCDF_SAFE_MODE");
+    if (env_str != NULL) {
+        if (*env_str == '0') safe_mode = 0;
+        else                 safe_mode = 1;
+    }
+
+    if (safe_mode) {
+        /* check if format is consistent with root's */
+        int root_format=format;
+
+        TRACE_COMM(MPI_Bcast)(&root_format, 1, MPI_INT, 0, MPI_COMM_WORLD);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast");
+
+        if (root_format != format) {
+            int rank;
+            MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+            /* formats are inconsistent, overwrite local format with root's */
+            printf("rank %d: Warning - inconsistent file format, overwrite with root's\n",rank);
+            format = root_format;
+            DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_OMODE)
+        }
+    }
+
+
+    /* Make sure only valid format is set. */
+    if (format != NC_FORMAT_CLASSIC &&
+        format != NC_FORMAT_CDF2 &&
+        format != NC_FORMAT_CDF5) {
+        DEBUG_RETURN_ERROR(NC_EINVAL)
+    }
+    default_create_format = format;
+
+    return status;
+}
+
+/* returns a value suitable for a create flag.  Will return one or more of the
+ * following values OR-ed together:
+ * NC_64BIT_OFFSET, NC_CLOBBER, NC_LOCK, NC_SHARE */
+int
+ncmpi_inq_default_format(int *formatp)
+{
+    if (formatp == NULL) DEBUG_RETURN_ERROR(NC_EINVAL)
+
+    *formatp = default_create_format;
+    return NC_NOERR;
+}
+
+/*----< ncmpii_dup_NC() >----------------------------------------------------*/
+NC *
+ncmpii_dup_NC(const NC *ref)
+{
+    NC *ncp;
+
+    ncp = (NC *) NCI_Malloc(sizeof(NC));
+    if (ncp == NULL) return NULL;
+
+    memset(ncp, 0, sizeof(NC));
+
+    if (ncmpii_dup_NC_dimarray(&ncp->dims,   &ref->dims)  != NC_NOERR ||
+        ncmpii_dup_NC_attrarray(&ncp->attrs, &ref->attrs) != NC_NOERR ||
+        ncmpii_dup_NC_vararray(&ncp->vars,   &ref->vars)  != NC_NOERR) {
+        ncmpii_free_NC(ncp);
+        return NULL;
+    }
+
+    ncp->xsz       = ref->xsz;
+    ncp->begin_var = ref->begin_var;
+    ncp->begin_rec = ref->begin_rec;
+    ncp->recsize   = ref->recsize;
+
+    NC_set_numrecs(ncp, NC_get_numrecs(ref));
+    return ncp;
+}
+
+
+/*
+ *  Verify that this is a user nc_type
+ * Formerly
+NCcktype()
+ * Sense of the return is changed.
+ */
+inline int
+ncmpii_cktype(int     cdf_ver,
+              nc_type type)
+{
+    /* the max data type supported by CDF-5 is NC_UINT64 */
+    if (type <= 0 || type > NC_UINT64)
+        DEBUG_RETURN_ERROR(NC_EBADTYPE)
+
+    /* For CDF-1 and CDF-2 files, only classic types are allowed. */
+    if (cdf_ver < 5 && type > NC_DOUBLE)
+        DEBUG_RETURN_ERROR(NC_ESTRICTCDF2)
+
+    return NC_NOERR;
+}
+
+
+/*
+ * How many objects of 'type'
+ * will fit into xbufsize?
+ */
+inline MPI_Offset
+ncmpix_howmany(nc_type type, MPI_Offset xbufsize)
+{
+    switch(type){
+        case NC_BYTE:
+        case NC_UBYTE:
+        case NC_CHAR:   return xbufsize;
+        case NC_SHORT:  return xbufsize/X_SIZEOF_SHORT;
+        case NC_USHORT: return xbufsize/X_SIZEOF_USHORT;
+        case NC_INT:    return xbufsize/X_SIZEOF_INT;
+        case NC_UINT:   return xbufsize/X_SIZEOF_UINT;
+        case NC_FLOAT:  return xbufsize/X_SIZEOF_FLOAT;
+        case NC_DOUBLE: return xbufsize/X_SIZEOF_DOUBLE;
+        case NC_INT64:  return xbufsize/X_SIZEOF_INT64;
+        case NC_UINT64: return xbufsize/X_SIZEOF_UINT64;
+        default:
+                assert("ncmpix_howmany: Bad type" == 0);
+                return(0);
+    }
+}
+
+#define D_RNDUP(x, align) _RNDUP(x, (off_t)(align))
+
+/*----< NC_begins() >--------------------------------------------------------*/
+/*
+ * This function is only called at enddef().
+ * It computes each variable's 'begin' offset, and sets/updates the followings:
+ *    ncp->xsz                   ---- header size
+ *    ncp->vars.value[*]->begin  ---- each variable's 'begin' offset
+ *    ncp->begin_var             ---- offset of first non-record variable
+ *    ncp->begin_rec             ---- offset of first     record variable
+ *    ncp->recsize               ---- sum of single records
+ *    ncp->numrecs               ---- number of records (set only if new file)
+ */
+static int
+NC_begins(NC         *ncp,
+          MPI_Offset  h_align,  /* header alignment */
+          MPI_Offset  h_minfree,/* free space for header */
+          MPI_Offset  v_align,  /* alignment for each fixed variable */
+          MPI_Offset  v_minfree,/* free space for fixed variable section */
+          MPI_Offset  r_align)  /* alignment for record variable section */
+{
+    int i, j, rank, cdf_format, mpireturn;
+    MPI_Offset end_var=0;
+    NC_var *last = NULL;
+    NC_var *first_var = NULL;       /* first "non-record" var */
+
+    /* cdf_format determines the size of variable's "begin" in the header */
+    if (fIsSet(ncp->flags, NC_64BIT_DATA))
+        cdf_format = 5;  /* CDF-5 */
+    else if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
+        cdf_format = 2;  /* CDF-2 */
+    else
+        cdf_format = 1;  /* CDF-1 */
+
+    /* get the true header size (un-aligned one) */
+    MPI_Comm_rank(ncp->nciop->comm, &rank);
+    if (rank ==0) ncp->xsz = ncmpii_hdr_len_NC(ncp);
+
+    /* only root's header size matters */
+    TRACE_COMM(MPI_Bcast)(&ncp->xsz, 1, MPI_OFFSET, 0, ncp->nciop->comm);
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+
+    /* This function is called in ncmpi_enddef(), which can happen either when
+     * creating a new file or opening an existing file with metadata modified.
+     * For the former case, ncp->begin_var == 0 here.
+     * For the latter case, we set begin_var a new value only if the new header
+     * grows out of its extent or the start of non-record variables is not
+     * aligned as requested by h_align.
+     * Note ncp->xsz is header size and ncp->begin_var is header extent.
+     * Add the minimum header free space requested by user.
+     */
+    if (h_minfree < 0) h_minfree = 0;
+    ncp->begin_var = D_RNDUP(ncp->xsz + h_minfree, h_align);
+
+    if (ncp->old != NULL) {
+        /* If this define mode was entered from a redef(), we check whether
+         * the new begin_var against the old begin_var. We do not shrink
+         * the header extent.
+         */
+        if (ncp->begin_var < ncp->old->begin_var)
+            ncp->begin_var = ncp->old->begin_var;
+    }
+
+    /* ncp->begin_var is the aligned starting file offset of the first
+       variable, also the extent of file header */
+
+    /* Now calculate the starting file offsets for all variables.
+       loop thru vars, first pass is for the 'non-record' vars */
+    end_var = ncp->begin_var;
+    for (j=0, i=0; i<ncp->vars.ndefined; i++) {
+        if (IS_RECVAR(ncp->vars.value[i]))
+            /* skip record variables on this pass */
+            continue;
+        if (first_var == NULL) first_var = ncp->vars.value[i];
+
+        /* for CDF-1 check if over the file size limit 32-bit integer */
+        if (cdf_format == 1 && end_var > X_OFF_MAX)
+            DEBUG_RETURN_ERROR(NC_EVARSIZE)
+
+        /* this will pad out non-record variables with zero to the
+         * requested alignment.  record variables are a bit trickier.
+         * we don't do anything special with them */
+        ncp->vars.value[i]->begin = D_RNDUP(end_var, v_align);
+
+        if (ncp->old != NULL) {
+            /* move to the next fixed variable */
+            for (; j<ncp->old->vars.ndefined; j++)
+                if (!IS_RECVAR(ncp->old->vars.value[j]))
+                    break;
+            if (j < ncp->old->vars.ndefined) {
+                if (ncp->vars.value[i]->begin < ncp->old->vars.value[j]->begin)
+                    /* the first ncp->vars.ndefined non-record variables should
+                       be the same. If the new begin is smaller, reuse the old
+                       begin */
+                    ncp->vars.value[i]->begin = ncp->old->vars.value[j]->begin;
+                j++;
+            }
+        }
+        /* end_var is the end offset of variable i */
+        end_var = ncp->vars.value[i]->begin + ncp->vars.value[i]->len;
+    }
+
+    /* end_var now is pointing to the end of last non-record variable */
+
+    /* only (re)calculate begin_rec if there is not sufficient
+     * space at end of non-record variables or if start of record
+     * variables is not aligned as requested by r_align.
+     * If the existing begin_rec is already >= index, then leave the
+     * begin_rec as is (in case some non-record variables are deleted)
+     */
+    if (ncp->begin_rec < end_var ||
+        ncp->begin_rec != D_RNDUP(ncp->begin_rec, v_align))
+        ncp->begin_rec = D_RNDUP(end_var, v_align);
+
+    /* expand free space for fixed variable section */
+    if (ncp->begin_rec < end_var + v_minfree)
+        ncp->begin_rec = D_RNDUP(end_var + v_minfree, v_align);
+
+    /* align the starting offset for record variable section */
+    if (r_align > 1)
+        ncp->begin_rec = D_RNDUP(ncp->begin_rec, r_align);
+
+    if (ncp->old != NULL) {
+        /* check whether the new begin_rec is smaller */
+        if (ncp->begin_rec < ncp->old->begin_rec)
+            ncp->begin_rec = ncp->old->begin_rec;
+    }
+
+    if (first_var != NULL)
+        ncp->begin_var = first_var->begin;
+    else
+        ncp->begin_var = ncp->begin_rec;
+
+    end_var = ncp->begin_rec;
+    /* end_var now is pointing to the beginning of record variables
+     * note that this can be larger than the end of last non-record variable
+     */
+
+    ncp->recsize = 0;
+
+    /* TODO: alignment for record variables (maybe using a new hint) */
+
+    /* loop thru vars, second pass is for the 'record' vars,
+     * re-calculate the starting offset for each record variable */
+    for (j=0, i=0; i<ncp->vars.ndefined; i++) {
+        if (!IS_RECVAR(ncp->vars.value[i]))
+            /* skip non-record variables on this pass */
+            continue;
+
+        /* X_OFF_MAX is the max of 32-bit integer */
+        if (cdf_format == 1 && end_var > X_OFF_MAX)
+            DEBUG_RETURN_ERROR(NC_EVARSIZE)
+
+        /* A few attempts at aligning record variables have failed
+         * (either with range error or 'value read not that expected',
+         * or with an error in ncmpi_redef )).  Not sufficient to align
+         * 'begin', but haven't figured out what else to adjust */
+        ncp->vars.value[i]->begin = end_var;
+
+        if (ncp->old != NULL) {
+            /* move to the next record variable */
+            for (; j<ncp->old->vars.ndefined; j++)
+                if (IS_RECVAR(ncp->old->vars.value[j]))
+                    break;
+            if (j < ncp->old->vars.ndefined) {
+                if (ncp->vars.value[i]->begin < ncp->old->vars.value[j]->begin)
+                    /* if the new begin is smaller, use the old begin */
+                    ncp->vars.value[i]->begin = ncp->old->vars.value[j]->begin;
+                j++;
+            }
+        }
+        end_var += ncp->vars.value[i]->len;
+        /* end_var is the end offset of record variable i */
+
+        /* check if record size must fit in 32-bits */
+#if SIZEOF_OFF_T == SIZEOF_SIZE_T && SIZEOF_SIZE_T == 4
+        if (ncp->recsize > X_UINT_MAX - ncp->vars.value[i]->len)
+            DEBUG_RETURN_ERROR(NC_EVARSIZE)
+#endif
+        ncp->recsize += ncp->vars.value[i]->len;
+        last = ncp->vars.value[i];
+    }
+
+    /*
+     * for special case (Check CDF-1 and CDF-2 file format specifications.)
+     * "A special case: Where there is exactly one record variable, we drop the
+     * requirement that each record be four-byte aligned, so in this case there
+     * is no record padding."
+     */
+    if (last != NULL) {
+        if (ncp->recsize == last->len) {
+            /* exactly one record variable, pack value */
+            ncp->recsize = *last->dsizes * last->xsz;
+        }
+#if 0
+        else if (last->len == UINT32_MAX) { /* huge last record variable */
+            ncp->recsize += *last->dsizes * last->xsz;
+        }
+#endif
+    }
+
+/* below is only needed if alignment is performed on record variables */
+#if 0
+    /*
+     * for special case of exactly one record variable, pack value
+     */
+    /* if there is exactly one record variable, then there is no need to
+     * pad for alignment -- there's nothing after it */
+    if (last != NULL && ncp->recsize == last->len)
+        ncp->recsize = *last->dsizes * last->xsz;
+#endif
+
+    if (NC_IsNew(ncp))
+        NC_set_numrecs(ncp, 0);
+
+    return NC_NOERR;
+}
+
+#define NC_NUMRECS_OFFSET 4
+
+/*----< ncmpii_sync_numrecs() >-----------------------------------------------*/
+/* Synchronize the number of records in memory and write numrecs to file.
+ * This function is called by:
+ * 1. ncmpi_sync_numrecs(): by the user
+ * 2. ncmpi_sync(): by the user
+ * 3. ncmpii_end_indep_data(): exit from independent data mode
+ * 4. all blocking collective put APIs (getput.m4) when writing record variable
+ * 5. collective nonblocking wait API (ncmpii_wait_getput)
+ * 6. ncmpii_close(): file close and currently in independent data mode
+ *
+ * This function is collective.
+ */
+int
+ncmpii_sync_numrecs(NC         *ncp,
+                    MPI_Offset  new_numrecs)
+{
+    int rank, status=NC_NOERR, mpireturn, err;
+    MPI_File fh;
+    MPI_Offset max_numrecs;
+
+    assert(!NC_readonly(ncp));
+    assert(!NC_indef(ncp)); /* can only be called by APIs in data mode */
+
+    /* find the max new_numrecs among all processes
+     * Note new_numrecs may be smaller than ncp->numrecs
+     */
+    TRACE_COMM(MPI_Allreduce)(&new_numrecs, &max_numrecs, 1, MPI_OFFSET,
+                              MPI_MAX, ncp->nciop->comm);
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_Allreduce");
+
+    fh = ncp->nciop->collective_fh;
+    if (NC_indep(ncp))
+        fh = ncp->nciop->independent_fh;
+
+    /* root process writes numrecs in file */
+    MPI_Comm_rank(ncp->nciop->comm, &rank);
+    if (rank == 0 && /* Only root process writes to file header */
+        (max_numrecs > ncp->numrecs || NC_ndirty(ncp))) {
+         /* For collective data mode, we check max_numrecs against root's
+          * ncp->numrecs because root's numrecs has not been updated.
+          * For independent data mode, we check NC_ndirty bit, because root's
+          * numrecs may have been updated and in this case NC_ndirty bit has
+          * been set to dirty. */
+        int len;
+        char pos[8], *buf=pos;
+        MPI_Status mpistatus;
+
+        if (ncp->flags & NC_64BIT_DATA) {
+            len = X_SIZEOF_INT64;
+            status = ncmpix_put_uint64((void**)&buf, max_numrecs);
+        }
+        else {
+            if (max_numrecs != (int)max_numrecs) DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+            len = X_SIZEOF_SIZE_T;
+            status = ncmpix_put_uint32((void**)&buf, (uint)max_numrecs);
+        }
+        /* ncmpix_put_xxx advances the 1st argument with size len */
+
+        /* root's file view always includes the entire file header */
+
+        TRACE_IO(MPI_File_write_at)(fh, NC_NUMRECS_OFFSET, (void*)pos, len,
+                                    MPI_BYTE, &mpistatus);
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_File_write_at");
+            if (status == NC_NOERR && err == NC_EFILE) DEBUG_ASSIGN_ERROR(status, NC_EWRITE)
+        }
+        else {
+            int put_size;
+            MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
+            ncp->nciop->put_size += put_size;
+        }
+    }
+    /* update numrecs in all processes's memory only if the new one is larger.
+     * Note new_numrecs may be smaller than ncp->numrecs
+     */
+    if (max_numrecs > ncp->numrecs) ncp->numrecs = max_numrecs;
+
+    if (ncp->safe_mode == 1) {
+        /* broadcast root's status, because only root writes to the file */
+        int root_status = status;
+        TRACE_COMM(MPI_Bcast)(&root_status, 1, MPI_INT, 0, ncp->nciop->comm);
+        /* root's write has failed, which is serious */
+        if (root_status == NC_EWRITE) DEBUG_ASSIGN_ERROR(status, NC_EWRITE)
+    }
+
+    /* clear numrecs dirty bit */
+    fClr(ncp->flags, NC_NDIRTY);
+
+    return status;
+}
+
+/*
+ * Read in the header
+ * It is expensive.
+ */
+
+inline int
+ncmpii_read_NC(NC *ncp) {
+  int status = NC_NOERR;
+
+  ncmpii_free_NC_dimarray(&ncp->dims);
+  ncmpii_free_NC_attrarray(&ncp->attrs);
+  ncmpii_free_NC_vararray(&ncp->vars);
+
+  status = ncmpii_hdr_get_NC(ncp);
+
+  if (status == NC_NOERR)
+      fClr(ncp->flags, NC_NDIRTY);
+
+  return status;
+}
+
+/*----< write_NC() >---------------------------------------------------------*/
+/*
+ * This function is collective and only called by enddef().
+ * Write out the header
+ * 1. Call ncmpii_hdr_put_NC() to copy the header object, ncp, to a buffer.
+ * 2. Call NC_check_header() to check if header is consistent across all
+ *    processes.
+ * 3. Process rank 0 writes the header to file.
+ * This is a collective call.
+ */
+static int
+write_NC(NC *ncp)
+{
+    void *buf;
+    int status, mpireturn, err, max_err, rank;
+    MPI_Offset local_xsz;
+
+    assert(!NC_readonly(ncp));
+
+    /* ncp->xsz is root's header size, we need to calculate local's */
+    local_xsz = ncmpii_hdr_len_NC(ncp);
+
+    buf = NCI_Malloc((size_t)local_xsz); /* buffer for local header object */
+
+    /* copy the entire local header object to buffer */
+    status = ncmpii_hdr_put_NC(ncp, buf);
+    if (status != NC_NOERR) { /* a fatal error */
+        NCI_Free(buf);
+        return status;
+    }
+
+    /* check the header consistency across all processes and sync header.
+     * When safe_mode is on:
+     *   The returned status on root can be either NC_NOERR (all headers are
+     *   consistent) or NC_EMULTIDEFINE (some headers are inconsistent).
+     *   The returned status on non-root processes can be NC_NOERR, fatal
+     *   error (>-250), or inconsistency error (-250 to -269).
+     * When safe_mode is off:
+     *   The returned status on root is always NC_NOERR
+     *   The returned status on non-root processes can be NC_NOERR, fatal
+     *   error (>-250), or inconsistency error (-250 to -269).
+     * For fatal error, we should stop. For others, we can continue.
+     */
+    status = NC_check_header(ncp, buf, local_xsz);
+
+    /* check for fatal error */
+    err =  (status != NC_NOERR && !ErrIsHeaderDiff(status)) ? 1 : 0;
+    max_err = err;
+
+    if (ncp->safe_mode == 1)
+        TRACE_COMM(MPI_Allreduce)(&err, &max_err, 1, MPI_INT, MPI_MAX,
+                                  ncp->nciop->comm);
+
+    if (max_err == 1) { /* some processes encounter a fatal error */
+        NCI_Free(buf);
+        return status;
+    }
+    /* For non-fatal error, we continue to write header to the file, as now the
+     * header object in memory has been sync-ed across all processes. */
+
+    /* only rank 0's header gets written to the file */
+    MPI_Comm_rank(ncp->nciop->comm, &rank);
+    if (rank == 0) {
+        /* rank 0's fileview already includes the file header */
+        MPI_Status mpistatus;
+        if (ncp->xsz != (int)ncp->xsz) DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+        TRACE_IO(MPI_File_write_at)(ncp->nciop->collective_fh, 0, buf,
+                                    (int)ncp->xsz, MPI_BYTE, &mpistatus);
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_File_write_at");
+            /* write has failed, which is more serious than inconsistency */
+            if (err == NC_EFILE) DEBUG_ASSIGN_ERROR(status, NC_EWRITE)
+        }
+        else {
+            int put_size;
+            MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
+            ncp->nciop->put_size += put_size;
+        }
+    }
+
+    if (ncp->safe_mode == 1) {
+        /* broadcast root's status, because only root writes to the file */
+        int root_status = status;
+        TRACE_COMM(MPI_Bcast)(&root_status, 1, MPI_INT, 0, ncp->nciop->comm);
+        /* root's write has failed, which is more serious than inconsistency */
+        if (root_status == NC_EWRITE) DEBUG_ASSIGN_ERROR(status, NC_EWRITE)
+    }
+
+    fClr(ncp->flags, NC_NDIRTY);
+    NCI_Free(buf);
+
+    return status;
+}
+
+inline int
+ncmpii_dset_has_recvars(NC *ncp)
+{
+    /* possible further optimization: set a flag on the header data
+     * structure when record variable created so we can skip this loop*/
+    int i;
+    NC_var **vpp;
+
+    vpp = ncp->vars.value;
+    for (i=0; i< ncp->vars.ndefined; i++, vpp++) {
+        if (IS_RECVAR(*vpp)) return 1;
+    }
+    return 0;
+}
+
+
+#if 0
+/*
+ * header size increases, shift all record and non-record variables down
+ */
+static int
+move_data_r(NC *ncp, NC *old) {
+    /* no new record or non-record variable inserted, header size increases,
+     * must shift (move) the whole contiguous data part down
+     * Note ncp->numrecs may be > old->numrecs
+     */
+    return ncmpiio_move(ncp->nciop, ncp->begin_var, old->begin_var,
+                        old->begin_rec - old->begin_var +
+                        ncp->recsize * ncp->numrecs);
+}
+#endif
+
+/*
+ * Move the record variables down,
+ * re-arrange records as needed
+ * Fill as needed.
+ */
+static int
+move_recs_r(NC *ncp, NC *old) {
+    int status;
+    MPI_Offset recno;
+    const MPI_Offset nrecs = ncp->numrecs;
+    const MPI_Offset ncp_recsize = ncp->recsize;
+    const MPI_Offset old_recsize = old->recsize;
+    const off_t ncp_off = ncp->begin_rec;
+    const off_t old_off = old->begin_rec;
+
+    assert(ncp_recsize >= old_recsize);
+
+    if (ncp_recsize == old_recsize) {
+        if (ncp_recsize == 0) /* no record variable defined yet */
+            return NC_NOERR;
+
+        /* No new record variable inserted, move all record variables as a whole */
+        status = ncmpiio_move(ncp->nciop, ncp_off, old_off, ncp_recsize * nrecs);
+        if (status != NC_NOERR)
+            return status;
+    } else {
+        /* new record variables inserted, move one whole record at a time */
+        for (recno = nrecs-1; recno >= 0; recno--) {
+            status = ncmpiio_move(ncp->nciop,
+                                  ncp_off+recno*ncp_recsize,
+                                  old_off+recno*old_recsize,
+                                  old_recsize);
+            if (status != NC_NOERR)
+                return status;
+        }
+    }
+
+    return NC_NOERR;
+}
+
+
+#if 0
+/*
+ * Move the "non record" variables "out".
+ * Fill as needed.
+ */
+
+static int
+move_vars_r(NC *ncp, NC *old) {
+  return ncmpiio_move(ncp->nciop, ncp->begin_var, old->begin_var,
+                   old->begin_rec - old->begin_var);
+}
+#endif
+
+/*
+ * Given a valid ncp, return NC_EVARSIZE if any variable has a bad len
+ * (product of non-rec dim sizes too large), else return NC_NOERR.
+ */
+static int
+ncmpii_NC_check_vlens(NC *ncp)
+{
+    NC_var **vpp;
+    /* maximum permitted variable size (or size of one record's worth
+       of a record variable) in bytes.  This is different for format 1
+       and format 2. */
+    MPI_Offset vlen_max;
+    MPI_Offset ii;
+    MPI_Offset large_vars_count;
+    MPI_Offset rec_vars_count;
+    int last = 0;
+
+    if(ncp->vars.ndefined == 0)
+       return NC_NOERR;
+
+    if ((ncp->flags & NC_64BIT_DATA) && SIZEOF_OFF_T > 4)
+       return NC_NOERR;
+
+    if ((ncp->flags & NC_64BIT_OFFSET) && SIZEOF_OFF_T > 4) {
+       /* CDF2 format and LFS */
+       vlen_max = X_UINT_MAX - 3; /* "- 3" handles rounded-up size */
+    } else {
+       /* CDF1 format */
+       vlen_max = X_INT_MAX - 3;
+    }
+    /* Loop through vars, first pass is for non-record variables.   */
+    large_vars_count = 0;
+    rec_vars_count = 0;
+    vpp = ncp->vars.value;
+    for (ii = 0; ii < ncp->vars.ndefined; ii++, vpp++) {
+       if( !IS_RECVAR(*vpp) ) {
+           last = 0;
+           if( ncmpii_NC_check_vlen(*vpp, vlen_max) == 0 ) {
+               large_vars_count++;
+               last = 1;
+           }
+       } else {
+         rec_vars_count++;
+       }
+    }
+    /* OK if last non-record variable size too large, since not used to
+       compute an offset */
+    if( large_vars_count > 1) { /* only one "too-large" variable allowed */
+      DEBUG_RETURN_ERROR(NC_EVARSIZE)
+    }
+    /* and it has to be the last one */
+    if( large_vars_count == 1 && last == 0) {
+      DEBUG_RETURN_ERROR(NC_EVARSIZE)
+    }
+    if( rec_vars_count > 0 ) {
+       /* and if it's the last one, there can't be any record variables */
+       if( large_vars_count == 1 && last == 1) {
+           DEBUG_RETURN_ERROR(NC_EVARSIZE)
+       }
+       /* Loop through vars, second pass is for record variables.   */
+       large_vars_count = 0;
+       vpp = ncp->vars.value;
+       for (ii = 0; ii < ncp->vars.ndefined; ii++, vpp++) {
+           if( IS_RECVAR(*vpp) ) {
+               last = 0;
+               if( ncmpii_NC_check_vlen(*vpp, vlen_max) == 0 ) {
+                   large_vars_count++;
+                   last = 1;
+               }
+           }
+       }
+       /* OK if last record variable size too large, since not used to
+          compute an offset */
+       if( large_vars_count > 1) { /* only one "too-large" variable allowed */
+           DEBUG_RETURN_ERROR(NC_EVARSIZE)
+       }
+       /* and it has to be the last one */
+       if( large_vars_count == 1 && last == 0) {
+           DEBUG_RETURN_ERROR(NC_EVARSIZE)
+       }
+    }
+    return NC_NOERR;
+}
+
+#define DEFAULT_ALIGNMENT 512
+#define HEADER_ALIGNMENT_LB 4
+
+/* Many subroutines called in ncmpii_NC_enddef() are collective. We check the
+ * error codes of all processes only in safe mode, so the program can stop
+ * collectively, if any one process got an error. However, when safe mode is
+ * off, we simply return the error and program may hang if some processes
+ * do not get error and proceed to the next subroutine call.
+ */ 
+#define CHECK_ERROR(status) {                                                \
+    if (ncp->safe_mode == 1) {                                               \
+        int g_status;                                                        \
+        TRACE_COMM(MPI_Allreduce)(&status, &g_status, 1, MPI_INT, MPI_MIN,   \
+                                  ncp->nciop->comm);                         \
+        if (mpireturn != MPI_SUCCESS)                                        \
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce");          \
+        if (g_status != NC_NOERR) return status;                             \
+    }                                                                        \
+    else if (status != NC_NOERR)                                             \
+        return status;                                                       \
+}
+
+/*----< ncmpii_NC_enddef() >-------------------------------------------------*/
+static int
+ncmpii_NC_enddef(NC         *ncp,
+                 MPI_Offset  h_align,
+                 MPI_Offset  h_minfree,
+                 MPI_Offset  v_align,
+                 MPI_Offset  v_minfree,
+                 MPI_Offset  r_align)
+{
+    int i, err, status=NC_NOERR, mpireturn;
+    char value[MPI_MAX_INFO_VAL];
+#ifdef ENABLE_SUBFILING
+    NC *ncp_sf=NULL;
+#endif
+
+    assert(h_align > 0);  /* alignment size cannot be zero */
+    assert(v_align > 0);
+    assert(r_align > 0);
+
+    /* all CDF formats require 4-bytes alignment */
+    h_align = D_RNDUP(h_align, 4);
+    v_align = D_RNDUP(v_align, 4);
+    r_align = D_RNDUP(r_align, 4);
+
+    /* reflect the hint changes to the MPI info object, so the user can
+     * query exactly what hint values are being used
+     */
+    ncp->nciop->hints.h_align = h_align;
+    ncp->nciop->hints.v_align = v_align;
+    ncp->nciop->hints.r_align = r_align;
+
+    sprintf(value, "%lld", h_align);
+    MPI_Info_set(ncp->nciop->mpiinfo, "nc_header_align_size", value);
+    sprintf(value, "%lld", v_align);
+    MPI_Info_set(ncp->nciop->mpiinfo, "nc_var_align_size", value);
+    sprintf(value, "%lld", r_align);
+    MPI_Info_set(ncp->nciop->mpiinfo, "nc_record_align_size", value);
+
+#ifdef ENABLE_SUBFILING
+    /* num of subfiles has been determined already */
+    ncp->subfile_mode    = ncp->nciop->hints.subfile_mode;
+    ncp->nc_num_subfiles = ncp->nciop->hints.num_subfiles;
+
+    if (ncp->nc_num_subfiles > 1) {
+        /* TODO: should return subfile-related msg when there's an error */
+        status = ncmpii_subfile_partition(ncp, &ncp->ncid_sf);
+        if (status != NC_NOERR)
+            printf("Error in file %s line %d (%s)\n",__FILE__,__LINE__,
+                   ncmpi_strerror(status));
+
+        CHECK_ERROR(status)
+    }
+#endif
+
+    /* check on dimension lengths */
+    status = ncmpii_NC_check_vlens(ncp);
+    CHECK_ERROR(status)
+
+    /* When ncp->old == NULL, this enddef is called the first time after file
+     * create call. In this case, we compute each variable's 'begin', starting
+     * file offset as well as the offsets of record variables.
+     * When ncp->old != NULL, this enddef is called after a redef. In this
+     * case, we re-used all variable offsets as many as possible.
+     */
+    status = NC_begins(ncp, h_align, h_minfree, v_align, v_minfree, r_align);
+    CHECK_ERROR(status)
+
+#ifdef ENABLE_SUBFILING
+    if (ncp->nc_num_subfiles > 1) {
+        /* get ncp info for the subfile */
+        status = ncmpii_NC_check_id(ncp->ncid_sf, &ncp_sf);
+        CHECK_ERROR(status)
+
+        status = NC_begins(ncp_sf, h_align, h_minfree, v_align, v_minfree,
+                           r_align);
+        CHECK_ERROR(status)
+    }
+#endif
+
+    if (ncp->old != NULL) {
+        /* The current define mode was entered from ncmpi_redef, not from
+         * ncmpi_create. We must check if header has been expanded.
+         */
+
+        assert(!NC_IsNew(ncp));
+        assert(fIsSet(ncp->flags, NC_INDEF));
+        assert(ncp->begin_rec >= ncp->old->begin_rec);
+        assert(ncp->begin_var >= ncp->old->begin_var);
+        assert(ncp->vars.ndefined >= ncp->old->vars.ndefined);
+        /* ncp->numrecs has already sync-ed in ncmpi_redef */
+
+        if (ncp->vars.ndefined > 0) { /* no. record and non-record variables */
+            if (ncp->begin_var > ncp->old->begin_var) {
+                /* header size increases, shift the entire data part down */
+                /* shift record variables first */
+                status = move_recs_r(ncp, ncp->old);
+                CHECK_ERROR(status)
+
+                /* shift non-record variables */
+                /* status = move_vars_r(ncp, ncp->old); */
+                status = ncmpiio_move_fixed_vars(ncp, ncp->old);
+                CHECK_ERROR(status)
+            }
+            else if (ncp->begin_rec > ncp->old->begin_rec ||
+                     ncp->recsize   > ncp->old->recsize) {
+                /* number of non-record variables increases, or
+                   number of records of record variables increases,
+                   shift and move all record variables down */
+                status = move_recs_r(ncp, ncp->old);
+                CHECK_ERROR(status)
+            }
+        }
+    } /* ... ncp->old != NULL */
+
+    /* first sync header objects in memory across all processes, and then root
+     * writes the header to file. Note safe_mode error check is already done
+     * in write_NC() */
+    status = write_NC(ncp);
+
+    /* we should continue to exit define mode, even if header is inconsistent
+     * among processes, so the program can proceed, say to close file properly.
+     * However, if ErrIsHeaderDiff(status) is true, this error should
+     * be considered fatal, as inconsistency is about the data structure,
+     * rather then contents (such as attribute values) */
+
+#ifdef ENABLE_SUBFILING
+    /* write header to subfile */
+    if (ncp->nc_num_subfiles > 1) {
+        err = write_NC(ncp_sf);
+        if (status == NC_NOERR) status = err;
+    }
+#endif
+
+    /* update the total number of record variables */
+    ncp->vars.num_rec_vars = 0;
+    for (i=0; i<ncp->vars.ndefined; i++)
+        ncp->vars.num_rec_vars += IS_RECVAR(ncp->vars.value[i]);
+
+    /* fill variables according to their fill mode settings */
+    err = ncmpii_fill_vars(ncp);
+    if (status == NC_NOERR) status = err;
+
+    if (ncp->old != NULL) {
+        ncmpii_free_NC(ncp->old);
+        ncp->old = NULL;
+    }
+    fClr(ncp->flags, NC_CREAT | NC_INDEF);
+
+#ifdef ENABLE_SUBFILING
+    if (ncp->nc_num_subfiles > 1)
+        fClr(ncp_sf->flags, NC_CREAT | NC_INDEF);
+#endif
+
+    /* If the user sets NC_SHARE, we enforce a stronger data consistency */
+    if (NC_doFsync(ncp))
+        ncmpiio_sync(ncp->nciop); /* calling MPI_File_sync() */
+
+    return status;
+}
+
+/*----< ncmpii_inq_env_align_hints() >---------------------------------------*/
+/* check if environment variable PNETCDF_HINTS sets any of the following hints.
+ * nc_header_align_size      if yes, set its value to h_align
+ * nc_var_align_size         if yes, set its value to v_align
+ * nc_header_read_chunk_size if yes, set its value to h_chunk
+ * nc_record_align_size      if yes, set its value to r_align
+ */
+static int
+ncmpii_inq_env_align_hints(MPI_Offset *h_align,
+                           MPI_Offset *v_align,
+                           MPI_Offset *h_chunk,
+                           MPI_Offset *r_align)
+{
+    char *env_str=NULL, *hint_str;
+
+    *h_align = 0;
+    *v_align = 0;
+    *h_chunk = 0;
+    *r_align = 0;
+
+    env_str = getenv("PNETCDF_HINTS");
+    if (env_str != NULL) {
+        hint_str = strtok(env_str, ";");
+        while (hint_str != NULL) {
+            char key[128], *val;
+            strcpy(key, hint_str);
+            val = strchr(key, '=');
+            *val = '\0';
+            val++;
+            if (strcasecmp(key, "nc_header_align_size") == 0)
+                *h_align = atoll(val);
+            else if (strcasecmp(key, "nc_var_align_size") == 0)
+                *v_align = atoll(val);
+            else if (strcasecmp(key, "nc_header_read_chunk_size") == 0)
+                *h_chunk = atoll(val);
+            else if (strcasecmp(key, "nc_record_align_size") == 0)
+                *r_align = atoll(val);
+            hint_str = strtok(NULL, ";");
+        }
+    }
+    return 1;
+}
+
+/*----< ncmpii_enddef() >----------------------------------------------------*/
+int
+ncmpii_enddef(NC *ncp)
+{
+    int i, flag, striping_unit;
+    char value[MPI_MAX_INFO_VAL];
+    MPI_Offset h_align, v_align, r_align, all_var_size;
+    MPI_Offset env_h_align, env_v_align, env_h_chunk, env_r_align;
+
+    assert(!NC_readonly(ncp));
+    assert(NC_indef(ncp));
+
+    /* calculate a good align size for PnetCDF level hints:
+     * header_align_size and var_align_size based on the MPI-IO hint
+     * striping_unit. This hint can be either supplied by the user or obtained
+     * from MPI-IO (for example, ROMIO's Lustre driver makes a system call to
+     * get the striping parameters of a file).
+     */
+    MPI_Info_get(ncp->nciop->mpiinfo, "striping_unit", MPI_MAX_INFO_VAL-1,
+                 value, &flag);
+    striping_unit = 0;
+    if (flag) striping_unit = atoi(value);
+    ncp->nciop->striping_unit = striping_unit;
+
+    all_var_size = 0;  /* sum of all defined variables */
+    for (i=0; i<ncp->vars.ndefined; i++)
+        all_var_size += ncp->vars.value[i]->len;
+
+    /* check if any hints have been set in the environment variable
+     * PNETCDF_HINTS, as they will overwrite the ones set in the MPI_info
+     * provided in ncmpi_creat() or ncmpi_open() */
+    ncmpii_inq_env_align_hints(&env_h_align, &env_v_align, &env_h_chunk,
+                               &env_r_align);
+
+    /* align file offsets for file header space and fixed variables.
+       These alignment hints have been extracted from the MPI_Info object when
+       ncmpi_create() is called.
+     */
+    h_align = (env_h_align == 0) ? ncp->nciop->hints.h_align : env_h_align;
+    v_align = (env_v_align == 0) ? ncp->nciop->hints.v_align : env_v_align;
+    r_align = (env_r_align == 0) ? ncp->nciop->hints.r_align : env_r_align;
+
+    if (h_align == 0) { /* user info does not set hint nc_header_align_size */
+        if (striping_unit &&
+            all_var_size > HEADER_ALIGNMENT_LB * striping_unit)
+            /* if striping_unit is available and file size sufficiently large */
+            h_align = striping_unit;
+        else
+            h_align = DEFAULT_ALIGNMENT;
+    }
+    /* else respect user hint */
+
+    if (v_align == 0) { /* user info does not set hint nc_var_align_size */
+        if (striping_unit &&
+            all_var_size > HEADER_ALIGNMENT_LB * striping_unit)
+            /* if striping_unit is available and file size sufficiently large */
+            v_align = striping_unit;
+        else
+            v_align = DEFAULT_ALIGNMENT;
+    }
+    /* else respect user hint */
+
+    if (r_align == 0) { /* user info does not set hint nc_record_align_size */
+        if (striping_unit)
+            r_align = striping_unit;
+        else
+            r_align = DEFAULT_ALIGNMENT;
+    }
+    /* else respect user hint */
+
+    return ncmpii_NC_enddef(ncp, h_align, 0, v_align, 0, r_align);
+}
+
+/*----< ncmpii__enddef() >---------------------------------------------------*/
+int
+ncmpii__enddef(NC         *ncp,
+               MPI_Offset  h_minfree,
+               MPI_Offset  v_align,
+               MPI_Offset  v_minfree,
+               MPI_Offset  r_align)
+{
+    int i, flag, striping_unit;
+    char value[MPI_MAX_INFO_VAL];
+    MPI_Offset h_align, all_var_size;
+    MPI_Offset env_h_align, env_v_align, env_h_chunk, env_r_align;
+
+    assert(!NC_readonly(ncp));
+    assert(NC_indef(ncp));
+
+    /* calculate a good align size for PnetCDF level hints:
+     * header_align_size and var_align_size based on the MPI-IO hint
+     * striping_unit. This hint can be either supplied by the user or obtained
+     * from MPI-IO (for example, ROMIO's Lustre driver makes a system call to
+     * get the striping parameters of a file).
+     */
+    MPI_Info_get(ncp->nciop->mpiinfo, "striping_unit", MPI_MAX_INFO_VAL-1,
+                 value, &flag);
+    striping_unit = 0;
+    if (flag) striping_unit = atoi(value);
+    ncp->nciop->striping_unit = striping_unit;
+
+    all_var_size = 0;  /* sum of all defined variables */
+    for (i=0; i<ncp->vars.ndefined; i++)
+        all_var_size += ncp->vars.value[i]->len;
+
+    /* check if any hints have been set in the environment variable
+     * PNETCDF_HINTS, as they will overwrite the ones passed in this function
+     * and those passed-in alignment values will overwrite the ones set in the
+     * MPI_info provided in ncmpi_creat() or ncmpi_open() */
+    ncmpii_inq_env_align_hints(&env_h_align, &env_v_align, &env_h_chunk,
+                               &env_r_align);
+
+    /* align file offsets for file header space and fixed variables */
+    h_align = (env_h_align == 0) ? ncp->nciop->hints.h_align : env_h_align;
+    v_align = (env_v_align == 0) ? v_align                   : env_v_align;
+    r_align = (env_r_align == 0) ? r_align                   : env_r_align;
+
+    if (v_align == 0) /* 0 means let PnetCDF decide, 1 means no align */
+        v_align = ncp->nciop->hints.v_align;
+
+    if (r_align == 0) /* 0 means let PnetCDF decide, 1 means no align */
+        r_align = ncp->nciop->hints.r_align;
+
+    if (h_align == 0) { /* user does not set hint nc_header_align_size */
+        if (striping_unit &&
+            all_var_size > HEADER_ALIGNMENT_LB * striping_unit)
+            /* if striping_unit is available and file size sufficiently large */
+            h_align = striping_unit;
+        else
+            h_align = DEFAULT_ALIGNMENT;
+    }
+    /* else respect user hint */
+
+    if (v_align == 0) { /* user does not set hint nc_var_align_size */
+        if (striping_unit &&
+            all_var_size > HEADER_ALIGNMENT_LB * striping_unit)
+            /* if striping_unit is available and file size sufficiently large */
+            v_align = striping_unit;
+        else
+            v_align = DEFAULT_ALIGNMENT;
+    }
+    /* else respect user hint */
+
+    if (r_align == 0) { /* user does not set hint nc_record_align_size */
+        if (striping_unit)
+            r_align = striping_unit;
+        else
+            r_align = DEFAULT_ALIGNMENT;
+    }
+    /* else respect user hint */
+
+    return ncmpii_NC_enddef(ncp, h_align, h_minfree, v_align, v_minfree,
+                            r_align);
+}
+
+/*----< ncmpii_close() >------------------------------------------------------*/
+/* This function is collective */
+int
+ncmpii_close(NC *ncp)
+{
+    int num_reqs, err, status=NC_NOERR, *req_ids=NULL, *statuses=NULL;
+    NC_req *cur_req;
+
+    if (NC_indef(ncp)) { /* currently in define mode */
+        status = ncmpii_enddef(ncp); /* TODO: defaults */
+        if (status != NC_NOERR ) {
+            /* To do: Abort new definition, if any */
+            if (ncp->old != NULL) {
+                ncmpii_free_NC(ncp->old);
+                ncp->old = NULL;
+                fClr(ncp->flags, NC_INDEF);
+            }
+        }
+    }
+
+    if (!NC_readonly(ncp) &&  /* file is open for write */
+         NC_indep(ncp)) {     /* exit independent data mode will sync header */
+        err = ncmpii_end_indep_data(ncp);
+        if (status == NC_NOERR ) status = err;
+    }
+
+    /* if entering this function in  collective data mode, we do not have to
+     * update header in file, as file header is always up-to-date */
+
+#ifdef ENABLE_SUBFILING
+    /* ncmpii_enddef() will update nc_num_subfiles */
+    /* TODO: should check ncid_sf? */
+    /* if the file has subfiles, close them first */
+    if (ncp->nc_num_subfiles > 1)
+        ncmpii_subfile_close(ncp);
+#endif
+
+    /* cancel or complete all outstanding nonblocking I/O */
+    num_reqs = 0;
+    cur_req = ncp->head;
+    while (cur_req != NULL) {
+        num_reqs++;
+        cur_req = cur_req->next;
+    }
+    if (num_reqs > 0) { /* fill in req_ids[] */
+        req_ids = (int*) NCI_Malloc((size_t)num_reqs * 2 * SIZEOF_INT);
+        statuses = req_ids + num_reqs;
+        num_reqs = 0;
+        cur_req = ncp->head;
+        while (cur_req != NULL) {
+            req_ids[num_reqs++] = cur_req->id;
+            cur_req = cur_req->next;
+        }
+#ifdef COMPLETE_NONBLOCKING_IO
+        ncmpii_wait(ncp, COLL_IO, num_reqs, req_ids, statuses);
+#else
+        ncmpii_cancel(ncp, num_reqs, req_ids, statuses);
+#endif
+        NCI_Free(req_ids);
+    }
+
+    /* If the user wants a stronger data consistency by setting NC_SHARE */
+    if (fIsSet(ncp->nciop->ioflags, NC_SHARE))
+        ncmpiio_sync(ncp->nciop); /* calling MPI_File_sync() */
+
+    /* calling MPI_File_close() */
+    ncmpiio_close(ncp->nciop, 0);
+    ncp->nciop = NULL;
+
+    /* remove this file from the list of opened files */
+    ncmpii_del_from_NCList(ncp);
+
+    /* free up space occupied by the header metadata */
+    ncmpii_free_NC(ncp);
+
+    return status;
+}
+
+/* Public */
+
+int
+ncmpi_inq(int  ncid,
+          int *ndimsp,
+          int *nvarsp,
+          int *nattsp,
+          int *xtendimp)
+{
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        return status;
+
+    if (ndimsp != NULL)
+        *ndimsp = (int) ncp->dims.ndefined;
+    if (nvarsp != NULL)
+        *nvarsp = (int) ncp->vars.ndefined;
+    if (nattsp != NULL)
+        *nattsp = (int) ncp->attrs.ndefined;
+    if (xtendimp != NULL)
+        *xtendimp = ncmpii_find_NC_Udim(&ncp->dims, NULL);
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_version() >-----------------------------------------------*/
+int
+ncmpi_inq_version(int ncid, int *nc_mode)
+{
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        return status;
+
+    if (fIsSet(ncp->flags, NC_64BIT_DATA))
+        *nc_mode = NC_64BIT_DATA;
+    else if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
+        *nc_mode = NC_64BIT_OFFSET;
+    else
+        *nc_mode = NC_CLASSIC_MODEL;
+
+    return NC_NOERR;
+}
+
+
+int
+ncmpi_inq_ndims(int ncid, int *ndimsp)
+{
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (ndimsp != NULL)
+        *ndimsp = (int) ncp->dims.ndefined;
+
+    return NC_NOERR;
+}
+
+int
+ncmpi_inq_nvars(int ncid, int *nvarsp)
+{
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (nvarsp != NULL)
+        *nvarsp = (int) ncp->vars.ndefined;
+
+    return NC_NOERR;
+}
+
+int
+ncmpi_inq_natts(int ncid, int *nattsp)
+{
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (nattsp != NULL)
+        *nattsp = (int) ncp->attrs.ndefined;
+
+    return NC_NOERR;
+}
+
+int
+ncmpi_inq_unlimdim(int ncid, int *xtendimp)
+{
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (xtendimp != NULL)
+        *xtendimp = ncmpii_find_NC_Udim(&ncp->dims, NULL);
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_num_rec_vars() >-------------------------------------------*/
+int
+ncmpi_inq_num_rec_vars(int ncid, int *nvarsp)
+{
+    int i, status;
+    NC *ncp;
+
+    /* get ncp object */
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        return status;
+
+    if (nvarsp != NULL) {
+        if (NC_indef(ncp)) {
+            /* if in define mode, recalculate the number of record variables */
+            *nvarsp = 0;
+            for (i=0; i<ncp->vars.ndefined; i++)
+                *nvarsp += IS_RECVAR(ncp->vars.value[i]);
+        }
+        else
+            *nvarsp = ncp->vars.num_rec_vars;
+    }
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_num_fix_vars() >-------------------------------------------*/
+int
+ncmpi_inq_num_fix_vars(int ncid, int *nvarsp)
+{
+    int i, status;
+    NC *ncp;
+
+    /* get ncp object */
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        return status;
+
+    if (nvarsp != NULL) {
+        if (NC_indef(ncp)) {
+            /* if in define mode, recalculate the number of record variables */
+            *nvarsp = 0;
+            for (i=0; i<ncp->vars.ndefined; i++)
+                *nvarsp += IS_RECVAR(ncp->vars.value[i]);
+        }
+        else
+            *nvarsp = ncp->vars.num_rec_vars;
+
+        /* no. fixed-size == ndefined - no. record variables */
+        *nvarsp = ncp->vars.ndefined- *nvarsp;
+    }
+
+    return NC_NOERR;
+}
+
diff --git a/src/lib/nc.h b/src/lib/nc.h
new file mode 100644
index 0000000..2c322d9
--- /dev/null
+++ b/src/lib/nc.h
@@ -0,0 +1,939 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: nc.h 2299 2016-01-09 06:14:37Z wkliao $ */
+#ifndef _NC_H_
+#define _NC_H_
+
+/*
+ * netcdf library 'private' data structures, objects and interfaces
+ */
+
+#include <stddef.h>     /* size_t */
+#include <sys/types.h>  /* off_t */
+
+#include "ncio.h"       /* ncio */
+#include "fbits.h"
+
+/* for put request less than 4KB, copy it to a buffer and do byte swap there,
+ * so if the user buffer is immutable (assuming smaller than 4KB), it will not
+ * cause seg fault. Not a perfect solution, but should be sufficient for most
+ * of the cases.
+ */
+#define NC_BYTE_SWAP_BUFFER_SIZE 4096
+
+/* define MPI_OFFSET if not defined */
+#ifndef HAVE_MPI_OFFSET_DATATYPE
+    #ifdef HAVE_MPI_LONG_LONG_INT
+        #define MPI_OFFSET MPI_LONG_LONG_INT
+    #else
+        #define MPI_OFFSET MPI_INT
+    #endif
+#endif
+
+enum API_KIND {
+    API_VARD, /* do not check start and count, no flexible APIs */
+    API_VARN, /* do not check start and count */
+    API_VAR,  /* do not check start and count */
+    API_VAR1, /* check start */
+    API_VARA, /* check start and count */
+    API_VARS, /* check start and count */
+    API_VARM  /* check start and count */
+};
+
+#define WRITE_REQ 0
+#define READ_REQ  1
+
+#define INDEP_IO 0
+#define COLL_IO  1
+#define NONBLOCKING_IO  -1
+
+/* C macros for TRACE MPI calls */
+#ifdef PNETCDF_TRACE_MPI_COMM
+#define TRACE_COMM(x) printf("TRACE-MPI-COMM: FILE %s FUNC %s() LINE %d calling %s()\n",__FILE__,__func__,__LINE__,#x),mpireturn=x
+#else
+#define TRACE_COMM(x) mpireturn=x
+#endif
+
+#ifdef PNETCDF_TRACE_MPI_IO
+#define TRACE_IO(x) printf("TRACE-MPI-IO:   FILE %s FUNC %s() LINE %d calling %s()\n",__FILE__,__func__,__LINE__,#x),mpireturn=x
+#else
+#define TRACE_IO(x) mpireturn=x
+#endif
+
+
+/* XXX: this seems really low.  do we end up spending a ton of time mallocing?
+ * could we reduce that by increasing this to something 21st century? */
+#ifndef NC_ARRAY_GROWBY
+#define NC_ARRAY_GROWBY 4
+#endif
+
+/* ncmpi_create/ncmpi_open set up header to be 'chunksize' big and to grow
+ * by 'chunksize' as new items adde. This used to be 4k. 256k lets us read
+ * in an entire climate header in one go */
+#define NC_DEFAULT_CHUNKSIZE 262144
+
+/* when variable's nctype is NC_CHAR, I/O buffer's MPI type must be MPI_CHAR
+ * and vice versa */
+#define NCMPII_ECHAR(nctype, mpitype) ((((nctype) == NC_CHAR) == ((mpitype) != MPI_CHAR)) ? NC_ECHAR : NC_NOERR)
+
+/*
+ * The extern size of an empty
+ * netcdf version 1 file.
+ * The initial value of ncp->xsz.
+ */
+#define MIN_NC_XSZ 32
+
+/* netcdf file format:
+     netcdf_file  = header  data
+     header       = magic  numrecs  dim_list  gatt_list  var_list
+     magic        = 'C'  'D'  'F'  VERSION
+     VERSION      = \x01 | \x02 | \x05
+     numrecs      = NON_NEG | STREAMING
+     dim_list     = ABSENT | NC_DIMENSION  nelems  [dim ...]
+     gatt_list    = att_list
+     att_list     = ABSENT | NC_ATTRIBUTE  nelems  [attr ...]
+     var_list     = ABSENT | NC_VARIABLE   nelems  [var ...]
+     ABSENT       = ZERO  ZERO                  // Means list is not present
+     ZERO         = \x00 \x00 \x00 \x00         // 32-bit zero
+
+  Minimum happens when nothing is defined, i.e.
+     magic              -- 4 bytes
+     numrecs            -- 4 bytes for CDF-1 and CDF-2, 8 bytes for CDF-5
+     dim_list = ABSENT  -- 8 bytes
+     gatt_list = ABSENT -- 8 bytes
+     var_list = ABSENT  -- 8 bytes
+*/
+
+typedef struct NC NC; /* forward reference */
+
+/*
+ *  The internal data types
+ */
+typedef enum {
+    NC_UNSPECIFIED =  0,
+/*  NC_BITFIELD    =  7, */
+/*  NC_STRING      =  8, */
+    NC_DIMENSION   = 10,
+    NC_VARIABLE    = 11,
+    NC_ATTRIBUTE   = 12
+} NCtype;
+
+
+/*
+ * Counted string for names and such
+ */
+typedef struct {
+    /* all xdr'd */
+    MPI_Offset  nchars;
+    char       *cp;     /* [nchars+1] one additional char for '\0' */
+} NC_string;
+
+extern NC *
+ncmpii_new_NC(const MPI_Offset *chunkp);
+
+extern NC *
+ncmpii_dup_NC(const NC *ref);
+
+/* Begin defined in string.c */
+extern void
+ncmpii_free_NC_string(NC_string *ncstrp);
+
+extern int
+ncmpii_NC_check_name(const char *name, int file_ver);
+
+extern NC_string *
+ncmpii_new_NC_string(size_t slen, const char *str);
+
+extern int
+ncmpii_set_NC_string(NC_string *ncstrp, const char *str);
+
+/* End defined in string.c */
+
+/*
+ * NC dimension structure
+ */
+typedef struct {
+    /* all xdr'd */
+    NC_string *name;
+    MPI_Offset size;
+#ifdef ENABLE_SUBFILING
+    int range[2]; /* subfile range {start, end} */
+    MPI_Offset rcount; /* subfile range count */
+    int num_subfiles;
+#endif
+} NC_dim;
+
+/* the dimension ID returned from ncmpi_def_dim() is an integer pointer
+ * which means the total number of defined dimension allowed in a file
+ * is up to 2^31-1. Thus, the member ndefined below should be of type int.
+ */
+typedef struct NC_dimarray {
+    int      nalloc;    /* number allocated >= ndefined */
+    int      ndefined;  /* number of defined dimensions */
+    NC_dim **value;
+} NC_dimarray;
+
+/* Begin defined in dim.c */
+
+extern void
+ncmpii_free_NC_dim(NC_dim *dimp);
+
+extern NC_dim *
+ncmpii_new_x_NC_dim(NC_string *name);
+
+extern int
+ncmpii_find_NC_Udim(const NC_dimarray *ncap, NC_dim **dimpp);
+
+extern int
+incr_NC_dimarray(NC_dimarray *ncap, NC_dim *newdimp);
+
+extern NC_dim*
+dup_NC_dim(const NC_dim *dimp);
+
+/* dimarray */
+
+extern void
+ncmpii_free_NC_dimarray(NC_dimarray *ncap);
+
+extern int
+ncmpii_dup_NC_dimarray(NC_dimarray *ncap, const NC_dimarray *ref);
+
+extern NC_dim *
+ncmpii_elem_NC_dimarray(const NC_dimarray *ncap, int elem);
+
+extern int
+ncmpi_def_dim(int ncid, const char *name, MPI_Offset size, int *dimidp);
+
+extern int
+ncmpi_rename_dim( int ncid, int dimid, const char *newname);
+
+extern int
+ncmpi_inq_dimid(int ncid, const char *name, int *dimid_ptr);
+
+extern int
+ncmpi_inq_dim(int ncid, int dimid, char *name, MPI_Offset *sizep);
+
+extern int
+ncmpi_inq_dimname(int ncid, int dimid, char *name);
+
+extern int
+ncmpi_inq_dimlen(int ncid, int dimid, MPI_Offset *lenp);
+/* End defined in dim.c */
+
+/*
+ * NC attribute
+ *
+ * Number of attributes is limited by 2^31-1 because the argument attnump in
+ *  int nc_inq_attid(int ncid, int varid, const char *name, int *attnump);
+ * is a signed 4-byte integer.
+ */
+typedef struct {
+    MPI_Offset xsz;      /* amount of space at xvalue (4-byte aligned) */
+    NC_string *name;     /* name of the attributes */
+    nc_type    type;     /* the discriminant */
+    MPI_Offset nelems;   /* number of attribute elements */
+    void      *xvalue;   /* the actual data, in external representation */
+} NC_attr;
+
+typedef struct NC_attrarray {
+    int       nalloc;    /* number allocated >= ndefined */
+    int       ndefined;  /* number of defined attributes */
+    NC_attr **value;
+} NC_attrarray;
+
+/* Begin defined in attr.c */
+
+extern void
+ncmpii_free_NC_attr(NC_attr *attrp);
+
+extern NC_attr *
+ncmpii_new_x_NC_attr(NC_string *strp, nc_type type, MPI_Offset nelems);
+
+extern int
+incr_NC_attrarray(NC_attrarray *ncap, NC_attr *newelemp);
+
+extern NC_attr*
+dup_NC_attr(const NC_attr *rattrp);
+
+extern int
+ncmpii_NC_findattr(const NC_attrarray *ncap, const char *uname);
+
+/* attrarray */
+
+extern void
+ncmpii_free_NC_attrarray(NC_attrarray *ncap);
+
+extern int
+ncmpii_dup_NC_attrarray(NC_attrarray *ncap, const NC_attrarray *ref);
+
+extern NC_attr *
+ncmpii_elem_NC_attrarray(const NC_attrarray *ncap, MPI_Offset elem);
+
+extern int
+ncmpi_put_att_text(int ncid, int varid, const char *name,
+        MPI_Offset nelems, const char *value);
+
+extern int
+ncmpi_get_att_text(int ncid, int varid, const char *name, char *str);
+
+extern int
+ncmpi_put_att_schar(int ncid, int varid, const char *name,
+        nc_type type, MPI_Offset nelems, const signed char *value);
+
+extern int
+ncmpi_get_att_schar(int ncid, int varid, const char *name, signed char *tp);
+
+extern int
+ncmpi_put_att_uchar(int ncid, int varid, const char *name,
+        nc_type type, MPI_Offset nelems, const unsigned char *value);
+
+extern int
+ncmpi_get_att_uchar(int ncid, int varid, const char *name, unsigned char *tp);
+
+extern int
+ncmpi_put_att_short(int ncid, int varid, const char *name,
+        nc_type type, MPI_Offset nelems, const short *value);
+
+extern int
+ncmpi_get_att_short(int ncid, int varid, const char *name, short *tp);
+
+extern int
+ncmpi_put_att_int(int ncid, int varid, const char *name,
+        nc_type type, MPI_Offset nelems, const int *value);
+
+extern int
+ncmpi_get_att_int(int ncid, int varid, const char *name, int *tp);
+
+extern int
+ncmpi_put_att_long(int ncid, int varid, const char *name,
+        nc_type type, MPI_Offset nelems, const long *value);
+
+extern int
+ncmpi_get_att_long(int ncid, int varid, const char *name, long *tp);
+
+extern int
+ncmpi_put_att_float(int ncid, int varid, const char *name,
+        nc_type type, MPI_Offset nelems, const float *value);
+extern int
+ncmpi_get_att_float(int ncid, int varid, const char *name, float *tp);
+extern int
+ncmpi_put_att_double(int ncid, int varid, const char *name,
+        nc_type type, MPI_Offset nelems, const double *value);
+extern int
+ncmpi_get_att_double(int ncid, int varid, const char *name, double *tp);
+
+extern int
+ncmpi_inq_attid(int ncid, int varid, const char *name, int *attnump);
+
+extern int
+ncmpi_inq_atttype(int ncid, int varid, const char *name, nc_type *datatypep);
+
+extern int
+ncmpi_inq_attlen(int ncid, int varid, const char *name, MPI_Offset *lenp);
+
+extern int
+ncmpi_inq_att(int ncid, int varid, const char *name,
+        nc_type *datatypep, MPI_Offset *lenp);
+
+extern int
+ncmpi_copy_att(int ncid_in, int varid_in, const char *name,
+        int ncid_out, int ovarid);
+
+extern int
+ncmpi_rename_att( int ncid, int varid, const char *name, const char *newname);
+
+extern int
+ncmpi_del_att(int ncid, int varid, const char *name);
+
+extern int
+ncmpi_inq_attname(int ncid, int varid, int attnum, char *name);
+/* End defined in attr.c */
+
+/*
+ * NC variable: description and data
+ */
+typedef struct {
+    int           xsz;    /* byte size of 1 array element */
+    MPI_Offset   *shape;  /* dim->size of each dim */
+    MPI_Offset   *dsizes; /* the right to left product of shape */
+    NC_string    *name;   /* name of the variable */
+    int           ndims;  /* number of dimensions */
+    int          *dimids; /* array of dimension IDs */
+    NC_attrarray  attrs;  /* attribute array */
+    nc_type       type;   /* variable's data type */
+    MPI_Offset    len;    /* this is the "vsize" defined in header format, the
+                             total size in bytes of the array variable.
+                             For record variable, this is the record size */
+    MPI_Offset    begin;  /* starting file offset of this variable */
+    int           no_fill;
+#ifdef ENABLE_SUBFILING
+    int           ndims_org;  /* ndims before subfiling */
+    int          *dimids_org; /* dimids before subfiling */
+    int           num_subfiles;
+#endif
+} NC_var;
+
+/* note: we only allow less than 2^31-1 variables defined in a file */
+typedef struct NC_vararray {
+    int      nalloc;      /* number allocated >= ndefined */
+    int      ndefined;    /* number of defined variables */
+    int      num_rec_vars;/* number of defined record variables */
+    NC_var **value;
+} NC_vararray;
+
+/* Begin defined in var.c */
+
+extern void
+ncmpii_free_NC_var(NC_var *varp);
+
+extern NC_var *
+ncmpii_new_x_NC_var(NC_string *strp, int ndims);
+
+extern NC_var*
+dup_NC_var(const NC_var *rvarp);
+
+extern int
+incr_NC_vararray(NC_vararray *ncap, NC_var *newvarp);
+
+/* vararray */
+
+extern void
+ncmpii_free_NC_vararray(NC_vararray *ncap);
+
+extern int
+ncmpii_dup_NC_vararray(NC_vararray *ncap, const NC_vararray *ref);
+
+extern int
+ncmpii_NC_var_shape64(NC *ncp, NC_var *varp, const NC_dimarray *dims);
+
+extern int
+ncmpii_NC_check_vlen(NC_var *varp, MPI_Offset vlen_max);
+
+extern int
+ncmpii_NC_lookupvar(NC *ncp, int varid, NC_var **varp);
+
+extern int
+ncmpi_def_var(int ncid, const char *name, nc_type type,
+        int ndims, const int *dimidsp, int *varidp);
+
+extern int
+ncmpi_rename_var(int ncid, int varid, const char *newname);
+
+extern int
+ncmpi_inq_var(int ncid, int varid, char *name, nc_type *typep,
+        int *ndimsp, int *dimids, int *nattsp);
+
+extern int
+ncmpi_inq_varid(int ncid, const char *name, int *varid_ptr);
+
+extern int
+ncmpi_inq_varname(int ncid, int varid, char *name);
+
+extern int
+ncmpi_inq_vartype(int ncid, int varid, nc_type *typep);
+
+extern int
+ncmpi_inq_varndims(int ncid, int varid, int *ndimsp);
+
+extern int
+ncmpi_inq_vardimid(int ncid, int varid, int *dimids);
+
+extern int
+ncmpi_inq_varnatts(int ncid, int varid, int *nattsp);
+
+extern int
+ncmpi_rename_var(int ncid, int varid, const char *newname);
+/* End defined in var.c */
+
+#define IS_RECVAR(vp) \
+        ((vp)->shape != NULL ? (*(vp)->shape == NC_UNLIMITED) : 0 )
+
+/*
+ *  The PnetCDF non-blocking I/O request type
+ */
+typedef struct NC_req {
+    int            id;
+    int            rw_flag;
+    void          *buf;         /* the original user buffer */
+    void          *xbuf;        /* the buffer used to read/write, may point to
+                                   the same address as buf */
+    int            buftype_is_contig;
+    int            need_swap_back_buf;
+    int            abuf_index;  /* index in the abuf occupy_table
+                                   -1 means not using attached buffer */
+
+    void          *tmpBuf;      /* tmp buffer to be freed, used only by
+                                   nonblocking varn when buftype is noncontig */
+    void          *userBuf;     /* user buffer to be unpacked from tmpBuf. used
+                                   only by by nonblocking varn when buftype is
+                                   noncontig */
+    NC_var        *varp;
+    MPI_Offset    *start;        /* [varp->ndims] */
+    MPI_Offset    *count;        /* [varp->ndims] */
+    MPI_Offset    *stride;       /* [varp->ndims] */
+    MPI_Offset     bnelems;      /* number of elements in user buffer */
+    MPI_Offset     offset_start; /* starting of aggregate access region */
+    MPI_Offset     offset_end;   /*   ending of aggregate access region */
+    MPI_Offset     bufcount;     /* the number of buftype in this request */
+    MPI_Datatype   buftype;      /* user defined derived data type */
+    MPI_Datatype   ptype;        /* element data type in buftype */
+    MPI_Datatype   imaptype;     /* derived data type constructed from imap */
+    int           *status;       /* pointer to user's status */
+    int            num_subreqs;  /* each record is a subrequest */
+    struct NC_req *subreqs;      /* [num_subreq] */
+    struct NC_req *next;
+} NC_req;
+
+#define NC_ABUF_DEFAULT_TABLE_SIZE 128
+
+typedef struct NC_buf_status {
+    int        is_used;
+    MPI_Aint   buf_addr;
+    MPI_Offset req_size;
+} NC_buf_status;
+
+typedef struct NC_buf {
+    MPI_Offset     size_allocated;
+    MPI_Offset     size_used;
+    int            table_size;
+    NC_buf_status *occupy_table; /* [table_size] */
+    int            tail;         /* index of last free entry */
+    void          *buf;
+} NC_buf;
+
+struct NC {
+    /* linked list of currently opened netcdf files */
+    struct NC *next;
+    struct NC *prev;
+#ifdef ENABLE_SUBFILING
+    int nc_num_subfiles; /* # of subfiles */
+    int ncid_sf; /* ncid of subfile */
+#endif
+    /* contains the previous NC during redef. */
+    struct NC *old;
+    /* flags */
+#define NC_INDEP  0x10000   /* in independent data mode, cleared by endindep */
+#define NC_CREAT  0x20000   /* in create phase, cleared by ncenddef */
+#define NC_INDEF  0x80000   /* in define mode, cleared by ncenddef */
+#define NC_NSYNC  0x100000  /* synchronise numrecs on change */
+#define NC_HSYNC  0x200000  /* synchronise whole header on change */
+#define NC_NDIRTY 0x400000  /* numrecs has changed */
+#define NC_HDIRTY 0x800000  /* header info has changed */
+/* NC_NOFILL is defined in netcdf.h, historical interface */
+    int           flags;
+    int           safe_mode;    /* 0 or 1, for parameter consistency check */
+    int           subfile_mode; /* 0 or 1, for disable/enable subfiling */
+    ncio         *nciop;
+    MPI_Offset    chunk;    /* largest extent this layer will request from
+                               ncio->get() */
+    MPI_Offset    xsz;      /* external size of this header, <= var[0].begin */
+    MPI_Offset    begin_var;/* file offset of the first (non-record) var */
+    MPI_Offset    begin_rec;/* file offset of the first 'record' */
+
+    MPI_Offset    recsize;  /* length of 'record': sum of single record sizes
+                               of all the record variables */
+    MPI_Offset    numrecs;  /* number of 'records' allocated */
+    NC_dimarray   dims;     /* dimensions defined */
+    NC_attrarray  attrs;    /* global attributes defined */
+    NC_vararray   vars;     /* variables defined */
+    NC_req       *head;     /* linked list head of nonblocking requests */
+    NC_req       *tail;     /* tail of the linked list */
+    NC_buf       *abuf;     /* attached buffer, used by bput APIs */
+};
+
+#define NC_readonly(ncp) \
+        (!fIsSet((ncp)->nciop->ioflags, NC_WRITE))
+
+#define NC_IsNew(ncp) \
+        fIsSet((ncp)->flags, NC_CREAT)
+
+#define NC_indep(ncp) \
+        fIsSet((ncp)->flags, NC_INDEP)
+
+#define NC_indef(ncp) \
+        (NC_IsNew(ncp) || fIsSet((ncp)->flags, NC_INDEF))
+
+#define set_NC_ndirty(ncp) \
+        fSet((ncp)->flags, NC_NDIRTY)
+
+#define NC_ndirty(ncp) \
+        fIsSet((ncp)->flags, NC_NDIRTY)
+
+#define set_NC_hdirty(ncp) \
+        fSet((ncp)->flags, NC_HDIRTY)
+
+#define NC_hdirty(ncp) \
+        fIsSet((ncp)->flags, NC_HDIRTY)
+
+#define NC_dofill(ncp) \
+        (!fIsSet((ncp)->flags, NC_NOFILL))
+
+#define NC_doFsync(ncp) \
+        fIsSet((ncp)->nciop->ioflags, NC_SHARE)
+
+#define NC_doHsync(ncp) \
+        fIsSet((ncp)->flags, NC_HSYNC)
+
+#define NC_doNsync(ncp) \
+        fIsSet((ncp)->flags, NC_NSYNC)
+
+#define NC_get_numrecs(ncp) \
+        ((ncp)->numrecs)
+
+#define NC_set_numrecs(ncp, nrecs) \
+        {((ncp)->numrecs = (nrecs));}
+
+#define NC_increase_numrecs(ncp, nrecs) \
+        {if((nrecs) > (ncp)->numrecs) ((ncp)->numrecs = (nrecs));}
+
+#define ErrIsHeaderDiff(err) \
+        (NC_EMULTIDEFINE_FIRST >= (err) && (err) >= NC_EMULTIDEFINE_LAST)
+
+#define IsPrimityMPIType(buftype) (buftype == MPI_FLOAT          || \
+                                   buftype == MPI_DOUBLE         || \
+                                   buftype == MPI_INT            || \
+                                   buftype == MPI_CHAR           || \
+                                   buftype == MPI_SIGNED_CHAR    || \
+                                   buftype == MPI_UNSIGNED_CHAR  || \
+                                   buftype == MPI_SHORT          || \
+                                   buftype == MPI_UNSIGNED_SHORT || \
+                                   buftype == MPI_UNSIGNED       || \
+                                   buftype == MPI_LONG           || \
+                                   buftype == MPI_LONG_LONG_INT  || \
+                                   buftype == MPI_UNSIGNED_LONG_LONG)
+
+/* Begin defined in nc.c */
+
+extern int
+ncmpii_NC_check_id(int ncid, NC **ncpp);
+
+extern int
+ncmpii_cktype(int cdf_ver, nc_type datatype);
+
+extern MPI_Offset
+ncmpix_howmany(nc_type type, MPI_Offset xbufsize);
+
+extern int
+ncmpii_dset_has_recvars(NC *ncp);
+
+extern int
+ncmpii_write_header(NC *ncp);
+
+extern void
+ncmpii_free_NC(NC *ncp);
+
+extern void
+ncmpii_add_to_NCList(NC *ncp);
+
+extern void
+ncmpii_del_from_NCList(NC *ncp);
+
+extern int
+ncmpii_read_NC(NC *ncp);
+
+extern int
+ncmpii_enddef(NC *ncp);
+
+extern int
+ncmpii__enddef(NC *ncp, MPI_Offset h_minfree, MPI_Offset v_align,
+               MPI_Offset v_minfree, MPI_Offset r_align);
+
+extern int
+ncmpii_close(NC *ncp);
+
+extern int
+ncmpi_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *xtendimp);
+
+extern int
+ncmpi_inq_ndims(int ncid, int *ndimsp);
+
+extern int
+ncmpi_inq_nvars(int ncid, int *nvarsp);
+
+extern int
+ncmpi_inq_natts(int ncid, int *nattsp);
+
+extern int
+ncmpi_inq_unlimdim(int ncid, int *xtendimp);
+
+extern int
+ncmpi_get_default_format(void);
+
+extern int
+ncmpi_inq_num_rec_vars(int ncid, int *nump);
+
+extern int
+ncmpi_inq_num_fix_vars(int ncid, int *nump);
+
+/* End defined in nc.c */
+
+#if 0
+/* Begin defined in v1hpg.c */
+
+extern size_t
+ncx_len_NC(const NC *ncp, MPI_Offset sizeof_off_t);
+
+extern int
+ncx_put_NC(const NC *ncp, void **xpp, MPI_Offset offset, MPI_Offset extent);
+
+extern int
+nc_get_NC( NC *ncp);
+
+/* End defined in v1hpg.c */
+
+/* Begin defined in putget.c */
+
+extern int
+ncmpii_fill_NC_var(NC *ncp, const NC_var *varp, MPI_Offset recno);
+
+extern int
+ncmpii_inq_rec(int ncid, MPI_Offset *nrecvars, MPI_Offset *recvarids, MPI_Offset *recsizes);
+
+extern int
+ncmpii_get_rec(int ncid, MPI_Offset recnum, void **datap);
+
+extern int
+ncmpii_put_rec(int ncid, MPI_Offset recnum, void *const *datap);
+#endif
+
+/* End defined in putget.c */
+
+/* Begin defined in header.c */
+typedef struct bufferinfo {
+    ncio       *nciop;
+    MPI_Offset  offset;   /* current read/write offset in the file */
+    int         version;  /* 1, 2, and 5 for CDF-1, 2, and 5 respectively */
+    int         safe_mode;/* 0: disabled, 1: enabled */
+    void       *base;     /* beginning of read/write buffer */
+    void       *pos;      /* current position in buffer */
+    MPI_Offset  size;     /* size of the buffer */
+    MPI_Offset  index;    /* index of current position in buffer */
+    MPI_Offset  put_size; /* amount of writes so far in bytes */
+    MPI_Offset  get_size; /* amount of reads  so far in bytes */
+} bufferinfo;
+
+extern int
+ncmpix_len_nctype(nc_type type);
+
+#if 0
+extern int
+hdr_put_NC_attrarray(bufferinfo *pbp, const NC_attrarray *ncap);
+#endif
+
+extern MPI_Offset
+ncmpii_hdr_len_NC(const NC *ncp);
+
+extern int
+ncmpii_hdr_get_NC(NC *ncp);
+
+extern int
+ncmpii_hdr_put_NC(NC *ncp, void *buf);
+
+extern int
+ncmpii_NC_computeshapes(NC *ncp);
+
+extern int
+ncmpii_hdr_check_NC(bufferinfo *getbuf, NC *ncp);
+/* end defined in header.c */
+
+/* begin defined in mpincio.c */
+extern int
+ncmpiio_create(MPI_Comm comm, const char *path, int ioflags, MPI_Info info,
+               NC *ncp);
+
+extern int
+ncmpiio_open(MPI_Comm comm, const char *path, int ioflags, MPI_Info info,
+             NC *ncp);
+extern int
+ncmpiio_sync(ncio *nciop);
+
+extern int
+ncmpiio_move(ncio *const nciop, MPI_Offset to, MPI_Offset from,
+             MPI_Offset nbytes);
+
+extern int
+ncmpiio_move_fixed_vars(NC *ncp, NC *old);
+
+extern int
+ncmpiio_get_hint(NC *ncp, char *key, char *value, int *flag);
+
+extern int
+NC_computeshapes(NC *ncp);
+
+/* end defined in mpincio.h */
+
+/* begin defined in error.c */
+const char* ncmpi_strerror(int err);
+
+int ncmpii_handle_error(int mpi_errorcode, char *msg);
+
+/* end defined in error.c */
+/*
+ * These functions are used to support
+ * interface version 2 backward compatibility.
+ * N.B. these are tested in ../nc_test even though they are
+ * not public. So, be careful to change the declarations in
+ * ../nc_test/tests.h if you change these.
+ */
+
+int ncmpii_x_putn_schar (void *xbuf, const void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_putn_uchar (void *xbuf, const void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_putn_short (void *xbuf, const void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_putn_ushort(void *xbuf, const void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_putn_int   (void *xbuf, const void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_putn_uint  (void *xbuf, const void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_putn_float (void *xbuf, const void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_putn_double(void *xbuf, const void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_putn_int64 (void *xbuf, const void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_putn_uint64(void *xbuf, const void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_getn_schar (const void *xbuf, void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_getn_uchar (const void *xbuf, void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_getn_short (const void *xbuf, void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_getn_ushort(const void *xbuf, void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_getn_int   (const void *xbuf, void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_getn_uint  (const void *xbuf, void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_getn_float (const void *xbuf, void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_getn_double(const void *xbuf, void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_getn_int64 (const void *xbuf, void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+int ncmpii_x_getn_uint64(const void *xbuf, void *buf, MPI_Offset nelems,
+                        MPI_Datatype datatype);
+
+int NC_start_count_stride_ck(const NC *ncp, const NC_var *varp,
+                const MPI_Offset *start, const MPI_Offset *count,
+                const MPI_Offset *stride, const int rw_flag);
+
+int ncmpii_need_convert(nc_type nctype,MPI_Datatype mpitype);
+
+int ncmpii_need_swap(nc_type nctype,MPI_Datatype mpitype);
+
+void ncmpii_swapn(void *dest_p, const void* src_p, MPI_Offset nelems, int esize);
+
+void ncmpii_in_swapn(void *buf, MPI_Offset nelems, int esize);
+
+int ncmpii_is_request_contiguous(NC *ncp, NC_var *varp,
+                const MPI_Offset starts[], const MPI_Offset  counts[]);
+
+int ncmpii_get_offset(NC *ncp, NC_var *varp, const MPI_Offset starts[],
+                const MPI_Offset counts[], const MPI_Offset strides[],
+                const int rw_flag, MPI_Offset *offset_ptr);
+
+int ncmpii_check_mpifh(NC* ncp, int collective);
+
+int ncmpii_sync_numrecs(NC *ncp, MPI_Offset newnumrecs);
+
+int ncmpii_vars_create_filetype(NC* ncp, NC_var* varp,
+                const MPI_Offset start[], const MPI_Offset count[],
+                const MPI_Offset stride[], int rw_flag, int *blocklen,
+                MPI_Offset *offset, MPI_Datatype *filetype,
+                int *is_filetype_contig);
+
+extern int
+ncmpii_igetput_varm(NC *ncp, NC_var *varp, const MPI_Offset *start,
+                const MPI_Offset *stride, const MPI_Offset *imap,
+                const MPI_Offset *count, void *buf, MPI_Offset bufcount,
+                MPI_Datatype datatype, int *reqid, int rw_flag, int use_abuf,
+                int isSameGroup);
+
+extern int
+ncmpii_wait(NC *ncp, int io_method, int num_reqs, int *req_ids,
+                int *statuses);
+
+extern int
+ncmpii_cancel(NC *ncp, int num_req, int *req_ids, int *statuses);
+
+extern int
+ncmpii_inq_malloc_size(MPI_Offset *size);
+
+extern int
+ncmpii_inq_malloc_max_size(MPI_Offset *size);
+
+extern int
+ncmpii_inq_malloc_list(void);
+
+#ifdef PNC_MALLOC_TRACE
+void ncmpii_init_malloc_tracing(void);
+#endif
+
+extern void *
+NCI_Malloc_fn(size_t size, const int lineno, const char *func,
+              const char *filename);
+
+extern void *
+NCI_Calloc_fn(size_t nelem, size_t elsize, const int lineno, const char *func,
+              const char *filename);
+
+extern void *
+NCI_Realloc_fn(void *ptr, size_t size, const int lineno, const char *func,
+               const char *filename);
+
+extern void
+NCI_Free_fn(void *ptr, const int lineno, const char *func,
+            const char *filename);
+
+extern int
+ncmpii_inq_files_opened(int *num, int *ncids);
+
+extern MPI_Datatype
+ncmpii_nc2mpitype(nc_type type);
+
+extern int
+ncmpii_set_iget_callback(NC *ncp, int reqid, void *tmpBuf, void *userBuf,
+                         int userBufCount, MPI_Datatype userBufType);
+
+extern int
+ncmpii_set_iput_callback(NC *ncp, int reqid, void *tmpPutBuf);
+
+extern int
+ncmpii_end_indep_data(NC *ncp); 
+
+extern int                
+ncmpii_file_set_view(NC *ncp, MPI_File fh, MPI_Offset *offset, MPI_Datatype filetype);
+
+extern int
+ncmpii_create_imaptype(NC_var *varp, const MPI_Offset *count,
+                       const MPI_Offset *imap, const MPI_Offset  bnelems,
+                       const int el_size, MPI_Datatype ptype,
+                       MPI_Datatype *imaptype);
+
+extern int
+ncmpii_calc_datatype_elems(NC *ncp, NC_var *varp, const MPI_Offset *start,
+                           const MPI_Offset *count, const MPI_Offset *stride,
+                           int rw_flag, MPI_Datatype buftype,
+                           MPI_Datatype *ptype, MPI_Offset *bufcount,
+                           MPI_Offset *bnelems, MPI_Offset *nbytes,
+                           int *el_size, int *buftype_is_contig);
+
+extern int
+ncmpii_fill_vars(NC *ncp);
+
+extern int
+ncmpii_sanity_check(int ncid, int varid, const MPI_Offset *start,
+                    const MPI_Offset *count, MPI_Offset bufcount,
+                    enum API_KIND api, int mustInDataMode, int isFlexAPI,
+                    int rw_flag, int io_method, NC **ncp, NC_var **varp);
+
+extern char*
+ncmpii_err_code_name(int err);
+
+#endif /* _NC_H_ */
diff --git a/src/lib/ncconfig.h.in b/src/lib/ncconfig.h.in
new file mode 100644
index 0000000..5337808
--- /dev/null
+++ b/src/lib/ncconfig.h.in
@@ -0,0 +1,483 @@
+/* src/lib/ncconfig.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* configure command-line arguments used */
+#undef CONFIGURE_ARGS_CLEAN
+
+/* Define if to disable MPI_File_sync */
+#undef DISABLE_FILE_SYNC
+
+/* Define if to disable in-place byte swap */
+#undef DISABLE_IN_PLACE_SWAP
+
+/* Define if able to support CDF-5 file format */
+#undef ENABLE_CDF5
+
+/* Define if able to support nonblocking routines */
+#undef ENABLE_NONBLOCKING
+
+/* Define if to enable subfiling feature */
+#undef ENABLE_SUBFILING
+
+/* Define if Fortran names are lower case */
+#undef F77_NAME_LOWER
+
+/* Define if Fortran names are lower case with two trailing underscore2 */
+#undef F77_NAME_LOWER_2USCORE
+
+/* Define if Fortran names are lower case with one trailing underscore */
+#undef F77_NAME_LOWER_USCORE
+
+/* Define if Fortran names are uppercase */
+#undef F77_NAME_UPPER
+
+/* Define to dummy `main' function (if any) required to link to the Fortran
+   libraries. */
+#undef FC_DUMMY_MAIN
+
+/* Define if F77 and FC dummy `main' functions are identical. */
+#undef FC_DUMMY_MAIN_EQ_F77
+
+/* Define to 1 if you have the `access' function. */
+#undef HAVE_ACCESS
+
+/* Define if C++ macro __FUNCTION__ is defined */
+#undef HAVE_FUNCTION_MACRO
+
+/* Define if C++ macro __func__ is defined */
+#undef HAVE_FUNC_MACRO
+
+/* Define to 1 if the system has the type `int64'. */
+#undef HAVE_INT64
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if the system has the type `longlong'. */
+#undef HAVE_LONGLONG
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* available */
+#undef HAVE_MPI_BYTE
+
+/* available */
+#undef HAVE_MPI_CHAR
+
+/* available */
+#undef HAVE_MPI_CHARACTER
+
+/* available */
+#undef HAVE_MPI_COMBINER_DARRAY
+
+/* available */
+#undef HAVE_MPI_COMBINER_DUP
+
+/* available */
+#undef HAVE_MPI_COMBINER_F90_COMPLEX
+
+/* available */
+#undef HAVE_MPI_COMBINER_F90_INTEGER
+
+/* available */
+#undef HAVE_MPI_COMBINER_F90_REAL
+
+/* available */
+#undef HAVE_MPI_COMBINER_HINDEXED_INTEGER
+
+/* available */
+#undef HAVE_MPI_COMBINER_HVECTOR_INTEGER
+
+/* available */
+#undef HAVE_MPI_COMBINER_INDEXED_BLOCK
+
+/* available */
+#undef HAVE_MPI_COMBINER_RESIZED
+
+/* available */
+#undef HAVE_MPI_COMBINER_STRUCT_INTEGER
+
+/* available */
+#undef HAVE_MPI_COMBINER_SUBARRAY
+
+/* available */
+#undef HAVE_MPI_COMPLEX16
+
+/* available */
+#undef HAVE_MPI_COMPLEX32
+
+/* available */
+#undef HAVE_MPI_COMPLEX8
+
+/* available */
+#undef HAVE_MPI_DOUBLE
+
+/* available */
+#undef HAVE_MPI_DOUBLE_PRECISION
+
+/* available */
+#undef HAVE_MPI_ERR_ACCESS
+
+/* available */
+#undef HAVE_MPI_ERR_AMODE
+
+/* available */
+#undef HAVE_MPI_ERR_BAD_FILE
+
+/* available */
+#undef HAVE_MPI_ERR_FILE_EXISTS
+
+/* available */
+#undef HAVE_MPI_ERR_NOT_SAME
+
+/* available */
+#undef HAVE_MPI_ERR_NO_SPACE
+
+/* available */
+#undef HAVE_MPI_ERR_NO_SUCH_FILE
+
+/* available */
+#undef HAVE_MPI_ERR_QUOTA
+
+/* available */
+#undef HAVE_MPI_ERR_READ_ONLY
+
+/* available */
+#undef HAVE_MPI_FLOAT
+
+/* Define to 1 if you have the `MPI_Get_address' function. */
+#undef HAVE_MPI_GET_ADDRESS
+
+/* Define to 1 if you have the `MPI_Info_dup' function. */
+#undef HAVE_MPI_INFO_DUP
+
+/* Define to 1 if you have the `MPI_Info_free' function. */
+#undef HAVE_MPI_INFO_FREE
+
+/* available */
+#undef HAVE_MPI_INT
+
+/* available */
+#undef HAVE_MPI_INTEGER
+
+/* available */
+#undef HAVE_MPI_INTEGER1
+
+/* available */
+#undef HAVE_MPI_INTEGER16
+
+/* available */
+#undef HAVE_MPI_INTEGER2
+
+/* available */
+#undef HAVE_MPI_INTEGER4
+
+/* available */
+#undef HAVE_MPI_INTEGER8
+
+/* available */
+#undef HAVE_MPI_LB
+
+/* available */
+#undef HAVE_MPI_LONG
+
+/* available */
+#undef HAVE_MPI_LONG_LONG_INT
+
+/* available */
+#undef HAVE_MPI_OFFSET_DATATYPE
+
+/* available */
+#undef HAVE_MPI_REAL
+
+/* available */
+#undef HAVE_MPI_REAL16
+
+/* available */
+#undef HAVE_MPI_REAL4
+
+/* available */
+#undef HAVE_MPI_REAL8
+
+/* available */
+#undef HAVE_MPI_SHORT
+
+/* available */
+#undef HAVE_MPI_SIGNED_CHAR
+
+/* Define to 1 if you have the `MPI_Type_create_hindexed' function. */
+#undef HAVE_MPI_TYPE_CREATE_HINDEXED
+
+/* Define to 1 if you have the `MPI_Type_create_hvector' function. */
+#undef HAVE_MPI_TYPE_CREATE_HVECTOR
+
+/* Define to 1 if you have the `MPI_Type_create_resized' function. */
+#undef HAVE_MPI_TYPE_CREATE_RESIZED
+
+/* Define to 1 if you have the `MPI_Type_create_struct' function. */
+#undef HAVE_MPI_TYPE_CREATE_STRUCT
+
+/* Define to 1 if you have the `MPI_Type_create_subarray' function. */
+#undef HAVE_MPI_TYPE_CREATE_SUBARRAY
+
+/* Define to 1 if you have the `MPI_Type_get_extent' function. */
+#undef HAVE_MPI_TYPE_GET_EXTENT
+
+/* available */
+#undef HAVE_MPI_UB
+
+/* available */
+#undef HAVE_MPI_UNSIGNED
+
+/* available */
+#undef HAVE_MPI_UNSIGNED_CHAR
+
+/* available */
+#undef HAVE_MPI_UNSIGNED_LONG_LONG
+
+/* available */
+#undef HAVE_MPI_UNSIGNED_SHORT
+
+/* Define to 1 if the system has the type `ptrdiff_t'. */
+#undef HAVE_PTRDIFF_T
+
+/* Define to 1 if you have the <search.h> header file. */
+#undef HAVE_SEARCH_H
+
+/* Define to 1 if the system has the type `ssize_t'. */
+#undef HAVE_SSIZE_T
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the `tdelete' function. */
+#undef HAVE_TDELETE
+
+/* Define to 1 if you have the `tsearch' function. */
+#undef HAVE_TSEARCH
+
+/* Define to 1 if the system has the type `uchar'. */
+#undef HAVE_UCHAR
+
+/* Define to 1 if the system has the type `uint'. */
+#undef HAVE_UINT
+
+/* Define to 1 if the system has the type `uint64'. */
+#undef HAVE_UINT64
+
+/* Define to 1 if the system has the type `ulonglong'. */
+#undef HAVE_ULONGLONG
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `unlink' function. */
+#undef HAVE_UNLINK
+
+/* Define to 1 if the system has the type `ushort'. */
+#undef HAVE_USHORT
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Type of NC_BYTE */
+#undef NCBYTE_T
+
+/* Type of NC_SHORT */
+#undef NCSHORT_T
+
+/* C type for Fortran double */
+#undef NF_DOUBLEPRECISION_IS_C_
+
+/* C type for Fortran INT1 */
+#undef NF_INT1_IS_C_
+
+/* Type for Fortran INT1 */
+#undef NF_INT1_T
+
+/* C type for Fortran INT2 */
+#undef NF_INT2_IS_C_
+
+/* Type for Fortran INT2 */
+#undef NF_INT2_T
+
+/* C type for Fortran INT8 */
+#undef NF_INT8_IS_C_
+
+/* Type for Fortran INT8 */
+#undef NF_INT8_T
+
+/* C type for Fortran INT */
+#undef NF_INT_IS_C_
+
+/* C type for Fortran REAL */
+#undef NF_REAL_IS_C_
+
+/* Does system have IEEE FLOAT */
+#undef NO_IEEE_FLOAT
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define if to enable debugging */
+#undef PNC_DEBUG
+
+/* Define if to enable malloc tracing */
+#undef PNC_MALLOC_TRACE
+
+/* PnetCDF release date string */
+#undef PNETCDF_RELEASE_DATE
+
+/* full PnetCDF version string */
+#undef PNETCDF_VERSION
+
+/* major version number */
+#undef PNETCDF_VERSION_MAJOR
+
+/* minor version number */
+#undef PNETCDF_VERSION_MINOR
+
+/* pre-release string */
+#undef PNETCDF_VERSION_PRE
+
+/* sub version number */
+#undef PNETCDF_VERSION_SUB
+
+/* The size of `double', as computed by sizeof. */
+#undef SIZEOF_DOUBLE
+
+/* The size of `float', as computed by sizeof. */
+#undef SIZEOF_FLOAT
+
+/* The size of `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of `longlong', as computed by sizeof. */
+#undef SIZEOF_LONGLONG
+
+/* The size of `long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
+
+/* The size of `MPI_Aint', as computed by sizeof. */
+#undef SIZEOF_MPI_AINT
+
+/* The size of `MPI_Offset', as computed by sizeof. */
+#undef SIZEOF_MPI_OFFSET
+
+/* The size of `off_t', as computed by sizeof. */
+#undef SIZEOF_OFF_T
+
+/* The size of `short', as computed by sizeof. */
+#undef SIZEOF_SHORT
+
+/* The size of `signed char', as computed by sizeof. */
+#undef SIZEOF_SIGNED_CHAR
+
+/* The size of `size_t', as computed by sizeof. */
+#undef SIZEOF_SIZE_T
+
+/* The size of `uint', as computed by sizeof. */
+#undef SIZEOF_UINT
+
+/* The size of `ulonglong', as computed by sizeof. */
+#undef SIZEOF_ULONGLONG
+
+/* The size of `unsigned char', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_CHAR
+
+/* The size of `unsigned int', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_INT
+
+/* The size of `unsigned long long', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_LONG_LONG
+
+/* The size of `unsigned short', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_SHORT
+
+/* The size of `ushort', as computed by sizeof. */
+#undef SIZEOF_USHORT
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+#  undef WORDS_BIGENDIAN
+# endif
+#endif
+
+/* Enable large inode numbers on Mac OS X 10.5.  */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to 1 if type `char' is unsigned and you are not using gcc.  */
+#ifndef __CHAR_UNSIGNED__
+# undef __CHAR_UNSIGNED__
+#endif
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `long int' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
diff --git a/src/lib/ncio.h b/src/lib/ncio.h
new file mode 100644
index 0000000..a145b6f
--- /dev/null
+++ b/src/lib/ncio.h
@@ -0,0 +1,95 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: ncio.h 2017 2015-04-01 21:27:21Z wkliao $ */
+
+#ifndef _NCIO_H_
+#define _NCIO_H_
+
+#include <stddef.h>       /* size_t */
+#include <sys/types.h>    /* off_t */
+#include <mpi.h>
+#include "pnetcdf.h"
+
+#define MPI_COLLECTIVE_FH 2
+#define MPI_INDEPENDENT_FH 8
+
+#define NC_collectiveFhOpened(nciop) \
+    (fIsSet(nciop->mpioflags, MPI_COLLECTIVE_FH))
+
+#define NC_independentFhOpened(nciop) \
+    (fIsSet(nciop->mpioflags, MPI_INDEPENDENT_FH))
+
+#define set_NC_collectiveFh(nciop) \
+    fSet((nciop)->mpioflags, MPI_COLLECTIVE_FH)
+
+#define set_NC_independentFh(nciop) \
+    fSet((nciop)->mpioflags, MPI_INDEPENDENT_FH)
+
+
+/*
+ * I/O hints used by PnetCDF, but MPI-IO
+ */
+typedef struct {
+    MPI_Offset h_align; /* file alignment size for header */
+    MPI_Offset v_align; /* file alignment size for each fixed variable */
+    MPI_Offset r_align; /* file alignment size for record variable section */
+    MPI_Offset header_read_chunk_size;
+#ifdef ENABLE_SUBFILING
+    int subfile_mode;
+    int num_subfiles;
+#endif
+} nc_hints;
+
+/*
+ * netcdf i/o abstraction
+ */
+typedef struct {
+    /*
+     * A copy of the ioflags argument passed in to ncmpiio_open()
+     * or ncmpiio_create().
+     */
+    int ioflags;
+
+    /*
+     * The file descriptor of the netcdf file.
+     * This gets handed to the user as the netcdf id.
+     */
+    int fd;
+
+    /*
+     * The MPI File handle and the communicator
+     */
+    MPI_File collective_fh;
+    MPI_File independent_fh;
+    MPI_Comm comm;
+    MPI_Info mpiinfo;
+
+    int mpiomode;        /* mode used in MPI_File_open */
+    int mpioflags;       /* MPI_COLLECTIVE_FH or MPI_INDEPENDENT_FH */
+    int striping_unit;   /* file stripe size of the file */
+
+    nc_hints hints;      /* I/O hints used by PnetCDF only */
+
+    /*
+     * A copy of the 'path' argument passed in to ncmpiio_open()
+     * or ncmpiio_create(). Used by ncabort() to remove (unlink)
+     * the file and by error messages.
+     */
+    const char *path;
+
+    MPI_Offset put_size;  /* amount of writes committed so far in bytes */
+    MPI_Offset get_size;  /* amount of reads  committed so far in bytes */
+} ncio;
+
+extern ncio *
+ncmpiio_new(const char *path, int ioflags);
+
+extern void
+ncmpiio_free(ncio *nciop);
+
+extern int
+ncmpiio_close(ncio *nciop, int doUnlink);
+
+#endif /* _NCIO_H_ */
diff --git a/src/lib/ncmpidtype.c b/src/lib/ncmpidtype.c
new file mode 100644
index 0000000..bcd5745
--- /dev/null
+++ b/src/lib/ncmpidtype.c
@@ -0,0 +1,575 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: ncmpidtype.c 2290 2016-01-02 18:37:46Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncmpidtype.h"
+#include "macro.h"
+
+/*@
+  ncmpii_type_filter - Map a basic MPI datatype into one of the eight
+  that we process natively.
+
+  We unfortunately need to wrap all these types in case they aren't defined.
+
+  Return:
+  On success, one of MPI_CHAR, MPI_SIGNED_CHAR, MPI_UNSIGNED_CHAR, MPI_BYTE,
+  MPI_SHORT, MPI_INT, MPI_LONG, MPI_FLOAT, and MPI_DOUBLE.
+  On failure, MPI_DATATYPE_NULL.
+@*/
+static MPI_Datatype ncmpii_type_filter(MPI_Datatype type)
+{
+    /* char types */
+#ifdef HAVE_MPI_CHARACTER
+    if (type == MPI_CHARACTER)
+        return  MPI_CHAR;
+#endif
+    if (type == MPI_CHAR)
+        return  MPI_CHAR;
+
+    /* unsigned char types */
+    if (type == MPI_UNSIGNED_CHAR)
+        return  MPI_UNSIGNED_CHAR;
+
+    /* signed char types */
+    if (type == MPI_SIGNED_CHAR)
+        return  MPI_SIGNED_CHAR;
+
+#ifdef HAVE_MPI_INTEGER1
+    if (type == MPI_INTEGER1)
+        return  MPI_SIGNED_CHAR;
+#endif
+    if (type == MPI_BYTE)
+        return  MPI_BYTE;
+
+    /* 2-byte integer types (only supported if MPI_SHORT is 2-bytes). */
+#if (SIZEOF_SHORT == 2)
+  #ifdef HAVE_MPI_INTEGER2
+    if (type == MPI_INTEGER2)
+        return  MPI_SHORT;
+  #endif
+    if (type == MPI_SHORT)
+        return  MPI_SHORT;
+
+    if (type == MPI_UNSIGNED_SHORT)
+        return  MPI_UNSIGNED_SHORT;
+#endif
+
+    /* 4-byte integer types */
+  {
+    MPI_Datatype int_4byte, uint_4byte;
+#if (SIZEOF_INT == 4)
+     int_4byte = MPI_INT;
+    uint_4byte = MPI_UNSIGNED;
+#elif (SIZEOF_SHORT == 4)
+     int_4byte = MPI_SHORT;
+    uint_4byte = MPI_UNSIGNED_SHORT;
+#else
+     int_4byte = MPI_DATATYPE_NULL; /* no 4-byte type? */
+    uint_4byte = MPI_DATATYPE_NULL;
+#endif
+
+#ifdef HAVE_MPI_INTEGER
+    if (type == MPI_INTEGER)
+        return int_4byte;
+    if (type == MPI_UNSIGNED)
+        return uint_4byte;
+#endif
+#ifdef HAVE_MPI_INTEGER4
+    if (type == MPI_INTEGER4)
+        return int_4byte;
+#endif
+#if (SIZEOF_LONG == 4)
+    if (type == MPI_LONG)
+        return int_4byte;
+    if (type == MPI_UNSIGNED_LONG)
+        return uint_4byte;
+#endif
+#if (SIZEOF_INT == 4)
+    if (type == MPI_INT)
+        return  MPI_INT;
+    if (type == MPI_UNSIGNED)
+        return  MPI_UNSIGNED;
+#elif (SIZEOF_SHORT == 4)
+    if (type == MPI_SHORT)
+        return  MPI_SHORT;
+    if (type == MPI_UNSIGNED_SHORT)
+        return  MPI_UNSIGNED_SHORT;
+#endif
+  }
+
+     /* 8-byte integer types (only supported if MPI_INT or MPI_LONG
+      * is 8-bytes).
+      */
+#if (SIZEOF_INT == 8) || (SIZEOF_LONG == 8)
+  #ifdef HAVE_MPI_INTEGER8
+    if (type == MPI_INTEGER8)
+      #if (SIZEOF_INT == 8)
+        return MPI_INT;
+      #else
+        return MPI_LONG;
+      #endif
+  #endif
+  #ifdef HAVE_MPI_UNSIGNED_INTEGER8
+    if (type == MPI_UNSIGNED_INTEGER8)
+      #if (SIZEOF_UINT == 8)
+        return MPI_UNSIGNED;
+      #else
+        return MPI_UNSIGNED_LONG;
+      #endif
+  #endif
+
+  #if (SIZEOF_INT == 8)
+    if (type == MPI_INT)
+        return  MPI_INT;
+    if (type == MPI_UNSIGNED)
+        return  MPI_UNSIGNED;
+  #endif
+  #if (SIZEOF_LONG == 8)
+    if (type == MPI_LONG)
+      #if (SIZEOF_INT == 8)
+        return MPI_INT;
+      #else
+        return MPI_LONG;
+      #endif
+    if (type == MPI_UNSIGNED_LONG)
+      #if (SIZEOF_UINT == 8)
+        return MPI_UNSIGNED;
+      #else
+        return MPI_UNSIGNED_LONG;
+      #endif
+  #endif
+#endif
+
+    /* 4-byte float types (we assume float is 4-bytes). */
+#ifdef HAVE_MPI_REAL
+    if (type == MPI_REAL)
+        return  MPI_FLOAT;
+#endif
+#ifdef HAVE_MPI_REAL4
+    if (type == MPI_REAL4)
+        return  MPI_FLOAT;
+#endif
+    if (type == MPI_FLOAT)
+        return  MPI_FLOAT;
+
+    /* 8-byte float types (we assume double is 8-bytes). */
+#ifdef HAVE_MPI_REAL8
+    if (type == MPI_REAL8)
+        return MPI_DOUBLE;
+#endif
+#ifdef HAVE_MPI_DOUBLE_PRECISION
+    if (type == MPI_DOUBLE_PRECISION)
+        return  MPI_DOUBLE;
+#endif
+    if (type == MPI_DOUBLE)
+        return  MPI_DOUBLE;
+
+    if (type == MPI_LONG_LONG_INT)
+        return  MPI_LONG_LONG_INT;
+
+    if (type == MPI_UNSIGNED_LONG_LONG)
+        return  MPI_UNSIGNED_LONG_LONG;
+
+/* HP-MPI for example needs to handle MPI_LB and MPI_UB */
+#ifdef HAVE_MPI_LB
+    if (type == MPI_LB) {
+#if SIZEOF_SIZE_T == 8
+        return MPI_DOUBLE;
+#elif SIZEOF_SIZE_T == 4
+        return MPI_DOUBLE;
+#endif
+    }
+#endif
+#ifdef HAVE_MPI_UB
+    if (type == MPI_UB) {
+#if SIZEOF_SIZE_T == 8
+        return MPI_DOUBLE;
+#elif SIZEOF_SIZE_T == 4
+        return MPI_DOUBLE;
+#endif
+    }
+#endif
+
+/* default */
+    return MPI_DATATYPE_NULL;
+}
+
+/*@
+  ncmpi_darray_get_totalblock - Count the total number of blocks assigned
+  to the calling process by the darray datatype.
+
+  Input:
+. rank - rank of calling process
+. ndims - number of dimensions for the array and process grid
+. array_of_gsizes - Number of elements of type oldtype in each dimension
+                    of global array (array of positive integers)
+. array_of_distribs - Distribution of array in each dimension (array of state)
+. array_of_dargs - Distribution argument in each dimension
+                   (array of positive integers)
+. array_of_psizes - Size of process grid in each dimension
+                    (array of positive integers)
+
+  Return:
+. total number of blocks assigned from the distributed array
+@*/
+#ifdef HAVE_MPI_COMBINER_DARRAY
+static int
+ncmpii_darray_get_totalblks(int rank,
+                            MPI_Offset ndims,
+                            int array_of_gsizes[],
+                            int array_of_distribs[],
+                            int array_of_dargs[],
+                            int array_of_psizes[])
+{
+  int total_blocks = 1;
+  int subblocks, cycle, remain_cycle;
+  int i;
+  int pcoord;
+
+  /* Process Grid ranking is always in C ORDER,
+     so compute proc coordinates from last dim */
+
+  for (i=(int)ndims-1; i>=0; i--) {
+    if ( array_of_distribs[i] == MPI_DISTRIBUTE_NONE ) {
+      total_blocks *= array_of_gsizes[i];
+    } else {
+
+      pcoord = rank % array_of_psizes[i];
+      rank /= array_of_psizes[i];
+      if ( array_of_dargs[i] == MPI_DISTRIBUTE_DFLT_DARG ) {
+        subblocks = array_of_gsizes[i]/array_of_psizes[i];
+        if ( subblocks*array_of_psizes[i]+pcoord < array_of_gsizes[i] )
+          subblocks++;
+      } else {
+        cycle = array_of_dargs[i]*array_of_psizes[i];
+        remain_cycle = array_of_gsizes[i] % cycle;
+
+        subblocks = remain_cycle - pcoord*array_of_dargs[i];
+        if (subblocks > array_of_dargs[i])
+          subblocks = array_of_dargs[i];
+        else if (subblocks < 0)
+          subblocks = 0;
+
+        subblocks += array_of_gsizes[i]/cycle * array_of_dargs[i];
+      }
+
+      if (subblocks == 0)
+        return 0;
+      total_blocks *= subblocks;
+
+    }
+  }
+
+  return total_blocks;
+}
+#endif
+
+
+/*@
+  ncmpii_dtype_decode - Decode the MPI derived datatype to get the bottom
+  level primitive datatype information.
+
+  Input:
+. dtype - The MPI derived datatype to be decoded (can be predefined type).
+
+  Output:
+. ptype - The bottom level primitive datatype (only one allowed) in buftype
+. el_size - The size of the ptype
+. nelems - Number of elements/entries of such ptype in one buftype object
+. iscontig_of_ptypes - Whether dtype is a contiguous number of ptype
+@*/
+int ncmpii_dtype_decode(MPI_Datatype dtype,
+                        MPI_Datatype *ptype,
+                        int *el_size,
+                        MPI_Offset *nelems,
+                        int *isderived,
+                        int *iscontig_of_ptypes)
+{
+  int i;
+  MPI_Offset tmpnelems, total_blocks;
+  int tmpel_size;
+  MPI_Datatype tmpptype;
+  int num_ints, num_adds, num_dtypes, combiner;
+  int *array_of_ints;
+  MPI_Aint *array_of_adds;
+  MPI_Datatype *array_of_dtypes;
+  MPI_Offset count;
+  int ndims;
+  int status = NC_NOERR;
+
+  *isderived = 0;
+
+  if (dtype == MPI_DATATYPE_NULL) {
+    *nelems = 0;
+    *ptype = dtype;
+    *el_size = 0;
+    *iscontig_of_ptypes = 1;
+    return NC_NOERR;
+  }
+
+  MPI_Type_get_envelope(dtype, &num_ints, &num_adds, &num_dtypes, &combiner);
+
+  if (
+#ifdef HAVE_MPI_COMBINER_F90_INTEGER
+      combiner == MPI_COMBINER_F90_INTEGER ||
+#endif
+#ifdef HAVE_MPI_COMBINER_F90_REAL
+      combiner == MPI_COMBINER_F90_REAL ||
+#endif
+#ifdef HAVE_MPI_COMBINER_F90_COMPLEX
+      combiner == MPI_COMBINER_F90_COMPLEX ||
+#endif
+     0 )
+  {
+    fprintf(stderr,
+            "FIXME: F90_INTEGER, F90_REAL or F90_COMPLEX are not supported.\n");
+  }
+
+  if ( combiner == MPI_COMBINER_NAMED ) {
+    /* Predefined datatype */
+    *nelems = 1;
+    if ( (*ptype = ncmpii_type_filter(dtype)) == MPI_DATATYPE_NULL )
+      DEBUG_RETURN_ERROR(NC_EUNSPTETYPE)
+    MPI_Type_size(dtype, el_size);
+    *iscontig_of_ptypes = 1;
+    return NC_NOERR;
+  }
+
+  array_of_ints = (int *) NCI_Malloc(num_ints * SIZEOF_INT);
+  array_of_adds = (MPI_Aint *) NCI_Malloc(num_adds * SIZEOF_MPI_AINT);
+  array_of_dtypes = (MPI_Datatype *) NCI_Malloc(num_dtypes * sizeof(MPI_Datatype));
+
+  MPI_Type_get_contents(dtype, num_ints, num_adds, num_dtypes,
+                        array_of_ints, array_of_adds, array_of_dtypes);
+
+  switch (combiner) {
+
+    /* single etype */
+
+    case MPI_COMBINER_CONTIGUOUS:
+    case MPI_COMBINER_HVECTOR:
+    case MPI_COMBINER_VECTOR:
+    case MPI_COMBINER_HINDEXED:
+    case MPI_COMBINER_INDEXED:
+#ifdef HAVE_MPI_COMBINER_DUP
+    case MPI_COMBINER_DUP:
+#endif
+#ifdef HAVE_MPI_COMBINER_HVECTOR_INTEGER
+    case MPI_COMBINER_HVECTOR_INTEGER:
+#endif
+#ifdef HAVE_MPI_COMBINER_INDEXED_BLOCK
+    case MPI_COMBINER_INDEXED_BLOCK:
+#endif
+#ifdef HAVE_MPI_COMBINER_HINDEXED_INTEGER
+    case MPI_COMBINER_HINDEXED_INTEGER:
+#endif
+#ifdef HAVE_MPI_COMBINER_SUBARRAY
+    case MPI_COMBINER_SUBARRAY:
+#endif
+#ifdef HAVE_MPI_COMBINER_DARRAY
+    case MPI_COMBINER_DARRAY:
+#endif
+#ifdef HAVE_MPI_COMBINER_RESIZED
+    case MPI_COMBINER_RESIZED:
+#endif
+
+        status = ncmpii_dtype_decode(array_of_dtypes[0], ptype, el_size,
+                                     nelems, isderived, iscontig_of_ptypes);
+        if (*isderived)
+          MPI_Type_free(array_of_dtypes);
+
+        break;
+
+    /* multiple etypes */
+
+    case MPI_COMBINER_STRUCT:
+#ifdef HAVE_MPI_COMBINER_STRUCT_INTEGER
+    case MPI_COMBINER_STRUCT_INTEGER:
+#endif
+        count = array_of_ints[0];
+        *el_size = 0;
+        for (i=0; i<count && *el_size==0; i++) {
+          /* need to skip null/marker types */
+          status = ncmpii_dtype_decode(array_of_dtypes[i],
+                                       ptype,
+                                       el_size,
+                                       nelems,
+                                       isderived,
+                                       iscontig_of_ptypes);
+          if (status != NC_NOERR)
+            return status;
+          if (*isderived)
+            MPI_Type_free(array_of_dtypes+i);
+          if (*el_size > 0)
+            *nelems *= array_of_ints[1+i];
+        }
+        for ( ; i<count; i++) {
+          status = ncmpii_dtype_decode(array_of_dtypes[i],
+                                       &tmpptype,
+                                       &tmpel_size,
+                                       &tmpnelems,
+                                       isderived,
+                                       iscontig_of_ptypes);
+          if (status != NC_NOERR)
+            return status;
+          if (*isderived)
+            MPI_Type_free(array_of_dtypes+i);
+          if (tmpel_size > 0) {
+            if (tmpptype != *ptype)
+              DEBUG_RETURN_ERROR(NC_EMULTITYPES)
+            *nelems += tmpnelems*array_of_ints[1+i];
+          }
+        }
+
+        *iscontig_of_ptypes = 0;
+
+        break;
+
+    default:
+        break;
+  }
+
+  *isderived = 1;
+
+  switch (combiner) {
+
+    /* single etype */
+
+    case MPI_COMBINER_CONTIGUOUS:
+        total_blocks = array_of_ints[0];
+        break;
+
+    case MPI_COMBINER_HVECTOR:
+    case MPI_COMBINER_VECTOR:
+#ifdef HAVE_MPI_COMBINER_HVECTOR_INTEGER
+    case MPI_COMBINER_HVECTOR_INTEGER:
+#endif
+#ifdef HAVE_MPI_COMBINER_INDEXED_BLOCK
+    case MPI_COMBINER_INDEXED_BLOCK:
+#endif
+        *iscontig_of_ptypes = 0;
+        total_blocks = array_of_ints[0]*array_of_ints[1];
+        break;
+
+    case MPI_COMBINER_HINDEXED:
+    case MPI_COMBINER_INDEXED:
+#ifdef HAVE_MPI_COMBINER_HINDEXED_INTEGER
+    case MPI_COMBINER_HINDEXED_INTEGER:
+#endif
+        *iscontig_of_ptypes = 0;
+        for (i=0, total_blocks=0; i<array_of_ints[0]; i++)
+          total_blocks += array_of_ints[1+i];
+        break;
+
+#ifdef HAVE_MPI_COMBINER_SUBARRAY
+    case MPI_COMBINER_SUBARRAY:
+        *iscontig_of_ptypes = 0;
+        ndims = array_of_ints[0];
+        for (i=0, total_blocks=1; i<ndims; i++)
+          total_blocks *= array_of_ints[1+ndims+i];
+        break;
+#endif
+
+#ifdef HAVE_MPI_COMBINER_DARRAY
+    case MPI_COMBINER_DARRAY:
+        *iscontig_of_ptypes = 0;
+        ndims = array_of_ints[2];
+
+        /* seldom reached, so put it in a separate function */
+        total_blocks = ncmpii_darray_get_totalblks(array_of_ints[1],
+                                                   ndims,
+                                                   array_of_ints+3,
+                                                   array_of_ints+3+ndims,
+                                                   array_of_ints+3+2*ndims,
+                                                   array_of_ints+3+3*ndims);
+        break;
+#endif
+
+#ifdef HAVE_MPI_COMBINER_RESIZED
+    case MPI_COMBINER_RESIZED:
+        *iscontig_of_ptypes = 0;
+        total_blocks = 1;
+        break;
+#endif
+
+    default: /* DUP etc. */
+        total_blocks = 1;
+        break;
+  }
+
+  *nelems *= total_blocks;
+
+  NCI_Free(array_of_ints);
+  NCI_Free(array_of_adds);
+  NCI_Free(array_of_dtypes);
+
+  return status;
+}
+
+/*@
+  ncmpii_data_repack - copy data between two buffers with different datatypes.
+
+  Input:
+. inbuf - input buffer where data is copied from
+. incount - number of input elements
+. intype - datatype of each element in input buffer
+. outbuf - output buffer where data is copied to
+. outcount - number of output elements
+. outtype - datatype of each element in output buffer
+@*/
+
+int ncmpii_data_repack(void *inbuf,
+                       MPI_Offset incount,
+                       MPI_Datatype intype,
+                       void *outbuf,
+                       MPI_Offset outcount,
+                       MPI_Datatype outtype)
+{
+  int intypesz, outtypesz;
+  int packsz;
+  void *packbuf;
+  int packpos;
+
+  MPI_Type_size(intype, &intypesz);
+  MPI_Type_size(outtype, &outtypesz);
+
+  if (incount*intypesz != outcount*outtypesz) {
+    /* input data amount does not match output data amount */
+    /* NOTE: we ignore it for user responsibility or add error handling ? */
+
+    /* for rescue, guarantee output data amount <= input data amount */
+    if (incount*intypesz < outcount*outtypesz)
+      outcount = incount*intypesz/outtypesz;
+  }
+
+  if (incount == 0)
+    return NC_NOERR;
+
+  /* local pack-n-unpack, using MPI_COMM_SELF */
+  if (incount  != (int)incount)  DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+  if (outcount != (int)outcount) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+
+  MPI_Pack_size((int)incount, intype, MPI_COMM_SELF, &packsz);
+  packbuf = (void *)NCI_Malloc((size_t)packsz);
+  packpos = 0;
+  MPI_Pack(inbuf, (int)incount, intype, packbuf, packsz, &packpos, MPI_COMM_SELF);
+  packpos = 0;
+  MPI_Unpack(packbuf, packsz, &packpos, outbuf, (int)outcount, outtype, MPI_COMM_SELF);
+  NCI_Free(packbuf);
+
+  return NC_NOERR;
+}
diff --git a/src/lib/ncmpidtype.h b/src/lib/ncmpidtype.h
new file mode 100644
index 0000000..5ed6a8f
--- /dev/null
+++ b/src/lib/ncmpidtype.h
@@ -0,0 +1,24 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: ncmpidtype.h 1468 2013-10-26 16:53:18Z wkliao $ */
+
+#ifndef NCMPI_DTYPE_H
+#define NCMPI_DTYPE_H
+
+int ncmpii_dtype_decode(MPI_Datatype dtype,
+			MPI_Datatype *ptype,
+			int *el_size,
+			MPI_Offset *nelems,
+			int *isderived,
+			int *iscontig_of_ptypes);
+
+int ncmpii_data_repack(void *inbuf,
+                       MPI_Offset incount,
+                       MPI_Datatype intype,
+                       void *outbuf,
+                       MPI_Offset outcount,
+                       MPI_Datatype outtype);
+
+#endif
diff --git a/src/lib/nctypes.h b/src/lib/nctypes.h
new file mode 100644
index 0000000..938a675
--- /dev/null
+++ b/src/lib/nctypes.h
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: nctypes.h 2301 2016-01-10 19:21:33Z wkliao $ */
+
+#ifndef NCTYPES_H
+#define NCTYPES_H
+
+#ifndef HAVE_PTRDIFF_T
+typedef int ptrdiff_t;
+#endif
+
+#ifndef HAVE_SSIZE_T
+typedef int ssize_t;
+#endif
+
+#ifndef HAVE_UCHAR
+typedef unsigned char uchar;
+#endif
+
+#ifndef HAVE_USHORT
+typedef unsigned short int ushort;
+#endif
+
+#ifndef HAVE_UINT
+typedef unsigned int uint;
+#endif
+
+#ifndef HAVE_LONGLONG
+typedef long long longlong;
+#endif
+
+#ifndef HAVE_ULONGLONG
+typedef unsigned long long ulonglong;
+#endif
+
+#ifndef HAVE_INT64
+typedef long long int64;
+#endif
+
+#ifndef HAVE_UINT64
+typedef unsigned long long uint64;
+#endif
+
+#endif
diff --git a/src/lib/ncx.h b/src/lib/ncx.h
new file mode 100644
index 0000000..053507e
--- /dev/null
+++ b/src/lib/ncx.h
@@ -0,0 +1,979 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* "$Id: ncx.h 2301 2016-01-10 19:21:33Z wkliao $" */
+
+#ifndef _NCX_H_
+#define _NCX_H_
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncio.h"
+#include "fbits.h"
+#include "nctypes.h"
+
+/*
+ * An external data representation interface.
+
+ *
+ * This started out as a general replacement for ONC XDR,
+ * specifically, the xdrmem family of functions.
+ *
+ * We eventually realized that we could write more portable
+ * code if we decoupled any association between the 'C' types
+ * and the external types. (XDR has this association between the 'C'
+ * types and the external representations, like xdr_int() takes
+ * an int argument and goes to an external int representation.)
+ * So, now there is a matrix of functions.
+ *
+ */
+
+#include "rnd.h"
+#include <stddef.h> /* size_t */
+#include <errno.h>
+#include <sys/types.h> /* off_t */
+
+
+#if defined(_CRAY) && !defined(_CRAYIEEE) && !defined(__crayx1)
+#define CRAYFLOAT 1 /* CRAY Floating point */
+#elif defined(_SX) && defined(_FLOAT2)	/* NEC SUPER-UX in CRAY mode */
+#define CRAYFLOAT 1 /* CRAY Floating point */
+#endif
+
+/*
+ * External sizes of the primitive elements.
+ */
+#define X_SIZEOF_CHAR		1
+#define X_SIZEOF_SHORT		2
+#define X_SIZEOF_INT		4	/* xdr_int */
+#if 0
+#define X_SIZEOF_LONG		8 */	/* xdr_long_long */
+#endif
+#define X_SIZEOF_FLOAT		4
+#define X_SIZEOF_DOUBLE		8
+
+/* additional data types in CDF-5 */
+#define X_SIZEOF_UBYTE		1
+#define X_SIZEOF_USHORT		2
+#define X_SIZEOF_UINT		4
+#define X_SIZEOF_LONGLONG	8
+#define X_SIZEOF_ULONGLONG	8
+#define X_SIZEOF_INT64		8
+#define X_SIZEOF_UINT64		8
+
+/*
+ * For now, netcdf is limited to 32 bit sizes,
+ * If compiled with support for "large files", then
+ * netcdf will use a 64 bit off_t and it can then write a file
+ * using 64 bit offsets.
+ *  see also X_SIZE_MAX, X_OFF_MAX below
+ */
+/* #define X_SIZEOF_OFF_T		(sizeof(off_t)) */
+#define X_SIZEOF_OFF_T		SIZEOF_OFF_T
+#define X_SIZEOF_SIZE_T		X_SIZEOF_INT
+
+/*
+ * limits of the external representation
+ */
+#define X_SCHAR_MIN	(-128)
+#define X_SCHAR_MAX	127
+#define X_UCHAR_MAX	255U
+#define X_SHORT_MIN	(-32768)
+#define X_SHRT_MIN	X_SHORT_MIN	/* alias compatible with limits.h */
+#define X_SHORT_MAX	32767
+#define X_SHRT_MAX	X_SHORT_MAX	/* alias compatible with limits.h */
+#define X_USHORT_MAX	65535U
+#define X_USHRT_MAX	X_USHORT_MAX	/* alias compatible with limits.h */
+#define X_INT_MIN	(-2147483647-1)
+#define X_INT_MAX	2147483647
+#define X_UINT_MAX	4294967295U
+#define X_LONGLONG_MIN	(-9223372036854775807LL-1LL)
+#define X_LONGLONG_MAX	9223372036854775807LL
+#define X_ULONGLONG_MAX	18446744073709551615ULL
+#define X_FLOAT_MAX	3.402823466e+38f
+#define X_FLOAT_MIN	(-X_FLOAT_MAX)
+#define X_FLT_MAX	X_FLOAT_MAX	/* alias compatible with limits.h */
+#if defined(CRAYFLOAT) && CRAYFLOAT != 0
+/* ldexp(1. - ldexp(.5 , -46), 1024) */
+#define X_DOUBLE_MAX    1.79769313486230e+308
+#else
+/* scalb(1. - scalb(.5 , -52), 1024) */
+#define X_DOUBLE_MAX	1.7976931348623157e+308
+#endif
+#define X_DOUBLE_MIN	(-X_DOUBLE_MAX)
+#define X_DBL_MAX	X_DOUBLE_MAX	/* alias compatible with limits.h */
+
+#define X_SIZE_MAX	X_UINT_MAX
+#define X_OFF_MAX	X_INT_MAX
+
+
+/* Begin ncmpix_len */
+
+/*
+ * ncmpix_len_xxx() interfaces are defined as macros below,
+ * These give the length of an array of nelems of the type.
+ * N.B. The 'char' and 'short' interfaces give the X_ALIGNED length.
+ */
+#define X_ALIGN			4	/* a.k.a. BYTES_PER_XDR_UNIT */
+
+#define ncmpix_len_char(nelems) \
+	_RNDUP((nelems), X_ALIGN)
+
+#define ncmpix_len_short(nelems) \
+	(((nelems) + (nelems)%2)  * X_SIZEOF_SHORT)
+
+#define ncmpix_len_int(nelems) \
+	((nelems) * X_SIZEOF_INT)
+
+#define ncmpix_len_long(nelems) \
+	((nelems) * X_SIZEOF_LONG)
+
+#define ncmpix_len_float(nelems) \
+	((nelems) * X_SIZEOF_FLOAT)
+
+#define ncmpix_len_double(nelems) \
+	((nelems) * X_SIZEOF_DOUBLE)
+
+#define ncmpix_len_ubyte(nelems) \
+	_RNDUP((nelems), X_ALIGN)
+
+#define ncmpix_len_ushort(nelems) \
+	(((nelems) + (nelems)%2)  * X_SIZEOF_USHORT)
+
+#define ncmpix_len_uint(nelems) \
+	((nelems) * X_SIZEOF_UINT)
+
+#define ncmpix_len_int64(nelems) \
+	((nelems) * X_SIZEOF_INT64)
+
+#define ncmpix_len_uint64(nelems) \
+	((nelems) * X_SIZEOF_UINT64)
+
+/* End ncmpix_len */
+
+#if defined(__CHAR_UNSIGNED__) && __CHAR_UNSIGNED__ != 0
+	/* 'char' is unsigned, declare ncbyte as 'signed char' */
+typedef signed char schar;
+
+#else
+	/* 'char' is signed */
+typedef signed char schar;
+
+#endif	/* __CHAR_UNSIGNED__ */
+
+/*
+ * Primitive numeric conversion functions.
+ * The `put' functions convert from native internal
+ * type to the external type, while the `get' functions
+ * convert from the external to the internal.
+ *
+ * These take the form
+ *	int ncmpix_get_{external_type}_{internal_type}(
+ *		const void *xp,
+ *		internal_type *ip
+ *	);
+ *	int ncmpix_put_{external_type}_{internal_type}(
+ *		void *xp,
+ *		const internal_type *ip
+ *	);
+ * where
+ *	`external_type' and `internal_type' chosen from
+		schar
+		uchar
+		short
+		ushort
+		int
+		uint
+		long
+		ulong
+		float
+		double
+ *
+ * Not all combinations make sense.
+ * We may not implement all combinations that make sense.
+ * The netcdf functions that use this ncmpix interface don't
+ * use these primitive conversion functions. They use the
+ * aggregate conversion functions declared below.
+ *
+ * Storage for a single element of external type is at the `void * xp'
+ * argument.
+ *
+ * Storage for a single element of internal type is at `ip' argument.
+ *
+ * These functions return NC_NOERR when no error occured,
+ * or NC_ERANGE when the value being converted is too large.
+ * When NC_ERANGE occurs, an undefined (implementation dependent)
+ * conversion may have occured.
+ *
+ * Note that loss of precision may occur silently.
+ *
+ */
+
+/*
+ * Other primitive conversion functions
+ * N.B. slightly different interface
+ * Used by netcdf.
+ */
+
+/* ncmpix_get_int_size_t */
+extern int
+ncmpix_get_size_t(const void **xpp, size_t *ulp);
+/* ncmpix_get_int_off_t */
+extern int
+ncmpix_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t);
+
+/* ncmpix_put_int_size_t */
+extern int
+ncmpix_put_size_t(void **xpp, const size_t *ulp);
+/* ncmpix_put_int_off_t */
+extern int
+ncmpix_put_off_t(void **xpp, const off_t *lp, size_t sizeof_off_t);
+
+extern int
+ncmpix_get_uint32(const void **xpp, unsigned int *ip);
+extern int
+ncmpix_get_uint64(const void **xpp, unsigned long long *ip);
+extern int
+ncmpix_put_uint32(void **xpp, const unsigned int ip);
+extern int
+ncmpix_put_uint64(void **xpp, const unsigned long long ip);
+
+
+/*
+ * Aggregate numeric conversion functions.
+ * Convert an array.  Replaces xdr_array(...).
+ * These functions are used by netcdf. Unlike the xdr
+ * interface, we optimize for aggregate conversions.
+ * This functions should be implemented to take advantage
+ * of multiple processor / parallel hardware where available.
+ *
+ * These take the form
+ *	int ncmpix_getn_{external_type}_{internal_type}(
+ *		const void *xpp,
+ *		size_t nelems,
+ *		internal_type *ip
+ *	);
+ *	int ncmpix_putn_{external_type}_{internal_type}(
+ *		void **xpp,
+ *		size_t nelems,
+ *		const internal_type *ip
+ *	);
+ * Where the types are as in the primitive numeric conversion functions.
+ *
+ * The value of the pointer to pointer argument, *xpp, is
+ * expected to reference storage for `nelems' of the external
+ * type.  On return, it modified to reference just past the last
+ * converted external element.
+ *
+ * The types whose external size is less than X_ALIGN also have `pad'
+ * interfaces. These round (and zero fill on put) *xpp up to X_ALIGN
+ * boundaries. (This is the usual xdr behavior.)
+ *
+ * The `ip' argument should point to an array of `nelems' of
+ * internal_type.
+ *
+ * Range errors (NC_ERANGE) for a individual values in the array
+ * DO NOT terminate the array conversion. All elements are converted,
+ * with some having undefined values.
+ * If any range error occurs, the function returns NC_ERANGE.
+ *
+ */
+
+/*---- schar ----------------------------------------------------------------*/
+extern int
+ncmpix_getn_schar_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_getn_schar_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_getn_schar_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_getn_schar_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
+extern int
+ncmpix_getn_schar_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_getn_schar_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_getn_schar_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_getn_schar_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_getn_schar_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_getn_schar_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_getn_schar_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_pad_getn_schar_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_pad_getn_schar_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_pad_getn_schar_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_pad_getn_schar_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
+extern int
+ncmpix_pad_getn_schar_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_pad_getn_schar_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_pad_getn_schar_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_pad_getn_schar_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_pad_getn_schar_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_pad_getn_schar_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_pad_getn_schar_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_putn_schar_schar (void **xpp, MPI_Offset nelems, const schar   *ip);
+extern int
+ncmpix_putn_schar_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_putn_schar_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_putn_schar_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_putn_schar_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_putn_schar_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_putn_schar_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_putn_schar_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_putn_schar_double(void **xpp, MPI_Offset nelems, const double  *ip);
+extern int
+ncmpix_putn_schar_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_putn_schar_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+extern int
+ncmpix_pad_putn_schar_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
+extern int
+ncmpix_pad_putn_schar_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_pad_putn_schar_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_pad_putn_schar_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_pad_putn_schar_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_pad_putn_schar_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_pad_putn_schar_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_pad_putn_schar_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_pad_putn_schar_double(void **xpp, MPI_Offset nelems, const double *ip);
+extern int
+ncmpix_pad_putn_schar_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_pad_putn_schar_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+/*---- uchar ----------------------------------------------------------------*/
+extern int
+ncmpix_getn_uchar_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_getn_uchar_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_getn_uchar_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_getn_uchar_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
+extern int
+ncmpix_getn_uchar_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_getn_uchar_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_getn_uchar_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_getn_uchar_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_getn_uchar_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_getn_uchar_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_getn_uchar_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_pad_getn_uchar_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_pad_getn_uchar_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_pad_getn_uchar_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_pad_getn_uchar_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
+extern int
+ncmpix_pad_getn_uchar_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_pad_getn_uchar_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_pad_getn_uchar_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_pad_getn_uchar_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_pad_getn_uchar_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_pad_getn_uchar_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_pad_getn_uchar_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_putn_uchar_schar (void **xpp, MPI_Offset nelems, const schar   *ip);
+extern int
+ncmpix_putn_uchar_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_putn_uchar_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_putn_uchar_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_putn_uchar_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_putn_uchar_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_putn_uchar_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_putn_uchar_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_putn_uchar_double(void **xpp, MPI_Offset nelems, const double  *ip);
+extern int
+ncmpix_putn_uchar_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_putn_uchar_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+extern int
+ncmpix_pad_putn_uchar_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
+extern int
+ncmpix_pad_putn_uchar_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_pad_putn_uchar_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_pad_putn_uchar_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_pad_putn_uchar_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_pad_putn_uchar_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_pad_putn_uchar_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_pad_putn_uchar_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_pad_putn_uchar_double(void **xpp, MPI_Offset nelems, const double *ip);
+extern int
+ncmpix_pad_putn_uchar_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_pad_putn_uchar_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+/*---- short ----------------------------------------------------------------*/
+extern int
+ncmpix_getn_short_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_getn_short_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_getn_short_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_getn_short_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
+extern int
+ncmpix_getn_short_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_getn_short_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_getn_short_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_getn_short_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_getn_short_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_getn_short_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_getn_short_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_pad_getn_short_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_pad_getn_short_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_pad_getn_short_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_pad_getn_short_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
+extern int
+ncmpix_pad_getn_short_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_pad_getn_short_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_pad_getn_short_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_pad_getn_short_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_pad_getn_short_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_pad_getn_short_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_pad_getn_short_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_putn_short_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
+extern int
+ncmpix_putn_short_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_putn_short_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_putn_short_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_putn_short_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_putn_short_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_putn_short_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_putn_short_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_putn_short_double(void **xpp, MPI_Offset nelems, const double *ip);
+extern int
+ncmpix_putn_short_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_putn_short_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+extern int
+ncmpix_pad_putn_short_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
+extern int
+ncmpix_pad_putn_short_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_pad_putn_short_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_pad_putn_short_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_pad_putn_short_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_pad_putn_short_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_pad_putn_short_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_pad_putn_short_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_pad_putn_short_double(void **xpp, MPI_Offset nelems, const double *ip);
+extern int
+ncmpix_pad_putn_short_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_pad_putn_short_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+/*---- ushort ---------------------------------------------------------------*/
+extern int
+ncmpix_getn_ushort_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_getn_ushort_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_getn_ushort_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_getn_ushort_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
+extern int
+ncmpix_getn_ushort_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_getn_ushort_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_getn_ushort_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_getn_ushort_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_getn_ushort_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_getn_ushort_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_getn_ushort_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_pad_getn_ushort_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_pad_getn_ushort_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_pad_getn_ushort_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_pad_getn_ushort_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
+extern int
+ncmpix_pad_getn_ushort_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_pad_getn_ushort_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_pad_getn_ushort_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_pad_getn_ushort_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_pad_getn_ushort_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_pad_getn_ushort_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_pad_getn_ushort_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_putn_ushort_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
+extern int
+ncmpix_putn_ushort_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_putn_ushort_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_putn_ushort_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_putn_ushort_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_putn_ushort_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_putn_ushort_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_putn_ushort_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_putn_ushort_double(void **xpp, MPI_Offset nelems, const double *ip);
+extern int
+ncmpix_putn_ushort_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_putn_ushort_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+extern int
+ncmpix_pad_putn_ushort_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
+extern int
+ncmpix_pad_putn_ushort_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_pad_putn_ushort_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_pad_putn_ushort_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_pad_putn_ushort_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_pad_putn_ushort_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_pad_putn_ushort_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_pad_putn_ushort_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_pad_putn_ushort_double(void **xpp, MPI_Offset nelems, const double *ip);
+extern int
+ncmpix_pad_putn_ushort_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_pad_putn_ushort_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+/*---- int ------------------------------------------------------------------*/
+extern int
+ncmpix_getn_int_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_getn_int_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_getn_int_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_getn_int_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
+extern int
+ncmpix_getn_int_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_getn_int_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_getn_int_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_getn_long_long (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_getn_int_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_getn_int_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_getn_int_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_getn_int_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_putn_int_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
+extern int
+ncmpix_putn_int_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_putn_int_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_putn_int_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_putn_int_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_putn_int_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_putn_int_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_putn_long_long (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_putn_int_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_putn_int_double(void **xpp, MPI_Offset nelems, const double *ip);
+extern int
+ncmpix_putn_int_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_putn_int_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+/*---- uint -----------------------------------------------------------------*/
+extern int
+ncmpix_getn_uint_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_getn_uint_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_getn_uint_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_getn_uint_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
+extern int
+ncmpix_getn_uint_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_getn_uint_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_getn_uint_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_getn_long_long (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_getn_uint_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_getn_uint_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_getn_uint_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_getn_uint_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_putn_uint_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
+extern int
+ncmpix_putn_uint_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_putn_uint_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_putn_uint_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_putn_uint_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_putn_uint_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_putn_uint_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_putn_long_long (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_putn_uint_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_putn_uint_double(void **xpp, MPI_Offset nelems, const double *ip);
+extern int
+ncmpix_putn_uint_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_putn_uint_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+/*---- float ----------------------------------------------------------------*/
+extern int
+ncmpix_getn_float_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_getn_float_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_getn_float_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_getn_float_ushort(const void **xpp, MPI_Offset nelems, ushort *ip);
+extern int
+ncmpix_getn_float_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_getn_float_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_getn_float_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_getn_float_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_getn_float_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_getn_float_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_getn_float_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_putn_float_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
+extern int
+ncmpix_putn_float_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_putn_float_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_putn_float_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_putn_float_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_putn_float_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_putn_float_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_putn_float_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_putn_float_double(void **xpp, MPI_Offset nelems, const double *ip);
+extern int
+ncmpix_putn_float_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_putn_float_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+/*---- double ---------------------------------------------------------------*/
+extern int
+ncmpix_getn_double_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_getn_double_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_getn_double_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_getn_double_ushort(const void **xpp, MPI_Offset nelems, ushort  *ip);
+extern int
+ncmpix_getn_double_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_getn_double_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_getn_double_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_getn_double_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_getn_double_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_getn_double_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_getn_double_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_putn_double_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
+extern int
+ncmpix_putn_double_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_putn_double_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_putn_double_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_putn_double_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_putn_double_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_putn_double_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_putn_double_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_putn_double_double(void **xpp, MPI_Offset nelems, const double *ip);
+extern int
+ncmpix_putn_double_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_putn_double_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+/*---- int64 ----------------------------------------------------------------*/
+extern int
+ncmpix_getn_int64_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_getn_int64_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_getn_int64_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_getn_int64_ushort(const void **xpp, MPI_Offset nelems, ushort  *ip);
+extern int
+ncmpix_getn_int64_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_getn_int64_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_getn_int64_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_getn_int64_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_getn_int64_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_getn_int64_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_getn_int64_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_putn_int64_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
+extern int
+ncmpix_putn_int64_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_putn_int64_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_putn_int64_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_putn_int64_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_putn_int64_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_putn_int64_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_putn_int64_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_putn_int64_double(void **xpp, MPI_Offset nelems, const double *ip);
+extern int
+ncmpix_putn_int64_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_putn_int64_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+/*---- uint64 ---------------------------------------------------------------*/
+extern int
+ncmpix_getn_uint64_schar (const void **xpp, MPI_Offset nelems, schar  *ip);
+extern int
+ncmpix_getn_uint64_uchar (const void **xpp, MPI_Offset nelems, uchar  *ip);
+extern int
+ncmpix_getn_uint64_short (const void **xpp, MPI_Offset nelems, short  *ip);
+extern int
+ncmpix_getn_uint64_ushort(const void **xpp, MPI_Offset nelems, ushort  *ip);
+extern int
+ncmpix_getn_uint64_int   (const void **xpp, MPI_Offset nelems, int    *ip);
+extern int
+ncmpix_getn_uint64_uint  (const void **xpp, MPI_Offset nelems, uint   *ip);
+extern int
+ncmpix_getn_uint64_long  (const void **xpp, MPI_Offset nelems, long   *ip);
+extern int
+ncmpix_getn_uint64_float (const void **xpp, MPI_Offset nelems, float  *ip);
+extern int
+ncmpix_getn_uint64_double(const void **xpp, MPI_Offset nelems, double *ip);
+extern int
+ncmpix_getn_uint64_longlong (const void **xpp, MPI_Offset nelems, longlong  *ip);
+extern int
+ncmpix_getn_uint64_ulonglong(const void **xpp, MPI_Offset nelems, ulonglong *ip);
+
+extern int
+ncmpix_putn_uint64_schar (void **xpp, MPI_Offset nelems, const schar  *ip);
+extern int
+ncmpix_putn_uint64_uchar (void **xpp, MPI_Offset nelems, const uchar  *ip);
+extern int
+ncmpix_putn_uint64_short (void **xpp, MPI_Offset nelems, const short  *ip);
+extern int
+ncmpix_putn_uint64_ushort(void **xpp, MPI_Offset nelems, const ushort *ip);
+extern int
+ncmpix_putn_uint64_int   (void **xpp, MPI_Offset nelems, const int    *ip);
+extern int
+ncmpix_putn_uint64_uint  (void **xpp, MPI_Offset nelems, const uint   *ip);
+extern int
+ncmpix_putn_uint64_long  (void **xpp, MPI_Offset nelems, const long   *ip);
+extern int
+ncmpix_putn_uint64_float (void **xpp, MPI_Offset nelems, const float  *ip);
+extern int
+ncmpix_putn_uint64_double(void **xpp, MPI_Offset nelems, const double *ip);
+extern int
+ncmpix_putn_uint64_longlong (void **xpp, MPI_Offset nelems, const longlong  *ip);
+extern int
+ncmpix_putn_uint64_ulonglong(void **xpp, MPI_Offset nelems, const ulonglong *ip);
+
+
+/*
+ * Other aggregate conversion functions.
+ */
+
+/* read ASCII characters */
+extern int
+ncmpix_getn_text(const void **xpp, MPI_Offset nchars, char *cp);
+extern int
+ncmpix_pad_getn_text(const void **xpp, MPI_Offset nchars, char *cp);
+
+/* write ASCII characters */
+extern int
+ncmpix_putn_text(void **xpp, MPI_Offset nchars, const char *cp);
+extern int
+ncmpix_pad_putn_text(void **xpp, MPI_Offset nchars, const char *cp);
+
+/* for symmetry */
+#define ncmpix_getn_char_char(xpp, nelems, fillp) ncmpix_getn_text(xpp, nelems, fillp)
+#define ncmpix_putn_char_char(xpp, nelems, fillp) ncmpix_putn_text(xpp, nelems, fillp)
+
+/* read opaque data */
+extern int
+ncmpix_getn_void(const void **xpp, MPI_Offset nchars, void *vp);
+extern int
+ncmpix_pad_getn_void(const void **xpp, MPI_Offset nchars, void *vp);
+
+/* write opaque data */
+extern int
+ncmpix_putn_void(void **xpp, MPI_Offset nchars, const void *vp);
+extern int
+ncmpix_pad_putn_void(void **xpp, MPI_Offset nchars, const void *vp);
+
+#endif /* _NCX_H_ */
diff --git a/src/lib/ncx.m4 b/src/lib/ncx.m4
new file mode 100644
index 0000000..b7b7554
--- /dev/null
+++ b/src/lib/ncx.m4
@@ -0,0 +1,3551 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: ncx.m4 2299 2016-01-09 06:14:37Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mpi.h>
+
+/*
+ * The only error code returned from subroutines in this file is NC_ERANGE,
+ * if errors are detected.
+ */
+
+/*
+ * An external data representation interface.
+ */
+
+#include <string.h>
+#include <limits.h>
+#include "ncx.h"
+#include "nc.h"
+#include "macro.h"
+
+/* alias poorly named limits.h macros */
+#define  SHORT_MAX  SHRT_MAX
+#define  SHORT_MIN  SHRT_MIN
+#define USHORT_MAX USHRT_MAX
+#ifndef LLONG_MAX
+#   define LLONG_MAX	9223372036854775807LL
+#   define LLONG_MIN	(-LLONG_MAX - 1LL)
+#   define ULLONG_MAX	18446744073709551615ULL
+#endif
+#ifndef LONG_LONG_MAX
+#define LONG_LONG_MAX LLONG_MAX
+#endif
+#ifndef LONGLONG_MAX
+#define LONGLONG_MAX LONG_LONG_MAX
+#endif
+#ifndef LONG_LONG_MIN
+#define LONG_LONG_MIN LLONG_MIN
+#endif
+#ifndef LONGLONG_MIN
+#define LONGLONG_MIN LONG_LONG_MIN
+#endif
+#ifndef ULONG_LONG_MAX
+#define ULONG_LONG_MAX ULLONG_MAX
+#endif
+#ifndef ULONGLONG_MAX
+#define ULONGLONG_MAX ULONG_LONG_MAX
+#endif
+#include <float.h>
+#ifndef FLT_MAX /* This POSIX macro missing on some systems */
+# ifndef NO_IEEE_FLOAT
+# define FLT_MAX 3.40282347e+38f
+# else
+# error "You will need to define FLT_MAX"
+# endif
+#endif
+/* alias poorly named float.h macros */
+#define FLOAT_MAX FLT_MAX
+#define FLOAT_MIN (-FLT_MAX)
+#define DOUBLE_MAX DBL_MAX
+#define DOUBLE_MIN (-DBL_MAX)
+#define FLOAT_MAX_EXP FLT_MAX_EXP
+#define DOUBLE_MAX_EXP DBL_MAX_EXP
+#include <assert.h>
+#define UCHAR_MIN 0
+#define Min(a,b) ((a) < (b) ? (a) : (b))
+#define Max(a,b) ((a) > (b) ? (a) : (b))
+
+#ifndef SIZEOF_UCHAR
+#define SIZEOF_UCHAR SIZEOF_UNSIGNED_CHAR
+#endif
+#ifndef SIZEOF_USHORT
+#define SIZEOF_USHORT SIZEOF_UNSIGNED_SHORT_INT
+#endif
+#ifndef SIZEOF_UINT
+#define SIZEOF_UINT SIZEOF_UNSIGNED_INT
+#endif
+#ifndef SIZEOF_LONGLONG
+#define SIZEOF_LONGLONG SIZEOF_LONG_LONG
+#endif
+#ifndef SIZEOF_ULONGLONG
+#define SIZEOF_ULONGLONG SIZEOF_UNSIGNED_LONG_LONG
+#endif
+
+/*
+ * If the machine's float domain is "smaller" than the external one
+ * use the machine domain
+ */
+#if defined(FLT_MAX_EXP) && FLT_MAX_EXP < 128 /* 128 is X_FLT_MAX_EXP */
+#undef X_FLOAT_MAX
+# define X_FLOAT_MAX FLT_MAX
+#undef X_FLOAT_MIN
+# define X_FLOAT_MIN (-X_FLOAT_MAX)
+#endif
+
+#if defined(_SX) && _SX != 0 /* NEC SUPER UX */
+#define LOOPCNT 256    /* must be no longer than hardware vector length */
+#if _INT64
+#undef  INT_MAX /* workaround cpp bug */
+#define INT_MAX  X_INT_MAX
+#undef  INT_MIN /* workaround cpp bug */
+#define INT_MIN  X_INT_MIN
+#undef  LONG_MAX /* workaround cpp bug */
+#define LONG_MAX  X_INT_MAX
+#undef  LONG_MIN /* workaround cpp bug */
+#define LONG_MIN  X_INT_MIN
+#elif _LONG64
+#undef  LONG_MAX /* workaround cpp bug */
+#define LONG_MAX  4294967295L
+#undef  LONG_MIN /* workaround cpp bug */
+#define LONG_MIN -4294967295L
+#endif
+#if !_FLOAT0
+#error "FLOAT1 and FLOAT2 not supported"
+#endif
+#endif /* _SX */
+
+static const char nada[X_ALIGN] = {0, 0, 0, 0};
+
+#ifndef WORDS_BIGENDIAN
+/* LITTLE_ENDIAN: DEC and intel */
+/*
+ * Routines to convert to BIG ENDIAN.
+ * Optimize the swapn?b() and swap?b() routines aggressively.
+ */
+
+#define SWAP2(a) ( (((a) & 0xff) << 8) | \
+		(((a) >> 8) & 0xff) )
+
+#define SWAP4(a) ( ((a) << 24) | \
+		(((a) <<  8) & 0x00ff0000) | \
+		(((a) >>  8) & 0x0000ff00) | \
+		(((a) >> 24) & 0x000000ff) )
+
+
+static void
+swapn2b(void *dst, const void *src, MPI_Offset nn)
+{
+	char *op = dst;
+	const char *ip = src;
+
+/* unroll the following to reduce loop overhead
+ *
+ *	while (nn-- > 0)
+ *	{
+ *		*op++ = *(++ip);
+ *		*op++ = *(ip++ -1);
+ *	}
+ */
+	while (nn > 3)
+	{
+		*op++ = *(++ip);
+		*op++ = *(ip++ -1);
+		*op++ = *(++ip);
+		*op++ = *(ip++ -1);
+		*op++ = *(++ip);
+		*op++ = *(ip++ -1);
+		*op++ = *(++ip);
+		*op++ = *(ip++ -1);
+		nn -= 4;
+	}
+	while (nn-- > 0)
+	{
+		*op++ = *(++ip);
+		*op++ = *(ip++ -1);
+	}
+}
+
+# ifndef vax
+static void
+swap4b(void *dst, const void *src)
+{
+	char *op = dst;
+	const char *ip = src;
+	op[0] = ip[3];
+	op[1] = ip[2];
+	op[2] = ip[1];
+	op[3] = ip[0];
+
+/* We can use bitwise operations as below.
+   Here, unsigned int must be of size 4 bytes.
+
+    unsigned int *cp = (unsigned int *) dst;
+    unsigned int *ip = (unsigned int *) src;
+
+    *cp =  ((*ip) << 24)
+        | (((*ip) & 0x0000ff00) << 8)
+        | (((*ip) & 0x00ff0000) >> 8)
+        | (((*ip) >> 24));
+*/
+}
+# endif /* !vax */
+
+static void
+swapn4b(void *dst, const void *src, MPI_Offset nn)
+{
+	char *op = dst;
+	const char *ip = src;
+
+/* unroll the following to reduce loop overhead
+ *	while (nn-- > 0)
+ *	{
+ *		op[0] = ip[3];
+ *		op[1] = ip[2];
+ *		op[2] = ip[1];
+ *		op[3] = ip[0];
+ *		op += 4;
+ *		ip += 4;
+ *	}
+ */
+	while (nn > 3)
+	{
+		op[0] = ip[3];
+		op[1] = ip[2];
+		op[2] = ip[1];
+		op[3] = ip[0];
+		op[4] = ip[7];
+		op[5] = ip[6];
+		op[6] = ip[5];
+		op[7] = ip[4];
+		op[8] = ip[11];
+		op[9] = ip[10];
+		op[10] = ip[9];
+		op[11] = ip[8];
+		op[12] = ip[15];
+		op[13] = ip[14];
+		op[14] = ip[13];
+		op[15] = ip[12];
+		op += 16;
+		ip += 16;
+		nn -= 4;
+	}
+	while (nn-- > 0)
+	{
+		op[0] = ip[3];
+		op[1] = ip[2];
+		op[2] = ip[1];
+		op[3] = ip[0];
+		op += 4;
+		ip += 4;
+	}
+}
+
+# ifndef vax
+static void
+swap8b(void *dst, const void *src)
+{
+	char *op = dst;
+	const char *ip = src;
+#  ifndef FLOAT_WORDS_BIGENDIAN
+	op[0] = ip[7];
+	op[1] = ip[6];
+	op[2] = ip[5];
+	op[3] = ip[4];
+	op[4] = ip[3];
+	op[5] = ip[2];
+	op[6] = ip[1];
+	op[7] = ip[0];
+#  else
+	op[0] = ip[3];
+	op[1] = ip[2];
+	op[2] = ip[1];
+	op[3] = ip[0];
+	op[4] = ip[7];
+	op[5] = ip[6];
+	op[6] = ip[5];
+	op[7] = ip[4];
+#endif
+}
+# endif /* !vax */
+
+# ifndef vax
+static void
+swapn8b(void *dst, const void *src, MPI_Offset nn)
+{
+	char *op = dst;
+	const char *ip = src;
+
+/* unroll the following to reduce loop overhead
+ *	while (nn-- > 0)
+ *	{
+ *		op[0] = ip[7];
+ *		op[1] = ip[6];
+ *		op[2] = ip[5];
+ *		op[3] = ip[4];
+ *		op[4] = ip[3];
+ *		op[5] = ip[2];
+ *		op[6] = ip[1];
+ *		op[7] = ip[0];
+ *		op += 8;
+ *		ip += 8;
+ *	}
+ */
+#  ifndef FLOAT_WORDS_BIGENDIAN
+	while (nn > 1)
+	{
+		op[0] = ip[7];
+		op[1] = ip[6];
+		op[2] = ip[5];
+		op[3] = ip[4];
+		op[4] = ip[3];
+		op[5] = ip[2];
+		op[6] = ip[1];
+		op[7] = ip[0];
+		op[8] = ip[15];
+		op[9] = ip[14];
+		op[10] = ip[13];
+		op[11] = ip[12];
+		op[12] = ip[11];
+		op[13] = ip[10];
+		op[14] = ip[9];
+		op[15] = ip[8];
+		op += 16;
+		ip += 16;
+		nn -= 2;
+	}
+	while (nn-- > 0)
+	{
+		op[0] = ip[7];
+		op[1] = ip[6];
+		op[2] = ip[5];
+		op[3] = ip[4];
+		op[4] = ip[3];
+		op[5] = ip[2];
+		op[6] = ip[1];
+		op[7] = ip[0];
+		op += 8;
+		ip += 8;
+	}
+#  else
+	while (nn-- > 0)
+	{
+		op[0] = ip[3];
+		op[1] = ip[2];
+		op[2] = ip[1];
+		op[3] = ip[0];
+		op[4] = ip[7];
+		op[5] = ip[6];
+		op[6] = ip[5];
+		op[7] = ip[4];
+		op += 8;
+		ip += 8;
+	}
+#endif
+}
+# endif /* !vax */
+
+#endif /* LITTLE_ENDIAN */
+
+dnl dnl dnl
+dnl
+dnl Upcase(str)
+dnl
+define(`Upcase',dnl
+`dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)')dnl
+dnl
+dnl dnl dnl
+dnl
+define(`Isizeof',     ``SIZEOF_'Upcase($1)')dnl
+define(`Xsizeof',   ``X_SIZEOF_'Upcase($1)')dnl
+define(`IXsizeof', ``SIZEOF_IX_'Upcase($1)')dnl
+define(`Imax',                 `Upcase($1)`_MAX'')dnl
+define(`Imin',                 `Upcase($1)`_MIN'')dnl
+define(`Xmax',             ``X_'Upcase($1)`_MAX'')dnl
+define(`Xmin',             ``X_'Upcase($1)`_MIN'')dnl
+define(`IXmax',           ``IX_'Upcase($1)`_MAX'')dnl
+dnl
+define(`Fmin',  `ifelse(index(`$1',`u'), 0, `0', `(double)Imin($1)')')dnl
+define(`Dmin',  `ifelse(index(`$1',`u'), 0, `0', `(double)Imin($1)')')dnl
+define(`FXmin', `ifelse(index(`$1',`u'), 0, `0', `(double)Xmin($1)')')dnl
+define(`DXmin', `ifelse(index(`$1',`u'), 0, `0',         `Xmin($1)')')dnl
+
+dnl
+dnl For GET APIs:
+dnl       check for negative $3 if $1 is   signed && $2 is unsigned
+dnl Don't check for negative $3 if $1 is   signed && $2 is   signed
+dnl Don't check for negative $3 if $1 is unsigned
+dnl $5 is either "return" or "status ="
+dnl
+define(`GETI_CheckNegReturn',
+       `ifelse(index(`$1',`u'), 0, ,
+               index(`$2',`u'), 0,
+               `if ($3 < 0) DEBUG_RETURN_ERROR(NC_ERANGE) /* because $4 is unsigned */')')dnl
+
+define(`GETI_CheckNegAssign',
+       `ifelse(index(`$1',`u'), 0, ,
+               index(`$2',`u'), 0,
+               `if ($3 < 0) DEBUG_ASSIGN_ERROR(status, NC_ERANGE) /* because $4 is unsigned */')')dnl
+
+define(`Cast_Signed2Unsigned',
+       `ifelse(index(`$1',`u'), 0,
+               `ifelse(index(`$2',`u'), 0, , `(signed)')')')dnl
+
+dnl
+dnl For PUT APIs:
+dnl       check for negative $3 if $1 is unsigned && $2 is   signed
+dnl Don't check for negative $3 if $1 is unsigned && $2 is unsigned
+dnl Don't check for negative $3 if $1 is   signed
+dnl
+define(`PUTI_CheckNeg',
+       `ifelse(index(`$1',`u'), 0,
+               `ifelse(index(`$2',`u'), 0, ,
+                       `	if ($3 < 0) DEBUG_RETURN_ERROR(NC_ERANGE) /* because $4 is unsigned */')')')dnl
+
+dnl
+dnl For GET APIs boundary check
+dnl
+define(`GETF_CheckBND',
+`if (xx > (double)Upcase($1)_MAX || xx < Dmin($1)) DEBUG_RETURN_ERROR(NC_ERANGE)
+	*ip = ($1)xx;')
+
+dnl
+dnl For GET APIs boudnary check for when $1 is either 'longlong' or 'ulonglong'
+dnl
+define(`GETF_CheckBND2',
+       `ifelse(index(`$1',`u'), 0,
+`if (xx == Upcase($1)_MAX)      *ip = Upcase($1)_MAX;',dnl for unsigned type
+`if (xx == Upcase($1)_MAX)      *ip = Upcase($1)_MAX;
+	else if (xx == Upcase($1)_MIN) *ip = Upcase($1)_MIN;')
+	else if (xx > (double)Upcase($1)_MAX || xx < Dmin($1)) DEBUG_RETURN_ERROR(NC_ERANGE)
+	else *ip = ($1)xx;')
+
+dnl
+dnl For PUT APIs and either $1 and $2 is float or double:
+dnl
+define(`PUTF_CheckBND',
+`ifelse(`$2', `double', `if (*ip > Xmax($1) || *ip < DXmin($1)) DEBUG_RETURN_ERROR(NC_ERANGE)',
+        `$2', `float',  `if (*ip > (double)Xmax($1) || *ip < FXmin($1)) DEBUG_RETURN_ERROR(NC_ERANGE)')')
+
+dnl
+dnl For GET APIs and $1 and $2 are not float or double
+dnl
+define(`GETI_CheckBND',
+``#'if IXmax($1) > Imax($2)
+	if (xx > Imax($2)'`ifelse(index(`$1',`u'), 0, ,
+                                  index(`$2',`u'), 0, ,
+                                  ` || xx < Imin($2)')'`) DEBUG_RETURN_ERROR(NC_ERANGE)'
+`#'endif)
+
+dnl
+dnl For PUT APIs and $1 and $2 are not float or double
+dnl
+define(`PUTI_CheckBND',
+``#'if IXmax($1) < Imax($2)
+	if (*ip > IXmax($1)'`ifelse(index(`$1',`u'), 0, ,
+                                    index(`$2',`u'), 0, ,
+                                    ` || *ip < Xmin($1)')'`) DEBUG_RETURN_ERROR(NC_ERANGE)'
+`#'endif)
+
+/*
+ * Primitive numeric conversion functions.
+ */
+
+dnl dnl dnl
+dnl
+dnl NCX_GET1F(xtype, itype) for floating-point types
+dnl
+define(`NCX_GET1F',dnl
+`dnl
+static int
+ncmpix_get_$1_$2(const void *xp, $2 *ip)
+{
+	ix_$1 xx;
+	get_ix_$1(xp, &xx);
+	ifelse(`$1', `float',  `ifelse(`$2',  `longlong', GETF_CheckBND2($2),
+	                               `$2', `ulonglong', GETF_CheckBND2($2),
+	                               `$2',    `double', `*ip = ($2)xx;',
+				                          GETF_CheckBND($2))',
+	       `$1', `double', `ifelse(`$2',  `longlong', GETF_CheckBND2($2),
+	                               `$2', `ulonglong', GETF_CheckBND2($2),
+				                          GETF_CheckBND($2))',
+	       `*ip = ($2)xx;')
+	return NC_NOERR;
+}
+')dnl
+
+dnl dnl dnl
+dnl
+dnl NCX_GET1I(xtype, itype, isComptable) for integral types
+dnl
+define(`NCX_GET1I',dnl
+`dnl
+static int
+ncmpix_get_$1_$2(const void *xp, $2 *ip)
+{
+ifelse(`$3', `1',
+``#'if IXsizeof($1) == Isizeof($2) && IXmax($1) == Upcase($2)_MAX
+	get_ix_$1(xp, (ix_$1 *)ip);
+`#'else
+')dnl
+	ix_$1 xx;
+	get_ix_$1(xp, &xx);
+GETI_CheckBND($1, $2)
+	GETI_CheckNegReturn($1, $2, xx, ip)
+	*ip = ($2) xx;
+ifelse(`$3', `1', ``#'endif
+')dnl
+	return NC_NOERR;
+}
+')dnl
+
+dnl dnl dnl
+dnl
+dnl NCX_PUT1F(xtype, itype) for floating-point types
+dnl
+define(`NCX_PUT1F',dnl
+`dnl
+static int
+ncmpix_put_$1_$2(void *xp, const $2 *ip)
+{
+	ix_$1 xx;
+	PUTF_CheckBND($1, $2)
+	xx = (ix_$1)*ip;
+	put_ix_$1(xp, &xx);
+	return NC_NOERR;
+}
+')dnl
+
+dnl dnl dnl
+dnl
+dnl NCX_PUT1I(xtype, itype, isComptable) for integral types
+dnl
+define(`NCX_PUT1I',dnl
+`dnl
+static int
+ncmpix_put_$1_$2(void *xp, const $2 *ip)
+{
+ifelse(`$3', `1',
+``#'if IXsizeof($1) == Isizeof($2) && IXmax($1) == Upcase($2)_MAX
+	put_ix_$1(xp, (const ix_$1 *)ip);
+`#'else
+')dnl
+	ix_$1 xx;
+PUTI_CheckBND($1, $2)
+PUTI_CheckNeg($1, $2, *ip, xp)
+	xx = (ix_$1)*ip;
+	put_ix_$1(xp, &xx);
+ifelse(`$3', `1', ``#'endif
+')dnl
+	return NC_NOERR;
+}
+')dnl
+
+/* x_schar */
+/* x_uchar */
+
+/* We don't implement any x_schar and x_uchar primitives. */
+
+
+/* x_short -------------------------------------------------------------------*/
+
+#if SHORT_MAX == X_SHORT_MAX
+typedef short ix_short;
+#define SIZEOF_IX_SHORT SIZEOF_SHORT
+#define IX_SHORT_MAX SHORT_MAX
+#elif INT_MAX >= X_SHORT_MAX
+typedef int ix_short;
+#define SIZEOF_IX_SHORT SIZEOF_INT
+#define IX_SHORT_MAX INT_MAX
+#elif LONG_MAX >= X_SHORT_MAX
+typedef long ix_short;
+#define SIZEOF_IX_SHORT SIZEOF_LONG
+#define IX_SHORT_MAX LONG_MAX
+#elif LLONG_MAX >= X_SHORT_MAX
+typedef long long ix_short;
+#define SIZEOF_IX_SHORT SIZEOF_LONGLONG
+#define IX_SHORT_MAX LLONG_MAX
+#else
+#error "ix_short implementation"
+#endif
+
+static void
+get_ix_short(const void *xp, ix_short *ip)
+{
+	const uchar *cp = (const uchar *) xp;
+	*ip = *cp++ << 8;
+#if SIZEOF_IX_SHORT > X_SIZEOF_SHORT
+	if (*ip & 0x8000)
+	{
+		/* extern is negative */
+		*ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */
+	}
+#endif
+	*ip |= *cp;
+}
+
+static void
+put_ix_short(void *xp, const ix_short *ip)
+{
+	uchar *cp = (uchar *) xp;
+	*cp++ = (*ip) >> 8;
+	*cp = (*ip) & 0xff;
+}
+
+NCX_GET1I(short, schar,     0)
+NCX_GET1I(short, short,     1)
+NCX_GET1I(short, int,       1)
+NCX_GET1I(short, long,      1)
+NCX_GET1I(short, longlong,  1)
+NCX_GET1I(short, ushort,    0)
+NCX_GET1I(short, uchar,     0)
+NCX_GET1I(short, uint,      0)
+NCX_GET1I(short, ulonglong, 0)
+NCX_GET1F(short, float)
+NCX_GET1F(short, double)
+
+static int
+ncmpix_put_short_schar(void *xp, const schar *ip)
+{
+	uchar *cp = (uchar *) xp;
+	if (*ip & 0x80)
+		*cp++ = 0xff;
+	else
+		*cp++ = 0;
+	*cp = (uchar)*ip;
+	return NC_NOERR;
+}
+
+static int
+ncmpix_put_short_uchar(void *xp, const uchar *ip)
+{
+	uchar *cp = (uchar *) xp;
+	*cp++ = 0;
+	*cp = *ip;
+	return NC_NOERR;
+}
+
+NCX_PUT1I(short, short,     1)
+NCX_PUT1I(short, int,       1)
+NCX_PUT1I(short, long,      1)
+NCX_PUT1I(short, longlong,  1)
+NCX_PUT1I(short, ushort,    0)
+NCX_PUT1I(short, uint,      0)
+NCX_PUT1I(short, ulonglong, 0)
+NCX_PUT1F(short, float)
+NCX_PUT1F(short, double)
+
+/* x_ushort ------------------------------------------------------------------*/
+
+#if USHORT_MAX == X_USHORT_MAX
+typedef unsigned short ix_ushort;
+#define SIZEOF_IX_USHORT SIZEOF_USHORT
+#define IX_USHORT_MAX USHORT_MAX
+#elif UINT_MAX >= X_USHORT_MAX
+typedef unsigned int ix_ushort;
+#define SIZEOF_IX_USHORT SIZEOF_UINT
+#define IX_USHORT_MAX UINT_MAX
+#elif ULONG_MAX >= X_USHORT_MAX
+typedef unsigned long ix_ushort;
+#define SIZEOF_IX_USHORT SIZEOF_ULONG
+#define IX_USHORT_MAX ULONG_MAX
+#elif ULLONG_MAX >= X_USHORT_MAX
+typedef unsigned long long ix_ushort;
+#define SIZEOF_IX_USHORT SIZEOF_ULONGLONG
+#define IX_USHORT_MAX ULLONG_MAX
+#else
+#error "ix_ushort implementation"
+#endif
+
+static void
+get_ix_ushort(const void *xp, ix_ushort *ip)
+{
+	const uchar *cp = (const uchar *) xp;
+	*ip = *cp++ << 8;
+#if SIZEOF_IX_SHORT > X_SIZEOF_SHORT
+	if (*ip & 0x8000)
+	{
+		/* extern is negative */
+		*ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */
+	}
+#endif
+	*ip |= *cp;
+}
+
+static void
+put_ix_ushort(void *xp, const ix_ushort *ip)
+{
+	uchar *cp = (uchar *) xp;
+	*cp++ = (*ip) >> 8;
+	*cp = (*ip) & 0xff;
+}
+
+NCX_GET1I(ushort, schar,     0)
+NCX_GET1I(ushort, short,     0)
+NCX_GET1I(ushort, int,       0)
+NCX_GET1I(ushort, long,      0)
+NCX_GET1I(ushort, longlong,  0)
+NCX_GET1I(ushort, ushort,    1)
+NCX_GET1I(ushort, uchar,     1)
+NCX_GET1I(ushort, uint,      1)
+NCX_GET1I(ushort, ulonglong, 1)
+NCX_GET1F(ushort, float)
+NCX_GET1F(ushort, double)
+
+static int
+ncmpix_put_ushort_schar(void *xp, const schar *ip)
+{
+	uchar *cp;
+        if (*ip < 0) DEBUG_RETURN_ERROR(NC_ERANGE)
+	cp = (uchar *) xp;
+	if (*ip & 0x80)
+		*cp++ = 0xff;
+	else
+		*cp++ = 0;
+	*cp = (uchar)*ip;
+
+	return NC_NOERR;
+}
+
+static int
+ncmpix_put_ushort_uchar(void *xp, const uchar *ip)
+{
+	uchar *cp = (uchar *) xp;
+	*cp++ = 0;
+	*cp = *ip;
+	return NC_NOERR;
+}
+
+NCX_PUT1I(ushort, short,     0)
+NCX_PUT1I(ushort, int,       0)
+NCX_PUT1I(ushort, long,      0)
+NCX_PUT1I(ushort, longlong,  0)
+NCX_PUT1I(ushort, ushort,    1)
+NCX_PUT1I(ushort, uint,      1)
+NCX_PUT1I(ushort, ulonglong, 1)
+NCX_PUT1F(ushort, float)
+NCX_PUT1F(ushort, double)
+
+/* x_int ---------------------------------------------------------------------*/
+
+#if SHORT_MAX == X_INT_MAX
+typedef short ix_int;
+#define SIZEOF_IX_INT SIZEOF_SHORT
+#define IX_INT_MAX SHORT_MAX
+#elif INT_MAX  >= X_INT_MAX
+typedef int ix_int;
+#define SIZEOF_IX_INT SIZEOF_INT
+#define IX_INT_MAX INT_MAX
+#elif LONG_MAX  >= X_INT_MAX
+typedef long ix_int;
+#define SIZEOF_IX_INT SIZEOF_LONG
+#define IX_INT_MAX LONG_MAX
+#else
+#error "ix_int implementation"
+#endif
+
+
+static void
+get_ix_int(const void *xp, ix_int *ip)
+{
+	const uchar *cp = (const uchar *) xp;
+
+	*ip = *cp++ << 24;
+#if SIZEOF_IX_INT > X_SIZEOF_INT
+	if (*ip & 0x80000000)
+	{
+		/* extern is negative */
+		*ip |= (~(0xffffffff)); /* N.B. Assumes "twos complement" */
+	}
+#endif
+	*ip |= (*cp++ << 16);
+	*ip |= (*cp++ << 8);
+	*ip |= *cp;
+}
+
+static void
+put_ix_int(void *xp, const ix_int *ip)
+{
+	uchar *cp = (uchar *) xp;
+
+	*cp++ = (*ip) >> 24;
+	*cp++ = ((*ip) & 0x00ff0000) >> 16;
+	*cp++ = ((*ip) & 0x0000ff00) >>  8;
+	*cp   = ((*ip) & 0x000000ff);
+}
+
+#if X_SIZEOF_INT != SIZEOF_INT
+NCX_GET1I(int, int,       1)
+#endif
+NCX_GET1I(int, schar,     0)
+NCX_GET1I(int, short,     1)
+NCX_GET1I(int, long,      1)
+NCX_GET1I(int, longlong,  1)
+NCX_GET1I(int, ushort,    0)
+NCX_GET1I(int, uchar,     0)
+NCX_GET1I(int, uint,      0)
+NCX_GET1I(int, ulonglong, 0)
+NCX_GET1F(int, float)
+NCX_GET1F(int, double)
+
+static int
+ncmpix_put_int_schar(void *xp, const schar *ip)
+{
+	uchar *cp = (uchar *) xp;
+	if (*ip & 0x80)
+	{
+		*cp++ = 0xff;
+		*cp++ = 0xff;
+		*cp++ = 0xff;
+	}
+	else
+	{
+		*cp++ = 0x00;
+		*cp++ = 0x00;
+		*cp++ = 0x00;
+	}
+	*cp = (uchar)*ip;
+	return NC_NOERR;
+}
+
+static int
+ncmpix_put_int_uchar(void *xp, const uchar *ip)
+{
+	uchar *cp = (uchar *) xp;
+	*cp++ = 0x00;
+	*cp++ = 0x00;
+	*cp++ = 0x00;
+	*cp   = *ip;
+	return NC_NOERR;
+}
+
+#if X_SIZEOF_INT != SIZEOF_INT
+NCX_PUT1I(int, int,       1)
+#endif
+NCX_PUT1I(int, short,     1)
+NCX_PUT1I(int, long,      1)
+NCX_PUT1I(int, longlong,  1)
+NCX_PUT1I(int, ushort,    0)
+NCX_PUT1I(int, uint,      0)
+NCX_PUT1I(int, ulonglong, 0)
+NCX_PUT1F(int, float)
+NCX_PUT1F(int, double)
+
+
+/* x_uint --------------------------------------------------------------------*/
+
+#if USHORT_MAX == X_UINT_MAX
+typedef ushort ix_uint;
+#define SIZEOF_IX_UINT SIZEOF_USHORT
+#define IX_UINT_MAX USHORT_MAX
+#elif UINT_MAX  >= X_UINT_MAX
+typedef uint ix_uint;
+#define SIZEOF_IX_UINT SIZEOF_UINT
+#define IX_UINT_MAX UINT_MAX
+#elif ULONG_MAX  >= X_UINT_MAX
+typedef ulong ix_uint;
+#define SIZEOF_IX_UINT SIZEOF_ULONG
+#define IX_UINT_MAX ULONG_MAX
+#else
+#error "ix_uint implementation"
+#endif
+
+
+static void
+get_ix_uint(const void *xp, ix_uint *ip)
+{
+	const uchar *cp = (const uchar *) xp;
+
+	*ip  = (ix_uint)(*cp++ << 24);
+	*ip |= (ix_uint)(*cp++ << 16);
+	*ip |= (ix_uint)(*cp++ << 8);
+	*ip |= *cp;
+}
+
+static void
+put_ix_uint(void *xp, const ix_uint *ip)
+{
+	uchar *cp = (uchar *) xp;
+
+	*cp++ = (*ip) >> 24;
+	*cp++ = ((*ip) & 0x00ff0000) >> 16;
+	*cp++ = ((*ip) & 0x0000ff00) >>  8;
+	*cp   = ((*ip) & 0x000000ff);
+}
+
+#if X_SIZEOF_UINT != SIZEOF_UINT
+NCX_GET1I(uint, uint,      1)
+#endif
+
+NCX_GET1I(uint, schar,     0)
+NCX_GET1I(uint, short,     0)
+NCX_GET1I(uint, int,       0)
+NCX_GET1I(uint, long,      0)
+NCX_GET1I(uint, longlong,  0)
+NCX_GET1I(uint, ushort,    1)
+NCX_GET1I(uint, uchar,     1)
+NCX_GET1I(uint, ulonglong, 1)
+NCX_GET1F(uint, float)
+NCX_GET1F(uint, double)
+
+static int
+ncmpix_put_uint_schar(void *xp, const schar *ip)
+{
+	uchar *cp;
+	if (*ip < 0) DEBUG_RETURN_ERROR(NC_ERANGE)
+
+	cp = (uchar *) xp;
+	*cp++ = 0x00;
+	*cp++ = 0x00;
+	*cp++ = 0x00;
+	*cp = (uchar)*ip;
+
+	return NC_NOERR;
+}
+
+static int
+ncmpix_put_uint_uchar(void *xp, const uchar *ip)
+{
+	uchar *cp = (uchar *) xp;
+	*cp++ = 0x00;
+	*cp++ = 0x00;
+	*cp++ = 0x00;
+	*cp   = *ip;
+	return NC_NOERR;
+}
+
+#if X_SIZEOF_UINT != SIZEOF_UINT
+NCX_PUT1I(uint, uint,      1)
+#endif
+
+NCX_PUT1I(uint, short,     0)
+NCX_PUT1I(uint, int,       0)
+NCX_PUT1I(uint, long,      0)
+NCX_PUT1I(uint, longlong,  0)
+NCX_PUT1I(uint, ushort,    1)
+NCX_PUT1I(uint, ulonglong, 1)
+NCX_PUT1F(uint, float)
+NCX_PUT1F(uint, double)
+
+
+/* x_float -------------------------------------------------------------------*/
+
+#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)
+
+static void
+get_ix_float(const void *xp, float *ip)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(ip, xp, SIZEOF_FLOAT);
+#else
+	swap4b(ip, xp);
+#endif
+}
+
+static void
+put_ix_float(void *xp, const float *ip)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(xp, ip, X_SIZEOF_FLOAT);
+#else
+	swap4b(xp, ip);
+#endif
+}
+
+#elif defined(vax) && vax != 0
+
+/* What IEEE single precision floating point looks like on a Vax */
+struct	ieee_single {
+	unsigned int	exp_hi       : 7;
+	unsigned int	sign         : 1;
+	unsigned int 	mant_hi      : 7;
+	unsigned int	exp_lo       : 1;
+	unsigned int	mant_lo_hi   : 8;
+	unsigned int	mant_lo_lo   : 8;
+};
+
+/* Vax single precision floating point */
+struct	vax_single {
+	unsigned int	mantissa1 : 7;
+	unsigned int	exp       : 8;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 16;
+};
+
+#define VAX_SNG_BIAS	0x81
+#define IEEE_SNG_BIAS	0x7f
+
+static struct sgl_limits {
+	struct vax_single s;
+	struct ieee_single ieee;
+} max = {
+	{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
+	{ 0x7f, 0x0, 0x0, 0x1, 0x0, 0x0 }		/* Max IEEE */
+};
+static struct sgl_limits min = {
+	{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
+	{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }		/* Min IEEE */
+};
+
+dnl dnl dnl
+dnl
+dnl GET_VAX_DFLOAT_Body(xp) (body for get_ix_float)
+dnl
+define(`GET_VAX_DFLOAT_Body',dnl
+`dnl
+		struct vax_single *const vsp = (struct vax_single *) ip;
+		const struct ieee_single *const isp =
+			 (const struct ieee_single *) $1;
+		unsigned exp = isp->exp_hi << 1 | isp->exp_lo;
+
+		switch(exp) {
+		case 0 :
+			/* ieee subnormal */
+			if (isp->mant_hi == min.ieee.mant_hi
+				&& isp->mant_lo_hi == min.ieee.mant_lo_hi
+				&& isp->mant_lo_lo == min.ieee.mant_lo_lo)
+			{
+				*vsp = min.s;
+			}
+			else
+			{
+				unsigned mantissa = (isp->mant_hi << 16)
+					 | isp->mant_lo_hi << 8
+					 | isp->mant_lo_lo;
+				unsigned tmp = mantissa >> 20;
+				if (tmp >= 4) {
+					vsp->exp = 2;
+				} else if (tmp >= 2) {
+					vsp->exp = 1;
+				} else {
+					*vsp = min.s;
+					break;
+				} /* else */
+				tmp = mantissa - (1 << (20 + vsp->exp ));
+				tmp <<= 3 - vsp->exp;
+				vsp->mantissa2 = tmp;
+				vsp->mantissa1 = (tmp >> 16);
+			}
+			break;
+		case 0xfe :
+		case 0xff :
+			*vsp = max.s;
+			break;
+		default :
+			vsp->exp = exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
+			vsp->mantissa2 = isp->mant_lo_hi << 8 | isp->mant_lo_lo;
+			vsp->mantissa1 = isp->mant_hi;
+		}
+
+		vsp->sign = isp->sign;
+')dnl
+static void
+get_ix_float(const void *xp, float *ip)
+{
+GET_VAX_DFLOAT_Body(xp)
+}
+
+dnl dnl dnl
+dnl
+dnl PUT_VAX_DFLOAT_Body(xp) (body for get_ix_float)
+dnl
+define(`PUT_VAX_DFLOAT_Body',dnl
+`dnl
+		const struct vax_single *const vsp =
+			 (const struct vax_single *)ip;
+		struct ieee_single *const isp = (struct ieee_single *) $1;
+
+		switch(vsp->exp){
+		case 0 :
+			/* all vax float with zero exponent map to zero */
+			*isp = min.ieee;
+			break;
+		case 2 :
+		case 1 :
+		{
+			/* These will map to subnormals */
+			unsigned mantissa = (vsp->mantissa1 << 16)
+					 | vsp->mantissa2;
+			mantissa >>= 3 - vsp->exp;
+			mantissa += (1 << (20 + vsp->exp));
+			isp->mant_lo_lo = mantissa;
+			isp->mant_lo_hi = mantissa >> 8;
+			isp->mant_hi = mantissa >> 16;
+			isp->exp_lo = 0;
+			isp->exp_hi = 0;
+		}
+			break;
+		case 0xff : /* max.s.exp */
+			if (vsp->mantissa2 == max.s.mantissa2 &&
+			    vsp->mantissa1 == max.s.mantissa1)
+			{
+				/* map largest vax float to ieee infinity */
+				*isp = max.ieee;
+				break;
+			} /* else, fall thru */
+		default :
+		{
+			unsigned exp = vsp->exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
+			isp->exp_hi = exp >> 1;
+			isp->exp_lo = exp;
+			isp->mant_lo_lo = vsp->mantissa2;
+			isp->mant_lo_hi = vsp->mantissa2 >> 8;
+			isp->mant_hi = vsp->mantissa1;
+		}
+		}
+
+		isp->sign = vsp->sign;
+')dnl
+
+static void
+put_ix_float(void *xp, const float *ip)
+{
+PUT_VAX_DFLOAT_Body(xp)
+}
+
+	/* vax */
+#elif defined(_CRAY) && !defined(__crayx1)
+
+/*
+ * Return the number of bytes until the next "word" boundary
+ * N.B. This is based on the very weird YMP address structure,
+ * which puts the address within a word in the leftmost 3 bits
+ * of the address.
+ */
+static size_t
+word_align(const void *vp)
+{
+	const size_t rem = ((size_t)vp >> (64 - 3)) & 0x7;
+	return (rem != 0);
+}
+
+struct ieee_single_hi {
+	unsigned int	sign	: 1;
+	unsigned int	 exp	: 8;
+	unsigned int	mant	:23;
+	unsigned int	pad	:32;
+};
+typedef struct ieee_single_hi ieee_single_hi;
+
+struct ieee_single_lo {
+	unsigned int	pad	:32;
+	unsigned int	sign	: 1;
+	unsigned int	 exp	: 8;
+	unsigned int	mant	:23;
+};
+typedef struct ieee_single_lo ieee_single_lo;
+
+static const int ieee_single_bias = 0x7f;
+
+struct ieee_double {
+	unsigned int	sign	: 1;
+	unsigned int	 exp	:11;
+	unsigned int	mant	:52;
+};
+typedef struct ieee_double ieee_double;
+
+static const int ieee_double_bias = 0x3ff;
+
+#if defined(NO_IEEE_FLOAT)
+
+struct cray_single {
+	unsigned int	sign	: 1;
+	unsigned int	 exp	:15;
+	unsigned int	mant	:48;
+};
+typedef struct cray_single cray_single;
+
+static const int cs_ieis_bias = 0x4000 - 0x7f;
+
+static const int cs_id_bias = 0x4000 - 0x3ff;
+
+dnl dnl dnl
+dnl
+dnl GET_IX_FLOAT_Body (body for get_ix_float)
+dnl
+define(`GET_IX_FLOAT_Body',dnl
+`dnl
+		cray_single *csp = (cray_single *) ip;
+
+		if (isp->exp == 0)
+		{
+			/* ieee subnormal */
+			*ip = (double)isp->mant;
+			if (isp->mant != 0)
+			{
+				csp->exp -= (ieee_single_bias + 22);
+			}
+		}
+		else
+		{
+			csp->exp  = isp->exp + cs_ieis_bias + 1;
+			csp->mant = isp->mant << (48 - 1 - 23);
+			csp->mant |= (1 << (48 - 1));
+		}
+		csp->sign = isp->sign;
+
+')dnl
+dnl dnl dnl
+dnl
+dnl PUT_IX_FLOAT_Body (body for put_ix_float)
+dnl
+define(`PUT_IX_FLOAT_Body',dnl
+`dnl
+	const cray_single *csp = (const cray_single *) ip;
+	int ieee_exp = csp->exp - cs_ieis_bias -1;
+
+	isp->sign = csp->sign;
+
+	if (ieee_exp >= 0xff)
+	{
+		/* NC_ERANGE => ieee Inf */
+		isp->exp = 0xff;
+		isp->mant = 0x0;
+	}
+	else if (ieee_exp > 0)
+	{
+		/* normal ieee representation */
+		isp->exp  = ieee_exp;
+		/* assumes cray rep is in normal form */
+		assert(csp->mant & 0x800000000000);
+		isp->mant = (((csp->mant << 1) &
+				0xffffffffffff) >> (48 - 23));
+	}
+	else if (ieee_exp > -23)
+	{
+		/* ieee subnormal, right shift */
+		const int rshift = (48 - 23 - ieee_exp);
+
+		isp->mant = csp->mant >> rshift;
+
+#if 0
+		if (csp->mant & (1 << (rshift -1)))
+		{
+			/* round up */
+			isp->mant++;
+		}
+#endif
+
+		isp->exp  = 0;
+	}
+	else
+	{
+		/* smaller than ieee can represent */
+		isp->exp = 0;
+		isp->mant = 0;
+	}
+')dnl
+
+static void
+get_ix_float(const void *xp, float *ip)
+{
+
+	if (word_align(xp) == 0)
+	{
+		const ieee_single_hi *isp = (const ieee_single_hi *) xp;
+GET_IX_FLOAT_Body
+	}
+	else
+	{
+		const ieee_single_lo *isp = (const ieee_single_lo *) xp;
+GET_IX_FLOAT_Body
+	}
+}
+
+static void
+put_ix_float(void *xp, const float *ip)
+{
+	if (word_align(xp) == 0)
+	{
+		ieee_single_hi *isp = (ieee_single_hi*)xp;
+PUT_IX_FLOAT_Body
+	}
+	else
+	{
+		ieee_single_lo *isp = (ieee_single_lo*)xp;
+PUT_IX_FLOAT_Body
+	}
+}
+
+#else
+	/* IEEE Cray with only doubles */
+static void
+get_ix_float(const void *xp, float *ip)
+{
+
+	ieee_double *idp = (ieee_double *) ip;
+
+	if (word_align(xp) == 0)
+	{
+		const ieee_single_hi *isp = (const ieee_single_hi *) xp;
+		if (isp->exp == 0 && isp->mant == 0)
+		{
+			idp->exp = 0;
+			idp->mant = 0;
+		}
+		else
+		{
+			idp->exp = isp->exp + (ieee_double_bias - ieee_single_bias);
+			idp->mant = isp->mant << (52 - 23);
+		}
+		idp->sign = isp->sign;
+	}
+	else
+	{
+		const ieee_single_lo *isp = (const ieee_single_lo *) xp;
+		if (isp->exp == 0 && isp->mant == 0)
+		{
+			idp->exp = 0;
+			idp->mant = 0;
+		}
+		else
+		{
+			idp->exp = isp->exp + (ieee_double_bias - ieee_single_bias);
+			idp->mant = isp->mant << (52 - 23);
+		}
+		idp->sign = isp->sign;
+	}
+}
+
+static void
+put_ix_float(void *xp, const float *ip)
+{
+	const ieee_double *idp = (const ieee_double *) ip;
+	if (word_align(xp) == 0)
+	{
+		ieee_single_hi *isp = (ieee_single_hi*)xp;
+		if (idp->exp > (ieee_double_bias - ieee_single_bias))
+			isp->exp = idp->exp - (ieee_double_bias - ieee_single_bias);
+		else
+			isp->exp = 0;
+		isp->mant = idp->mant >> (52 - 23);
+		isp->sign = idp->sign;
+	}
+	else
+	{
+		ieee_single_lo *isp = (ieee_single_lo*)xp;
+		if (idp->exp > (ieee_double_bias - ieee_single_bias))
+			isp->exp = idp->exp - (ieee_double_bias - ieee_single_bias);
+		else
+			isp->exp = 0;
+		isp->mant = idp->mant >> (52 - 23);
+		isp->sign = idp->sign;
+	}
+}
+#endif
+
+#else
+#error "ix_float implementation"
+#endif
+
+#if X_SIZEOF_FLOAT != SIZEOF_FLOAT || defined(NO_IEEE_FLOAT)
+static int
+ncmpix_get_float_float(const void *xp, float *ip)
+{
+	/* TODO */
+	get_ix_float(xp, ip);
+	return NC_NOERR;
+}
+#endif
+
+#define ix_float float
+
+NCX_GET1F(float, schar)
+NCX_GET1F(float, short)
+NCX_GET1F(float, int)
+NCX_GET1F(float, long)
+NCX_GET1F(float, double)
+NCX_GET1F(float, longlong)
+NCX_GET1F(float, uchar)
+NCX_GET1F(float, ushort)
+NCX_GET1F(float, uint)
+NCX_GET1F(float, ulonglong)
+
+#if X_SIZEOF_FLOAT != SIZEOF_FLOAT || defined(NO_IEEE_FLOAT)
+static int
+ncmpix_put_float_float(void *xp, const float *ip)
+{
+#ifdef NO_IEEE_FLOAT
+	if (*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN)
+		DEBUG_RETURN_ERROR(NC_ERANGE)
+#endif
+	put_ix_float(xp, ip);
+	return NC_NOERR;
+}
+#endif
+
+NCX_PUT1F(float, schar)
+NCX_PUT1F(float, short)
+NCX_PUT1F(float, int)
+NCX_PUT1F(float, long)
+NCX_PUT1F(float, double)
+NCX_PUT1F(float, longlong)
+NCX_PUT1F(float, uchar)
+NCX_PUT1F(float, ushort)
+NCX_PUT1F(float, uint)
+NCX_PUT1F(float, ulonglong)
+
+
+/* x_double ------------------------------------------------------------------*/
+
+#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE  && !defined(NO_IEEE_FLOAT)
+
+static void
+get_ix_double(const void *xp, double *ip)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(ip, xp, SIZEOF_DOUBLE);
+#else
+	swap8b(ip, xp);
+#endif
+}
+
+static void
+put_ix_double(void *xp, const double *ip)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(xp, ip, X_SIZEOF_DOUBLE);
+#else
+	swap8b(xp, ip);
+#endif
+}
+
+#elif defined(vax) && vax != 0
+
+/* What IEEE double precision floating point looks like on a Vax */
+struct	ieee_double {
+	unsigned int	exp_hi   : 7;
+	unsigned int	sign     : 1;
+	unsigned int 	mant_6   : 4;
+	unsigned int	exp_lo   : 4;
+	unsigned int	mant_5   : 8;
+	unsigned int	mant_4   : 8;
+
+	unsigned int	mant_lo  : 32;
+};
+
+/* Vax double precision floating point */
+struct  vax_double {
+	unsigned int	mantissa1 : 7;
+	unsigned int	exp       : 8;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 16;
+	unsigned int	mantissa3 : 16;
+	unsigned int	mantissa4 : 16;
+};
+
+#define VAX_DBL_BIAS	0x81
+#define IEEE_DBL_BIAS	0x3ff
+#define MASK(nbits)	((1 << nbits) - 1)
+
+static const struct dbl_limits {
+	struct	vax_double d;
+	struct	ieee_double ieee;
+} dbl_limits[2] = {
+	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
+	{ 0x7f, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0}}, /* Max IEEE */
+	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
+	{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, /* Min IEEE */
+};
+
+
+dnl dnl dnl
+dnl
+dnl GET_VAX_DDOUBLE_Body(xp) (body for get_ix_double)
+dnl
+define(`GET_VAX_DDOUBLE_Body',dnl
+`dnl
+	struct vax_double *const vdp =
+			 (struct vax_double *)ip;
+	const struct ieee_double *const idp =
+			 (const struct ieee_double *) $1;
+	{
+		const struct dbl_limits *lim;
+		int ii;
+		for (ii = 0, lim = dbl_limits;
+			ii < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+			ii++, lim++)
+		{
+			if ((idp->mant_lo == lim->ieee.mant_lo)
+				&& (idp->mant_4 == lim->ieee.mant_4)
+				&& (idp->mant_5 == lim->ieee.mant_5)
+				&& (idp->mant_6 == lim->ieee.mant_6)
+				&& (idp->exp_lo == lim->ieee.exp_lo)
+				&& (idp->exp_hi == lim->ieee.exp_hi)
+				)
+			{
+				*vdp = lim->d;
+				goto doneit;
+			}
+		}
+	}
+	{
+		unsigned exp = idp->exp_hi << 4 | idp->exp_lo;
+		vdp->exp = exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
+	}
+	{
+		unsigned mant_hi = ((idp->mant_6 << 16)
+				 | (idp->mant_5 << 8)
+				 | idp->mant_4);
+		unsigned mant_lo = SWAP4(idp->mant_lo);
+		vdp->mantissa1 = (mant_hi >> 13);
+		vdp->mantissa2 = ((mant_hi & MASK(13)) << 3)
+				| (mant_lo >> 29);
+		vdp->mantissa3 = (mant_lo >> 13);
+		vdp->mantissa4 = (mant_lo << 3);
+	}
+	doneit:
+		vdp->sign = idp->sign;
+')dnl
+static void
+get_ix_double(const void *xp, double *ip)
+{
+GET_VAX_DDOUBLE_Body(xp)
+}
+
+
+dnl dnl dnl
+dnl
+dnl PUT_VAX_DDOUBLE_Body(xp) (body for put_ix_double)
+dnl
+define(`PUT_VAX_DDOUBLE_Body',dnl
+`dnl
+	const struct vax_double *const vdp =
+			(const struct vax_double *)ip;
+	struct ieee_double *const idp =
+			 (struct ieee_double *) $1;
+
+	if ((vdp->mantissa4 > (dbl_limits[0].d.mantissa4 - 3)) &&
+		(vdp->mantissa3 == dbl_limits[0].d.mantissa3) &&
+		(vdp->mantissa2 == dbl_limits[0].d.mantissa2) &&
+		(vdp->mantissa1 == dbl_limits[0].d.mantissa1) &&
+		(vdp->exp == dbl_limits[0].d.exp))
+	{
+		*idp = dbl_limits[0].ieee;
+		goto shipit;
+	}
+	if ((vdp->mantissa4 == dbl_limits[1].d.mantissa4) &&
+		(vdp->mantissa3 == dbl_limits[1].d.mantissa3) &&
+		(vdp->mantissa2 == dbl_limits[1].d.mantissa2) &&
+		(vdp->mantissa1 == dbl_limits[1].d.mantissa1) &&
+		(vdp->exp == dbl_limits[1].d.exp))
+	{
+		*idp = dbl_limits[1].ieee;
+		goto shipit;
+	}
+
+	{
+		unsigned exp = vdp->exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
+
+		unsigned mant_lo = ((vdp->mantissa2 & MASK(3)) << 29) |
+			(vdp->mantissa3 << 13) |
+			((vdp->mantissa4 >> 3) & MASK(13));
+
+		unsigned mant_hi = (vdp->mantissa1 << 13)
+				 | (vdp->mantissa2 >> 3);
+
+		if ((vdp->mantissa4 & 7) > 4)
+		{
+			/* round up */
+			mant_lo++;
+			if (mant_lo == 0)
+			{
+				mant_hi++;
+				if (mant_hi > 0xffffff)
+				{
+					mant_hi = 0;
+					exp++;
+				}
+			}
+		}
+
+		idp->mant_lo = SWAP4(mant_lo);
+		idp->mant_6 = mant_hi >> 16;
+		idp->mant_5 = (mant_hi & 0xff00) >> 8;
+		idp->mant_4 = mant_hi;
+		idp->exp_hi = exp >> 4;
+		idp->exp_lo = exp;
+	}
+
+	shipit:
+		idp->sign = vdp->sign;
+')dnl
+static void
+put_ix_double(void *xp, const double *ip)
+{
+PUT_VAX_DDOUBLE_Body(xp)
+}
+
+	/* vax */
+#elif defined(_CRAY) && !defined(__crayx1)
+
+static void
+get_ix_double(const void *xp, double *ip)
+{
+	const ieee_double *idp = (const ieee_double *) xp;
+	cray_single *csp = (cray_single *) ip;
+
+	if (idp->exp == 0)
+	{
+		/* ieee subnormal */
+		*ip = (double)idp->mant;
+		if (idp->mant != 0)
+		{
+			csp->exp -= (ieee_double_bias + 51);
+		}
+	}
+	else
+	{
+		csp->exp  = idp->exp + cs_id_bias + 1;
+		csp->mant = idp->mant >> (52 - 48 + 1);
+		csp->mant |= (1 << (48 - 1));
+	}
+	csp->sign = idp->sign;
+}
+
+static void
+put_ix_double(void *xp, const double *ip)
+{
+	ieee_double *idp = (ieee_double *) xp;
+	const cray_single *csp = (const cray_single *) ip;
+
+	int ieee_exp = csp->exp - cs_id_bias -1;
+
+	idp->sign = csp->sign;
+
+	if (ieee_exp >= 0x7ff)
+	{
+		/* NC_ERANGE => ieee Inf */
+		idp->exp = 0x7ff;
+		idp->mant = 0x0;
+	}
+	else if (ieee_exp > 0)
+	{
+		/* normal ieee representation */
+		idp->exp  = ieee_exp;
+		/* assumes cray rep is in normal form */
+		assert(csp->mant & 0x800000000000);
+		idp->mant = (((csp->mant << 1) &
+				0xffffffffffff) << (52 - 48));
+	}
+	else if (ieee_exp >= (-(52 -48)))
+	{
+		/* ieee subnormal, left shift */
+		const int lshift = (52 - 48) + ieee_exp;
+		idp->mant = csp->mant << lshift;
+		idp->exp  = 0;
+	}
+	else if (ieee_exp >= -52)
+	{
+		/* ieee subnormal, right shift */
+		const int rshift = (- (52 - 48) - ieee_exp);
+
+		idp->mant = csp->mant >> rshift;
+
+#if 0
+		if (csp->mant & (1 << (rshift -1)))
+		{
+			/* round up */
+			idp->mant++;
+		}
+#endif
+
+		idp->exp  = 0;
+	}
+	else
+	{
+		/* smaller than ieee can represent */
+		idp->exp = 0;
+		idp->mant = 0;
+	}
+}
+#else
+#error "ix_double implementation"
+#endif
+
+#define ix_double double
+
+NCX_GET1F(double, schar)
+NCX_GET1F(double, short)
+NCX_GET1F(double, int)
+NCX_GET1F(double, long)
+NCX_GET1F(double, longlong)
+NCX_GET1F(double, uchar)
+NCX_GET1F(double, ushort)
+NCX_GET1F(double, uint)
+NCX_GET1F(double, ulonglong)
+
+static int
+ncmpix_get_double_float(const void *xp, float *ip)
+{
+	double xx;
+	get_ix_double(xp, &xx);
+	if (xx > FLT_MAX)
+	{
+		*ip = FLT_MAX;
+		DEBUG_RETURN_ERROR(NC_ERANGE)
+	}
+	if (xx < (-FLT_MAX))
+	{
+		*ip = (-FLT_MAX);
+		DEBUG_RETURN_ERROR(NC_ERANGE)
+	}
+	*ip = (float) xx;
+	return NC_NOERR;
+}
+
+#if X_SIZEOF_DOUBLE != SIZEOF_DOUBLE  || defined(NO_IEEE_FLOAT)
+static int
+ncmpix_get_double_double(const void *xp, double *ip)
+{
+	/* TODO */
+	get_ix_double(xp, ip);
+	return NC_NOERR;
+}
+#endif
+
+NCX_PUT1F(double, schar)
+NCX_PUT1F(double, uchar)
+NCX_PUT1F(double, short)
+NCX_PUT1F(double, ushort)
+NCX_PUT1F(double, int)
+NCX_PUT1F(double, long)
+NCX_PUT1F(double, uint)
+NCX_PUT1F(double, longlong)
+NCX_PUT1F(double, ulonglong)
+
+static int
+ncmpix_put_double_float(void *xp, const float *ip)
+{
+#if 0	/* TODO: figure this out (if condition below will never be true)*/
+	if ((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN)
+		DEBUG_RETURN_ERROR(NC_ERANGE)
+#endif
+	double xx = (double) *ip;
+	put_ix_double(xp, &xx);
+	return NC_NOERR;
+}
+
+#if X_SIZEOF_DOUBLE != SIZEOF_DOUBLE  || defined(NO_IEEE_FLOAT)
+static int
+ncmpix_put_double_double(void *xp, const double *ip)
+{
+#ifdef NO_IEEE_FLOAT
+	if (*ip > X_DOUBLE_MAX || *ip < X_DOUBLE_MIN)
+		DEBUG_RETURN_ERROR(NC_ERANGE)
+#endif
+	put_ix_double(xp, ip);
+	return NC_NOERR;
+}
+#endif
+
+
+/* x_int64 -------------------------------------------------------------------*/
+
+#if SHORT_MAX == X_INT64_MAX
+typedef short ix_int64;
+#define SIZEOF_IX_INT64 SIZEOF_SHORT
+#define IX_INT64_MAX SHORT_MAX
+#elif LONG_LONG_MAX  >= X_INT64_MAX
+typedef longlong ix_int64;
+#define SIZEOF_IX_INT64 SIZEOF_LONGLONG
+#define IX_INT64_MAX LONG_LONG_MAX
+#elif LONG_MAX  >= X_INT64_MAX
+typedef long ix_int64;
+#define SIZEOF_IX_INT64 SIZEOF_LONG
+#define IX_INT64_MAX LONG_MAX
+#else
+#error "ix_int64 implementation"
+#endif
+
+
+static void
+get_ix_int64(const void *xp, ix_int64 *ip)
+{
+    const uchar *cp = (const uchar *) xp;
+
+    *ip  = ((ix_int64)(*cp++) << 56);
+    *ip |= ((ix_int64)(*cp++) << 48);
+    *ip |= ((ix_int64)(*cp++) << 40);
+    *ip |= ((ix_int64)(*cp++) << 32);
+    *ip |= ((ix_int64)(*cp++) << 24);
+    *ip |= ((ix_int64)(*cp++) << 16);
+    *ip |= ((ix_int64)(*cp++) <<  8);
+    *ip |=  (ix_int64)*cp;
+}
+
+static void
+put_ix_int64(void *xp, const ix_int64 *ip)
+{
+    uchar *cp = (uchar *) xp;
+
+    *cp++ = (*ip) >> 56;
+    *cp++ = ((*ip) & 0x00ff000000000000LL) >> 48;
+    *cp++ = ((*ip) & 0x0000ff0000000000LL) >> 40;
+    *cp++ = ((*ip) & 0x000000ff00000000LL) >> 32;
+    *cp++ = ((*ip) & 0x00000000ff000000LL) >> 24;
+    *cp++ = ((*ip) & 0x0000000000ff0000LL) >> 16;
+    *cp++ = ((*ip) & 0x000000000000ff00LL) >>  8;
+    *cp   = ((*ip) & 0x00000000000000ffLL);
+}
+
+#if X_SIZEOF_INT64 != SIZEOF_LONGLONG
+NCX_GET1I(int64, longlong,  1)
+#endif
+NCX_GET1I(int64, schar,     0)
+NCX_GET1I(int64, short,     1)
+NCX_GET1I(int64, int,       1)
+NCX_GET1I(int64, long,      1)
+NCX_GET1I(int64, ushort,    0)
+NCX_GET1I(int64, uchar,     0)
+NCX_GET1I(int64, uint,      0)
+NCX_GET1I(int64, ulonglong, 0)
+NCX_GET1F(int64, float)
+NCX_GET1F(int64, double)
+
+#if X_SIZEOF_INT64 != SIZEOF_LONGLONG
+NCX_PUT1I(int64, longlong,  1)
+#endif
+NCX_PUT1I(int64, schar,     0)
+NCX_PUT1I(int64, short,     1)
+NCX_PUT1I(int64, int,       1)
+NCX_PUT1I(int64, long,      1)
+NCX_PUT1I(int64, ushort,    0)
+NCX_PUT1I(int64, uchar,     0)
+NCX_PUT1I(int64, uint,      0)
+NCX_PUT1I(int64, ulonglong, 0)
+NCX_PUT1F(int64, float)
+NCX_PUT1F(int64, double)
+
+
+/* x_uint64 -----------------------------------------------------------------*/
+
+#if USHORT_MAX == X_UINT64_MAX
+typedef ushort ix_uint64;
+#define SIZEOF_IX_UINT64 SIZEOF_USHORT
+#define IX_UINT64_MAX USHORT_MAX
+#elif ULONG_LONG_MAX  >= X_UINT64_MAX
+typedef ulonglong ix_uint64;
+#define SIZEOF_IX_UINT64 SIZEOF_ULONGLONG
+#define IX_UINT64_MAX ULONG_LONG_MAX
+#elif ULONG_MAX  >= X_UINT64_MAX
+typedef ulong ix_uint64;
+#define SIZEOF_IX_UINT64 SIZEOF_ULONG
+#define IX_UINT64_MAX ULONG_MAX
+#else
+#error "ix_uint64 implementation"
+#endif
+
+
+static void
+get_ix_uint64(const void *xp, ix_uint64 *ip)
+{
+    const uchar *cp = (const uchar *) xp;
+
+    *ip  = ((ix_uint64)(*cp++) << 56);
+    *ip |= ((ix_uint64)(*cp++) << 48);
+    *ip |= ((ix_uint64)(*cp++) << 40);
+    *ip |= ((ix_uint64)(*cp++) << 32);
+    *ip |= ((ix_uint64)(*cp++) << 24);
+    *ip |= ((ix_uint64)(*cp++) << 16);
+    *ip |= ((ix_uint64)(*cp++) <<  8);
+    *ip |=  (ix_uint64)*cp;
+}
+
+static void
+put_ix_uint64(void *xp, const ix_uint64 *ip)
+{
+    uchar *cp = (uchar *) xp;
+
+    *cp++ = (*ip) >> 56;
+    *cp++ = ((*ip) & 0x00ff000000000000ULL) >> 48;
+    *cp++ = ((*ip) & 0x0000ff0000000000ULL) >> 40;
+    *cp++ = ((*ip) & 0x000000ff00000000ULL) >> 32;
+    *cp++ = ((*ip) & 0x00000000ff000000ULL) >> 24;
+    *cp++ = ((*ip) & 0x0000000000ff0000ULL) >> 16;
+    *cp++ = ((*ip) & 0x000000000000ff00ULL) >>  8;
+    *cp   = ((*ip) & 0x00000000000000ffULL);
+}
+
+#if X_SIZEOF_UINT64 != SIZEOF_ULONGLONG
+NCX_GET1I(uint64, ulonglong, 1)
+#endif
+NCX_GET1I(uint64, schar,     0)
+NCX_GET1I(uint64, short,     0)
+NCX_GET1I(uint64, int,       0)
+NCX_GET1I(uint64, long,      0)
+NCX_GET1I(uint64, longlong,  0)
+NCX_GET1I(uint64, ushort,    1)
+NCX_GET1I(uint64, uchar,     1)
+NCX_GET1I(uint64, uint,      1)
+NCX_GET1F(uint64, float)
+NCX_GET1F(uint64, double)
+
+#if X_SIZEOF_UINT64 != SIZEOF_ULONGLONG
+NCX_PUT1I(uint64, ulonglong, 1)
+#endif
+NCX_PUT1I(uint64, schar,     0)
+NCX_PUT1I(uint64, short,     0)
+NCX_PUT1I(uint64, int,       0)
+NCX_PUT1I(uint64, long,      0)
+NCX_PUT1I(uint64, longlong,  0)
+NCX_PUT1I(uint64, uchar,     1)
+NCX_PUT1I(uint64, ushort,    1)
+NCX_PUT1I(uint64, uint,      1)
+NCX_PUT1F(uint64, float)
+NCX_PUT1F(uint64, double)
+
+
+/* x_size_t */
+
+#if SIZEOF_SIZE_T < X_SIZEOF_SIZE_T
+#error "x_size_t implementation"
+/* netcdf requires size_t which can hold a values from 0 to 2^32 -1 */
+#endif
+
+int
+ncmpix_put_size_t(void **xpp, const size_t *ulp)
+{
+	/* similar to put_ix_int() */
+	uchar *cp = (uchar *) *xpp;
+	assert(*ulp <= X_SIZE_MAX);
+
+	*cp++ = (uchar)((*ulp) >> 24);
+	*cp++ = (uchar)(((*ulp) & 0x00ff0000) >> 16);
+	*cp++ = (uchar)(((*ulp) & 0x0000ff00) >>  8);
+	*cp   = (uchar)((*ulp) & 0x000000ff);
+
+	*xpp = (void *)((char *)(*xpp) + X_SIZEOF_SIZE_T);
+	return NC_NOERR;
+}
+
+int
+ncmpix_get_size_t(const void **xpp,  size_t *ulp)
+{
+	/* similar to get_ix_int */
+	const uchar *cp = (const uchar *) *xpp;
+
+	*ulp  = (size_t)(*cp++ << 24);
+	*ulp |= (size_t)(*cp++ << 16);
+	*ulp |= (size_t)(*cp++ << 8);
+	*ulp |= *cp;
+
+	*xpp = (const void *)((const char *)(*xpp) + X_SIZEOF_SIZE_T);
+	return NC_NOERR;
+}
+
+/* x_off_t */
+
+int
+ncmpix_put_off_t(void **xpp, const off_t *lp, size_t sizeof_off_t)
+{
+	/* No negative offsets stored in netcdf */
+	if (*lp < 0) {
+	  /* Assume this is an overflow of a 32-bit int... */
+	  DEBUG_RETURN_ERROR(NC_ERANGE)
+	}
+
+	assert(sizeof_off_t == 4 || sizeof_off_t == 8);
+
+	/* similar to put_ix_int() */
+	uchar *cp = (uchar *) *xpp;
+
+	if (sizeof_off_t == 4) {
+		*cp++ = (uchar) ((*lp)               >> 24);
+		*cp++ = (uchar)(((*lp) & 0x00ff0000) >> 16);
+		*cp++ = (uchar)(((*lp) & 0x0000ff00) >>  8);
+		*cp   = (uchar)( (*lp) & 0x000000ff);
+	} else {
+#if SIZEOF_OFF_T == 4
+/* Write a 64-bit offset on a system with only a 32-bit offset */
+		*cp++ = (uchar)0;
+		*cp++ = (uchar)0;
+		*cp++ = (uchar)0;
+		*cp++ = (uchar)0;
+
+		*cp++ = (uchar)(((*lp) & 0xff000000) >> 24);
+		*cp++ = (uchar)(((*lp) & 0x00ff0000) >> 16);
+		*cp++ = (uchar)(((*lp) & 0x0000ff00) >>  8);
+		*cp   = (uchar)( (*lp) & 0x000000ff);
+#else
+		*cp++ = (uchar) ((*lp)                          >> 56);
+		*cp++ = (uchar)(((*lp) & 0x00ff000000000000LL) >> 48);
+		*cp++ = (uchar)(((*lp) & 0x0000ff0000000000LL) >> 40);
+		*cp++ = (uchar)(((*lp) & 0x000000ff00000000LL) >> 32);
+		*cp++ = (uchar)(((*lp) & 0x00000000ff000000LL) >> 24);
+		*cp++ = (uchar)(((*lp) & 0x0000000000ff0000LL) >> 16);
+		*cp++ = (uchar)(((*lp) & 0x000000000000ff00LL) >>  8);
+		*cp   = (uchar)( (*lp) & 0x00000000000000ffLL);
+#endif
+	}
+	*xpp = (void *)((char *)(*xpp) + sizeof_off_t);
+	return NC_NOERR;
+}
+
+int
+ncmpix_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t)
+{
+	/* similar to get_ix_int() */
+	const uchar *cp = (const uchar *) *xpp;
+	assert(sizeof_off_t == 4 || sizeof_off_t == 8);
+
+ 	if (sizeof_off_t == 4) {
+		*lp =  (off_t)(*cp++ << 24);
+		*lp |= (off_t)(*cp++ << 16);
+		*lp |= (off_t)(*cp++ <<  8);
+		*lp |= (off_t)*cp;
+	} else {
+#if SIZEOF_OFF_T == 4
+/* Read a 64-bit offset on a system with only a 32-bit offset */
+/* If the offset overflows, set an error code and return */
+		*lp =  ((off_t)(*cp++) << 24);
+		*lp |= ((off_t)(*cp++) << 16);
+		*lp |= ((off_t)(*cp++) <<  8);
+		*lp |= ((off_t)(*cp++));
+/*
+ * lp now contains the upper 32-bits of the 64-bit offset.  if lp is
+ * not zero, then the dataset is larger than can be represented
+ * on this system.  Set an error code and return.
+ */
+		if (*lp != 0) {
+		  DEBUG_RETURN_ERROR(NC_ERANGE)
+		}
+
+		*lp  = ((off_t)(*cp++) << 24);
+		*lp |= ((off_t)(*cp++) << 16);
+		*lp |= ((off_t)(*cp++) <<  8);
+		*lp |=  (off_t)*cp;
+
+		if (*lp < 0) {
+		  /*
+		   * If this fails, then the offset is >2^31, but less
+		   * than 2^32 which is not allowed, but is not caught
+		   * by the previous check
+		   */
+		  DEBUG_RETURN_ERROR(NC_ERANGE)
+		}
+#else
+		*lp =  ((off_t)(*cp++) << 56);
+		*lp |= ((off_t)(*cp++) << 48);
+		*lp |= ((off_t)(*cp++) << 40);
+		*lp |= ((off_t)(*cp++) << 32);
+		*lp |= ((off_t)(*cp++) << 24);
+		*lp |= ((off_t)(*cp++) << 16);
+		*lp |= ((off_t)(*cp++) <<  8);
+		*lp |=  (off_t)*cp;
+#endif
+	}
+	*xpp = (const void *)((const char *)(*xpp) + sizeof_off_t);
+	return NC_NOERR;
+}
+
+/*----< ncmpix_get_uint32() >-------------------------------------------------*/
+int
+ncmpix_get_uint32(const void **xpp, uint *ip)
+{
+#ifdef WORDS_BIGENDIAN
+    /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on
+     * some system, such as HPUX */
+    (void) memcpy(ip, *xpp, X_SIZEOF_INT);
+#else
+    const uchar *cp = (const uchar *) *xpp;
+
+    *ip  = (*cp++ << 24);
+    *ip |= (*cp++ << 16);
+    *ip |= (*cp++ <<  8);
+    *ip |=  *cp;
+#endif
+    /* advance *xpp 4 bytes */
+    *xpp = (void *)((const char *)(*xpp) + 4);
+
+    return NC_NOERR;
+}
+
+/*----< ncmpix_get_uint64() >-------------------------------------------------*/
+int
+ncmpix_get_uint64(const void **xpp, unsigned long long *llp)
+{
+#ifdef WORDS_BIGENDIAN
+    /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on
+     * some system, such as HPUX */
+    (void) memcpy(llp, *xpp, X_SIZEOF_INT64);
+#else
+    const uchar *cp = (const uchar *) *xpp;
+
+    /* below is the same as calling swap8b(llp, *xpp) */
+    *llp  = ((long long)(*cp++) << 56);
+    *llp |= ((long long)(*cp++) << 48);
+    *llp |= ((long long)(*cp++) << 40);
+    *llp |= ((long long)(*cp++) << 32);
+    *llp |= ((long long)(*cp++) << 24);
+    *llp |= ((long long)(*cp++) << 16);
+    *llp |= ((long long)(*cp++) <<  8);
+    *llp |=  (long long)*cp;
+#endif
+    /* advance *xpp 8 bytes */
+    *xpp = (void *)((const char *)(*xpp) + 8);
+
+    return NC_NOERR;
+}
+
+/*---< ncmpix_put_uint32() >--------------------------------------------------*/
+/* copy the contents of ip (an unsigned 32-bit integer) to xpp in Big Endian
+ * form and advance *xpp 4 bytes
+ */
+int
+ncmpix_put_uint32(void **xpp, const unsigned int ip)
+{
+#ifdef WORDS_BIGENDIAN
+    /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on
+     * some system, such as HPUX */
+    (void) memcpy(*xpp, &ip, X_SIZEOF_INT);
+#else
+    /* bitwise shifts below are to produce an integer in Big Endian */
+    uchar *cp = (uchar *) *xpp;
+    *cp++ = (uchar)((ip & 0xff000000) >> 24);
+    *cp++ = (uchar)((ip & 0x00ff0000) >> 16);
+    *cp++ = (uchar)((ip & 0x0000ff00) >>  8);
+    *cp   = (uchar)( ip & 0x000000ff);
+#endif
+    /* advance *xpp 4 bytes */
+    *xpp  = (void *)((char *)(*xpp) + 4);
+
+    return NC_NOERR;
+}
+
+/*---< ncmpix_put_uint64() >--------------------------------------------------*/
+/* copy the contents of ip (an unsigned 64-bit integer) to xpp in Big Endian
+ * form and advance *xpp 8 bytes
+ */
+int
+ncmpix_put_uint64(void **xpp, const unsigned long long ip)
+{
+#ifdef WORDS_BIGENDIAN
+    /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on
+     * some system, such as HPUX */
+    (void) memcpy(*xpp, &ip, X_SIZEOF_INT64);
+#else
+    uchar *cp = (uchar *) *xpp;
+    /* below is the same as calling swap8b(*xpp, &ip) */
+    *cp++ = (uchar) (ip                         >> 56);
+    *cp++ = (uchar)((ip & 0x00ff000000000000LL) >> 48);
+    *cp++ = (uchar)((ip & 0x0000ff0000000000LL) >> 40);
+    *cp++ = (uchar)((ip & 0x000000ff00000000LL) >> 32);
+    *cp++ = (uchar)((ip & 0x00000000ff000000LL) >> 24);
+    *cp++ = (uchar)((ip & 0x0000000000ff0000LL) >> 16);
+    *cp++ = (uchar)((ip & 0x000000000000ff00LL) >>  8);
+    *cp   = (uchar) (ip & 0x00000000000000ffLL);
+#endif
+    /* advance *xpp 8 bytes */
+    *xpp  = (void *)((char *)(*xpp) + 8);
+
+    return NC_NOERR;
+}
+
+
+/*
+ * Aggregate numeric conversion functions.
+ */
+dnl
+define(`GETN_CheckBND', `ifelse(index(`$1',`u'), 0, , index(`$2',`u'), 0, `|| xp[i] < 0', `|| xp[i] < Imin($2)')')dnl
+define(`PUTN_CheckBND', `ifelse(index(`$2',`u'), 0, , index(`$1',`u'), 0, `|| tp[i] < 0', `|| tp[i] < Xmin($1)')')dnl
+
+dnl
+dnl dnl dnl
+dnl
+dnl NCX_GETN_Byte_Body (body for one byte types on diagonal)
+dnl
+define(`NCX_GETN_Byte_Body',dnl
+`dnl
+	(void) memcpy(tp, *xpp, (size_t)nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+	return NC_NOERR;
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_PAD_GETN_Byte_body (body for one byte types on diagonal)
+dnl
+define(`NCX_PAD_GETN_Byte_Body',dnl
+`dnl
+	MPI_Offset rndup = nelems % X_ALIGN;
+
+	if (rndup)
+		rndup = X_ALIGN - rndup;
+
+	(void) memcpy(tp, *xpp, (size_t)nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems + rndup);
+
+	return NC_NOERR;
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_GETN_CHAR(Type)
+dnl
+define(`NCX_GETN_CHAR',dnl
+`dnl
+int
+ncmpix_getn_$1_$2(const void **xpp, MPI_Offset nelems, $2 *tp)
+{
+	int status = NC_NOERR;
+	$1 *xp = ($1 *)(*xpp);
+
+	while (nelems-- != 0)
+	{
+		GETI_CheckNegAssign($1, $2, *xp, tp)
+		*tp++ = ($2) Cast_Signed2Unsigned($2,$1) (*xp++);  /* type cast from $1 to $2 */
+		/* TODO: skip the assignment if NC_ERANGE occurs?
+		 * However, if doing so, many nc_test/nf_test will fail
+		 */
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_PAD_GETN_CHAR(Type)
+dnl
+define(`NCX_PAD_GETN_CHAR',dnl
+`dnl
+int
+ncmpix_pad_getn_$1_$2(const void **xpp, MPI_Offset nelems, $2 *tp)
+{
+	int status = NC_NOERR;
+	MPI_Offset rndup = nelems % X_ALIGN;
+	$1 *xp = ($1 *) *xpp;
+
+	if (rndup)
+		rndup = X_ALIGN - rndup;
+
+	while (nelems-- != 0)
+	{
+		GETI_CheckNegAssign($1, $2, *xp, tp)
+		*tp++ = ($2) Cast_Signed2Unsigned($2,$1) (*xp++);  /* type cast from $1 to $2 */
+		/* TODO: skip the assignment if NC_ERANGE occurs?
+		 * However, if doing so, many nc_test/nf_test will fail
+		 */
+	}
+
+	*xpp = (void *)(xp + rndup);
+	return status;
+}
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_GETNo(XType, Type) deprecated
+dnl
+define(`NCX_GETNo',dnl
+`dnl
+int
+ncmpix_getn_$1_$2(const void **xpp, MPI_Offset nelems, $2 *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = NC_NOERR;
+	$1 xx;
+
+	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
+	{
+		const int lstatus = ncmpix_get_$1_$1(xp, &xx);
+		*tp = ($2)xx;
+		if (status == NC_NOERR) /* report the first encountered error */
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_GETN(XType, Type, condition)
+dnl
+define(`NCX_GETN',dnl
+`dnl
+int
+ncmpix_getn_$1_$2(const void **xpp, MPI_Offset nelems, $2 *tp)
+{
+`#'if defined(_SX) && _SX != 0 && Xsizeof($1) == Isizeof($1)
+
+ /* basic algorithm is:
+  *   - ensure sane alignment of input data
+  *   - copy (conversion happens automatically) input data
+  *     to output
+  *   - update xpp to point at next unconverted input, and tp to point
+  *     at next location for converted output
+  */
+  long i, j, ni;
+  $1 tmp[LOOPCNT];        /* in case input is misaligned */
+  $1 *xp;
+  int nrange = 0;         /* number of range errors */
+  int realign = 0;        /* "do we need to fix input data alignment?" */
+  long cxp = (long) *((char**)xpp);
+
+  realign = (cxp & 7) % Isizeof($1);
+  /* sjl: manually stripmine so we can limit amount of
+   * vector work space reserved to LOOPCNT elements. Also
+   * makes vectorisation easy */
+  for (j=0; j<nelems && nrange==0; j+=LOOPCNT) {
+    ni=Min(nelems-j,LOOPCNT);
+    if (realign) {
+      memcpy(tmp, *xpp, (size_t)(ni*Isizeof($1)));
+      xp = tmp;
+    } else {
+      xp = ($1 *) *xpp;
+    }
+   /* copy the next block */
+#pragma cdir loopcnt=LOOPCNT
+#pragma cdir shortloop
+    for (i=0; i<ni; i++) {
+      tp[i] = ($2) Max( Imin($2), Min(Imax($2), ($2) xp[i]));
+     /* test for range errors (not always needed but do it anyway) */
+     /* if xpp is unsigned, we need not check if xp[i] < Imin */
+     /* if xpp is signed && tp is unsigned, we need check if xp[i] >= 0 */
+      nrange += xp[i] > Imax($2) GETN_CheckBND($1, $2);
+    }
+   /* update xpp and tp */
+    if (realign) xp = ($1 *) *xpp;
+    xp += ni;
+    tp += ni;
+    *xpp = (void*)xp;
+  }
+  return nrange == 0 ? NC_NOERR : NC_ERANGE;
+
+#else   /* not SX */
+	const char *xp = (const char *) *xpp;
+	int status = NC_NOERR;
+
+	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
+	{
+		const int lstatus = ncmpix_get_$1_$2(xp, tp);
+		if (status == NC_NOERR) /* report the first encountered error */
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+#endif
+}
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_PAD_GETN_SHORT(xtype ttype)
+dnl
+define(`NCX_PAD_GETN_SHORT',dnl
+`dnl
+int
+ncmpix_pad_getn_$1_$2(const void **xpp, MPI_Offset nelems, $2 *tp)
+{
+	const MPI_Offset rndup = nelems % 2;
+
+	const char *xp = (const char *) *xpp;
+	int status = NC_NOERR;
+
+	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
+	{
+		const int lstatus = ncmpix_get_$1_$2(xp, tp);
+		if (status == NC_NOERR) /* report the first encountered error */
+			status = lstatus;
+	}
+
+	if (rndup != 0)
+		xp += Xsizeof($1);
+
+	*xpp = (void *)xp;
+	return status;
+}
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_PUTN_Byte_Body(Type) (body for one byte types)
+dnl
+define(`NCX_PUTN_Byte_Body',dnl
+`dnl
+	(void) memcpy(*xpp, tp, (size_t)nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+
+	return NC_NOERR;
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_PAD_PUTN_Byte_Body(Type) (body for one byte types)
+dnl
+define(`NCX_PAD_PUTN_Byte_Body',dnl
+	MPI_Offset rndup = nelems % X_ALIGN;
+
+	if (rndup)
+		rndup = X_ALIGN - rndup;
+
+	(void) memcpy(*xpp, tp, (size_t)nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+
+	if (rndup)
+	{
+		(void) memcpy(*xpp, nada, (size_t)rndup);
+		*xpp = (void *)((char *)(*xpp) + rndup);
+	}
+
+	return NC_NOERR;
+`dnl
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_PUTN_CHAR(Type)
+dnl
+define(`NCX_PUTN_CHAR',dnl
+`dnl
+int
+ncmpix_putn_$1_$2(void **xpp, MPI_Offset nelems, const $2 *tp)
+{
+	int status = NC_NOERR;
+	$1 *xp = ($1 *) *xpp;
+
+	while (nelems-- != 0)
+	{
+		if (*tp > ($2)Xmax($1) ifelse(index(`$2',`u'), 0, , index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)'))
+			DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
+		*xp++ = ($1) Cast_Signed2Unsigned($1,$2) *tp++; /* type cast from $2 to $1 */
+		/* TODO: skip the assignment if NC_ERANGE occurs?
+		 * However, if doing so, many nc_test/nf_test will fail
+		 */
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_PAD_PUTN_CHAR(xtype, ttype)
+dnl
+define(`NCX_PAD_PUTN_CHAR',dnl
+`dnl
+int
+ncmpix_pad_putn_$1_$2(void **xpp, MPI_Offset nelems, const $2 *tp)
+{
+	int status = NC_NOERR;
+	MPI_Offset rndup = nelems % X_ALIGN;
+	$1 *xp = ($1 *) *xpp;
+
+	if (rndup)
+		rndup = X_ALIGN - rndup;
+
+	while (nelems-- != 0)
+	{
+		if (*tp > ($2)Xmax($1) ifelse(index(`$2',`u'), 0, , index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)'))
+			DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
+		*xp++ = ($1) Cast_Signed2Unsigned($1,$2) *tp++; /* type cast from $2 to $1 */
+		/* TODO: skip the assignment if NC_ERANGE occurs?
+		 * However, if doing so, many nc_test/nf_test will fail
+		 */
+	}
+
+
+	if (rndup)
+	{
+		(void) memcpy(xp, nada, (size_t)rndup);
+		xp += rndup;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_PUTNo(XType, Type) deprecated
+dnl
+define(`NCX_PUTNo',dnl
+`dnl
+int
+ncmpix_putn_$1_$2(void **xpp, MPI_Offset nelems, const $2 *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = NC_NOERR;
+	$1 xx;
+
+	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
+	{
+		xx = ($1) *tp;
+		{
+		int lstatus = ncmpix_put_$1_$1(xp, &xx);
+		if (status == NC_NOERR) /* report the first encountered error */
+			status = lstatus;
+		}
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_PUTN(XType, Type, condition)
+dnl
+define(`NCX_PUTN',dnl
+`dnl
+int
+ncmpix_putn_$1_$2(void **xpp, MPI_Offset nelems, const $2 *tp)
+{
+`#'if defined(_SX) && _SX != 0 && Xsizeof($1) == Isizeof($1)
+
+ /* basic algorithm is:
+  *   - ensure sane alignment of output data
+  *   - copy (conversion happens automatically) input data
+  *     to output
+  *   - update tp to point at next unconverted input, and xpp to point
+  *     at next location for converted output
+  */
+  long i, j, ni;
+  $1 tmp[LOOPCNT];        /* in case input is misaligned */
+  $1 *xp;
+ifelse( $1$2, intfloat,dnl
+`dnl
+  double d;               /* special case for ncmpix_putn_int_float */
+')dnl
+  int nrange = 0;         /* number of range errors */
+  int realign = 0;        /* "do we need to fix input data alignment?" */
+  long cxp = (long) *((char**)xpp);
+
+  realign = (cxp & 7) % Isizeof($1);
+  /* sjl: manually stripmine so we can limit amount of
+   * vector work space reserved to LOOPCNT elements. Also
+   * makes vectorisation easy */
+  for (j=0; j<nelems && nrange==0; j+=LOOPCNT) {
+    ni=Min(nelems-j,LOOPCNT);
+    if (realign) {
+      xp = tmp;
+    } else {
+      xp = ($1 *) *xpp;
+    }
+   /* copy the next block */
+#pragma cdir loopcnt=LOOPCNT
+#pragma cdir shortloop
+    for (i=0; i<ni; i++) {
+ifelse( $1$2, intfloat,dnl
+`dnl
+      /* for some reason int to float, for putn, requires a special case */
+      d = tp[i];
+      xp[i] = ($1) Max( Xmin($1), Min(Xmax($1), ($1) d));
+      nrange += tp[i] > Xmax($1) PUTN_CheckBND($1, $2);
+',dnl
+`dnl
+      /* the normal case: */
+      xp[i] = ($1) Max( Xmin($1), Min(Xmax($1), ($1) tp[i]));
+     /* test for range errors (not always needed but do it anyway) */
+     /* if xpp is unsigned && tp is signed, we need check if tp[i] >= 0 */
+     /* if tp is unsigned, we need not check if tp[i] < Xmin */
+      nrange += tp[i] > Xmax($1) PUTN_CheckBND($1, $2);
+')dnl
+    }
+   /* copy workspace back if necessary */
+    if (realign) {
+      memcpy(*xpp, tmp, (size_t)*ni*Xsizeof($1)));
+      xp = ($1 *) *xpp;
+    }
+   /* update xpp and tp */
+    xp += ni;
+    tp += ni;
+    *xpp = (void*)xp;
+  }
+  return nrange == 0 ? NC_NOERR : NC_ERANGE;
+
+#else   /* not SX */
+
+	char *xp = (char *) *xpp;
+	int status = NC_NOERR;
+
+	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
+	{
+		int lstatus = ncmpix_put_$1_$2(xp, tp);
+		if (status == NC_NOERR) /* report the first encountered error */
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+#endif
+}
+')dnl
+dnl dnl dnl
+dnl
+dnl NCX_PAD_PUTN_SHORT(xtype, ttype)
+dnl
+define(`NCX_PAD_PUTN_SHORT',dnl
+`dnl
+int
+ncmpix_pad_putn_$1_$2(void **xpp, MPI_Offset nelems, const $2 *tp)
+{
+	const MPI_Offset rndup = nelems % 2;
+
+	char *xp = (char *) *xpp;
+	int status = NC_NOERR;
+
+	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
+	{
+		int lstatus = ncmpix_put_$1_$2(xp, tp);
+		if (status == NC_NOERR) /* report the first encountered error */
+			status = lstatus;
+	}
+
+	if (rndup != 0)
+	{
+		(void) memcpy(xp, nada, (size_t)(Xsizeof($1)));
+		xp += Xsizeof($1);
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+')dnl
+
+dnl dnl dnl
+dnl
+dnl Declare & define routines
+dnl
+dnl dnl dnl
+
+/* schar ---------------------------------------------------------------------*/
+
+dnl NCX_GETN_CHAR(schar, schar)
+int
+ncmpix_getn_schar_schar(const void **xpp, MPI_Offset nelems, schar *tp)
+{
+	NCX_GETN_Byte_Body
+}
+dnl NCX_GETN_CHAR(schar, uchar)
+int
+ncmpix_getn_schar_uchar(const void **xpp, MPI_Offset nelems, uchar *tp)
+{
+	NCX_GETN_Byte_Body
+}
+NCX_GETN_CHAR(schar, short)
+NCX_GETN_CHAR(schar, int)
+NCX_GETN_CHAR(schar, long)
+NCX_GETN_CHAR(schar, float)
+NCX_GETN_CHAR(schar, double)
+NCX_GETN_CHAR(schar, longlong)
+NCX_GETN_CHAR(schar, ushort)
+NCX_GETN_CHAR(schar, uint)
+NCX_GETN_CHAR(schar, ulonglong)
+
+dnl NCX_PAD_GETN_CHAR(schar, schar)
+int
+ncmpix_pad_getn_schar_schar(const void **xpp, MPI_Offset nelems, schar *tp)
+{
+	NCX_PAD_GETN_Byte_Body
+}
+dnl NCX_PAD_GETN_CHAR(schar, uchar)
+int
+ncmpix_pad_getn_schar_uchar(const void **xpp, MPI_Offset nelems, uchar *tp)
+{
+	NCX_PAD_GETN_Byte_Body
+}
+NCX_PAD_GETN_CHAR(schar, short)
+NCX_PAD_GETN_CHAR(schar, int)
+NCX_PAD_GETN_CHAR(schar, long)
+NCX_PAD_GETN_CHAR(schar, float)
+NCX_PAD_GETN_CHAR(schar, double)
+NCX_PAD_GETN_CHAR(schar, longlong)
+NCX_PAD_GETN_CHAR(schar, ushort)
+NCX_PAD_GETN_CHAR(schar, uint)
+NCX_PAD_GETN_CHAR(schar, ulonglong)
+
+dnl NCX_PUTN_CHAR(schar, schar)
+int
+ncmpix_putn_schar_schar(void **xpp, MPI_Offset nelems, const schar *tp)
+{
+	NCX_PUTN_Byte_Body
+}
+dnl NCX_PUTN_CHAR(schar, uchar)
+int
+ncmpix_putn_schar_uchar(void **xpp, MPI_Offset nelems, const uchar *tp)
+{
+	NCX_PUTN_Byte_Body
+}
+NCX_PUTN_CHAR(schar, short)
+NCX_PUTN_CHAR(schar, int)
+NCX_PUTN_CHAR(schar, long)
+NCX_PUTN_CHAR(schar, float)
+NCX_PUTN_CHAR(schar, double)
+NCX_PUTN_CHAR(schar, longlong)
+NCX_PUTN_CHAR(schar, ushort)
+NCX_PUTN_CHAR(schar, uint)
+NCX_PUTN_CHAR(schar, ulonglong)
+
+dnl NCX_PAD_PUTN_CHAR(schar, schar)
+int
+ncmpix_pad_putn_schar_schar(void **xpp, MPI_Offset nelems, const schar *tp)
+{
+	NCX_PAD_PUTN_Byte_Body
+}
+dnl NCX_PAD_PUTN_CHAR(schar, uchar)
+int
+ncmpix_pad_putn_schar_uchar(void **xpp, MPI_Offset nelems, const uchar *tp)
+{
+	NCX_PAD_PUTN_Byte_Body
+}
+NCX_PAD_PUTN_CHAR(schar, short)
+NCX_PAD_PUTN_CHAR(schar, int)
+NCX_PAD_PUTN_CHAR(schar, long)
+NCX_PAD_PUTN_CHAR(schar, float)
+NCX_PAD_PUTN_CHAR(schar, double)
+NCX_PAD_PUTN_CHAR(schar, longlong)
+NCX_PAD_PUTN_CHAR(schar, ushort)
+NCX_PAD_PUTN_CHAR(schar, uint)
+NCX_PAD_PUTN_CHAR(schar, ulonglong)
+
+
+/* uchar ---------------------------------------------------------------------*/
+dnl
+dnl NCX_GETN_CHAR(uchar, schar)
+int
+ncmpix_getn_uchar_schar(const void **xpp, MPI_Offset nelems, schar *tp)
+{
+	int status = NC_NOERR;
+	uchar *xp = (uchar *)(*xpp);
+
+	while (nelems-- != 0)
+	{
+		if (*xp > SCHAR_MAX)
+			DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
+		*tp++ = (schar) *xp++; /* type cast from uchar to schar */
+		/* TODO: skip the assignment if NC_ERANGE occurs?
+		 * However, if doing so, many nc_test/nf_test will fail
+		 */
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+dnl NCX_GETN_CHAR(uchar, uchar)
+int
+ncmpix_getn_uchar_uchar(const void **xpp, MPI_Offset nelems, uchar *tp)
+{
+	NCX_GETN_Byte_Body
+}
+NCX_GETN_CHAR(uchar, short)
+NCX_GETN_CHAR(uchar, int)
+NCX_GETN_CHAR(uchar, long)
+NCX_GETN_CHAR(uchar, float)
+NCX_GETN_CHAR(uchar, double)
+NCX_GETN_CHAR(uchar, longlong)
+NCX_GETN_CHAR(uchar, ushort)
+NCX_GETN_CHAR(uchar, uint)
+NCX_GETN_CHAR(uchar, ulonglong)
+
+dnl NCX_PAD_GETN_CHAR(uchar, schar)
+int
+ncmpix_pad_getn_uchar_schar(const void **xpp, MPI_Offset nelems, schar *tp)
+{
+        int status = NC_NOERR;
+        MPI_Offset rndup = nelems % X_ALIGN;
+        uchar *xp = (uchar *) *xpp;
+        
+        if (rndup)
+                rndup = X_ALIGN - rndup;
+        
+        while (nelems-- != 0)
+        {       
+                if (*xp > SCHAR_MAX)
+                        DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
+                *tp++ = (schar) *xp++; /* type cast from uchar to schar */
+                /* TODO: skip the assignment if NC_ERANGE occurs?
+                 * However, if doing so, many nc_test/nf_test will fail
+                 */
+        }
+        
+        *xpp = (void *)(xp + rndup);
+        return status;
+}
+dnl NCX_PAD_GETN_CHAR(uchar, uchar)
+int
+ncmpix_pad_getn_uchar_uchar(const void **xpp, MPI_Offset nelems, uchar *tp)
+{
+	NCX_PAD_GETN_Byte_Body
+}
+NCX_PAD_GETN_CHAR(uchar, short)
+NCX_PAD_GETN_CHAR(uchar, int)
+NCX_PAD_GETN_CHAR(uchar, long)
+NCX_PAD_GETN_CHAR(uchar, float)
+NCX_PAD_GETN_CHAR(uchar, double)
+NCX_PAD_GETN_CHAR(uchar, longlong)
+NCX_PAD_GETN_CHAR(uchar, ushort)
+NCX_PAD_GETN_CHAR(uchar, uint)
+NCX_PAD_GETN_CHAR(uchar, ulonglong)
+
+dnl NCX_PUTN_CHAR(uchar, schar)
+int
+ncmpix_putn_uchar_schar(void **xpp, MPI_Offset nelems, const schar *tp)
+{
+	int status = NC_NOERR;
+	uchar *xp = (uchar *) *xpp;
+
+	while (nelems-- != 0)
+	{
+		if (*tp < 0)
+			DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
+		*xp++ = (uchar) (signed) *tp++; /* type cast from schar to uchar */
+		/* TODO: skip the assignment if NC_ERANGE occurs?
+		 * However, if doing so, many nc_test/nf_test will fail
+		 */
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+dnl NCX_PUTN_CHAR(uchar, uchar)
+int
+ncmpix_putn_uchar_uchar(void **xpp, MPI_Offset nelems, const uchar *tp)
+{
+	NCX_PUTN_Byte_Body
+}
+NCX_PUTN_CHAR(uchar, short)
+NCX_PUTN_CHAR(uchar, int)
+NCX_PUTN_CHAR(uchar, long)
+NCX_PUTN_CHAR(uchar, float)
+NCX_PUTN_CHAR(uchar, double)
+NCX_PUTN_CHAR(uchar, longlong)
+NCX_PUTN_CHAR(uchar, ushort)
+NCX_PUTN_CHAR(uchar, uint)
+NCX_PUTN_CHAR(uchar, ulonglong)
+
+dnl NCX_PAD_PUTN_UCHAR(uchar, schar)
+int
+ncmpix_pad_putn_uchar_schar(void **xpp, MPI_Offset nelems, const schar *tp)
+{
+	int status = NC_NOERR;
+	MPI_Offset rndup = nelems % X_ALIGN;
+	uchar *xp = (uchar *) *xpp;
+
+	if (rndup)
+		rndup = X_ALIGN - rndup;
+
+	while (nelems-- != 0)
+	{
+		if (*tp < 0)
+			DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
+		*xp++ = (uchar) (signed) *tp++; /* type cast from schar to uchar */
+		/* TODO: skip the assignment if NC_ERANGE occurs?
+		 * However, if doing so, many nc_test/nf_test will fail
+		 */
+	}
+
+
+	if (rndup)
+	{
+		(void) memcpy(xp, nada, (size_t)rndup);
+		xp += rndup;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+dnl NCX_PAD_PUTN_UCHAR(uchar, uchar)
+int
+ncmpix_pad_putn_uchar_uchar(void **xpp, MPI_Offset nelems, const uchar *tp)
+{
+	NCX_PAD_PUTN_Byte_Body
+}
+NCX_PAD_PUTN_CHAR(uchar, short)
+NCX_PAD_PUTN_CHAR(uchar, int)
+NCX_PAD_PUTN_CHAR(uchar, long)
+NCX_PAD_PUTN_CHAR(uchar, float)
+NCX_PAD_PUTN_CHAR(uchar, double)
+NCX_PAD_PUTN_CHAR(uchar, longlong)
+NCX_PAD_PUTN_CHAR(uchar, ushort)
+NCX_PAD_PUTN_CHAR(uchar, uint)
+NCX_PAD_PUTN_CHAR(uchar, ulonglong)
+
+/* short ---------------------------------------------------------------------*/
+
+#if X_SIZEOF_SHORT == SIZEOF_SHORT
+/* optimized version */
+int
+ncmpix_getn_short_short(const void **xpp, MPI_Offset nelems, short *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_SHORT);
+# else
+	swapn2b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_SHORT);
+	return NC_NOERR;
+}
+#else
+NCX_GETN(short, short)
+#endif
+NCX_GETN(short, schar)
+NCX_GETN(short, int)
+NCX_GETN(short, long)
+NCX_GETN(short, float)
+NCX_GETN(short, double)
+NCX_GETN(short, longlong)
+NCX_GETN(short, uchar)
+NCX_GETN(short, ushort)
+NCX_GETN(short, uint)
+NCX_GETN(short, ulonglong)
+
+NCX_PAD_GETN_SHORT(short, schar)
+NCX_PAD_GETN_SHORT(short, uchar)
+NCX_PAD_GETN_SHORT(short, short)
+NCX_PAD_GETN_SHORT(short, int)
+NCX_PAD_GETN_SHORT(short, long)
+NCX_PAD_GETN_SHORT(short, float)
+NCX_PAD_GETN_SHORT(short, double)
+NCX_PAD_GETN_SHORT(short, uint)
+NCX_PAD_GETN_SHORT(short, longlong)
+NCX_PAD_GETN_SHORT(short, ulonglong)
+NCX_PAD_GETN_SHORT(short, ushort)
+
+#if X_SIZEOF_SHORT == SIZEOF_SHORT
+/* optimized version */
+int
+ncmpix_putn_short_short(void **xpp, MPI_Offset nelems, const short *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_SHORT);
+# else
+	swapn2b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_SHORT);
+	return NC_NOERR;
+}
+#else
+NCX_PUTN(short, short)
+#endif
+NCX_PUTN(short, schar)
+NCX_PUTN(short, int)
+NCX_PUTN(short, long)
+NCX_PUTN(short, float)
+NCX_PUTN(short, double)
+NCX_PUTN(short, longlong)
+NCX_PUTN(short, uchar)
+NCX_PUTN(short, uint)
+NCX_PUTN(short, ulonglong)
+NCX_PUTN(short, ushort)
+
+NCX_PAD_PUTN_SHORT(short, schar)
+NCX_PAD_PUTN_SHORT(short, uchar)
+NCX_PAD_PUTN_SHORT(short, short)
+NCX_PAD_PUTN_SHORT(short, int)
+NCX_PAD_PUTN_SHORT(short, long)
+NCX_PAD_PUTN_SHORT(short, float)
+NCX_PAD_PUTN_SHORT(short, double)
+NCX_PAD_PUTN_SHORT(short, uint)
+NCX_PAD_PUTN_SHORT(short, longlong)
+NCX_PAD_PUTN_SHORT(short, ulonglong)
+NCX_PAD_PUTN_SHORT(short, ushort)
+
+
+/* ushort --------------------------------------------------------------------*/
+
+#if X_SIZEOF_USHORT == SIZEOF_USHORT
+/* optimized version */
+int
+ncmpix_getn_ushort_ushort(const void **xpp, MPI_Offset nelems, unsigned short *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_UNSIGNED_SHORT);
+# else
+	swapn2b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_USHORT);
+	return NC_NOERR;
+}
+#else
+NCX_GETN(ushort, ushort)
+#endif
+NCX_GETN(ushort, schar)
+NCX_GETN(ushort, short)
+NCX_GETN(ushort, int)
+NCX_GETN(ushort, long)
+NCX_GETN(ushort, float)
+NCX_GETN(ushort, double)
+NCX_GETN(ushort, longlong)
+NCX_GETN(ushort, uchar)
+NCX_GETN(ushort, uint)
+NCX_GETN(ushort, ulonglong)
+
+NCX_PAD_GETN_SHORT(ushort, schar)
+NCX_PAD_GETN_SHORT(ushort, short)
+NCX_PAD_GETN_SHORT(ushort, int)
+NCX_PAD_GETN_SHORT(ushort, long)
+NCX_PAD_GETN_SHORT(ushort, float)
+NCX_PAD_GETN_SHORT(ushort, double)
+NCX_PAD_GETN_SHORT(ushort, uchar)
+NCX_PAD_GETN_SHORT(ushort, ushort)
+NCX_PAD_GETN_SHORT(ushort, uint)
+NCX_PAD_GETN_SHORT(ushort, longlong)
+NCX_PAD_GETN_SHORT(ushort, ulonglong)
+
+#if X_SIZEOF_USHORT == SIZEOF_USHORT
+/* optimized version */
+int
+ncmpix_putn_ushort_ushort(void **xpp, MPI_Offset nelems, const unsigned short *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_USHORT);
+# else
+	swapn2b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_USHORT);
+	return NC_NOERR;
+}
+#else
+NCX_PUTN(ushort, ushort)
+#endif
+NCX_PUTN(ushort, schar)
+NCX_PUTN(ushort, short)
+NCX_PUTN(ushort, int)
+NCX_PUTN(ushort, long)
+NCX_PUTN(ushort, float)
+NCX_PUTN(ushort, double)
+NCX_PUTN(ushort, longlong)
+NCX_PUTN(ushort, uchar)
+NCX_PUTN(ushort, uint)
+NCX_PUTN(ushort, ulonglong)
+
+NCX_PAD_PUTN_SHORT(ushort, schar)
+NCX_PAD_PUTN_SHORT(ushort, uchar)
+NCX_PAD_PUTN_SHORT(ushort, short)
+NCX_PAD_PUTN_SHORT(ushort, int)
+NCX_PAD_PUTN_SHORT(ushort, long)
+NCX_PAD_PUTN_SHORT(ushort, float)
+NCX_PAD_PUTN_SHORT(ushort, double)
+NCX_PAD_PUTN_SHORT(ushort, uint)
+NCX_PAD_PUTN_SHORT(ushort, longlong)
+NCX_PAD_PUTN_SHORT(ushort, ulonglong)
+NCX_PAD_PUTN_SHORT(ushort, ushort)
+
+
+/* int -----------------------------------------------------------------------*/
+
+#if X_SIZEOF_INT == SIZEOF_INT
+/* optimized version */
+int
+ncmpix_getn_int_int(const void **xpp, MPI_Offset nelems, int *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_INT);
+# else
+	swapn4b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_INT);
+	return NC_NOERR;
+}
+#else
+NCX_GETN(int, int)
+#endif
+NCX_GETN(int, schar)
+NCX_GETN(int, short)
+NCX_GETN(int, long)
+NCX_GETN(int, float)
+NCX_GETN(int, double)
+NCX_GETN(int, longlong)
+NCX_GETN(int, uchar)
+NCX_GETN(int, ushort)
+NCX_GETN(int, uint)
+NCX_GETN(int, ulonglong)
+
+#if X_SIZEOF_INT == SIZEOF_INT
+/* optimized version */
+int
+ncmpix_putn_int_int(void **xpp, MPI_Offset nelems, const int *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_INT);
+# else
+	swapn4b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_INT);
+	return NC_NOERR;
+}
+#else
+NCX_PUTN(int, int)
+#endif
+NCX_PUTN(int, schar)
+NCX_PUTN(int, short)
+NCX_PUTN(int, long)
+NCX_PUTN(int, float)
+NCX_PUTN(int, double)
+NCX_PUTN(int, longlong)
+NCX_PUTN(int, uchar)
+NCX_PUTN(int, ushort)
+NCX_PUTN(int, uint)
+NCX_PUTN(int, ulonglong)
+
+/* uint ----------------------------------------------------------------------*/
+
+#if X_SIZEOF_UINT == SIZEOF_UINT
+/* optimized version */
+int
+ncmpix_getn_uint_uint(const void **xpp, MPI_Offset nelems, unsigned int *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_UINT);
+# else
+	swapn4b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_UINT);
+	return NC_NOERR;
+}
+#else
+NCX_GETN(uint, uint)
+#endif
+NCX_GETN(uint, schar)
+NCX_GETN(uint, short)
+NCX_GETN(uint, int)
+NCX_GETN(uint, long)
+NCX_GETN(uint, float)
+NCX_GETN(uint, double)
+NCX_GETN(uint, longlong)
+NCX_GETN(uint, uchar)
+NCX_GETN(uint, ushort)
+NCX_GETN(uint, ulonglong)
+
+#if X_SIZEOF_UINT == SIZEOF_UINT
+/* optimized version */
+int
+ncmpix_putn_uint_uint(void **xpp, MPI_Offset nelems, const unsigned int *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_UINT);
+# else
+	swapn4b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_UINT);
+	return NC_NOERR;
+}
+#else
+NCX_PUTN(uint, uint)
+#endif
+NCX_PUTN(uint, schar)
+NCX_PUTN(uint, short)
+NCX_PUTN(uint, int)
+NCX_PUTN(uint, long)
+NCX_PUTN(uint, float)
+NCX_PUTN(uint, double)
+NCX_PUTN(uint, longlong)
+NCX_PUTN(uint, uchar)
+NCX_PUTN(uint, ushort)
+NCX_PUTN(uint, ulonglong)
+
+
+/* float ---------------------------------------------------------------------*/
+
+#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)
+/* optimized version */
+int
+ncmpix_getn_float_float(const void **xpp, MPI_Offset nelems, float *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_FLOAT);
+# else
+	swapn4b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_FLOAT);
+	return NC_NOERR;
+}
+#elif defined(vax) && vax != 0
+int
+ncmpix_getn_float_float(const void **xpp, MPI_Offset nfloats, float *ip)
+{
+	float *const end = ip + nfloats;
+
+	while (ip < end)
+	{
+GET_VAX_DFLOAT_Body(`(*xpp)')
+
+		ip++;
+		*xpp = (char *)(*xpp) + X_SIZEOF_FLOAT;
+	}
+	return NC_NOERR;
+}
+#else
+int
+ncmpix_getn_float_float(const void **xpp, MPI_Offset nelems, float *tp)
+{
+	const char *xp = *xpp;
+	int status = NC_NOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		const int lstatus = ncmpix_get_float_float(xp, tp);
+		if (status == NC_NOERR) /* report the first encountered error */
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+#endif
+NCX_GETN(float, schar)
+NCX_GETN(float, short)
+NCX_GETN(float, int)
+NCX_GETN(float, long)
+NCX_GETN(float, double)
+NCX_GETN(float, longlong)
+NCX_GETN(float, ushort)
+NCX_GETN(float, uchar)
+NCX_GETN(float, uint)
+NCX_GETN(float, ulonglong)
+
+#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)
+/* optimized version */
+int
+ncmpix_putn_float_float(void **xpp, MPI_Offset nelems, const float *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_FLOAT);
+# else
+	swapn4b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_FLOAT);
+	return NC_NOERR;
+}
+#elif defined(vax) && vax != 0
+int
+ncmpix_putn_float_float(void **xpp, MPI_Offset nfloats, const float *ip)
+{
+	const float *const end = ip + nfloats;
+
+	while (ip < end)
+	{
+PUT_VAX_DFLOAT_Body(`(*xpp)')
+
+		ip++;
+		*xpp = (char *)(*xpp) + X_SIZEOF_FLOAT;
+	}
+	return NC_NOERR;
+}
+#else
+int
+ncmpix_putn_float_float(void **xpp, MPI_Offset nelems, const float *tp)
+{
+	char *xp = *xpp;
+	int status = NC_NOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		int lstatus = ncmpix_put_float_float(xp, tp);
+		if (status == NC_NOERR) /* report the first encountered error */
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+#endif
+NCX_PUTN(float, schar)
+NCX_PUTN(float, short)
+NCX_PUTN(float, int)
+NCX_PUTN(float, long)
+NCX_PUTN(float, double)
+NCX_PUTN(float, longlong)
+NCX_PUTN(float, uchar)
+NCX_PUTN(float, ushort)
+NCX_PUTN(float, uint)
+NCX_PUTN(float, ulonglong)
+
+/* double --------------------------------------------------------------------*/
+
+#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT)
+/* optimized version */
+int
+ncmpix_getn_double_double(const void **xpp, MPI_Offset nelems, double *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_DOUBLE);
+# else
+	swapn8b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_DOUBLE);
+	return NC_NOERR;
+}
+#elif defined(vax) && vax != 0
+int
+ncmpix_getn_double_double(const void **xpp, MPI_Offset ndoubles, double *ip)
+{
+	double *const end = ip + ndoubles;
+
+	while (ip < end)
+	{
+GET_VAX_DDOUBLE_Body(`(*xpp)')
+		ip++;
+		*xpp = (char *)(*xpp) + X_SIZEOF_DOUBLE;
+	}
+	return NC_NOERR;
+}
+	/* vax */
+#else
+int
+ncmpix_getn_double_double(const void **xpp, MPI_Offset nelems, double *tp)
+{
+	const char *xp = *xpp;
+	int status = NC_NOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		const int lstatus = ncmpix_get_double_double(xp, tp);
+		if (status == NC_NOERR) /* report the first encountered error */
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+#endif
+NCX_GETN(double, schar)
+NCX_GETN(double, short)
+NCX_GETN(double, int)
+NCX_GETN(double, long)
+NCX_GETN(double, float)
+NCX_GETN(double, longlong)
+NCX_GETN(double, uchar)
+NCX_GETN(double, ushort)
+NCX_GETN(double, uint)
+NCX_GETN(double, ulonglong)
+
+#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT)
+/* optimized version */
+int
+ncmpix_putn_double_double(void **xpp, MPI_Offset nelems, const double *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_DOUBLE);
+# else
+	swapn8b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE);
+	return NC_NOERR;
+}
+#elif defined(vax) && vax != 0
+int
+ncmpix_putn_double_double(void **xpp, MPI_Offset ndoubles, const double *ip)
+{
+	const double *const end = ip + ndoubles;
+
+	while (ip < end)
+	{
+PUT_VAX_DDOUBLE_Body(`(*xpp)')
+		ip++;
+		*xpp = (char *)(*xpp) + X_SIZEOF_DOUBLE;
+	}
+	return NC_NOERR;
+}
+	/* vax */
+#else
+int
+ncmpix_putn_double_double(void **xpp, MPI_Offset nelems, const double *tp)
+{
+	char *xp = *xpp;
+	int status = NC_NOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		int lstatus = ncmpix_put_double_double(xp, tp);
+		if (status == NC_NOERR) /* report the first encountered error */
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+#endif
+NCX_PUTN(double, schar)
+NCX_PUTN(double, short)
+NCX_PUTN(double, int)
+NCX_PUTN(double, long)
+NCX_PUTN(double, float)
+NCX_PUTN(double, longlong)
+NCX_PUTN(double, uchar)
+NCX_PUTN(double, ushort)
+NCX_PUTN(double, uint)
+NCX_PUTN(double, ulonglong)
+
+
+/* longlong ------------------------------------------------------------------*/
+
+#if X_SIZEOF_INT64 == SIZEOF_LONGLONG
+/* optimized version */
+int
+ncmpix_getn_int64_longlong(const void **xpp, MPI_Offset nelems, long long *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_LONG_LONG);
+# else
+	swapn8b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_INT64);
+	return NC_NOERR;
+}
+#else
+NCX_GETN(int64, longlong)
+#endif
+NCX_GETN(int64, schar)
+NCX_GETN(int64, short)
+NCX_GETN(int64, int)
+NCX_GETN(int64, long)
+NCX_GETN(int64, float)
+NCX_GETN(int64, double)
+NCX_GETN(int64, uchar)
+NCX_GETN(int64, ushort)
+NCX_GETN(int64, uint)
+NCX_GETN(int64, ulonglong)
+
+#if X_SIZEOF_INT64 == SIZEOF_LONGLONG
+/* optimized version */
+int
+ncmpix_putn_int64_longlong(void **xpp, MPI_Offset nelems, const long long *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_INT64);
+# else
+	swapn8b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_INT64);
+	return NC_NOERR;
+}
+#else
+NCX_PUTN(int64, longlong)
+#endif
+NCX_PUTN(int64, schar)
+NCX_PUTN(int64, short)
+NCX_PUTN(int64, int)
+NCX_PUTN(int64, long)
+NCX_PUTN(int64, float)
+NCX_PUTN(int64, double)
+NCX_PUTN(int64, uchar)
+NCX_PUTN(int64, ushort)
+NCX_PUTN(int64, uint)
+NCX_PUTN(int64, ulonglong)
+
+/* uint64 --------------------------------------------------------------------*/
+
+#if X_SIZEOF_UINT64 == SIZEOF_ULONGLONG
+/* optimized version */
+int
+ncmpix_getn_uint64_ulonglong(const void **xpp, MPI_Offset nelems, unsigned long long *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_UNSIGNED_LONG_LONG);
+# else
+	swapn8b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_UINT64);
+	return NC_NOERR;
+}
+#else
+NCX_GETN(uint64, ulonglong)
+#endif
+NCX_GETN(uint64, schar)
+NCX_GETN(uint64, short)
+NCX_GETN(uint64, int)
+NCX_GETN(uint64, long)
+NCX_GETN(uint64, float)
+NCX_GETN(uint64, double)
+NCX_GETN(uint64, longlong)
+NCX_GETN(uint64, uchar)
+NCX_GETN(uint64, ushort)
+NCX_GETN(uint64, uint)
+
+#if X_SIZEOF_UINT64 == SIZEOF_ULONGLONG
+/* optimized version */
+int
+ncmpix_putn_uint64_ulonglong(void **xpp, MPI_Offset nelems, const unsigned long long *tp)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_UINT64);
+# else
+	swapn8b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_UINT64);
+	return NC_NOERR;
+}
+#else
+NCX_PUTN(uint64, ulonglong)
+#endif
+NCX_PUTN(uint64, schar)
+NCX_PUTN(uint64, short)
+NCX_PUTN(uint64, int)
+NCX_PUTN(uint64, long)
+NCX_PUTN(uint64, float)
+NCX_PUTN(uint64, double)
+NCX_PUTN(uint64, longlong)
+NCX_PUTN(uint64, uchar)
+NCX_PUTN(uint64, ushort)
+NCX_PUTN(uint64, uint)
+
+
+/*
+ * Other aggregate conversion functions.
+ */
+
+/* text */
+
+int
+ncmpix_getn_text(const void **xpp, MPI_Offset nelems, char *tp)
+{
+NCX_GETN_Byte_Body
+}
+
+int
+ncmpix_pad_getn_text(const void **xpp, MPI_Offset nelems, char *tp)
+{
+NCX_PAD_GETN_Byte_Body
+}
+
+int
+ncmpix_putn_text(void **xpp, MPI_Offset nelems, const char *tp)
+{
+NCX_PUTN_Byte_Body
+}
+
+int
+ncmpix_pad_putn_text(void **xpp, MPI_Offset nelems, const char *tp)
+{
+NCX_PAD_PUTN_Byte_Body
+}
+
+
+/* opaque */
+
+int
+ncmpix_getn_void(const void **xpp, MPI_Offset nelems, void *tp)
+{
+NCX_GETN_Byte_Body
+}
+
+int
+ncmpix_pad_getn_void(const void **xpp, MPI_Offset nelems, void *tp)
+{
+NCX_PAD_GETN_Byte_Body
+}
+
+int
+ncmpix_putn_void(void **xpp, MPI_Offset nelems, const void *tp)
+{
+NCX_PUTN_Byte_Body
+}
+
+int
+ncmpix_pad_putn_void(void **xpp, MPI_Offset nelems, const void *tp)
+{
+NCX_PAD_PUTN_Byte_Body
+}
diff --git a/src/lib/nonblocking.c b/src/lib/nonblocking.c
new file mode 100644
index 0000000..21086dd
--- /dev/null
+++ b/src/lib/nonblocking.c
@@ -0,0 +1,2201 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: nonblocking.c 2214 2015-12-08 00:33:40Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "ncmpidtype.h"
+#include "macro.h"
+
+
+/* buffer layers:
+
+        User Level              buf     (user defined buffer of MPI_Datatype)
+        MPI Datatype Level      cbuf    (contiguous buffer of ptype)
+        NetCDF XDR Level        xbuf    (XDR I/O buffer)
+*/
+
+/* Prototypes for functions used only in this file */
+static int ncmpii_wait_getput(NC *ncp, int num_reqs, NC_req *req_head,
+                              int rw_flag, int io_method);
+
+static int ncmpii_mgetput(NC *ncp, int num_reqs, NC_req *reqs, int rw_flag,
+                          int io_method);
+
+/*----< ncmpii_getput_zero_req() >--------------------------------------------*/
+/* This function is called when this process has zero-length I/O request and
+ * must participate all the MPI collective calls involved in the collective
+ * APIs and wait_all(), which include setting fileview, collective read/write,
+ * another setting fileview.
+ *
+ * This function is collective.
+ */
+static int
+ncmpii_getput_zero_req(NC  *ncp,
+                       int  rw_flag)      /* WRITE_REQ or READ_REQ */
+{
+    int err, mpireturn, status=NC_NOERR;
+    MPI_Status mpistatus;
+    MPI_File fh;
+
+    fh = ncp->nciop->collective_fh;
+
+    TRACE_IO(MPI_File_set_view)(fh, 0, MPI_BYTE, MPI_BYTE, "native",
+                                MPI_INFO_NULL);
+
+    if (rw_flag == READ_REQ) {
+        TRACE_IO(MPI_File_read_all)(fh, NULL, 0, MPI_BYTE, &mpistatus);
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_File_read_all");
+            status = (err == NC_EFILE) ? NC_EREAD : err;
+            DEBUG_ASSIGN_ERROR(status, status)
+        }
+    } else { /* WRITE_REQ */
+        TRACE_IO(MPI_File_write_all)(fh, NULL, 0, MPI_BYTE, &mpistatus);
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_File_write_all");
+            status = (err == NC_EFILE) ? NC_EWRITE : err;
+            DEBUG_ASSIGN_ERROR(status, status)
+        }
+    }
+
+    /* No longer need to reset the file view, as the root's fileview includes
+     * the whole file header.
+     TRACE_IO(MPI_File_set_view)(fh, 0, MPI_BYTE, MPI_BYTE, "native",
+                                 MPI_INFO_NULL);
+     */
+
+    return status;
+}
+
+/*----< ncmpii_abuf_coalesce() >---------------------------------------------*/
+/* this function should be called after all bput requests have been served */
+static int
+ncmpii_abuf_coalesce(NC *ncp)
+{
+    int i;
+
+    i = ncp->abuf->tail - 1;
+    /* tail is always pointing to the last (empty) entry of occupy_table[] */
+
+    /* coalesce the freed entries backwardly from the tail */
+    while (i >= 0) {
+        if (ncp->abuf->occupy_table[i].is_used == 0) {
+            ncp->abuf->size_used -= ncp->abuf->occupy_table[i].req_size;
+            i--;
+        }
+        else break;
+    }
+    ncp->abuf->tail = i + 1;
+    /* This may not be ideal, as we stop at the last one that is yet to be
+     * freed. There may be some freed entries before this yet-to-be-freed
+     * one, but we would like to keep the available space as contiguous as
+     * possible. Maybe some smart approach can be considered here.
+     */
+
+    return NC_NOERR;
+}
+
+#define FREE_REQUEST(req) {                                                   \
+    if (req->abuf_index >= 0)                                                 \
+        ncp->abuf->occupy_table[req->abuf_index].is_used = 0; /* mark free */ \
+    else if (req->xbuf != NULL && req->xbuf != req->buf)                      \
+        NCI_Free(req->xbuf);                                                  \
+    req->xbuf = NULL;                                                         \
+                                                                              \
+    for (j=0; j<req->num_subreqs; j++)                                        \
+        NCI_Free(req->subreqs[j].start);                                      \
+                                                                              \
+    if (req->num_subreqs > 0)                                                 \
+        NCI_Free(req->subreqs);                                               \
+    NCI_Free(req->start);                                                     \
+}
+
+/*----< ncmpi_cancel() >------------------------------------------------------*/
+int
+ncmpi_cancel(int  ncid,
+             int  num_req,  /* NC_REQ_ALL or non-negative value */
+             int *req_ids,  /* [num_req] */
+             int *statuses) /* [num_req] */
+{
+    int status;
+    NC *ncp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_EINDEFINE)
+
+    return ncmpii_cancel(ncp, num_req, req_ids, statuses);
+}
+
+/*----< ncmpii_cancel() >-----------------------------------------------------*/
+int
+ncmpii_cancel(NC  *ncp,
+              int  num_req,  /* NC_REQ_all means all pending requests */
+              int *req_ids,  /* [num_req]: IN/OUT */
+              int *statuses) /* [num_req] can be NULL (ignore status) */
+{
+    int i, j, status=NC_NOERR;
+    NC_req *pre_req, *cur_req;
+
+    if (num_req == 0)
+        return NC_NOERR;
+
+    /* cancel all pending requests, ignore req_ids and statuses */
+    if (num_req == NC_REQ_ALL) {
+        cur_req = ncp->head;
+        while (cur_req != NULL) {
+            FREE_REQUEST(cur_req)
+            NCI_Free(cur_req);
+            cur_req = cur_req->next;
+        }
+        ncp->head = NULL;
+        ncp->tail = NULL;
+        return NC_NOERR;
+    }
+
+    /* collect the requests from the linked list */
+    for (i=0; i<num_req; i++) {
+        int found_id=-1;
+        if (statuses != NULL) statuses[i] = NC_NOERR;
+
+        if (req_ids[i] == NC_REQ_NULL)
+            continue;
+
+        if (ncp->head == NULL) {
+            if (statuses != NULL) DEBUG_ASSIGN_ERROR(statuses[i], NC_EINVAL_REQUEST)
+            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EINVAL_REQUEST)
+            continue;
+        }
+
+        pre_req = cur_req = ncp->head;
+        while (cur_req != NULL) {
+            /* there may be more than one node with the same ID */
+            if (cur_req->id == req_ids[i]) {
+                if (cur_req == ncp->head) { /* move ncp->head ahead */
+                    ncp->head = cur_req->next;
+                    pre_req = ncp->head;
+                }
+                else /* move pre_req ahead */
+                    pre_req->next = cur_req->next;
+
+                FREE_REQUEST(cur_req)
+                NCI_Free(cur_req);
+                found_id = req_ids[i];
+                /* move cur_req ahead */
+                cur_req = (pre_req == ncp->head) ? pre_req : pre_req->next;
+            }
+            else if (found_id >= 0) break;
+            else {
+                if (cur_req == pre_req) cur_req = pre_req->next;
+                else {
+                    pre_req = cur_req;
+                    cur_req = pre_req->next;
+                }
+            }
+        }
+
+        if (found_id == -1) { /* no such request ID */
+            if (statuses != NULL) DEBUG_ASSIGN_ERROR(statuses[i], NC_EINVAL_REQUEST)
+            /* retain the first error status */
+            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EINVAL_REQUEST)
+        }
+        else req_ids[i] = NC_REQ_NULL;
+    }
+
+    /* make sure ncp->tail pointing to the tail */
+    ncp->tail = ncp->head;
+    while (ncp->tail != NULL && ncp->tail->next != NULL)
+        ncp->tail = ncp->tail->next;
+
+    return status;
+}
+
+/*----< ncmpi_inq_nreqs() >---------------------------------------------------*/
+/* TODO: add member num_reqs into NC_req to track this info */
+int
+ncmpi_inq_nreqs(int  ncid,
+                int *nreqs) /* OUT: number of pending requests */
+{
+    int     status, prev_id;
+    NC     *ncp;
+    NC_req *req_ptr;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    req_ptr = ncp->head;
+    *nreqs = 0;
+    prev_id = NC_REQ_NULL;
+    while (req_ptr != NULL) {
+        /* some requests in the linked list may share the same ID, they were
+         * corresponding to the subrequests made from iput/iget/bput varn APIs.
+         */
+        if (req_ptr->id != prev_id) {
+            prev_id = req_ptr->id;
+            (*nreqs)++;
+        }
+        req_ptr = req_ptr->next;
+    }
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_wait() >--------------------------------------------------------*/
+/* ncmpi_wait() is an independent call
+ * Argument num_reqs can be NC_REQ_ALL which means to flush all pending
+ * nonblocking requests. In this case, arguments req_ids and statuses will be
+ * ignored.
+ * Argument num_reqs must either be NC_REQ_ALL or a non-negative value.
+ * Argument statuses can be NULL, meaning the caller only cares about the
+ * error code returned by this call, but not the statuses of individual
+ * nonblocking requests.
+ */
+int
+ncmpi_wait(int ncid,
+           int num_reqs,
+           int *req_ids,  /* [num_reqs]: IN/OUT */
+           int *statuses) /* [num_reqs] */
+{
+    int  status=NC_NOERR;
+    NC  *ncp;
+
+    if (num_reqs == 0) return NC_NOERR;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+#ifdef ENABLE_NONBLOCKING
+    return ncmpii_wait(ncp, INDEP_IO, num_reqs, req_ids, statuses);
+#else
+    int i, err, *reqids=NULL;
+    if (num_reqs == NC_REQ_ALL) { /* flush all pending requests */
+        /* in this case, arguments req_ids and statuses are ignored */
+        int prev_id = NC_REQ_NULL;
+        NC_req *req_ptr = ncp->head;
+        num_reqs = 0;
+        while (req_ptr != NULL) {
+            /* some requests in the linked list may share the same ID, they were
+             * corresponding to the subrequests made from iput/iget/bput varn APIs.
+             */
+            if (req_ptr->id != prev_id) {
+                prev_id = req_ptr->id;
+                num_reqs++;
+            }
+            req_ptr = req_ptr->next;
+        }
+        /* allocate ID array */
+        reqids = (int*) NCI_Malloc(num_reqs * sizeof(int));
+        req_ptr = ncp->head;
+        num_reqs = 0;
+        prev_id = NC_REQ_NULL;
+        while (req_ptr != NULL) {
+            if (req_ptr->id != prev_id) {
+                prev_id = req_ptr->id;
+                reqids[num_reqs++] = prev_id;
+            }
+            req_ptr = req_ptr->next;
+        }
+        req_ids = reqids;
+    }
+    for (i=0; i<num_reqs; i++) { /* serve one request at a time */
+        if (statuses == NULL)
+            err = ncmpii_wait(ncp, INDEP_IO, 1, &req_ids[i], NULL);
+        else
+            err = ncmpii_wait(ncp, INDEP_IO, 1, &req_ids[i], &statuses[i]);
+        if (status == NC_NOERR) status = err;
+    }
+    if (reqids != NULL) NCI_Free(reqids);
+
+    return status; /* return the first error encountered */
+#endif
+}
+
+/*----< ncmpi_wait_all() >----------------------------------------------------*/
+/* ncmpi_wait_all() is a collective call
+ * Argument num_reqs can be NC_REQ_ALL which means to flush all pending
+ * nonblocking requests. In this case, arguments req_ids and statuses will be
+ * ignored.
+ * Argument num_reqs must either be NC_REQ_ALL or a non-negative value.
+ * Argument statuses can be NULL, meaning the caller only cares about the
+ * error code returned by this call, but not the statuses of individual
+ * nonblocking requests.
+ */
+int
+ncmpi_wait_all(int  ncid,
+               int  num_reqs, /* number of requests */
+               int *req_ids,  /* [num_reqs]: IN/OUT */
+               int *statuses) /* [num_reqs], can be NULL */
+{
+    int  status=NC_NOERR;
+    NC  *ncp;
+    /* the following line CANNOT be added, because ncmpi_wait_all() is a
+     * collective call, all processes must participate some MPI collective
+     * operations used later on.
+     */
+    /* if (num_reqs == 0) return NC_NOERR; */
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR)
+        /* must return the error now, parallel program might hang */
+        return status;
+
+#ifdef ENABLE_NONBLOCKING
+    return ncmpii_wait(ncp, COLL_IO, num_reqs, req_ids, statuses);
+#else
+    int i, err, *reqids=NULL;
+
+    /* This API is collective, so make it illegal in indep mode. This also
+       ensures the program will returns back to collective mode. */
+    if (NC_indep(ncp)) DEBUG_RETURN_ERROR(NC_EINDEP);
+
+    /* must enter independent mode, as num_reqs may be different among
+       processes */
+    err = ncmpi_begin_indep_data(ncid);
+    if (status == NC_NOERR) status = err;
+
+    if (num_reqs == NC_REQ_ALL) { /* flush all pending requests */
+        int prev_id = NC_REQ_NULL;
+        NC_req *req_ptr = ncp->head;
+        num_reqs = 0;
+        while (req_ptr != NULL) {
+            /* some requests in the linked list may share the same ID, they were
+             * corresponding to the subrequests made from iput/iget/bput varn APIs.
+             */
+            if (req_ptr->id != prev_id) {
+                prev_id = req_ptr->id;
+                num_reqs++;
+            }
+            req_ptr = req_ptr->next;
+        }
+        /* allocate ID array */
+        reqids = (int*) NCI_Malloc(num_reqs * sizeof(int));
+        req_ptr = ncp->head;
+        num_reqs = 0;
+        prev_id = NC_REQ_NULL;
+        while (req_ptr != NULL) {
+            if (req_ptr->id != prev_id) {
+                prev_id = req_ptr->id;
+                reqids[num_reqs++] = prev_id;
+            }
+            req_ptr = req_ptr->next;
+        }
+        req_ids = reqids;
+    }
+    for (i=0; i<num_reqs; i++) { /* serve one request at a time */
+        if (statuses == NULL)
+            err = ncmpii_wait(ncp, INDEP_IO, 1, &req_ids[i], NULL);
+        else
+            err = ncmpii_wait(ncp, INDEP_IO, 1, &req_ids[i], &statuses[i]);
+        if (status == NC_NOERR) status = err;
+    }
+    if (reqids != NULL) NCI_Free(reqids);
+
+    /* return to collective data mode */
+    err = ncmpi_end_indep_data(ncid);
+    if (status == NC_NOERR) status = err;
+
+    return status; /* return the first error encountered, if there is any */
+#endif
+}
+
+/*----< ncmpii_concatenate_datatypes() >--------------------------------------*/
+static int
+ncmpii_concatenate_datatypes(int           num,
+                             int          *blocklens,     /* IN: [num] */
+                             MPI_Offset   *displacements, /* IN: [num] */
+                             MPI_Datatype *dtypes,        /* IN: [num] */
+                             MPI_Datatype *datatype)      /* OUT: */
+{
+#if SIZEOF_MPI_AINT != SIZEOF_MPI_OFFSET
+    int i;
+#endif
+    int mpireturn, status=NC_NOERR;
+    MPI_Aint *addrs;
+
+    *datatype = MPI_BYTE;
+
+    if (num <= 0) return NC_NOERR;
+
+    /* on most 32 bit systems, MPI_Aint and MPI_Offset are different sizes.
+     * Possible that on those platforms some of the beginning offsets of
+     * these variables in the dataset won't fit into the aint used by
+     * MPI_Type_create_struct.  Minor optimization: we don't need to do any
+     * of this if MPI_Aint and MPI_Offset are the same size  */
+
+    /* at the configure time, size of MPI_Offset and MPI_Aint are checked */
+#if SIZEOF_MPI_AINT == SIZEOF_MPI_OFFSET
+    addrs = (MPI_Aint*) displacements; /* cast ok: types same size */
+#else
+    /* if (sizeof(MPI_Offset) != sizeof(MPI_Aint)) */
+    addrs = (MPI_Aint *) NCI_Malloc((size_t)num * SIZEOF_MPI_AINT);
+    for (i=0; i<num; i++) {
+        addrs[i] = displacements[i];
+        if (displacements[i] != addrs[i]) {
+            NCI_Free(addrs);
+            DEBUG_RETURN_ERROR(NC_EAINT_TOO_SMALL)
+        }
+    }
+#endif
+
+#ifdef HAVE_MPI_TYPE_CREATE_STRUCT
+    mpireturn = MPI_Type_create_struct(num, blocklens, addrs, dtypes, datatype);
+#else
+    mpireturn = MPI_Type_struct(num, blocklens, addrs, dtypes, datatype);
+#endif
+    if (mpireturn != MPI_SUCCESS)
+        status = ncmpii_handle_error(mpireturn, "MPI_Type_create_struct");
+    else
+        MPI_Type_commit(datatype);
+
+#if SIZEOF_MPI_AINT != SIZEOF_MPI_OFFSET
+    NCI_Free(addrs);
+#endif
+
+    return status;
+}
+
+/*----< ncmpii_construct_filetypes() >----------------------------------------*/
+/* concatenate the requests into a single MPI derived filetype */
+static int
+ncmpii_construct_filetypes(NC           *ncp,
+                           int           num_reqs,
+                           NC_req       *reqs,      /* [num_reqs] */
+                           int           rw_flag,
+                           MPI_Datatype *filetype)  /* OUT */
+{
+    int i, j, err, status=NC_NOERR, *blocklens;
+    MPI_Datatype *ftypes;
+    MPI_Offset *displacements;
+
+    if (num_reqs <= 0) { /* for participating collective call */
+        *filetype = MPI_BYTE;
+        return NC_NOERR;;
+    }
+
+    /* hereinafter, num_reqs > 0 */
+    blocklens     = (int*)          NCI_Malloc((size_t)num_reqs * SIZEOF_INT);
+    displacements = (MPI_Offset*)   NCI_Malloc((size_t)num_reqs * SIZEOF_MPI_OFFSET);
+    ftypes        = (MPI_Datatype*) NCI_Malloc((size_t)num_reqs * sizeof(MPI_Datatype));
+
+    /* create a filetype for each request */
+    int last_contig_req = -1; /* index of the last contiguous request */
+    j = 0;                    /* index of last valid ftypes */
+    for (i=0; i<num_reqs; i++, j++) {
+        int is_filetype_contig;
+        ftypes[j] = MPI_BYTE; /* in case the call below failed */
+        err = ncmpii_vars_create_filetype(ncp,
+                                          reqs[i].varp,
+                                          reqs[i].start,
+                                          reqs[i].count,
+                                          reqs[i].stride,
+                                          rw_flag,
+                                          &blocklens[j],
+                                          &displacements[j], /* to offset 0 */
+                                          &ftypes[j],
+                                          &is_filetype_contig);
+        if (err != NC_NOERR) {
+            reqs[i].bnelems = 0; /* make this request no effect */
+            if (reqs[i].status != NULL && *reqs[i].status == NC_NOERR)
+                *reqs[i].status = err;
+            if (status == NC_NOERR) status = err; /* report the first error */
+            continue;
+        }
+
+        if (is_filetype_contig) {
+            if (last_contig_req >= 0 &&
+                displacements[j] - displacements[last_contig_req] ==
+                blocklens[last_contig_req]) {
+                blocklens[last_contig_req] += blocklens[j];
+                j--;
+            }
+            else last_contig_req = j;
+        }
+        else last_contig_req = -1;
+    }
+    /* j is the new num_reqs */
+    num_reqs = j;
+
+    if (status != NC_NOERR) {
+        /* even if error occurs, we still must participate the collective
+           call to MPI_File_set_view() */
+        *filetype = MPI_BYTE;
+    }
+    else if (num_reqs == 1 && displacements[0] == 0) {
+        MPI_Type_dup(ftypes[0], filetype);
+    }
+    else { /* if (num_reqs > 1 || (num_reqs == 1 && displacements[0] > 0)) */
+        /* all ftypes[] created fine, now concatenate all ftypes[] */
+        err = ncmpii_concatenate_datatypes(num_reqs,
+                                           blocklens,
+                                           displacements,
+                                           ftypes,
+                                           filetype);
+        if (err != NC_NOERR) *filetype = MPI_BYTE;
+        if (status == NC_NOERR) status = err; /* report the first error */
+    }
+
+    for (i=0; i<num_reqs; i++) {
+        if (ftypes[i] != MPI_BYTE)
+            MPI_Type_free(&ftypes[i]);
+    }
+    NCI_Free(ftypes);
+    NCI_Free(displacements);
+    NCI_Free(blocklens);
+
+    return status;
+}
+
+/*----< ncmpii_construct_buffertypes() >--------------------------------------*/
+/* the input requests, reqs[], are non-interleaving requests */
+static int
+ncmpii_construct_buffertypes(int           num_reqs,
+                             NC_req       *reqs,         /* [num_reqs] */
+                             MPI_Datatype *buffer_type)  /* OUT */
+{
+    int i, j, status=NC_NOERR, mpireturn;
+
+    *buffer_type = MPI_BYTE;
+    if (num_reqs == 0) return NC_NOERR;
+
+    /* create the I/O buffer derived data type */
+    int *blocklengths = (int*) NCI_Malloc((size_t)num_reqs * SIZEOF_INT);
+    MPI_Aint *disps = (MPI_Aint*) NCI_Malloc((size_t)num_reqs*SIZEOF_MPI_AINT);
+    MPI_Aint a0, ai;
+
+    /* process only valid requests */
+    for (i=0, j=0; i<num_reqs; i++) {
+        /* check int overflow */
+        MPI_Offset int8 = reqs[i].bnelems * reqs[i].varp->xsz;
+        blocklengths[j] = (int)int8;
+        if (int8 != blocklengths[j]) { /* skip this request */
+            DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+            continue;
+        }
+#ifdef HAVE_MPI_GET_ADDRESS
+        MPI_Get_address(reqs[i].xbuf, &ai);
+#else
+        MPI_Address(reqs[i].xbuf, &ai);
+#endif
+        if (j == 0) a0 = ai;
+        disps[j] = ai - a0;
+        j++;
+    }
+    /* update num_reqs to number of valid requests */
+    num_reqs = j;
+
+    if (num_reqs > 0) {
+        /* concatenate buffer addresses into a single buffer type */
+#ifdef HAVE_MPI_TYPE_CREATE_HINDEXED
+        mpireturn = MPI_Type_create_hindexed(num_reqs, blocklengths, disps,
+                                             MPI_BYTE, buffer_type);
+#else
+        mpireturn = MPI_Type_hindexed(num_reqs, blocklengths, disps, MPI_BYTE,
+                                      buffer_type);
+#endif
+        if (mpireturn != MPI_SUCCESS) {
+            int err = ncmpii_handle_error(mpireturn, "MPI_Type_hindexed");
+            /* return the first encountered error if there is any */
+            if (status == NC_NOERR) status = err;
+        }
+        else
+            MPI_Type_commit(buffer_type);
+    }
+    NCI_Free(disps);
+    NCI_Free(blocklengths);
+
+    return status;
+}
+
+/*----< ncmpii_wait() >-------------------------------------------------------*/
+/* The buffer management flow is described below. The wait side starts from
+   the I/O step, i.e. step 5
+
+   for put_varm:
+     1. pack buf to lbuf based on buftype
+     2. create imap_type based on imap
+     3. pack lbuf to cbuf based on imap_type
+     4. type convert and byte swap cbuf to xbuf
+     5. write from xbuf
+     6. byte swap the buf to its original, if it is swapped
+     7. free up temp buffers, cbuf and xbuf if they were allocated separately
+
+   for get_varm:
+     1. allocate lbuf
+     2. create imap_type based on imap
+     3. allocate cbuf
+     4. allocate xbuf
+     5. read to xbuf
+     6. type convert and byte swap xbuf to cbuf
+     7. unpack cbuf to lbuf based on imap_type
+     8. unpack lbuf to buf based on buftype
+     9. free up temp buffers, cbuf and xbuf if they were allocated separately
+ */
+int
+ncmpii_wait(NC  *ncp,
+            int  io_method, /* COLL_IO or INDEP_IO */
+            int  num_reqs,  /* number of requests */
+            int *req_ids,   /* [num_reqs] */
+            int *statuses)  /* [num_reqs] */
+{
+    int i, j, err=NC_NOERR, status=NC_NOERR;
+    int do_read, do_write, num_w_reqs=0, num_r_reqs=0;
+    NC_req *pre_req, *cur_req, *next_req;
+    NC_req *w_req_head=NULL, *w_req_tail=NULL;
+    NC_req *r_req_head=NULL, *r_req_tail=NULL;
+
+    if (NC_indef(ncp)) { /* This API can only be called in data mode */
+        DEBUG_ASSIGN_ERROR(err, NC_EINDEFINE)
+        goto err_check;
+    }
+
+    /* check the MPI file handles for collective or independent mode */
+    if (io_method == INDEP_IO)
+        err = ncmpii_check_mpifh(ncp, 0);
+    else if (io_method == COLL_IO)
+        err = ncmpii_check_mpifh(ncp, 1);
+    if (err != NC_NOERR) goto err_check;
+
+    if (num_reqs == NC_REQ_ALL) { /* flush all pending requests */
+        /* in this case, arguments req_ids[] and statuses[] are ignored */
+        cur_req = ncp->head;
+        while (cur_req != NULL) {
+            cur_req->status = NULL;
+            next_req = cur_req->next;
+            if (cur_req->rw_flag == READ_REQ) {
+                /* add cur_req to r_req_tail */
+                if (r_req_head == NULL) {
+                    r_req_head = cur_req;
+                    r_req_tail = cur_req;
+                }
+                else {
+                    r_req_tail->next = cur_req;
+                    r_req_tail = r_req_tail->next;
+                }
+                r_req_tail->next = NULL;
+                num_r_reqs += (cur_req->num_subreqs == 0) ?
+                              1 : cur_req->num_subreqs;
+                /* if this request is to a record variable, then count all
+                 * its subrequests (one for each individual record) */
+            }
+            else { /* add cur_req to w_req_tail */
+                if (w_req_head == NULL) {
+                    w_req_head = cur_req;
+                    w_req_tail = cur_req;
+                }
+                else {
+                    w_req_tail->next = cur_req;
+                    w_req_tail = w_req_tail->next;
+                }
+                w_req_tail->next = NULL;
+                num_w_reqs += (cur_req->num_subreqs == 0) ?
+                              1 : cur_req->num_subreqs;
+                /* if this request is to a record variable, then count all
+                 * its subrequests (one for each individual record) */
+            }
+            cur_req = next_req;
+        }
+        ncp->head = NULL;
+        ncp->tail = NULL;
+        num_reqs = 0; /* to skip the loop below */
+    }
+    /* extract the matched requests from the pending queue (a linked list
+     * containing all nonblocking requests posted by far) into two separate
+     * linked lists for read and write. In the meantime coalesce the pending
+     * request queue.
+     */
+    for (i=0; i<num_reqs; i++) {
+        int found_id=-1;
+
+        if (statuses != NULL)
+            statuses[i] = NC_NOERR; /* initialize the request's status */
+
+        if (req_ids[i] == NC_REQ_NULL) continue; /* skip NULL request */
+
+        if (ncp->head == NULL) {
+            /* no more pending requests in the queue, this request is invalid */
+            if (statuses != NULL) DEBUG_ASSIGN_ERROR(statuses[i], NC_EINVAL_REQUEST)
+            /* retain the first error status */
+            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EINVAL_REQUEST)
+            continue;
+            /* don't break loop i, continue to set the error status */
+        }
+
+        /* find req_ids[i] from the pending queue */
+        pre_req = cur_req = ncp->head;
+        while (cur_req != NULL) {
+            /* there may be more than one pending request with the same ID.
+             * In this case, these requests are from a single nonblocking
+             * varn API.
+             */
+            if (cur_req->id == req_ids[i]) { /* found it */
+                /* point status of this request to user's statuses[i] */
+                if (statuses != NULL)
+                    cur_req->status = statuses + i;
+                else
+                    cur_req->status = NULL;
+                /* point all subrequests' statuses to status */
+                for (j=0; j<cur_req->num_subreqs; j++)
+                    cur_req->subreqs[j].status = cur_req->status;
+
+                /* remove cur_req from the ncp->head linked list */
+                if (cur_req == ncp->head) { /* move cur_req to next */
+                    ncp->head = cur_req->next;
+                    pre_req = ncp->head;
+                }
+                else /* move pre_req and cur_req to next */
+                    pre_req->next = cur_req->next;
+
+                next_req = cur_req->next;
+
+                if (cur_req->rw_flag == READ_REQ) {
+                    /* add cur_req to r_req_tail */
+                    if (r_req_head == NULL) {
+                        r_req_head = cur_req;
+                        r_req_tail = cur_req;
+                    }
+                    else {
+                        r_req_tail->next = cur_req;
+                        r_req_tail = r_req_tail->next;
+                    }
+                    r_req_tail->next = NULL;
+                    num_r_reqs += (cur_req->num_subreqs == 0) ?
+                                  1 : cur_req->num_subreqs;
+                    /* if this request is to a record variable, then count all
+                     * its subrequests (one for each individual record) */
+                }
+                else { /* add cur_req to w_req_tail */
+                    if (w_req_head == NULL) {
+                        w_req_head = cur_req;
+                        w_req_tail = cur_req;
+                    }
+                    else {
+                        w_req_tail->next = cur_req;
+                        w_req_tail = w_req_tail->next;
+                    }
+                    w_req_tail->next = NULL;
+                    num_w_reqs += (cur_req->num_subreqs == 0) ?
+                                  1 : cur_req->num_subreqs;
+                    /* if this request is to a record variable, then count all
+                     * its subrequests (one for each individual record) */
+                }
+                found_id = req_ids[i]; /* indicating previous found ID */
+                cur_req = next_req;
+            }
+            else if (found_id >= 0) {
+                /* same request IDs (for varn APIs) are stored contiguously in
+                 * the linked list so if it is already found and this next
+                 * request has a different ID, no need to continue checking
+                 * the rest list */
+                break; /* while loop */
+            }
+            else { /* not found: move on to next pending request in the queue */
+                if (cur_req == pre_req) cur_req = pre_req->next;
+                else {
+                    pre_req = cur_req;
+                    cur_req = pre_req->next;
+                }
+            }
+        } /* done with searching the entire linked list for this request ID */
+
+        if (found_id == -1) { /* no such request ID */
+            if (statuses != NULL) DEBUG_ASSIGN_ERROR(statuses[i], NC_EINVAL_REQUEST)
+            if (status == NC_NOERR) /* retain the first error status */
+                DEBUG_ASSIGN_ERROR(status, NC_EINVAL_REQUEST)
+        }
+        else req_ids[i] = NC_REQ_NULL;
+    }
+    /* make sure ncp->tail pointing to the tail of the pending request queue */
+    ncp->tail = ncp->head;
+    while (ncp->tail != NULL && ncp->tail->next != NULL)
+        ncp->tail = ncp->tail->next;
+
+err_check:
+    if (io_method == COLL_IO) {
+        int mpireturn;
+        int io_req[3], do_io[3];  /* [0]: read [1]: write [2]: error */
+        io_req[0] = num_r_reqs;
+        io_req[1] = num_w_reqs;
+        io_req[2] = -err;   /* all NC errors are negative */
+        TRACE_COMM(MPI_Allreduce)(io_req, do_io, 3, MPI_INT, MPI_MAX,
+                                  ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+ 	    return ncmpii_handle_error(mpireturn, "MPI_Allreduce"); 
+
+        /* if error occurs, return the API collectively */
+        if (do_io[2] != -NC_NOERR) return err;
+
+        /* if at least one process has a non-zero request, all processes must
+         * participate the collective read/write */
+        do_read  = do_io[0];
+        do_write = do_io[1];
+    }
+    else {
+        if (err != NC_NOERR) return err;
+        do_read  = num_r_reqs;
+        do_write = num_w_reqs;
+    }
+    /* carry out writes and reads separately (writes first) */
+    if (do_write > 0)
+        err = ncmpii_wait_getput(ncp, num_w_reqs, w_req_head, WRITE_REQ,
+                                 io_method);
+
+    if (do_read > 0)
+        err = ncmpii_wait_getput(ncp, num_r_reqs, r_req_head, READ_REQ,
+                                 io_method);
+
+    /* retain the first error status */
+    if (status == NC_NOERR) status = err;
+
+    /* post-IO data processing: In write case, we may need to byte-swap user
+     * write buf if it is used as the write buffer in MPI write call and the
+     * target machine is little Endian. For read case, we may need to
+     * unpack/byte-swap/type-convert a temp buffer to the user read buf
+     */
+
+    if (w_req_head != NULL) {
+        cur_req = w_req_head;
+        while (cur_req != NULL) {
+            /* must byte-swap the user buffer back to its original Endianness
+               only when the buffer itself has been byte-swapped before,
+               i.e. NOT buftype_is_contig && NOT ncmpii_need_convert() &&
+               ncmpii_need_swap()
+             */
+            if (cur_req->need_swap_back_buf)
+                ncmpii_in_swapn(cur_req->buf, cur_req->bnelems,
+                                ncmpix_len_nctype(cur_req->varp->type));
+            cur_req = cur_req->next;
+        }
+        cur_req = w_req_head;
+        while (cur_req != NULL) {
+            /* free temp space allocated for iput/bput varn requests. Note that
+             * tmpBuf is used only by nonblocking varn APIs. This while loop
+             * is not combined with the one above because the nonblocking varn
+             * APIs may be used. During the posting of a nonblocking varn
+             * request, the temporary buffer, if allocated, can be divided into
+             * several sub-buffers, each used in a separate requests. Only the
+             * first subrequest's tmpBuf will be set to non-NULL, indicating
+             * it should be freed.
+             */
+            if (cur_req->tmpBuf != NULL && cur_req->abuf_index == -1)
+                NCI_Free(cur_req->tmpBuf);
+
+            FREE_REQUEST(cur_req)
+            pre_req = cur_req;
+            cur_req = cur_req->next;
+            NCI_Free(pre_req);
+        }
+        /* once the bput requests are served, we reclaim the space and try
+         * coalesce the freed space for the attached buffer */
+        if (ncp->abuf != NULL) ncmpii_abuf_coalesce(ncp);
+    }
+
+    if (r_req_head != NULL) {
+        cur_req = r_req_head;
+        while (cur_req != NULL) {
+            NC_var *varp = cur_req->varp;
+
+            /* now, xbuf contains the data read from the file.
+             * It needs to be type-converted + byte-swapped to cbuf
+             */
+            void *cbuf, *lbuf;
+            int el_size, position;
+            MPI_Offset insize;
+
+            MPI_Type_size(cur_req->ptype, &el_size);
+            insize = cur_req->bnelems * el_size;
+            if (insize != (int)insize && status == NC_NOERR)
+                DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+
+            if (ncmpii_need_convert(varp->type, cur_req->ptype)) {
+                /* need type conversion from the external type to user buffer
+                   type */
+                if (cur_req->imaptype != MPI_DATATYPE_NULL ||
+                    !cur_req->buftype_is_contig)
+                    cbuf = NCI_Malloc((size_t)insize);
+                else
+                    cbuf = cur_req->buf;
+
+                /* type convert + byte swap from xbuf to cbuf */
+                DATATYPE_GET_CONVERT(varp->type, cur_req->xbuf, cbuf,
+                                     cur_req->bnelems, cur_req->ptype, err)
+                /* keep the first error */
+                if (cur_req->status != NULL && *cur_req->status == NC_NOERR)
+                    *cur_req->status = err;
+                if (status == NC_NOERR) status = err;
+            } else {
+                if (ncmpii_need_swap(varp->type, cur_req->ptype))
+                    ncmpii_in_swapn(cur_req->xbuf, cur_req->bnelems,
+                                    ncmpix_len_nctype(varp->type));
+                cbuf = cur_req->xbuf;
+            }
+
+            if (cur_req->imaptype != MPI_DATATYPE_NULL) {
+                /* handle the case for a true get_varm */
+                if (cur_req->buftype_is_contig)
+                    lbuf = cur_req->buf;
+                else
+                    lbuf = NCI_Malloc((size_t)insize);
+
+                /* unpack cbuf to lbuf based on imaptype */
+                position = 0;
+                MPI_Unpack(cbuf, (int)insize, &position, lbuf, 1,
+                           cur_req->imaptype, MPI_COMM_SELF);
+                MPI_Type_free(&cur_req->imaptype);
+
+                /* cbuf is no longer needed
+                 * for a true varm call, cbuf cannot be == cur_req->buf */
+                if (cbuf != cur_req->xbuf) NCI_Free(cbuf);
+                cbuf = NULL;
+            } else { /* get_vars */
+                lbuf = cbuf;
+            }
+
+            if (!cur_req->buftype_is_contig) {
+                /* unpack lbuf to buf based on buftype */
+                position = 0;
+                if (cur_req->bufcount != (int)cur_req->bufcount &&
+                    status == NC_NOERR)
+                    DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+                MPI_Unpack(lbuf, (int)insize, &position, cur_req->buf,
+                           (int)cur_req->bufcount, cur_req->buftype,
+                           MPI_COMM_SELF);
+                MPI_Type_free(&cur_req->buftype);
+            }
+            /* lbuf is no longer needed */
+            if (lbuf != cur_req->buf && lbuf != cur_req->xbuf)
+                NCI_Free(lbuf);
+
+            cur_req = cur_req->next;
+        }
+
+        cur_req = r_req_head;
+        while (cur_req != NULL) {
+            /* free space allocated for the request objects
+             * tmpBuf is used only by nonblocking varn APIs. This while loop
+             * is not combined with the one above because the nonblocking varn
+             * APIs may be used. During the posting of a nonblocking varn
+             * request, the temporary buffer, if allocated, can be divided into
+             * several sub-buffers, each used in a separate requests. Only the
+             * first subrequest's tmpBuf will be set to non-NULL, indicating
+             * it should be freed.
+             */
+            if (cur_req->tmpBuf != NULL) {
+                int position=0, bufsize;
+                MPI_Offset insize;
+
+                /* unpack tmpBuf to userBuf and free tmpBuf
+                 * Note this unpack must wait for all above unpacks are done
+                 * because cur_req->buf may be part of cur_req->userBuf
+                 */
+                MPI_Type_size(cur_req->buftype, &bufsize);
+                insize = cur_req->bufcount * bufsize;
+                if (insize != (int)insize && status == NC_NOERR)
+                    DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+
+                MPI_Unpack(cur_req->tmpBuf, (int)insize, &position,
+                           cur_req->userBuf, (int)cur_req->bufcount,
+                           cur_req->buftype, MPI_COMM_SELF);
+                NCI_Free(cur_req->tmpBuf);
+                MPI_Type_free(&cur_req->buftype);
+            }
+            FREE_REQUEST(cur_req)
+            pre_req = cur_req;
+            cur_req = cur_req->next;
+            NCI_Free(pre_req);
+        }
+    }
+    return status;
+}
+
+/* C struct for breaking down a request to a list of offset-length segments */
+typedef struct {
+    MPI_Offset off;      /* starting file offset of the request */
+    MPI_Offset len;      /* requested length in bytes starting from off */
+    MPI_Aint   buf_addr; /* distance of this request's I/O buffer to the first
+                            request to be merged */
+} off_len;
+
+/*----< off_compare() >-------------------------------------------------------*/
+/* used for sorting the offsets of the off_len array */
+static int
+off_compare(const void *a, const void *b)
+{
+    if (((off_len*)a)->off > ((off_len*)b)->off) return  1;
+    if (((off_len*)a)->off < ((off_len*)b)->off) return -1;
+    return 0;
+}
+
+/*----< ncmpii_flatten() >----------------------------------------------------*/
+/* flatten a subarray request into a list of offset-length pairs */
+static MPI_Offset
+ncmpii_flatten(int          ndim,    /* number of dimensions */
+               int          el_size, /* array element size */
+               MPI_Offset  *dimlen,  /* [ndim] dimension lengths */
+               MPI_Offset   offset,  /* starting file offset of variable */
+               MPI_Aint     buf_addr,/* starting buffer address */
+               MPI_Offset  *start,   /* [ndim] starts of subarray */
+               MPI_Offset  *count,   /* [ndim] counts of subarray */
+               MPI_Offset  *stride,  /* [ndim] strides of subarray */
+               MPI_Offset  *nseg,    /* OUT: number of segments */
+               off_len     *seg)     /* OUT: array of segments */
+{
+    int i, j, to_free_stride=0;
+    MPI_Offset seg_len, nstride, array_len, off, subarray_len;
+    off_len *ptr=seg, *seg0;
+
+    *nseg = 0;
+    if (ndim < 0) return *nseg;
+
+    if (ndim == 0) {  /* 1D record variable */
+        *nseg = 1;
+        seg->off      = offset;
+        seg->len      = el_size;
+        seg->buf_addr = buf_addr;
+        return *nseg;
+    }
+
+    if (stride == NULL) { /* equivalent to {1, 1, ..., 1} */
+        stride = (MPI_Offset*) NCI_Malloc((size_t)ndim * SIZEOF_MPI_OFFSET);
+        for (i=0; i<ndim; i++) stride[i] = 1;
+        to_free_stride = 1;
+    }
+
+    /* TODO: check if all stride[] >= 1
+       Q: Is it legal if any stride[] <= 0 ? */
+
+    /* calculate the number of offset-length pairs */
+    *nseg = (stride[ndim-1] == 1) ? 1 : count[ndim-1];
+    for (i=0; i<ndim-1; i++)
+        *nseg *= count[i];
+    if (*nseg == 0) {  /* not reachable, an error if count[] == 0 */
+        if (to_free_stride) NCI_Free(stride);
+        return *nseg;
+    }
+
+    /* the length of all segments are of the same size */
+    seg_len  = (stride[ndim-1] == 1) ? count[ndim-1] : 1;
+    seg_len *= el_size;
+    nstride  = (stride[ndim-1] == 1) ? 1 : count[ndim-1];
+
+    /* set the offset-length pairs for the lowest dimension */
+    off = offset + start[ndim-1] * el_size;
+    for (i=0; i<nstride; i++) {
+        ptr->off       = off;
+        ptr->len       = seg_len;
+        ptr->buf_addr  = buf_addr;
+        buf_addr      += seg_len;
+        off           += stride[ndim-1] * el_size;
+        ptr++;
+    }
+    ndim--;
+
+    subarray_len = nstride;
+    array_len = 1;
+    /* for higher dimensions */
+    while (ndim > 0) {
+        /* array_len is global array size from lowest up to ndim */
+        array_len *= dimlen[ndim];
+
+        /* off is the global array offset for this dimension, ndim-1 */
+        off = start[ndim-1] * array_len * el_size;
+
+        /* update all offsets from lowest up to dimension ndim-1 */
+        seg0 = seg;
+        for (j=0; j<subarray_len; j++) {
+            seg0->off += off;
+            seg0++;
+        }
+
+        /* update each plan subarray of dimension ndim-1 */
+        off = array_len * stride[ndim-1] * el_size;
+        for (i=1; i<count[ndim-1]; i++) {
+            seg0 = seg;
+            for (j=0; j<subarray_len; j++) {
+                ptr->off       = seg0->off + off;
+                ptr->len       = seg_len;
+                ptr->buf_addr  = buf_addr;
+                buf_addr      += seg_len;
+                ptr++;
+                seg0++;
+            }
+            off += array_len * stride[ndim-1] * el_size;
+        }
+        ndim--;  /* move to next higher dimension */
+        subarray_len *= count[ndim];
+    }
+    if (to_free_stride) NCI_Free(stride);
+
+    return *nseg;
+}
+
+/*----< ncmpii_merge_requests() >---------------------------------------------*/
+static int
+ncmpii_merge_requests(NC          *ncp,
+                      int          num_reqs,
+                      NC_req      *reqs,    /* [num_reqs] */
+                      void       **buf,     /* OUT: 1st I/O buf addr */
+                      MPI_Offset  *nsegs,   /* OUT: no. off-len pairs */
+                      off_len    **segs)    /* OUT: [*nsegs] */
+{
+    int i, j, status=NC_NOERR, ndims, is_recvar;
+    MPI_Offset  nseg, *start, *count, *shape, *stride;
+    MPI_Aint addr, buf_addr;
+
+    *nsegs = 0;    /* total number of offset-length pairs */
+    *segs  = NULL; /* array of offset-length pairs */
+
+    /* note invalid requests have been removed in ncmpii_wait_getput() */
+    *buf = reqs[0].xbuf; /* I/O buffer of first request */
+
+    /* buf_addr is the buffer address of the first request */
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(reqs[0].xbuf, &buf_addr);
+#else
+    MPI_Address(reqs[0].xbuf, &buf_addr);
+#endif
+
+    /* Count the number off-len pairs from reqs[], so we can malloc a
+     * contiguous memory space for storing off-len pairs
+     */
+    for (i=0; i<num_reqs; i++) {
+        is_recvar = IS_RECVAR(reqs[i].varp);
+
+        /* for record variable, each reqs[] is within a record */
+        ndims  = (is_recvar) ? reqs[i].varp->ndims - 1 : reqs[i].varp->ndims;
+        count  = (is_recvar) ? reqs[i].count + 1       : reqs[i].count;
+        stride = NULL;
+        if (reqs[i].stride != NULL)
+            stride = (is_recvar) ? reqs[i].stride + 1 : reqs[i].stride;
+
+        if (ndims < 0) continue;
+        if (ndims == 0) {  /* 1D record variable */
+            (*nsegs)++;
+            continue;
+        }
+        nseg = 1;
+        if (stride != NULL && stride[ndims-1] > 1)
+            nseg = count[ndims-1];  /* count of last dimension */
+        for (j=0; j<ndims-1; j++)
+            nseg *= count[j];  /* all count[] except the last dimension */
+
+        *nsegs += nseg;
+    }
+
+    /* now we can allocate a contiguous memory space for the off-len pairs */
+    off_len *seg_ptr = (off_len*) NCI_Malloc((size_t)(*nsegs) * sizeof(off_len));
+    *segs = seg_ptr;
+
+    /* now re-run the loop to fill in the off-len pairs */
+    for (i=0; i<num_reqs; i++) {
+        /* buf_addr is the buffer address of the first valid request */
+#ifdef HAVE_MPI_GET_ADDRESS
+        MPI_Get_address(reqs[i].xbuf, &addr);
+#else
+        MPI_Address(reqs[i].xbuf, &addr);
+#endif
+        addr -= buf_addr,  /* distance to the buf of first req */
+
+        is_recvar = IS_RECVAR(reqs[i].varp);
+
+        /* for record variable, each reqs[] is within a record */
+        ndims  = (is_recvar) ? reqs[i].varp->ndims  - 1 : reqs[i].varp->ndims;
+        start  = (is_recvar) ? reqs[i].start  + 1       : reqs[i].start;
+        count  = (is_recvar) ? reqs[i].count  + 1       : reqs[i].count;
+        shape  = (is_recvar) ? reqs[i].varp->shape  + 1 : reqs[i].varp->shape;
+        stride = NULL;
+        if (reqs[i].stride != NULL)
+            stride = (is_recvar) ? reqs[i].stride + 1 : reqs[i].stride;
+
+        /* find the starting file offset for this record */
+        MPI_Offset var_begin = reqs[i].varp->begin;
+        if (is_recvar) var_begin += reqs[i].start[0] * ncp->recsize;
+
+        /* flatten each request to a list of offset-length pairs */
+        ncmpii_flatten(ndims, reqs[i].varp->xsz, shape, var_begin,
+                       addr, start, count, stride,
+                       &nseg,    /* OUT: number of offset-length pairs */
+                       seg_ptr); /* OUT: array of offset-length pairs */
+        seg_ptr += nseg; /* append the list to the end of segs array */
+    }
+
+    /* check if (*segs)[].off are in an increasing order */
+    for (i=1; i<*nsegs; i++) {
+        if ((*segs)[i-1].off > (*segs)[i].off)
+            break;
+    }
+    if (i < *nsegs) /* not in an increasing order */
+        /* sort the off-len array, segs[], in an increasing order */
+        qsort(*segs, (size_t)(*nsegs), sizeof(off_len), off_compare);
+
+    /* merge the overlapped requests, skip the overlapped regions for those
+     * requests with higher j indices (i.e. requests with lower j indices
+     * win the writes to the overlapped regions)
+     */
+    for (i=0, j=1; j<*nsegs; j++) {
+        if ((*segs)[i].off + (*segs)[i].len >= (*segs)[j].off + (*segs)[j].len)
+            /* segment i completely covers segment j, skip j */
+            continue;
+
+        MPI_Offset gap = (*segs)[i].off + (*segs)[i].len - (*segs)[j].off;
+        if (gap >= 0) { /* segments i and j overlaps */
+            if ((*segs)[i].buf_addr + (*segs)[i].len ==
+                (*segs)[j].buf_addr + gap) {
+                /* buffers i and j are contiguous, merge j to i */
+                (*segs)[i].len += (*segs)[j].len - gap;
+            }
+            else { /* buffers are not contiguous, reduce j's len */
+                (*segs)[i+1].off      = (*segs)[j].off + gap;
+                (*segs)[i+1].len      = (*segs)[j].len - gap;
+                (*segs)[i+1].buf_addr = (*segs)[j].buf_addr + gap;
+                i++;
+            }
+        }
+        else { /* i and j do not overlap */
+            i++;
+            if (i < j) (*segs)[i] = (*segs)[j];
+        }
+    }
+
+    /* update number of segments, now all off-len pairs are not overlapped */
+    *nsegs = i+1;
+
+    return status;
+}
+
+/*----< ncmpii_construct_off_len_type() >-------------------------------------*/
+static int
+ncmpii_construct_off_len_type(MPI_Offset    nsegs,    /* no. off-len pairs */
+                              off_len      *segs,     /* [nsegs] off-en pairs */
+                              MPI_Datatype *filetype,
+                              MPI_Datatype *buf_type)
+{
+    int i, j, mpireturn, *blocklengths;
+    MPI_Aint   *displacements;
+    MPI_Offset  next_off, next_len;
+
+    assert(nsegs > 0);
+
+    /* create the file view MPI derived data type by concatenating the sorted
+       offset-length pairs */
+
+    /* For filetype, the segs[].off can be further coalesced. For example,
+     * when writing a consecutive columns of a 2D array, even though the I/O
+     * buffer addresses may not be able to coalesced, the file offsets on
+     * the same row can be coalesced. Thus, first calculate the length of
+     * coalesced off-len pairs (the memory space needed for malloc)
+     */
+    next_off = segs[0].off;
+    next_len = segs[0].len;
+    for (j=0,i=1; i<nsegs; i++) {
+        if (next_off + next_len == segs[i].off) /* j and i are contiguous */
+            next_len += segs[i].len;
+        else {
+            j++;
+            next_off = segs[i].off;
+            next_len = segs[i].len;
+        }
+    }
+    /* j+1 is the coalesced length */
+    blocklengths  = (int*)      NCI_Malloc((size_t)(j+1) * SIZEOF_INT);
+    displacements = (MPI_Aint*) NCI_Malloc((size_t)(j+1) * SIZEOF_MPI_AINT);
+
+    /* coalesce segs[].off and len to dispalcements[] and blocklengths[] */
+    if (segs[0].len != (int)segs[0].len) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    displacements[0] =      segs[0].off;
+    blocklengths[0]  = (int)segs[0].len;
+    for (j=0,i=1; i<nsegs; i++) {
+        if (segs[i].len != (int)segs[i].len) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        if (displacements[j] + blocklengths[j] == segs[i].off)
+            /* j and i are contiguous */
+            blocklengths[j] += (int)segs[i].len;
+            /* TODO: take care of 4-byte int overflow problem */
+        else {
+            j++;
+            displacements[j] =      segs[i].off;
+            blocklengths[j]  = (int)segs[i].len;
+        }
+    }
+    /* j+1 is the coalesced length */
+
+#ifdef HAVE_MPI_TYPE_CREATE_HINDEXED
+    mpireturn = MPI_Type_create_hindexed(j+1, blocklengths, displacements,
+                                         MPI_BYTE, filetype);
+#else
+    mpireturn = MPI_Type_hindexed(j+1, blocklengths, displacements, MPI_BYTE,
+                                  filetype);
+#endif
+    if (mpireturn != MPI_SUCCESS) {
+        *filetype = MPI_BYTE;
+        *buf_type = MPI_BYTE;
+        NCI_Free(displacements);
+        NCI_Free(blocklengths);
+        return ncmpii_handle_error(mpireturn, "MPI_Type_create_hindexed");
+    }
+    MPI_Type_commit(filetype);
+    NCI_Free(displacements);
+    NCI_Free(blocklengths);
+
+    /* create the I/O buffer derived data type from the I/O buffer's
+       offset-length pairs */
+
+    /* Although it is unlikely buffers can be coalesced, it will not harm to
+       check it out */
+    next_off = segs[0].buf_addr;
+    next_len = segs[0].len;
+    for (j=0,i=1; i<nsegs; i++) {
+        if (next_off + next_len == segs[i].buf_addr)
+            /* j and i are contiguous */
+            next_len += segs[i].len;
+        else {
+            j++;
+            next_off = segs[i].buf_addr;
+            next_len = segs[i].len;
+        }
+    }
+    /* j+1 is the coalesced length */
+    blocklengths  = (int*)      NCI_Malloc((size_t)(j+1) * SIZEOF_INT);
+    displacements = (MPI_Aint*) NCI_Malloc((size_t)(j+1) * SIZEOF_MPI_AINT);
+
+    /* coalesce segs[].off and len to dispalcements[] and blocklengths[] */
+    if (segs[0].len != (int)segs[0].len) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+    displacements[0] =      segs[0].buf_addr;
+    blocklengths[0]  = (int)segs[0].len;
+    for (j=0,i=1; i<nsegs; i++) {
+        if (segs[i].len != (int)segs[i].len) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        if (displacements[j] + blocklengths[j] == segs[i].buf_addr)
+            /* j and i are contiguous */
+            blocklengths[j] += (int)segs[i].len;
+        else {
+            j++;
+            displacements[j] =      segs[i].buf_addr;
+            blocklengths[j]  = (int)segs[i].len;
+        }
+    }
+    /* j+1 is the coalesced length */
+#ifdef HAVE_MPI_TYPE_CREATE_HINDEXED
+    mpireturn = MPI_Type_create_hindexed(j+1, blocklengths, displacements,
+                                         MPI_BYTE, buf_type);
+#else
+    mpireturn = MPI_Type_hindexed(j+1, blocklengths, displacements, MPI_BYTE,
+                                  buf_type);
+#endif
+    if (mpireturn != MPI_SUCCESS) {
+        if (*filetype != MPI_BYTE) MPI_Type_free(filetype);
+        *filetype = MPI_BYTE;
+        *buf_type = MPI_BYTE;
+        NCI_Free(displacements);
+        NCI_Free(blocklengths);
+        return ncmpii_handle_error(mpireturn, "MPI_Type_create_hindexed");
+    }
+    MPI_Type_commit(buf_type);
+    NCI_Free(displacements);
+    NCI_Free(blocklengths);
+
+    return NC_NOERR;
+}
+
+/*----< req_compare() >-------------------------------------------------------*/
+/* used to sort the the string file offsets of reqs[] */
+static int
+req_compare(const void *a, const void *b)
+{
+    if (((NC_req*)a)->offset_start > ((NC_req*)b)->offset_start) return (1);
+    if (((NC_req*)a)->offset_start < ((NC_req*)b)->offset_start) return (-1);
+    return (0);
+}
+
+/*----< ncmpii_req_aggregation() >--------------------------------------------*/
+/* aggregate multiple read/write (non-contiguous) requests and call MPI-IO
+ */
+static int
+ncmpii_req_aggregation(NC     *ncp,
+                       int     num_reqs,    /* # requests */
+                       NC_req *reqs,        /* sorted requests */
+                       int     rw_flag,     /* WRITE_REQ or READ_REQ */
+                       int     io_method,   /* COLL_IO or INDEP_IO */
+                       int     interleaved) /* interleaved in reqs[] */
+{
+    int i, type, err, status=NC_NOERR, ngroups;
+    int *group_index, *group_type;
+
+    if (num_reqs == 0) { /* only COLL_IO can reach here for 0 request */
+        assert(io_method == COLL_IO);
+        /* simply participate the collective call */
+        return ncmpii_getput_zero_req(ncp, rw_flag);
+    }
+    if (! interleaved) {
+        /* concatenate all filetypes into a single one and do I/O */
+        return ncmpii_mgetput(ncp, num_reqs, reqs, rw_flag, io_method);
+    }
+    /* now some request's aggregate access region is interleaved with other's */
+
+    /* divide the requests into groups.
+     * Two types of groups: one contains requests that all are not interleaved
+     * and the other contains requests that any 2 consecutive requests are
+     * interleaved. All requests will be aggregated into one and carried out
+     * by a single MPI-IO call.
+     * This approach is because MPI collective I/O requires each process's
+     * fileview must contain only monotonic non-decreasing file offsets. Thus
+     * if the nonblocking requests interleave with each other (although not
+     * overlapp), then we cannot simply concatenate the filetypes of individual
+     * requests. This approach flattens the requests of "interleaved" groups
+     * into offset-length pairs, sorts, and merges them into an aggregated
+     * filetype. Similar for building an aggregated I/O buffer type.
+     */
+
+    /* first calculate the number of groups, so group_index and group_type can
+       be malloc-ed. Group type: 0 for non-interleaved group and 1 for
+       interleaved group.
+     */
+    ngroups = 1;
+    type    = (reqs[0].offset_end > reqs[1].offset_start) ? 1 : 0;
+    for (i=1; i<num_reqs-1; i++) {
+        if (type == 0 && reqs[i].offset_end > reqs[i+1].offset_start) {
+            ngroups++;
+            type = 1;
+        }
+        else if (type == 1 && reqs[i].offset_end <= reqs[i+1].offset_start) {
+            type = 0;
+            if (i+2 < num_reqs && reqs[i+1].offset_end > reqs[i+2].offset_start)
+                type = 1; /* next group is also interleaved */
+            ngroups++;
+        }
+    }
+
+    group_index = (int*) NCI_Malloc((size_t)(ngroups+1) * SIZEOF_INT);
+    group_type  = (int*) NCI_Malloc((size_t)(ngroups+1) * SIZEOF_INT);
+
+    /* calculate the starting index of each group and determine group type */
+    ngroups        = 1;
+    type           = (reqs[0].offset_end > reqs[1].offset_start) ? 1 : 0;
+    group_index[0] = 0;
+    group_type[0]  = type;
+    for (i=1; i<num_reqs-1; i++) {
+        if (type == 0 &&
+            reqs[i].offset_end > reqs[i+1].offset_start) {
+            /* reqs[i] starts an interleaved group */
+            group_index[ngroups] = i;
+            type = 1;
+            group_type[ngroups] = type;
+            ngroups++;
+        }
+        else if (type == 1 &&
+                 reqs[i].offset_end <= reqs[i+1].offset_start) {
+            /* the interleaved group ends with reqs[i] */
+            group_index[ngroups] = i+1;
+            type = 0;
+            if (i+2 < num_reqs && reqs[i+1].offset_end > reqs[i+2].offset_start)
+                type = 1; /* next group is also interleaved */
+            group_type[ngroups] = type;
+            ngroups++;
+        }
+    }
+    group_index[ngroups] = num_reqs; /* to indicate end of groups */
+
+    /* for each group, construct one filetype by concatenating if the group
+     * is non-interleaved and by flatten/sort/merge if the group is
+     * interleaved. At the end, all ngroups filetypes are concatenated into
+     * a single filetype. Similar for constructing buffer types.
+     * Then use one collective I/O to commit.
+     */
+
+    void         *buf; /* point to starting buffer, used by MPI-IO call */
+    int          *f_blocklengths, *b_blocklengths;
+    MPI_Aint      b_begin, b_addr, *f_disps, *b_disps;
+    MPI_Datatype  filetype, buf_type, *ftypes, *btypes;
+
+    ftypes = (MPI_Datatype*) NCI_Malloc((size_t)ngroups*2*sizeof(MPI_Datatype));
+    btypes = ftypes + ngroups;
+    f_blocklengths = (int*) NCI_Malloc((size_t)ngroups*2*SIZEOF_INT);
+    b_blocklengths = f_blocklengths + ngroups;
+    f_disps = (MPI_Aint*) NCI_Malloc((size_t)ngroups*2*SIZEOF_MPI_AINT);
+    b_disps = f_disps + ngroups;
+
+    buf = reqs[0].xbuf; /* the buffer of 1st request */
+    b_disps[0] = 0;     /* relative to address of 1st buf */
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(buf, &b_begin);
+#else
+    MPI_Address(buf, &b_begin);
+#endif
+
+    /* for each group, build a filetype and a buffer type in ftypes[i] and
+       btypes[i] */
+    for (i=0; i<ngroups; i++) {
+        NC_req *g_reqs = reqs + group_index[i];
+        int     g_num_reqs = group_index[i+1] - group_index[i];
+        f_disps[i] = 0;  /* file displacements always to the file offset 0 */
+
+        if (group_type[i] == 0) {
+            /* This group contains no interleaved filetypes, so we can
+             * simply concatenate filetypes of this group into a single one
+             */
+            err = ncmpii_construct_filetypes(ncp, g_num_reqs, g_reqs, rw_flag,
+                                             &ftypes[i]);
+            if (status == NC_NOERR) status = err;
+            if (err != NC_NOERR) { /* skip this group */
+                ftypes[i] = btypes[i] = MPI_BYTE;
+                f_blocklengths[i] = 0;
+                continue;
+            }
+            f_blocklengths[i] = 1;
+
+            /* concatenate buffer types of this group into a single one */
+            err = ncmpii_construct_buffertypes(g_num_reqs, g_reqs, &btypes[i]);
+            if (status == NC_NOERR) status = err;
+            if (err != NC_NOERR) { /* skip this group */
+                ftypes[i] = btypes[i] = MPI_BYTE;
+                b_blocklengths[i] = 0;
+                f_blocklengths[i] = 0;
+                continue;
+            }
+        }
+        else { /* this group is interleaved */
+            /* flatten the interleaved requests in this group, so interleaved
+             * requests can be sorted and merged into a monotonically
+             * non-decreasing filetype. For example, multiple nonblocking
+             * requests each accessing a single column of a 2D array, that each
+             * produces a filetype interleaving with others'.
+             *
+             * The pitfall of this flattening is the additional memory
+             * requirement, as it will have to break down each request into a
+             * list of offset-length pairs, and merge all lists into a sorted
+             * list based on their offsets into an increasing order.
+             *
+             * Be warned! The additional memory requirement for this merging can
+             * be more than the I/O data itself. For example, each nonblocking
+             * request access a single column of a 2D array of 4-byte integer
+             * type. Each off-len pair represents only a 4-byte integer, but the
+             * off-len pair itself takes 24 bytes. Additional memory is also
+             * required for MPI arguments of displacements and blocklengths.
+             */
+            MPI_Offset  nsegs=0;   /* number of merged offset-length pairs */
+            off_len    *segs=NULL; /* array of the offset-length pairs */
+            void       *merged_buf;
+
+            /* merge all requests into sorted offset-length pairs */
+            err = ncmpii_merge_requests(ncp, g_num_reqs, g_reqs, &merged_buf,
+                                        &nsegs, &segs);
+            if (status == NC_NOERR) status = err;
+            if (err != NC_NOERR) { /* skip this group */
+                ftypes[i] = btypes[i] = MPI_BYTE;
+                b_blocklengths[i] = 0;
+                f_blocklengths[i] = 0;
+                if (segs != NULL) NCI_Free(segs);
+                continue;
+            }
+            assert(nsegs > 0);
+
+            /* sges[] will be used to construct fileview and buffer type */
+            err = ncmpii_construct_off_len_type(nsegs, segs, &ftypes[i],
+                                                &btypes[i]);
+            /* preserve the previous error if there is any */
+            if (status == NC_NOERR) status = err;
+            NCI_Free(segs);
+            if (err != NC_NOERR) { /* skip this group */
+                ftypes[i] = btypes[i] = MPI_BYTE;
+                b_blocklengths[i] = 0;
+                f_blocklengths[i] = 0;
+                continue;
+            }
+            f_blocklengths[i] = 1;
+        }
+
+        if (i > 0) {
+            /* get the buffer address of the first request in this group */
+#ifdef HAVE_MPI_GET_ADDRESS
+            MPI_Get_address(g_reqs[0].xbuf, &b_addr);
+#else
+            MPI_Address(g_reqs[0].xbuf, &b_addr);
+#endif
+            b_disps[i] = b_addr - b_begin; /* to 1st buffer of 1st group*/
+        }
+        b_blocklengths[i] = 1;
+    }
+    NCI_Free(group_index);
+    NCI_Free(group_type);
+
+    int mpireturn, buf_len=1;
+
+    if (ngroups == 1) {
+        /* use ftypes[0] and btypes[0] directly */
+        filetype = ftypes[0];
+        buf_type = btypes[0];
+    }
+    else {
+        /* concatenate all ftypes[] to filetype */
+#ifdef HAVE_MPI_TYPE_CREATE_STRUCT
+        mpireturn = MPI_Type_create_struct(ngroups, f_blocklengths, f_disps,
+                                           ftypes, &filetype);
+#else
+        mpireturn = MPI_Type_struct(ngroups, f_blocklengths, f_disps, ftypes,
+                                    &filetype);
+#endif
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_Type_create_struct");
+            /* return the first encountered error if there is any */
+            if (status == NC_NOERR) status = err;
+
+            buf_len  = 0; /* skip this request */
+            filetype = MPI_BYTE;
+        }
+        else
+            MPI_Type_commit(&filetype);
+
+        for (i=0; i<ngroups; i++) {
+            if (ftypes[i] != MPI_BYTE) MPI_Type_free(&ftypes[i]);
+        }
+
+        /* concatenate all btypes[] to buf_type */
+#ifdef HAVE_MPI_TYPE_CREATE_STRUCT
+        mpireturn = MPI_Type_create_struct(ngroups, b_blocklengths, b_disps,
+                                           btypes, &buf_type);
+#else
+        mpireturn = MPI_Type_struct(ngroups, b_blocklengths, b_disps, btypes,
+                                    &buf_type);
+#endif
+        if (mpireturn != MPI_SUCCESS) {
+            err = ncmpii_handle_error(mpireturn, "MPI_Type_create_struct");
+            /* return the first encountered error if there is any */
+            if (status == NC_NOERR) status = err;
+
+            buf_len  = 0; /* skip this request */
+            buf_type = MPI_BYTE;
+        }
+        else
+            MPI_Type_commit(&buf_type);
+
+        for (i=0; i<ngroups; i++) {
+            if (btypes[i] != MPI_BYTE) MPI_Type_free(&btypes[i]);
+        }
+    }
+
+    MPI_File fh;
+    MPI_Status mpistatus;
+
+    if (io_method == COLL_IO)
+        fh = ncp->nciop->collective_fh;
+    else
+        fh = ncp->nciop->independent_fh;
+
+    /* set the file view */
+    MPI_Offset offset=0;
+    err = ncmpii_file_set_view(ncp, fh, &offset, filetype);
+    if (err != NC_NOERR) {
+        buf_len = 0; /* skip this request */
+        if (status == NC_NOERR) status = err;
+    }
+
+    if (rw_flag == READ_REQ) {
+        if (io_method == COLL_IO) {
+            TRACE_IO(MPI_File_read_at_all)(fh, offset, buf, buf_len, buf_type,
+                                           &mpistatus);
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn, "MPI_File_read_at_all");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) {
+                    status = (err == NC_EFILE) ? NC_EREAD : err;
+                    DEBUG_ASSIGN_ERROR(status, status)
+                }
+            }
+        } else {
+            TRACE_IO(MPI_File_read_at)(fh, offset, buf, buf_len, buf_type,
+                                       &mpistatus);
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn, "MPI_File_read_at");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) {
+                    status = (err == NC_EFILE) ? NC_EREAD : err;
+                    DEBUG_ASSIGN_ERROR(status, status)
+                }
+            }
+        }
+        if (mpireturn == MPI_SUCCESS) {
+            int get_size;
+            MPI_Get_count(&mpistatus, MPI_BYTE, &get_size);
+            ncp->nciop->get_size += get_size;
+        }
+    } else { /* WRITE_REQ */
+        if (io_method == COLL_IO) {
+            TRACE_IO(MPI_File_write_at_all)(fh, offset, buf, buf_len, buf_type,
+                                            &mpistatus);
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn, "MPI_File_write_at_all");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) {
+                    status = (err == NC_EFILE) ? NC_EWRITE : err;
+                    DEBUG_ASSIGN_ERROR(status, status)
+                }
+            }
+        } else {
+            TRACE_IO(MPI_File_write_at)(fh, offset, buf, buf_len, buf_type,
+                                        &mpistatus);
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn, "MPI_File_write_at");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) {
+                    status = (err == NC_EFILE) ? NC_EWRITE : err;
+                    DEBUG_ASSIGN_ERROR(status, status)
+                }
+            }
+        }
+        if (mpireturn == MPI_SUCCESS) {
+            int put_size;
+            MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
+            ncp->nciop->put_size += put_size;
+        }
+    }
+
+    if (filetype != MPI_BYTE) MPI_Type_free(&filetype);
+    if (buf_type != MPI_BYTE) MPI_Type_free(&buf_type);
+
+    /* No longer need to reset the file view, as the root's fileview includes
+     * the whole file header.
+     TRACE_IO(MPI_File_set_view)(fh, 0, MPI_BYTE, MPI_BYTE, "native",
+                                 MPI_INFO_NULL);
+     */
+
+    NCI_Free(ftypes);
+    NCI_Free(f_blocklengths);
+    NCI_Free(f_disps);
+
+    return status;
+}
+
+/*----< ncmpii_wait_getput() >------------------------------------------------*/
+static int
+ncmpii_wait_getput(NC     *ncp,
+                   int     num_reqs,  /* # requests including subrequests */
+                   NC_req *req_head,  /* linked list not include subrequests */
+                   int     rw_flag,   /* WRITE_REQ or READ_REQ */
+                   int     io_method) /* COLL_IO or INDEP_IO */
+{
+    int i, j, err, status=NC_NOERR, access_interleaved=0;
+    NC_req *reqs, *cur_req;
+
+    /* pack the requests and sub-requests from the linked list into an array,
+     * so they can be sorted */
+    reqs = (NC_req*) NCI_Malloc((size_t)num_reqs * sizeof(NC_req));
+    i = 0;
+    cur_req = req_head;
+    while (cur_req != NULL) {
+        if (cur_req->num_subreqs == 0)
+            reqs[i++] = *cur_req;
+        else {
+            for (j=0; j<cur_req->num_subreqs; j++)
+                reqs[i++] = cur_req->subreqs[j];
+        }
+        cur_req = cur_req->next;
+    }
+
+#ifndef _DISALLOW_POST_NONBLOCKING_API_IN_DEFINE_MODE
+    /* move the offset calculation from posting API calls (pack_request) to
+     * wait call, such that posting a nonblocking request can be done in
+     * define mode  
+     */  
+    for (i=0; i<num_reqs; i++) {
+        /* get the starting file offset for this request */
+        ncmpii_get_offset(ncp, reqs[i].varp, reqs[i].start, NULL, NULL,
+                          reqs[i].rw_flag, &reqs[i].offset_start);
+
+        /* get the ending file offset for this request */
+        ncmpii_get_offset(ncp, reqs[i].varp, reqs[i].start, reqs[i].count,
+                          reqs[i].stride, reqs[i].rw_flag, &reqs[i].offset_end);
+        reqs[i].offset_end += reqs[i].varp->xsz - 1;
+    }
+#endif
+
+    /* check if reqs[].offset_start are in an increasing order */
+    for (i=1; i<num_reqs; i++) {
+        if (reqs[i-1].offset_start > reqs[i].offset_start) {
+            break;
+        }
+    }
+    if (i < num_reqs) /* a non-increasing order is found */
+        /* sort reqs[] based on reqs[].offset_start */
+        qsort(reqs, (size_t)num_reqs, sizeof(NC_req), req_compare);
+
+    /* check for any interleaved requests */
+    for (i=1; i<num_reqs; i++) {
+        if (reqs[i-1].offset_end > reqs[i].offset_start) {
+            access_interleaved = 1;
+            break;
+        }
+    }
+
+    /* aggregate requests and carry out the I/O */
+    err = ncmpii_req_aggregation(ncp, num_reqs, reqs, rw_flag, io_method,
+                                 access_interleaved);
+    if (status == NC_NOERR) status = err;
+
+    /* Update the number of records if new records have been created.
+     * For nonblocking APIs, there is no way for a process to know whether
+     * others write to a record variable or not. Hence, we must sync the
+     * number of records for write request
+     */
+    if (rw_flag == WRITE_REQ) {
+        /* Because netCDF allows only one unlimited dimension, find the
+         * maximum number of records from all nonblocking requests and
+         * update newnumrecs once
+         */
+        MPI_Offset newnumrecs = ncp->numrecs;
+        for (i=0; i<num_reqs; i++) {
+            if (!IS_RECVAR(reqs[i].varp)) continue; /* not a record var */
+            if (reqs[i].bnelems == 0) continue; /* 0-len or invalid request */
+
+            newnumrecs = MAX(newnumrecs, reqs[i].start[0] + reqs[i].count[0]);
+        }
+
+        if (io_method == COLL_IO) {
+            /* sync numrecs in memory and file. Note that even this process
+             * does not write to record variable, others might. Note in
+             * ncmpii_sync_numrecs(), new_numrecs is checked against
+             * ncp->numrecs and if NC_SHARE is set, MPI_File_sync() will
+             * be called.
+             */
+            err = ncmpii_sync_numrecs(ncp, newnumrecs);
+            if (status == NC_NOERR) status = err;
+            /* retain the first error if there is any */
+        }
+        else { /* INDEP_IO */
+            if (ncp->numrecs < newnumrecs) {
+                ncp->numrecs = newnumrecs;
+                set_NC_ndirty(ncp);
+                /* delay numrecs sync until end_indep, redef or close */
+            }
+        }
+
+        if (NC_doFsync(ncp)) { /* NC_SHARE is set */
+            int mpireturn;
+            if (io_method == INDEP_IO) {
+                TRACE_IO(MPI_File_sync)(ncp->nciop->independent_fh);
+                if (mpireturn != MPI_SUCCESS) {
+                    err = ncmpii_handle_error(mpireturn, "MPI_File_sync"); 
+                    if (status == NC_NOERR) status = err;
+                }
+            }
+            else {
+                TRACE_IO(MPI_File_sync)(ncp->nciop->collective_fh);
+                if (mpireturn != MPI_SUCCESS) {
+                    err = ncmpii_handle_error(mpireturn, "MPI_File_sync"); 
+                    if (status == NC_NOERR) status = err;
+                }
+                TRACE_COMM(MPI_Barrier)(ncp->nciop->comm);
+            }
+        }
+    }
+
+    if (reqs != NULL) NCI_Free(reqs);
+
+    return status;
+}
+
+/*----< ncmpii_mgetput() >----------------------------------------------------*/
+/* Before reaching to this subroutine, all the filetypes in the request array
+ * are sorted in a non-decreasing order and not interleaved. This subroutine
+ * concatenates the filetypes into a single fileview and calls MPI-IO function.
+ * This subroutine also concatenates user buffertypes into a single derived
+ * data type to be used in the MPI read/write function call.
+ */
+static int
+ncmpii_mgetput(NC           *ncp,
+               int           num_reqs,
+               NC_req       *reqs,        /* [num_reqs] */
+               int           rw_flag,     /* WRITE_REQ or READ_REQ */
+               int           io_method)   /* COLL_IO or INDEP_IO */
+{
+    int i, j, len=0, status=NC_NOERR, mpireturn, err;
+    void *buf=NULL;
+    MPI_Status mpistatus;
+    MPI_Datatype filetype, buf_type=MPI_BYTE;
+    MPI_File fh;
+
+    if (io_method == COLL_IO)
+        fh = ncp->nciop->collective_fh;
+    else
+        fh = ncp->nciop->independent_fh;
+
+    /* construct a MPI file type by concatenating fileviews of all requests */
+    status = ncmpii_construct_filetypes(ncp,num_reqs, reqs, rw_flag, &filetype);
+    if (status != NC_NOERR) { /* if failed, skip this request */
+        if (io_method == INDEP_IO) return status;
+
+        /* For collective I/O, we still need to participate the successive
+           collective calls: setview/read/write */
+        num_reqs = 0;
+        filetype = MPI_BYTE;
+    }
+
+    /* set the MPI-IO fileview */
+    MPI_Offset offset=0;
+    err = ncmpii_file_set_view(ncp, fh, &offset, filetype);
+    if (err != NC_NOERR) {
+        num_reqs = 0; /* skip this request */
+        if (status == NC_NOERR) status = err;
+    }
+
+    if (filetype != MPI_BYTE) MPI_Type_free(&filetype);
+
+    /* now construct buffer datatype */
+    if (num_reqs == 0) {
+        /* num_reqs == 0, simply participate the collective call */
+        buf = NULL;
+        len = 0;
+    }
+    else if (num_reqs == 1) {
+        MPI_Offset int8 = reqs[0].bnelems * reqs[0].varp->xsz;
+        len = (int)int8;
+        if (int8 != len) {
+            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+            len = 0; /* skip this request */
+        }
+        buf = reqs[0].xbuf;
+    }
+    else if (num_reqs > 1) { /* create the I/O buffer derived data type */
+        int *blocklengths = (int*) NCI_Malloc((size_t)num_reqs * SIZEOF_INT);
+        MPI_Aint *disps = (MPI_Aint*) NCI_Malloc((size_t)num_reqs*SIZEOF_MPI_AINT);
+        MPI_Aint a0=0, ai, a_last_contig;
+
+        int last_contig_req = 0; /* index of the last contiguous request */
+        buf = NULL;
+        /* process only valid requests */
+        for (i=0, j=0; i<num_reqs; i++) {
+            /* check int overflow */
+            MPI_Offset int8 = reqs[i].bnelems * reqs[i].varp->xsz;
+            blocklengths[j] = (int)int8;
+            if (int8 != blocklengths[j]) { /* int overflow */
+                if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+                blocklengths[j] = 0;
+                continue; /* skip this request */
+            }
+#ifdef HAVE_MPI_GET_ADDRESS
+            MPI_Get_address(reqs[i].xbuf, &ai);
+#else
+            MPI_Address(reqs[i].xbuf, &ai);
+#endif
+            if (j == 0) { /* first valid request */
+                a_last_contig = a0 = ai;
+                buf = reqs[i].xbuf;
+            }
+            disps[j] = ai - a0;
+
+            if (ai - a_last_contig == blocklengths[last_contig_req])
+                /* user buffer of request j is contiguous from j-1
+                 * we coalesce j to j-1 */
+                blocklengths[last_contig_req] += blocklengths[j];
+            else if (j > 0) {
+                /* not contiguous from request last_contig_req */
+                last_contig_req++;
+                a_last_contig = ai;
+                disps[last_contig_req] = ai - a0;
+                blocklengths[last_contig_req] = blocklengths[i];
+            }
+            j++;
+        }
+
+        /* last_contig_req is the index of last contiguous request */
+        if (last_contig_req == 0) {
+            /* user buffers can be concatenated into a contiguous buffer */
+            buf_type = MPI_BYTE;
+            len = blocklengths[0];
+        }
+        else {
+            /* after possible concatenating the user buffers, the true number
+             * of non-contiguous buffers is last_contig_req+1 */
+            num_reqs = last_contig_req+1;
+
+            /* concatenate buffer addresses into a single buffer type */
+#ifdef HAVE_MPI_TYPE_CREATE_HINDEXED
+            mpireturn = MPI_Type_create_hindexed(num_reqs, blocklengths, disps,
+                                                 MPI_BYTE, &buf_type);
+#else
+            mpireturn = MPI_Type_hindexed(num_reqs, blocklengths, disps,
+                                          MPI_BYTE, &buf_type);
+#endif
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn,"MPI_Type_create_hindexed");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) status = err;
+            }
+            else
+                mpireturn = MPI_Type_commit(&buf_type);
+
+            len = 1;
+        }
+        NCI_Free(disps);
+        NCI_Free(blocklengths);
+    }
+    /* if (buf_type == MPI_BYTE) then the whole buf is contiguous */
+
+    if (rw_flag == READ_REQ) {
+        if (io_method == COLL_IO) {
+            TRACE_IO(MPI_File_read_at_all)(fh, offset, buf, len, buf_type,
+                                           &mpistatus);
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn, "MPI_File_read_at_all");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) {
+                    status = (err == NC_EFILE) ? NC_EREAD : err;
+                    DEBUG_ASSIGN_ERROR(status, status)
+                }
+            }
+        } else {
+            TRACE_IO(MPI_File_read_at)(fh, offset, buf, len, buf_type,
+                                       &mpistatus);
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn, "MPI_File_read_at");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) {
+                    status = (err == NC_EFILE) ? NC_EREAD : err;
+                    DEBUG_ASSIGN_ERROR(status, status)
+                }
+            }
+        }
+        /* update the number of bytes read since file open */
+        int get_size;
+        MPI_Get_count(&mpistatus, MPI_BYTE, &get_size);
+        ncp->nciop->get_size += get_size;
+
+    } else { /* WRITE_REQ */
+        if (io_method == COLL_IO) {
+            TRACE_IO(MPI_File_write_at_all)(fh, offset, buf, len, buf_type,
+                                            &mpistatus);
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn, "MPI_File_write_at_all");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) {
+                    status = (err == NC_EFILE) ? NC_EWRITE : err;
+                    DEBUG_ASSIGN_ERROR(status, status)
+                }
+            }
+        } else {
+            TRACE_IO(MPI_File_write_at)(fh, offset, buf, len, buf_type,
+                                        &mpistatus);
+            if (mpireturn != MPI_SUCCESS) {
+                err = ncmpii_handle_error(mpireturn, "MPI_File_write_at");
+                /* return the first encountered error if there is any */
+                if (status == NC_NOERR) {
+                    status = (err == NC_EFILE) ? NC_EWRITE : err;
+                    DEBUG_ASSIGN_ERROR(status, status)
+                }
+            }
+        }
+        /* update the number of bytes written since file open */
+        int put_size;
+        MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
+        ncp->nciop->put_size += put_size;
+    }
+
+    if (buf_type != MPI_BYTE) /* free user buffer type */
+        mpireturn = MPI_Type_free(&buf_type);
+
+    /* No longer need to reset the file view, as the root's fileview includes
+     * the whole file header.
+     TRACE_IO(MPI_File_set_view)(fh, 0, MPI_BYTE, MPI_BYTE, "native",
+                                 MPI_INFO_NULL);
+     */
+
+    return status;
+}
+
+/*----< ncmpii_set_iget_callback() >-----------------------------------------*/
+/* this subroutine is only used by iget_varn API family and when its buftype
+ * argument indicated a noncontiguous data type. In this case, tmpBuf is never
+ * == userBuf
+ *
+ * iget_varn() divides userBuf into pieces, each is used in an iget_varm() and
+ * stored in a cur_req->buf. We cannot unpack each req->buf individually, as
+ * req->buf may need to type converted. So at the end of wait(), we unpack the
+ * entire tmpBuf into userBuf.
+ */
+int ncmpii_set_iget_callback(NC           *ncp,
+                             int           reqid,
+                             void         *tmpBuf,
+                             void         *userBuf,
+                             int           userBufCount,
+                             MPI_Datatype  userBufType)
+{
+    NC_req *cur_req;
+
+    if (reqid == NC_REQ_NULL) return NC_NOERR;
+
+    if (ncp->head == NULL) DEBUG_RETURN_ERROR(NC_EINVAL_REQUEST)
+
+    cur_req = ncp->head;
+    while (cur_req != NULL) {
+        /* find the first linked-list node with reqid, there may be more than
+         * one node with the same request ID
+         */
+        if (cur_req->id == reqid) {
+            MPI_Datatype dup_buftype;
+            MPI_Type_dup(userBufType, &dup_buftype);
+
+            cur_req->tmpBuf = tmpBuf;
+                     /* When not NULL, tmpBuf is an internal buffer allocated
+                      * in iget_varn(). At the end of nonblocking wait call,
+                      * tmpBuf will be unpacked to userBuf and freed.
+                      */
+            cur_req->userBuf = userBuf;
+                     /* User's buffer. iget_varn() divides userBuf into pieces,
+                      * each is used in an iget_varm() and stored in a
+                      * cur_req->buf.
+                      */
+            cur_req->bufcount = userBufCount;
+            cur_req->buftype  = dup_buftype;
+            break;
+        }
+        cur_req = cur_req->next;
+    }
+    if (cur_req == NULL) DEBUG_RETURN_ERROR(NC_EINVAL_REQUEST)
+
+    return NC_NOERR;
+}
+
+/*----< ncmpii_set_iput_callback() >-----------------------------------------*/
+/* this subroutine is only used by iput_varn API family, to tell wait() to
+ * free the temporary buffer at the end.
+ */
+int ncmpii_set_iput_callback(NC   *ncp,
+                             int   reqid,
+                             void *tmpPutBuf)
+{
+    int found_req_id=NC_REQ_NULL;
+    NC_req *cur_req;
+
+    if (reqid == NC_REQ_NULL) return NC_NOERR;
+
+    if (ncp->head == NULL) DEBUG_RETURN_ERROR(NC_EINVAL_REQUEST)
+
+    cur_req = ncp->head;
+    while (cur_req != NULL) {
+        /* there may be more than one linked-list node with the same ID */
+        if (cur_req->id == reqid) {
+            /* set tmpBuf only on the first node, so it is freed just once */
+            if (found_req_id == NC_REQ_NULL) cur_req->tmpBuf = tmpPutBuf;
+            found_req_id = reqid;
+        }
+        if (found_req_id != NC_REQ_NULL && cur_req->id != found_req_id)
+            break; /* requests with same ID are in consecutive linked nodes */
+        cur_req = cur_req->next;
+    }
+    if (found_req_id == NC_REQ_NULL) DEBUG_RETURN_ERROR(NC_EINVAL_REQUEST)
+
+    return NC_NOERR;
+}
diff --git a/src/lib/pnetcdf.h.in b/src/lib/pnetcdf.h.in
new file mode 100644
index 0000000..eaaa3c6
--- /dev/null
+++ b/src/lib/pnetcdf.h.in
@@ -0,0 +1,3906 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: pnetcdf.h.in 2290 2016-01-02 18:37:46Z wkliao $ */
+

+#ifndef _PNETCDF_
+#define _PNETCDF_
+
+#include <mpi.h>
+
+#ifndef PNETCDF_VERSION_MAJOR
+#define PNETCDF_VERSION_MAJOR @PNETCDF_VERSION_MAJOR@
+#define PNETCDF_VERSION_MINOR @PNETCDF_VERSION_MINOR@
+#define PNETCDF_VERSION_SUB @PNETCDF_VERSION_SUB@
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* NetCDF data types and their corresponding external types in C convention
+ * and type names used in PnetCDF APIs:
+    NC_BYTE   :   signed char       (for _schar     APIs)
+    NC_CHAR   : unsigned char       (for _text      APIs)
+    NC_SHORT  :   signed short int  (for _short     APIs)
+    NC_INT    :   signed int        (for _int       APIs)
+    NC_FLOAT  :          float      (for _float     APIs)
+    NC_DOUBLE :          double     (for _double    APIs)
+    NC_UBYTE  : unsigned char       (for _ubyte and
+                                         _uchar     APIs)
+    NC_USHORT : unsigned short int  (for _ushort    APIs)
+    NC_UINT   : unsigned int        (for _uint      APIs)
+    NC_INT64  :   signed long long  (for _longlong  APIs)
+    NC_UINT64 : unsigned long long  (for _ulonglong APIs)
+ */
+
+/* to make PnetCDF error codes compatible to netCDF, below we keep an exact
+ * same copy of netcdf.h and re-use their defined values
+ * Sync-ed with netcdf.h of version 4.4.0-rc5
+ */
+#ifndef _NETCDF_
+
+/*! The nc_type type is just an int. */
+typedef int nc_type;
+
+/*
+ *  The netcdf external data types
+ */
+#define	NC_NAT 	        0	/**< Not A Type */
+#define	NC_BYTE         1	/**< signed 1 byte integer */
+#define	NC_CHAR 	2	/**< ISO/ASCII character */
+#define	NC_SHORT 	3	/**< signed 2 byte integer */
+#define	NC_INT 	        4	/**< signed 4 byte integer */
+#define NC_LONG         NC_INT  /**< deprecated, but required for backward compatibility. */
+#define	NC_FLOAT 	5	/**< single precision floating point number */
+#define	NC_DOUBLE 	6	/**< double precision floating point number */
+#define	NC_UBYTE 	7	/**< unsigned 1 byte int */
+#define	NC_USHORT 	8	/**< unsigned 2-byte int */
+#define	NC_UINT 	9	/**< unsigned 4-byte int */
+#define	NC_INT64 	10	/**< signed 8-byte int */
+#define	NC_UINT64 	11	/**< unsigned 8-byte int */
+#define	NC_STRING 	12	/**< string */
+
+#define NC_MAX_ATOMIC_TYPE NC_STRING
+
+/* The following are use internally in support of user-defines
+ * types. They are also the class returned by nc_inq_user_type. */
+#define	NC_VLEN 	13	/**< vlen (variable-length) types */
+#define	NC_OPAQUE 	14	/**< opaque types */
+#define	NC_ENUM 	15	/**< enum types */
+#define	NC_COMPOUND 	16	/**< compound types */
+
+/* Define the first user defined type id (leave some room) */
+#define NC_FIRSTUSERTYPEID 32
+
+/** Default fill value. This is used unless _FillValue attribute
+ * is set.  These values are stuffed into newly allocated space as
+ * appropriate.  The hope is that one might use these to notice that a
+ * particular datum has not been set. */
+/**@{*/
+#define NC_FILL_BYTE	((signed char)-127)
+#define NC_FILL_CHAR	((char)0)
+#define NC_FILL_SHORT	((short)-32767)
+#define NC_FILL_INT	(-2147483647L)
+#define NC_FILL_FLOAT	(9.9692099683868690e+36f) /* near 15 * 2^119 */
+#define NC_FILL_DOUBLE	(9.9692099683868690e+36)
+#define NC_FILL_UBYTE   (255)
+#define NC_FILL_USHORT  (65535)
+#define NC_FILL_UINT    (4294967295U)
+#define NC_FILL_INT64   ((long long)-9223372036854775806LL)
+#define NC_FILL_UINT64  ((unsigned long long)18446744073709551614ULL)
+#define NC_FILL_STRING  ((char *)"")
+/**@}*/
+
+/*! Max or min values for a type. Nothing greater/smaller can be
+ * stored in a netCDF file for their associated types. Recall that a C
+ * compiler may define int to be any length it wants, but a NC_INT is
+ * *always* a 4 byte signed int. On a platform with 64 bit ints,
+ * there will be many ints which are outside the range supported by
+ * NC_INT. But since NC_INT is an external format, it has to mean the
+ * same thing everywhere. */
+/**@{*/
+#define NC_MAX_BYTE 127
+#define NC_MIN_BYTE (-NC_MAX_BYTE-1)
+#define NC_MAX_CHAR 255
+#define NC_MAX_SHORT 32767
+#define NC_MIN_SHORT (-NC_MAX_SHORT - 1)
+#define NC_MAX_INT 2147483647
+#define NC_MIN_INT (-NC_MAX_INT - 1)
+#define NC_MAX_FLOAT 3.402823466e+38f
+#define NC_MIN_FLOAT (-NC_MAX_FLOAT)
+#define NC_MAX_DOUBLE 1.7976931348623157e+308
+#define NC_MIN_DOUBLE (-NC_MAX_DOUBLE)
+#define NC_MAX_UBYTE NC_MAX_CHAR
+#define NC_MAX_USHORT 65535U
+#define NC_MAX_UINT 4294967295U
+#define NC_MAX_INT64 (9223372036854775807LL)
+#define NC_MIN_INT64 (-9223372036854775807LL-1)
+#define NC_MAX_UINT64 (18446744073709551615ULL)
+#define X_INT64_MAX     (9223372036854775807LL)
+#define X_INT64_MIN     (-X_INT64_MAX - 1)
+#define X_UINT64_MAX    (18446744073709551615ULL)
+/**@}*/
+
+/** Name of fill value attribute.  If you wish a variable to use a
+ * different value than the above defaults, create an attribute with
+ * the same type as the variable and this reserved name. The value you
+ * give the attribute will be used as the fill value for that
+ * variable. */
+#define _FillValue	"_FillValue"
+#define NC_FILL		0	/**< Argument to nc_set_fill() to clear NC_NOFILL */
+#define NC_NOFILL	0x100	/**< Argument to nc_set_fill() to turn off filling of data. */
+
+/* Define the ioflags bits for nc_create and nc_open.
+   currently unused:
+        0x0002
+	0x0040
+	0x0080
+   and the whole upper 16 bits
+*/
+
+#define NC_NOWRITE	 0x0000	/**< Set read-only access for nc_open(). */
+#define NC_WRITE    	 0x0001	/**< Set read-write access for nc_open(). */
+#define NC_CLOBBER	 0x0000 /**< Destroy existing file. Mode flag for nc_create(). */
+#define NC_NOCLOBBER     0x0004	/**< Don't destroy existing file. Mode flag for nc_create(). */
+
+#define NC_DISKLESS      0x0008  /**< Use diskless file. Mode flag for nc_open() or nc_create(). */
+#define NC_MMAP          0x0010  /**< Use diskless file with mmap. Mode flag for nc_open() or nc_create(). */
+
+#define NC_64BIT_DATA    0x0020  /**< CDF-5 format: classic model but 64 bit dimensions and sizes */
+#define NC_CDF5          NC_64BIT_DATA  /**< Alias NC_CDF5 to NC_64BIT_DATA */
+
+#define NC_CLASSIC_MODEL 0x0100 /**< Enforce classic model on netCDF-4. Mode flag for nc_create(). */
+#define NC_64BIT_OFFSET  0x0200  /**< Use large (64-bit) file offsets. Mode flag for nc_create(). */
+
+/** \deprecated The following flag currently is ignored, but use in
+ * nc_open() or nc_create() may someday support use of advisory
+ * locking to prevent multiple writers from clobbering a file
+ */
+#define NC_LOCK          0x0400
+
+/** Share updates, limit caching.
+Use this in mode flags for both nc_create() and nc_open(). */
+#define NC_SHARE         0x0800
+
+#define NC_NETCDF4       0x1000  /**< Use netCDF-4/HDF5 format. Mode flag for nc_create(). */
+
+/** Turn on MPI I/O.
+Use this in mode flags for both nc_create() and nc_open(). */
+#define NC_MPIIO         0x2000
+/** Turn on MPI POSIX I/O.
+Use this in mode flags for both nc_create() and nc_open(). */
+#define NC_MPIPOSIX      0x4000 /**< \deprecated As of libhdf5 1.8.13. */
+
+#define NC_INMEMORY      0x8000  /**< Read from memory. Mode flag for nc_open() or nc_create(). */
+
+#define NC_PNETCDF       (NC_MPIIO) /**< Use parallel-netcdf library; alias for NC_MPIIO. */
+
+/** Format specifier for nc_set_default_format() and returned
+ *  by nc_inq_format. This returns the format as provided by
+ *  the API. See nc_inq_format_extended to see the true file format.
+ *  Starting with version 3.6, there are different format netCDF files.
+ *  4.0 introduces the third one. \see netcdf_format
+ */
+/**@{*/
+#define NC_FORMAT_CLASSIC         (1)
+/* After adding CDF5 support, this flag
+   is somewhat confusing. So, it is renamed.
+   Note that the name in the contributed code
+   NC_FORMAT_64BIT was renamed to NC_FORMAT_CDF2
+*/
+#define NC_FORMAT_64BIT_OFFSET    (2)
+#define NC_FORMAT_64BIT           (NC_FORMAT_64BIT_OFFSET) /**< \deprecated Saved for compatibility.  Use NC_FORMAT_64BIT_OFFSET or NC_FORMAT_64BIT_DATA, from netCDF 4.4.0 onwards. */
+#define NC_FORMAT_NETCDF4         (3)
+#define NC_FORMAT_NETCDF4_CLASSIC (4)
+#define NC_FORMAT_64BIT_DATA      (5)
+
+/* Alias */
+#define NC_FORMAT_CDF5    NC_FORMAT_64BIT_DATA
+
+/**@}*/
+
+/** Extended format specifier returned by  nc_inq_format_extended()
+ *  Added in version 4.3.1. This returns the true format of the
+ *  underlying data.
+ * The function returns two values
+ * 1. a small integer indicating the underlying source type
+ *    of the data. Note that this may differ from what the user
+ *    sees from nc_inq_format() because this latter function
+ *    returns what the user can expect to see thru the API.
+ * 2. A mode value indicating what mode flags are effectively
+ *    set for this dataset. This usually will be a superset
+ *    of the mode flags used as the argument to nc_open
+ *    or nc_create.
+ * More or less, the #1 values track the set of dispatch tables.
+ * The #1 values are as follows.
+ * Note that CDF-5 returns NC_FORMAT_NC3, but sets the mode flag properly.
+ */
+/**@{*/
+
+#define NC_FORMATX_NC3       (1)
+#define NC_FORMATX_NC_HDF5   (2) /**< netCDF-4 subset of HDF5 */
+#define NC_FORMATX_NC4       NC_FORMATX_NC_HDF5 /**< alias */
+#define NC_FORMATX_NC_HDF4   (3) /**< netCDF-4 subset of HDF4 */
+#define NC_FORMATX_PNETCDF   (4)
+#define NC_FORMATX_DAP2      (5)
+#define NC_FORMATX_DAP4      (6)
+#define NC_FORMATX_UNDEFINED (0)
+
+  /* To avoid breaking compatibility (such as in the python library),
+   we need to retain the NC_FORMAT_xxx format as well. This may come
+  out eventually, as the NC_FORMATX is more clear that it's an extended
+  format specifier.*/
+
+#define NC_FORMAT_NC3       NC_FORMATX_NC3 /**< \deprecated As of 4.4.0, use NC_FORMATX_NC3 */
+#define NC_FORMAT_NC_HDF5   NC_FORMATX_NC_HDF5 /**< \deprecated As of 4.4.0, use NC_FORMATX_NC_HDF5 */
+#define NC_FORMAT_NC4       NC_FORMATX_NC4 /**< \deprecated As of 4.4.0, use NC_FORMATX_NC4 */
+#define NC_FORMAT_NC_HDF4   NC_FORMATX_NC_HDF4 /**< \deprecated As of 4.4.0, use NC_FORMATX_HDF4 */
+#define NC_FORMAT_PNETCDF   NC_FORMATX_PNETCDF /**< \deprecated As of 4.4.0, use NC_FORMATX_PNETCDF */
+#define NC_FORMAT_DAP2      NC_FORMATX_DAP2 /**< \deprecated As of 4.4.0, use NC_FORMATX_DAP2 */
+#define NC_FORMAT_DAP4      NC_FORMATX_DAP4 /**< \deprecated As of 4.4.0, use NC_FORMATX_DAP4 */
+#define NC_FORMAT_UNDEFINED NC_FORMATX_UNDEFINED /**< \deprecated As of 4.4.0, use NC_FORMATX_UNDEFINED */
+
+/**@}*/
+
+/** Let nc__create() or nc__open() figure out a suitable buffer size. */
+#define NC_SIZEHINT_DEFAULT 0
+
+/** In nc__enddef(), align to the buffer size. */
+#define NC_ALIGN_CHUNK ((size_t)(-1))
+
+/** Size argument to nc_def_dim() for an unlimited dimension. */
+#define NC_UNLIMITED 0L
+
+/** Attribute id to put/get a global attribute. */
+#define NC_GLOBAL -1
+
+/**
+Maximum for classic library.
+
+In the classic netCDF model there are maximum values for the number of
+dimensions in the file (\ref NC_MAX_DIMS), the number of global or per
+variable attributes (\ref NC_MAX_ATTRS), the number of variables in
+the file (\ref NC_MAX_VARS), and the length of a name (\ref
+NC_MAX_NAME).
+
+These maximums are enforced by the interface, to facilitate writing
+applications and utilities.  However, nothing is statically allocated
+to these sizes internally.
+
+These maximums are not used for netCDF-4/HDF5 files unless they were
+created with the ::NC_CLASSIC_MODEL flag.
+
+As a rule, NC_MAX_VAR_DIMS <= NC_MAX_DIMS.
+*/
+/**@{*/
+#define NC_MAX_DIMS	1024
+#define NC_MAX_ATTRS	8192
+#define NC_MAX_VARS	8192
+#define NC_MAX_NAME	256
+#define NC_MAX_VAR_DIMS	1024 /**< max per variable dimensions */
+/**@}*/
+
+/** This is the max size of an SD dataset name in HDF4 (from HDF4 documentation).*/
+#define NC_MAX_HDF4_NAME 64
+
+/** In HDF5 files you can set the endianness of variables with
+    nc_def_var_endian(). This define is used there. */
+/**@{*/
+#define NC_ENDIAN_NATIVE 0
+#define NC_ENDIAN_LITTLE 1
+#define NC_ENDIAN_BIG    2
+/**@}*/
+
+/** In HDF5 files you can set storage for each variable to be either
+ * contiguous or chunked, with nc_def_var_chunking().  This define is
+ * used there. */
+/**@{*/
+#define NC_CHUNKED    0
+#define NC_CONTIGUOUS 1
+/**@}*/
+
+/** In HDF5 files you can set check-summing for each variable.
+Currently the only checksum available is Fletcher-32, which can be set
+with the function nc_def_var_fletcher32.  These defines are used
+there. */
+/**@{*/
+#define NC_NOCHECKSUM 0
+#define NC_FLETCHER32 1
+/**@}*/
+
+/**@{*/
+/** Control the HDF5 shuffle filter. In HDF5 files you can specify
+ * that a shuffle filter should be used on each chunk of a variable to
+ * improve compression for that variable. This per-variable shuffle
+ * property can be set with the function nc_def_var_deflate(). */
+#define NC_NOSHUFFLE 0
+#define NC_SHUFFLE   1
+/**@}*/
+
+/** The netcdf version 3 functions all return integer error status.
+ * These are the possible values, in addition to certain values from
+ * the system errno.h.
+ */
+#define NC_ISSYSERR(err)	((err) > 0)
+
+#define	NC_NOERR	0   /**< No Error */
+#define NC2_ERR         (-1)       /**< Returned for all errors in the v2 API. */
+
+/** Not a netcdf id.
+
+The specified netCDF ID does not refer to an
+open netCDF dataset. */
+#define	NC_EBADID	(-33)
+#define	NC_ENFILE	(-34)	   /**< Too many netcdfs open */
+#define	NC_EEXIST	(-35)	   /**< netcdf file exists && NC_NOCLOBBER */
+#define	NC_EINVAL	(-36)	   /**< Invalid Argument */
+#define	NC_EPERM	(-37)	   /**< Write to read only */
+
+/** Operation not allowed in data mode. This is returned for netCDF
+classic or 64-bit offset files, or for netCDF-4 files, when they were
+been created with ::NC_CLASSIC_MODEL flag in nc_create(). */
+#define NC_ENOTINDEFINE	(-38)
+
+/** Operation not allowed in define mode.
+
+The specified netCDF is in define mode rather than data mode.
+
+With netCDF-4/HDF5 files, this error will not occur, unless
+::NC_CLASSIC_MODEL was used in nc_create().
+ */
+#define	NC_EINDEFINE	(-39)
+
+/** Index exceeds dimension bound.
+
+The specified corner indices were out of range for the rank of the
+specified variable. For example, a negative index or an index that is
+larger than the corresponding dimension length will cause an error. */
+#define	NC_EINVALCOORDS	(-40)
+
+/** NC_MAX_DIMS exceeded. Max number of dimensions exceeded in a
+classic or 64-bit offset file, or an netCDF-4 file with
+::NC_CLASSIC_MODEL on. */
+#define	NC_EMAXDIMS	(-41)
+
+#define	NC_ENAMEINUSE	(-42)	   /**< String match to name in use */
+#define NC_ENOTATT	(-43)	   /**< Attribute not found */
+#define	NC_EMAXATTS	(-44)	   /**< NC_MAX_ATTRS exceeded */
+#define NC_EBADTYPE	(-45)	   /**< Not a netcdf data type */
+#define NC_EBADDIM	(-46)	   /**< Invalid dimension id or name */
+#define NC_EUNLIMPOS	(-47)	   /**< NC_UNLIMITED in the wrong index */
+
+/** NC_MAX_VARS exceeded. Max number of variables exceeded in a
+classic or 64-bit offset file, or an netCDF-4 file with
+::NC_CLASSIC_MODEL on. */
+#define	NC_EMAXVARS	(-48)
+
+/** Variable not found.
+
+The variable ID is invalid for the specified netCDF dataset. */
+#define NC_ENOTVAR	(-49)
+#define NC_EGLOBAL	(-50)	   /**< Action prohibited on NC_GLOBAL varid */
+#define NC_ENOTNC	(-51)	   /**< Not a netcdf file */
+#define NC_ESTS        	(-52)	   /**< In Fortran, string too short */
+#define NC_EMAXNAME    	(-53)	   /**< NC_MAX_NAME exceeded */
+#define NC_EUNLIMIT    	(-54)	   /**< NC_UNLIMITED size already in use */
+#define NC_ENORECVARS  	(-55)	   /**< nc_rec op when there are no record vars */
+#define NC_ECHAR	(-56)	   /**< Attempt to convert between text & numbers */
+
+/** Start+count exceeds dimension bound.
+
+The specified edge lengths added to the specified corner would have
+referenced data out of range for the rank of the specified
+variable. For example, an edge length that is larger than the
+corresponding dimension length minus the corner index will cause an
+error. */
+#define NC_EEDGE	(-57)
+#define NC_ESTRIDE	(-58)	   /**< Illegal stride */
+#define NC_EBADNAME	(-59)	   /**< Attribute or variable name contains illegal characters */
+/* N.B. following must match value in ncx.h */
+
+/** Math result not representable.
+
+One or more of the values are out of the range of values representable
+by the desired type. */
+#define NC_ERANGE	(-60)
+#define NC_ENOMEM	(-61)	   /**< Memory allocation (malloc) failure */
+#define NC_EVARSIZE     (-62)      /**< One or more variable sizes violate format constraints */
+#define NC_EDIMSIZE     (-63)      /**< Invalid dimension size */
+#define NC_ETRUNC       (-64)      /**< File likely truncated or possibly corrupted */
+#define NC_EAXISTYPE    (-65)      /**< Unknown axis type. */
+
+/* Following errors are added for DAP */
+#define NC_EDAP         (-66)      /**< Generic DAP error */
+#define NC_ECURL        (-67)      /**< Generic libcurl error */
+#define NC_EIO          (-68)      /**< Generic IO error */
+#define NC_ENODATA      (-69)      /**< Attempt to access variable with no data */
+#define NC_EDAPSVC      (-70)      /**< DAP server error */
+#define NC_EDAS		(-71)      /**< Malformed or inaccessible DAS */
+#define NC_EDDS		(-72)      /**< Malformed or inaccessible DDS */
+#define NC_EDATADDS	(-73)      /**< Malformed or inaccessible DATADDS */
+#define NC_EDAPURL	(-74)      /**< Malformed DAP URL */
+#define NC_EDAPCONSTRAINT (-75)    /**< Malformed DAP Constraint*/
+#define NC_ETRANSLATION (-76)      /**< Untranslatable construct */
+#define NC_EACCESS      (-77)      /**< Access Failure */
+#define NC_EAUTH        (-78)      /**< Authorization Failure */
+
+/* Misc. additional errors */
+#define NC_ENOTFOUND     (-90)      /**< No such file */
+#define NC_ECANTREMOVE   (-91)      /**< Can't remove file */
+
+/* The following was added in support of netcdf-4. Make all netcdf-4
+   error codes < -100 so that errors can be added to netcdf-3 if
+   needed. */
+#define NC4_FIRST_ERROR  (-100)
+
+/** Error at HDF5 layer. */
+#define NC_EHDFERR       (-101)
+#define NC_ECANTREAD     (-102)    /**< Can't read. */
+#define NC_ECANTWRITE    (-103)    /**< Can't write. */
+#define NC_ECANTCREATE   (-104)    /**< Can't create. */
+#define NC_EFILEMETA     (-105)    /**< Problem with file metadata. */
+#define NC_EDIMMETA      (-106)    /**< Problem with dimension metadata. */
+#define NC_EATTMETA      (-107)    /**< Problem with attribute metadata. */
+#define NC_EVARMETA      (-108)    /**< Problem with variable metadata. */
+#define NC_ENOCOMPOUND   (-109)    /**< Not a compound type. */
+#define NC_EATTEXISTS    (-110)    /**< Attribute already exists. */
+#define NC_ENOTNC4       (-111)    /**< Attempting netcdf-4 operation on netcdf-3 file. */
+
+/** Attempting netcdf-4 operation on strict nc3 netcdf-4 file. */
+#define NC_ESTRICTNC3    (-112)
+#define NC_ENOTNC3       (-113)    /**< Attempting netcdf-3 operation on netcdf-4 file. */
+#define NC_ENOPAR        (-114)    /**< Parallel operation on file opened for non-parallel access. */
+#define NC_EPARINIT      (-115)    /**< Error initializing for parallel access. */
+#define NC_EBADGRPID     (-116)    /**< Bad group ID. */
+#define NC_EBADTYPID     (-117)    /**< Bad type ID. */
+#define NC_ETYPDEFINED   (-118)    /**< Type has already been defined and may not be edited. */
+#define NC_EBADFIELD     (-119)    /**< Bad field ID. */
+#define NC_EBADCLASS     (-120)    /**< Bad class. */
+#define NC_EMAPTYPE      (-121)    /**< Mapped access for atomic types only. */
+#define NC_ELATEFILL     (-122)    /**< Attempt to define fill value when data already exists. */
+#define NC_ELATEDEF      (-123)    /**< Attempt to define var properties, like deflate, after enddef. */
+#define NC_EDIMSCALE     (-124)    /**< Problem with HDF5 dimscales. */
+#define NC_ENOGRP        (-125)    /**< No group found. */
+#define NC_ESTORAGE      (-126)    /**< Can't specify both contiguous and chunking. */
+#define NC_EBADCHUNK     (-127)    /**< Bad chunksize. */
+#define NC_ENOTBUILT     (-128)    /**< Attempt to use feature that was not turned on when netCDF was built. */
+#define NC_EDISKLESS     (-129)    /**< Error in using diskless  access. */
+#define NC_ECANTEXTEND   (-130)    /**< Attempt to extend dataset during ind. I/O operation. */
+#define NC_EMPI          (-131)    /**< MPI operation failed. */
+
+#define NC4_LAST_ERROR   (-131)
+
+/* This is used in netCDF-4 files for dimensions without coordinate
+ * vars. */
+#define DIM_WITHOUT_VARIABLE "This is a netCDF dimension but not a netCDF variable."
+
+/* This is here at the request of the NCO team to support our
+ * mistake of having chunksizes be first ints, then size_t. Doh! */
+#define NC_HAVE_NEW_CHUNKING_API 1
+
+
+/*Errors for all remote access methods(e.g. DAP and CDMREMOTE)*/
+#define NC_EURL		(NC_EDAPURL)   /* Malformed URL */
+#define NC_ECONSTRAINT  (NC_EDAPCONSTRAINT)   /* Malformed Constraint*/
+
+#endif
+/* end of #ifndef _NETCDF_ */
+
+/* now some definitions used in PnetCDF only */
+
+#define NC_FORMAT_UNKNOWN -1
+
+/* CDF version 1, NC_32BIT is used internally and never
+   actually passed in to ncmpi_create  */
+#define NC_32BIT	0x1000000
+
+/* CDF-5 format, (64-bit) supported */
+#ifndef NC_64BIT_DATA
+#define NC_64BIT_DATA	0x0020
+#endif
+
+/* CDF-2 format, with NC_64BIT_OFFSET. */
+#ifndef NC_FORMAT_CDF2
+#define NC_FORMAT_CDF2  2
+#endif
+
+/* CDF-5 format, with NC_64BIT_DATA. */
+#ifndef NC_FORMAT_CDF5
+#define NC_FORMAT_CDF5  5
+#endif
+
+/* PnetCDF Error Codes: */
+#define NC_ESMALL			(-201) /**< size of MPI_Offset too small for format */
+#define NC_ENOTINDEP			(-202) /**< Operation not allowed in collective data mode */
+#define NC_EINDEP			(-203) /**< Operation not allowed in independent data mode */
+#define NC_EFILE			(-204) /**< Unknown error in file operation */
+#define NC_EREAD			(-205) /**< Unknown error in reading file */
+#define NC_EWRITE			(-206) /**< Unknown error in writing to file */
+#define NC_EOFILE			(-207) /**< file open/creation failed */
+#define NC_EMULTITYPES			(-208) /**< Multiple types used in memory data */
+#define NC_EIOMISMATCH			(-209) /**< Input/Output data amount mismatch */
+#define NC_ENEGATIVECNT			(-210) /**< Negative count is specified */
+#define NC_EUNSPTETYPE			(-211) /**< Unsupported etype in memory MPI datatype */
+#define NC_EINVAL_REQUEST		(-212) /**< invalid nonblocking request ID */
+#define NC_EAINT_TOO_SMALL		(-213) /**< MPI_Aint not large enough to hold requested value */
+#define NC_ENOTSUPPORT			(-214) /**< feature is not yet supported */
+#define NC_ENULLBUF			(-215) /**< trying to attach a NULL buffer */
+#define NC_EPREVATTACHBUF		(-216) /**< previous attached buffer is found */
+#define NC_ENULLABUF			(-217) /**< no attached buffer is found */
+#define NC_EPENDINGBPUT			(-218) /**< pending bput is found, cannot detach buffer */
+#define NC_EINSUFFBUF			(-219) /**< attached buffer is too small */
+#define NC_ENOENT			(-220) /**< File does not exist */
+#define NC_EINTOVERFLOW			(-221) /**< Overflow when type cast to 4-byte integer */
+#define NC_ENOTENABLED			(-222) /**< feature is not enabled */
+#define NC_EBAD_FILE			(-223) /**< Invalid file name (e.g., path name too long) */
+#define NC_ENO_SPACE			(-224) /**< Not enough space */
+#define NC_EQUOTA			(-225) /**< Quota exceeded */
+#define NC_ENULLSTART			(-226) /**< argument start is a NULL pointer */
+#define NC_ENULLCOUNT			(-227) /**< argument count is a NULL pointer */
+#define NC_EINVAL_CMODE			(-228) /**< Invalid file create mode, cannot have both NC_64BIT_OFFSET & NC_64BIT_DATA */
+#define NC_ETYPESIZE			(-229) /**< MPI derived data type size error (bigger than the variable size) */
+#define NC_ETYPE_MISMATCH		(-230) /**< element type of the MPI derived data type mismatches the variable type */
+#define NC_ETYPESIZE_MISMATCH		(-231) /**< file type size mismatches buffer type size */
+#define NC_ESTRICTCDF2			(-232) /**< Attempting CDF-5 operation on CDF-2 file */
+#define NC_ENOTRECVAR			(-233) /**< Attempting operation only for record variables */
+#define NC_ENOTFILL			(-234) /**< Attempting to fill a variable when its fill mode is off */
+/* add new error here */
+
+/* header inconsistency errors start from -250 */
+#define NC_EMULTIDEFINE			(-250) /**< NC definitions on multiprocesses conflict */
+#define NC_EMULTIDEFINE_OMODE		(-251) /**< create/open mode are inconsistent across processes */
+#define NC_EMULTIDEFINE_DIM_NUM		(-252) /**< inconsistent number of dimensions */
+#define NC_EMULTIDEFINE_DIM_SIZE	(-253) /**< inconsistent size of dimension */
+#define NC_EMULTIDEFINE_DIM_NAME	(-254) /**< inconsistent dimension names */
+#define NC_EMULTIDEFINE_VAR_NUM		(-255) /**< inconsistent number of variables */
+#define NC_EMULTIDEFINE_VAR_NAME	(-256) /**< inconsistent variable name */
+#define NC_EMULTIDEFINE_VAR_NDIMS	(-257) /**< inconsistent variable's number of dimensions */
+#define NC_EMULTIDEFINE_VAR_DIMIDS	(-258) /**< inconsistent variable's dimid */
+#define NC_EMULTIDEFINE_VAR_TYPE	(-259) /**< inconsistent variable's data type */
+#define NC_EMULTIDEFINE_VAR_LEN		(-260) /**< inconsistent variable's size */
+#define NC_EMULTIDEFINE_NUMRECS		(-261) /**< inconsistent number of records */
+#define NC_EMULTIDEFINE_VAR_BEGIN	(-262) /**< inconsistent variable file begin offset (internal use) */
+#define NC_EMULTIDEFINE_ATTR_NUM	(-263) /**< inconsistent number of attributes */
+#define NC_EMULTIDEFINE_ATTR_SIZE	(-264) /**< inconsistent memory space used by attribute (internal use) */
+#define NC_EMULTIDEFINE_ATTR_NAME	(-265) /**< inconsistent attribute name */
+#define NC_EMULTIDEFINE_ATTR_TYPE	(-266) /**< inconsistent attribute type */
+#define NC_EMULTIDEFINE_ATTR_LEN	(-267) /**< inconsistent attribute length */
+#define NC_EMULTIDEFINE_ATTR_VAL	(-268) /**< inconsistent attribute value */
+#define NC_EMULTIDEFINE_FNC_ARGS	(-269) /**< inconsistent function arguments used in collective API */
+#define NC_EMULTIDEFINE_FILL_MODE	(-270) /**< inconsistent dataset fill mode */
+#define NC_EMULTIDEFINE_VAR_FILL_MODE	(-271) /**< inconsistent variable fill mode */
+#define NC_EMULTIDEFINE_VAR_FILL_VALUE	(-272) /**< inconsistent variable fill value */
+
+#define NC_EMULTIDEFINE_FIRST		NC_EMULTIDEFINE
+#define NC_EMULTIDEFINE_LAST		NC_EMULTIDEFINE_FNC_ARGS
+
+/* backward compatible with PnetCDF 1.3.1 and earlier */
+#define NC_ECMODE			NC_EMULTIDEFINE_OMODE
+#define NC_EDIMS_NELEMS_MULTIDEFINE	NC_EMULTIDEFINE_DIM_NUM
+#define NC_EDIMS_SIZE_MULTIDEFINE	NC_EMULTIDEFINE_DIM_SIZE
+#define NC_EDIMS_NAME_MULTIDEFINE	NC_EMULTIDEFINE_DIM_NAME
+#define NC_EVARS_NELEMS_MULTIDEFINE	NC_EMULTIDEFINE_VAR_NUM
+#define NC_EVARS_NAME_MULTIDEFINE	NC_EMULTIDEFINE_VAR_NAME
+#define NC_EVARS_NDIMS_MULTIDEFINE	NC_EMULTIDEFINE_VAR_NDIMS
+#define NC_EVARS_DIMIDS_MULTIDEFINE	NC_EMULTIDEFINE_VAR_DIMIDS
+#define NC_EVARS_TYPE_MULTIDEFINE	NC_EMULTIDEFINE_VAR_TYPE
+#define NC_EVARS_LEN_MULTIDEFINE	NC_EMULTIDEFINE_VAR_LEN
+#define NC_ENUMRECS_MULTIDEFINE		NC_EMULTIDEFINE_NUMRECS
+#define NC_EVARS_BEGIN_MULTIDEFINE	NC_EMULTIDEFINE_VAR_BEGIN
+
+/* invalid nonblocking request ID and zero-length request */
+#define NC_REQ_NULL -1
+
+/* indicate to flush all pending non-blocking requests */
+#define NC_REQ_ALL -1
+
+

+/*
+ * The Interface
+ */
+
+/* Begin Prototypes */
+
+const char* ncmpi_strerror(int err);
+
+/* Begin Dataset Functions */
+
+int ncmpi_create(MPI_Comm comm, const char *path, int cmode, MPI_Info info, int *ncidp);
+
+int ncmpi_open(MPI_Comm comm, const char *path, int omode, MPI_Info info, int *ncidp);
+
+int ncmpi_inq_file_info(int ncid, MPI_Info *info_used);
+int ncmpi_get_file_info(int ncid, MPI_Info *info_used);
+
+int ncmpi_delete(char *filename, MPI_Info info);
+
+int ncmpi_enddef(int ncid);
+
+int ncmpi__enddef(int ncid, MPI_Offset h_minfree, MPI_Offset v_align,
+                  MPI_Offset v_minfree, MPI_Offset r_align);
+
+int ncmpi_redef(int ncid);
+
+int ncmpi_set_default_format(int format, int *old_formatp);
+
+int ncmpi_inq_default_format(int *formatp);
+
+int ncmpi_sync(int ncid);
+
+int ncmpi_sync_numrecs(int ncid);
+
+int ncmpi_abort(int ncid);
+
+int ncmpi_begin_indep_data(int ncid);
+
+int ncmpi_end_indep_data(int ncid);
+
+int ncmpi_close(int ncid);
+
+int ncmpi_set_fill(int ncid, int fillmode, int *old_modep);
+
+int ncmpi_def_var_fill(int ncid, int varid, int no_fill, void *fill_value);
+
+int ncmpi_inq_var_fill(int ncid, int varid, int *no_fill, void *fill_value);
+
+int ncmpi_fill_var_rec(int ncid, int varid, MPI_Offset recno);
+
+/* End Dataset Functions */
+
+/* Begin Define Mode Functions */
+
+int ncmpi_def_dim(int ncid, const char *name, MPI_Offset len, int *idp);
+
+int ncmpi_def_var(int ncid, const char *name, nc_type xtype,
+                  int ndims, const int *dimidsp, int *varidp);
+
+int ncmpi_rename_dim(int ncid, int dimid, const char *name);
+
+int ncmpi_rename_var(int ncid, int varid, const char *name);
+
+/* End Define Mode Functions */
+
+/* Begin Inquiry Functions */
+
+const char* ncmpi_inq_libvers(void);
+
+int ncmpi_inq(int ncid, int *ndimsp, int *nvarsp,
+              int *ngattsp, int *unlimdimidp);
+
+int ncmpi_inq_format(int ncid, int *formatp);
+
+int ncmpi_inq_file_format(char *filename, int *formatp);
+
+int ncmpi_inq_version(int ncid, int *NC_mode);
+
+int ncmpi_inq_striping(int ncid, int *striping_size, int *striping_count);
+
+int ncmpi_inq_ndims(int ncid, int *ndimsp);
+
+int ncmpi_inq_nvars(int ncid, int *nvarsp);
+
+int ncmpi_inq_num_rec_vars(int ncid, int *nvarsp);
+
+int ncmpi_inq_num_fix_vars(int ncid, int *nvarsp);
+
+int ncmpi_inq_natts(int ncid, int *ngattsp);
+
+int ncmpi_inq_unlimdim(int ncid, int *unlimdimidp);
+
+int ncmpi_inq_dimid(int ncid, const char *name, int *idp);
+
+int ncmpi_inq_dim(int ncid, int dimid, char *name, MPI_Offset *lenp);
+
+int ncmpi_inq_dimname(int ncid, int dimid, char *name);
+
+int ncmpi_inq_dimlen(int ncid, int dimid, MPI_Offset *lenp);
+
+int ncmpi_inq_var(int ncid, int varid, char *name, nc_type *xtypep,
+                  int *ndimsp, int *dimidsp, int *nattsp);
+
+int ncmpi_inq_varid(int ncid, const char *name, int *varidp);
+
+int ncmpi_inq_varname(int ncid, int varid, char *name);
+
+int ncmpi_inq_vartype(int ncid, int varid, nc_type *xtypep);
+
+int ncmpi_inq_varndims(int ncid, int varid, int *ndimsp);
+
+int ncmpi_inq_vardimid(int ncid, int varid, int *dimidsp);
+
+int ncmpi_inq_varnatts(int ncid, int varid, int *nattsp);
+
+int ncmpi_inq_varoffset(int ncid, int varid, MPI_Offset *offset);
+
+int ncmpi_inq_put_size(int ncid, MPI_Offset *size);
+
+int ncmpi_inq_get_size(int ncid, MPI_Offset *size);
+
+int ncmpi_inq_header_size(int ncid, MPI_Offset *size);
+
+int ncmpi_inq_header_extent(int ncid, MPI_Offset *extent);
+
+int ncmpi_inq_malloc_size(MPI_Offset *size);
+int ncmpi_inq_malloc_max_size(MPI_Offset *size);
+int ncmpi_inq_malloc_list(void);
+
+int ncmpi_inq_files_opened(int *num, int *ncids);
+
+int ncmpi_inq_recsize(int ncid, MPI_Offset *recsize);
+
+/* End Inquiry Functions */
+
+/* Begin _att */
+
+int ncmpi_inq_att(int ncid, int varid, const char *name,
+                  nc_type *xtypep, MPI_Offset *lenp);
+
+int ncmpi_inq_attid(int ncid, int varid, const char *name, int *idp);
+
+int ncmpi_inq_atttype(int ncid, int varid, const char *name,
+                      nc_type *xtypep);
+
+int ncmpi_inq_attlen(int ncid, int varid, const char *name,
+                     MPI_Offset *lenp);
+
+int ncmpi_inq_attname(int ncid, int varid, int attnum, char *name);
+
+int ncmpi_copy_att(int ncid_in, int varid_in, const char *name,
+                   int ncid_out, int varid_out);
+
+int ncmpi_rename_att(int ncid, int varid, const char *name,
+                     const char *newname);
+
+int ncmpi_del_att(int ncid, int varid, const char *name);
+
+int ncmpi_put_att(int ncid, int varid, const char *name, nc_type xtype,
+                  MPI_Offset nelems, const void *value);
+
+int ncmpi_put_att_text(int ncid, int varid, const char *name, MPI_Offset len,
+                  const char *op);
+
+int ncmpi_put_att_schar(int ncid, int varid, const char *name,
+                  nc_type xtype, MPI_Offset len, const signed char *op);
+
+int ncmpi_put_att_short(int ncid, int varid, const char *name,
+                  nc_type xtype, MPI_Offset len, const short *op);
+
+int ncmpi_put_att_int(int ncid, int varid, const char *name,
+                  nc_type xtype, MPI_Offset len, const int *op);
+
+int ncmpi_put_att_float(int ncid, int varid, const char *name,
+                  nc_type xtype, MPI_Offset len, const float *op);
+
+int ncmpi_put_att_double(int ncid, int varid, const char *name,
+                  nc_type xtype, MPI_Offset len, const double *op);
+
+int ncmpi_put_att_longlong(int ncid, int varid, const char *name,
+                  nc_type xtype, MPI_Offset len, const long long *op);
+
+int ncmpi_get_att(int ncid, int varid, const char *name, void *value);
+
+int ncmpi_get_att_text(int ncid, int varid, const char *name, char *ip);
+
+int ncmpi_get_att_schar(int ncid, int varid, const char *name,
+                  signed char *ip);
+
+int ncmpi_get_att_short(int ncid, int varid, const char *name, short *ip);
+
+int ncmpi_get_att_int(int ncid, int varid, const char *name, int *ip);
+
+int ncmpi_get_att_float(int ncid, int varid, const char *name, float *ip);
+
+int ncmpi_get_att_double(int ncid, int varid, const char *name, double *ip);
+
+int ncmpi_get_att_longlong(int ncid, int varid, const char *name, long long *ip);
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_put_att_uchar(int ncid, int varid, const char *name,
+                  nc_type xtype, MPI_Offset len, const unsigned char *op);
+
+int ncmpi_put_att_ubyte(int ncid, int varid, const char *name,
+                  nc_type xtype, MPI_Offset len, const unsigned char *op);
+
+int ncmpi_put_att_ushort(int ncid, int varid, const char *name,
+                  nc_type xtype, MPI_Offset len, const unsigned short *op);
+
+int ncmpi_put_att_uint(int ncid, int varid, const char *name,
+                  nc_type xtype, MPI_Offset len, const unsigned int *op);
+
+int ncmpi_put_att_long(int ncid, int varid, const char *name,
+                  nc_type xtype, MPI_Offset len, const long *op);
+
+int ncmpi_put_att_ulonglong(int ncid, int varid, const char *name,
+                  nc_type xtype, MPI_Offset len, const unsigned long long *op);
+
+int ncmpi_get_att_uchar(int ncid, int varid, const char *name,
+                  unsigned char *ip);
+
+int ncmpi_get_att_ubyte(int ncid, int varid, const char *name,
+                  unsigned char *ip);
+
+int ncmpi_get_att_ushort(int ncid, int varid, const char *name,
+                  unsigned short *ip);
+
+int ncmpi_get_att_uint(int ncid, int varid, const char *name,
+                  unsigned int *ip);
+
+int ncmpi_get_att_long(int ncid, int varid, const char *name,
+                  long *ip);
+
+int ncmpi_get_att_ulonglong(int ncid, int varid, const char *name,
+                  unsigned long long *ip);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End _att */
+
+/* Begin {put,get}_var1 */
+
+int ncmpi_put_var1(int ncid, int varid, const MPI_Offset index[],
+                   const void *buf, MPI_Offset bufcount, MPI_Datatype buftype);
+int ncmpi_put_var1_all(int ncid, int varid, const MPI_Offset index[],
+                   const void *buf, MPI_Offset bufcount, MPI_Datatype buftype);
+
+int ncmpi_put_var1_text(int ncid, int varid, const MPI_Offset index[],
+                   const char *op);
+int ncmpi_put_var1_text_all(int ncid, int varid, const MPI_Offset index[],
+                   const char *op);
+
+int ncmpi_put_var1_schar(int ncid, int varid, const MPI_Offset index[],
+                   const signed char *op);
+int ncmpi_put_var1_schar_all(int ncid, int varid, const MPI_Offset index[],
+                   const signed char *op);
+
+int ncmpi_put_var1_short(int ncid, int varid, const MPI_Offset index[],
+                   const short *op);
+int ncmpi_put_var1_short_all(int ncid, int varid, const MPI_Offset index[],
+                   const short *op);
+
+int ncmpi_put_var1_int(int ncid, int varid, const MPI_Offset index[],
+                   const int *op);
+int ncmpi_put_var1_int_all(int ncid, int varid, const MPI_Offset index[],
+                   const int *op);
+
+int ncmpi_put_var1_float(int ncid, int varid, const MPI_Offset index[],
+                   const float *op);
+int ncmpi_put_var1_float_all(int ncid, int varid, const MPI_Offset index[],
+                   const float *op);
+
+int ncmpi_put_var1_double(int ncid, int varid, const MPI_Offset index[],
+                   const double *op);
+int ncmpi_put_var1_double_all(int ncid, int varid, const MPI_Offset index[],
+                   const double *op);
+
+int ncmpi_put_var1_longlong(int ncid, int varid, const MPI_Offset index[],
+                   const long long *op);
+int ncmpi_put_var1_longlong_all(int ncid, int varid, const MPI_Offset index[],
+                   const long long *op);
+
+int ncmpi_get_var1(int ncid, int varid, const MPI_Offset index[],
+                   void *buf, MPI_Offset bufcount, MPI_Datatype buftype);
+int ncmpi_get_var1_all(int ncid, int varid, const MPI_Offset index[],
+                   void *buf, MPI_Offset bufcount, MPI_Datatype buftype);
+
+int ncmpi_get_var1_text(int ncid, int varid, const MPI_Offset index[],
+                   char *ip);
+int ncmpi_get_var1_text_all(int ncid, int varid, const MPI_Offset index[],
+                   char *ip);
+
+int ncmpi_get_var1_schar(int ncid, int varid, const MPI_Offset index[],
+                   signed char *ip);
+int ncmpi_get_var1_schar_all(int ncid, int varid, const MPI_Offset index[],
+                   signed char *ip);
+
+int ncmpi_get_var1_short(int ncid, int varid, const MPI_Offset index[],
+                   short *ip);
+int ncmpi_get_var1_short_all(int ncid, int varid, const MPI_Offset index[],
+                   short *ip);
+
+int ncmpi_get_var1_int(int ncid, int varid, const MPI_Offset index[],
+                   int *ip);
+int ncmpi_get_var1_int_all(int ncid, int varid, const MPI_Offset index[],
+                   int *ip);
+
+int ncmpi_get_var1_float(int ncid, int varid, const MPI_Offset index[],
+                   float *ip);
+int ncmpi_get_var1_float_all(int ncid, int varid, const MPI_Offset index[],
+                   float *ip);
+
+int ncmpi_get_var1_double(int ncid, int varid, const MPI_Offset index[],
+                   double *ip);
+int ncmpi_get_var1_double_all(int ncid, int varid, const MPI_Offset index[],
+                   double *ip);
+
+int ncmpi_get_var1_longlong(int ncid, int varid, const MPI_Offset index[],
+                   long long *ip);
+int ncmpi_get_var1_longlong_all(int ncid, int varid, const MPI_Offset index[],
+                   long long *ip);
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_put_var1_uchar(int ncid, int varid, const MPI_Offset index[],
+                   const unsigned char *op);
+int ncmpi_put_var1_uchar_all(int ncid, int varid, const MPI_Offset index[],
+                   const unsigned char *op);
+
+int ncmpi_put_var1_ushort(int ncid, int varid, const MPI_Offset index[],
+                   const unsigned short *op);
+int ncmpi_put_var1_ushort_all(int ncid, int varid, const MPI_Offset index[],
+                   const unsigned short *op);
+
+int ncmpi_put_var1_uint(int ncid, int varid, const MPI_Offset index[],
+                   const unsigned int *op);
+int ncmpi_put_var1_uint_all(int ncid, int varid, const MPI_Offset index[],
+                   const unsigned int *op);
+
+int ncmpi_put_var1_long(int ncid, int varid, const MPI_Offset index[],
+                   const long *ip);
+int ncmpi_put_var1_long_all(int ncid, int varid, const MPI_Offset index[],
+                   const long *ip);
+
+int ncmpi_put_var1_ulonglong(int ncid, int varid, const MPI_Offset index[],
+                   const unsigned long long *ip);
+int ncmpi_put_var1_ulonglong_all(int ncid, int varid, const MPI_Offset index[],
+                   const unsigned long long *ip);
+
+int ncmpi_get_var1_uchar(int ncid, int varid, const MPI_Offset index[],
+                   unsigned char *ip);
+int ncmpi_get_var1_uchar_all(int ncid, int varid, const MPI_Offset index[],
+                   unsigned char *ip);
+
+int ncmpi_get_var1_ushort(int ncid, int varid, const MPI_Offset index[],
+                   unsigned short *ip);
+int ncmpi_get_var1_ushort_all(int ncid, int varid, const MPI_Offset index[],
+                   unsigned short *ip);
+
+int ncmpi_get_var1_uint(int ncid, int varid, const MPI_Offset index[],
+                   unsigned int *ip);
+int ncmpi_get_var1_uint_all(int ncid, int varid, const MPI_Offset index[],
+                   unsigned int *ip);
+
+int ncmpi_get_var1_long(int ncid, int varid, const MPI_Offset index[],
+                   long *ip);
+int ncmpi_get_var1_long_all(int ncid, int varid, const MPI_Offset index[],
+                   long *ip);
+
+int ncmpi_get_var1_ulonglong(int ncid, int varid, const MPI_Offset index[],
+                   unsigned long long *ip);
+int ncmpi_get_var1_ulonglong_all(int ncid, int varid, const MPI_Offset index[],
+                   unsigned long long *ip);
+/* End Skip Prototypes for Fortran binding */
+
+/* End {put,get}_var1 */
+
+/* Begin {put,get}_var */
+
+int ncmpi_put_var(int ncid, int varid, const void *buf, MPI_Offset bufcount,
+                  MPI_Datatype buftype);
+
+int ncmpi_put_var_all(int ncid, int varid, const void *buf, MPI_Offset bufcount,
+                  MPI_Datatype buftype);
+
+int ncmpi_put_var_text(int ncid, int varid, const char *op);
+int ncmpi_put_var_text_all(int ncid, int varid, const char *op);
+
+int ncmpi_put_var_schar(int ncid, int varid, const signed char *op);
+int ncmpi_put_var_schar_all(int ncid, int varid, const signed char *op);
+
+int ncmpi_put_var_short(int ncid, int varid, const short *op);
+int ncmpi_put_var_short_all(int ncid, int varid, const short *op);
+
+int ncmpi_put_var_int(int ncid, int varid, const int *op);
+int ncmpi_put_var_int_all(int ncid, int varid, const int *op);
+
+int ncmpi_put_var_float(int ncid, int varid, const float *op);
+int ncmpi_put_var_float_all(int ncid, int varid, const float *op);
+
+int ncmpi_put_var_double(int ncid, int varid, const double *op);
+int ncmpi_put_var_double_all(int ncid, int varid, const double *op);
+
+int ncmpi_put_var_longlong(int ncid, int varid, const long long *op);
+int ncmpi_put_var_longlong_all(int ncid, int varid, const long long *op);
+
+int ncmpi_get_var(int ncid, int varid, void *buf, MPI_Offset bufcount,
+                  MPI_Datatype buftype);
+
+int ncmpi_get_var_all(int ncid, int varid, void *buf, MPI_Offset bufcount,
+                  MPI_Datatype buftype);
+
+int ncmpi_get_var_text(int ncid, int varid, char *ip);
+int ncmpi_get_var_text_all(int ncid, int varid, char *ip);
+
+int ncmpi_get_var_schar(int ncid, int varid, signed char *ip);
+int ncmpi_get_var_schar_all(int ncid, int varid, signed char *ip);
+
+int ncmpi_get_var_short(int ncid, int varid, short *ip);
+int ncmpi_get_var_short_all(int ncid, int varid, short *ip);
+
+int ncmpi_get_var_int(int ncid, int varid, int *ip);
+int ncmpi_get_var_int_all(int ncid, int varid, int *ip);
+
+int ncmpi_get_var_float(int ncid, int varid, float *ip);
+int ncmpi_get_var_float_all(int ncid, int varid, float *ip);
+
+int ncmpi_get_var_double(int ncid, int varid, double *ip);
+int ncmpi_get_var_double_all(int ncid, int varid, double *ip);
+
+int ncmpi_get_var_longlong(int ncid, int varid, long long *ip);
+int ncmpi_get_var_longlong_all(int ncid, int varid, long long *ip);
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_put_var_uchar(int ncid, int varid, const unsigned char *op);
+int ncmpi_put_var_uchar_all(int ncid, int varid, const unsigned char *op);
+
+int ncmpi_put_var_ushort(int ncid, int varid, const unsigned short *op);
+int ncmpi_put_var_ushort_all(int ncid, int varid, const unsigned short *op);
+
+int ncmpi_put_var_uint(int ncid, int varid, const unsigned int *op);
+int ncmpi_put_var_uint_all(int ncid, int varid, const unsigned int *op);
+
+int ncmpi_put_var_long(int ncid, int varid, const long *op);
+int ncmpi_put_var_long_all(int ncid, int varid, const long *op);
+
+int ncmpi_put_var_ulonglong(int ncid, int varid, const unsigned long long *op);
+int ncmpi_put_var_ulonglong_all(int ncid, int varid, const unsigned long long *op);
+
+int ncmpi_get_var_uchar(int ncid, int varid, unsigned char *ip);
+int ncmpi_get_var_uchar_all(int ncid, int varid, unsigned char *ip);
+
+int ncmpi_get_var_ushort(int ncid, int varid, unsigned short *ip);
+int ncmpi_get_var_ushort_all(int ncid, int varid, unsigned short *ip);
+
+int ncmpi_get_var_uint(int ncid, int varid, unsigned int *ip);
+int ncmpi_get_var_uint_all(int ncid, int varid, unsigned int *ip);
+
+int ncmpi_get_var_long(int ncid, int varid, long *ip);
+int ncmpi_get_var_long_all(int ncid, int varid, long *ip);
+
+int ncmpi_get_var_ulonglong(int ncid, int varid, unsigned long long *ip);
+int ncmpi_get_var_ulonglong_all(int ncid, int varid, unsigned long long *ip);
+/* End Skip Prototypes for Fortran binding */
+
+/* End {put,get}_var */
+
+/* Begin {put,get}_vara */
+
+int ncmpi_put_vara(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const void *buf,
+                   MPI_Offset bufcount, MPI_Datatype buftype);
+
+int ncmpi_put_vara_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const void *buf,
+                   MPI_Offset bufcount, MPI_Datatype buftype);
+
+int ncmpi_put_vara_text(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const char *op);
+
+int ncmpi_put_vara_text_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const char *op);
+
+int ncmpi_put_vara_schar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const signed char *op);
+
+int ncmpi_put_vara_schar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const signed char *op);
+
+int ncmpi_put_vara_short(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const short *op);
+
+int ncmpi_put_vara_short_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const short *op);
+
+int ncmpi_put_vara_int(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const int *op);
+
+int ncmpi_put_vara_int_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const int *op);
+
+int ncmpi_put_vara_float(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const float *op);
+
+int ncmpi_put_vara_float_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const float *op);
+
+int ncmpi_put_vara_double(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const double *op);
+
+int ncmpi_put_vara_double_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const double *op);
+
+int ncmpi_put_vara_longlong(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const long long *op);
+
+int ncmpi_put_vara_longlong_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const long long *op);
+
+int ncmpi_get_vara(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], void *buf, MPI_Offset bufcount,
+                   MPI_Datatype buftype);
+
+int ncmpi_get_vara_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], void *buf, MPI_Offset bufcount,
+                   MPI_Datatype buftype);
+
+int ncmpi_get_vara_text(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], char *ip);
+
+int ncmpi_get_vara_text_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], char *ip);
+
+int ncmpi_get_vara_schar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], signed char *ip);
+
+int ncmpi_get_vara_schar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], signed char *ip);
+
+int ncmpi_get_vara_short(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], short *ip);
+
+int ncmpi_get_vara_short_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], short *ip);
+
+int ncmpi_get_vara_int(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], int *ip);
+
+int ncmpi_get_vara_int_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], int *ip);
+
+int ncmpi_get_vara_float(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], float *ip);
+
+int ncmpi_get_vara_float_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], float *ip);
+
+int ncmpi_get_vara_double(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], double *ip);
+
+int ncmpi_get_vara_double_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], double *ip);
+
+int ncmpi_get_vara_longlong(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], long long *ip);
+
+int ncmpi_get_vara_longlong_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], long long *ip);
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_put_vara_uchar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const unsigned char *op);
+
+int ncmpi_put_vara_uchar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const unsigned char *op);
+
+int ncmpi_put_vara_ushort(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const unsigned short *op);
+
+int ncmpi_put_vara_ushort_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const unsigned short *op);
+
+int ncmpi_put_vara_uint(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const unsigned int *op);
+
+int ncmpi_put_vara_uint_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const unsigned int *op);
+
+int ncmpi_put_vara_long(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const long *op);
+
+int ncmpi_put_vara_long_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const long *op);
+
+int ncmpi_put_vara_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const unsigned long long *op);
+
+int ncmpi_put_vara_ulonglong_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const unsigned long long *op);
+
+int ncmpi_get_vara_uchar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], unsigned char *ip);
+
+int ncmpi_get_vara_uchar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], unsigned char *ip);
+
+int ncmpi_get_vara_ushort(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], unsigned short *ip);
+
+int ncmpi_get_vara_ushort_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], unsigned short *ip);
+
+int ncmpi_get_vara_uint(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], unsigned int *ip);
+
+int ncmpi_get_vara_uint_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], unsigned int *ip);
+
+int ncmpi_get_vara_long(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], long *ip);
+
+int ncmpi_get_vara_long_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], long *ip);
+
+int ncmpi_get_vara_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], unsigned long long *ip);
+
+int ncmpi_get_vara_ulonglong_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], unsigned long long *ip);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End {put,get}_vara */
+
+/* Begin {put,get}_vars */
+
+int ncmpi_put_vars(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const void *buf, MPI_Offset bufcount,
+                   MPI_Datatype buftype);
+
+int ncmpi_put_vars_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const void *buf, MPI_Offset bufcount,
+                   MPI_Datatype buftype);
+
+int ncmpi_put_vars_text(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const char *op);
+
+int ncmpi_put_vars_text_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const char *op);
+
+int ncmpi_put_vars_schar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const signed char *op);
+
+int ncmpi_put_vars_schar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const signed char *op);
+
+int ncmpi_put_vars_short(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const short *op);
+
+int ncmpi_put_vars_short_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const short *op);
+
+int ncmpi_put_vars_int(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const int *op);
+
+int ncmpi_put_vars_int_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const int *op);
+
+int ncmpi_put_vars_float(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const float *op);
+
+int ncmpi_put_vars_float_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const float *op);
+
+int ncmpi_put_vars_double(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const double *op);
+
+int ncmpi_put_vars_double_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const double *op);
+
+int ncmpi_put_vars_longlong(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const long long *op);
+
+int ncmpi_put_vars_longlong_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const long long *op);
+
+int ncmpi_get_vars(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   void *buf, MPI_Offset bufcount, MPI_Datatype buftype);
+
+int ncmpi_get_vars_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   void *buf, MPI_Offset bufcount, MPI_Datatype buftype);
+
+int ncmpi_get_vars_schar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   signed char *ip);
+
+int ncmpi_get_vars_schar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   signed char *ip);
+
+int ncmpi_get_vars_text(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   char *ip);
+
+int ncmpi_get_vars_text_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   char *ip);
+
+int ncmpi_get_vars_short(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   short *ip);
+
+int ncmpi_get_vars_short_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   short *ip);
+
+int ncmpi_get_vars_int(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   int *ip);
+
+int ncmpi_get_vars_int_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   int *ip);
+
+int ncmpi_get_vars_float(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   float *ip);
+
+int ncmpi_get_vars_float_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   float *ip);
+
+int ncmpi_get_vars_double(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   double *ip);
+
+int ncmpi_get_vars_double_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   double *ip);
+
+int ncmpi_get_vars_longlong(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   long long *ip);
+
+int ncmpi_get_vars_longlong_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   long long *ip);
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_put_vars_uchar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const unsigned char *op);
+
+int ncmpi_put_vars_uchar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const unsigned char *op);
+
+int ncmpi_put_vars_ushort(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const unsigned short *op);
+
+int ncmpi_put_vars_ushort_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const unsigned short *op);
+
+int ncmpi_put_vars_uint(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const unsigned int *op);
+
+int ncmpi_put_vars_uint_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const unsigned int *op);
+
+int ncmpi_put_vars_long(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const long *op);
+
+int ncmpi_put_vars_long_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const long *op);
+
+int ncmpi_put_vars_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const unsigned long long *op);
+
+int ncmpi_put_vars_ulonglong_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const unsigned long long *op);
+
+int ncmpi_get_vars_uchar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   unsigned char *ip);
+
+int ncmpi_get_vars_uchar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   unsigned char *ip);
+
+int ncmpi_get_vars_ushort(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   unsigned short *ip);
+
+int ncmpi_get_vars_ushort_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   unsigned short *ip);
+
+int ncmpi_get_vars_uint(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   unsigned int *ip);
+
+int ncmpi_get_vars_uint_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   unsigned int *ip);
+
+int ncmpi_get_vars_long(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   long *ip);
+
+int ncmpi_get_vars_long_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   long *ip);
+
+int ncmpi_get_vars_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   unsigned long long *ip);
+
+int ncmpi_get_vars_ulonglong_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   unsigned long long *ip);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End {put,get}_vars */
+
+/* Begin {put,get}_varm */
+
+int ncmpi_put_varm(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const void *buf,
+                   MPI_Offset bufcount, MPI_Datatype buftype);
+
+int ncmpi_put_varm_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const void *buf,
+                   MPI_Offset bufcount, MPI_Datatype buftype);
+
+int ncmpi_put_varm_text(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const char *op);
+
+int ncmpi_put_varm_text_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const char *op);
+
+int ncmpi_put_varm_schar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const signed char *op);
+
+int ncmpi_put_varm_schar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const signed char *op);
+
+int ncmpi_put_varm_short(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const short *op);
+
+int ncmpi_put_varm_short_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const short *op);
+
+int ncmpi_put_varm_int(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const int *op);
+
+int ncmpi_put_varm_int_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const int *op);
+
+int ncmpi_put_varm_float(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const float *op);
+
+int ncmpi_put_varm_float_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const float *op);
+
+int ncmpi_put_varm_double(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const double *op);
+
+int ncmpi_put_varm_double_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const double *op);
+
+int ncmpi_put_varm_longlong(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const long long *op);
+
+int ncmpi_put_varm_longlong_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const long long *op);
+
+int ncmpi_get_varm(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], void *buf, MPI_Offset bufcount,
+                   MPI_Datatype buftype);
+
+int ncmpi_get_varm_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], void *buf, MPI_Offset bufcount,
+                   MPI_Datatype buftype);
+
+int ncmpi_get_varm_schar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], signed char *ip);
+
+int ncmpi_get_varm_schar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], signed char *ip);
+
+int ncmpi_get_varm_text(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], char *ip);
+
+int ncmpi_get_varm_text_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], char *ip);
+
+int ncmpi_get_varm_short(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], short *ip);
+
+int ncmpi_get_varm_short_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], short *ip);
+
+int ncmpi_get_varm_int(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], int *ip);
+
+int ncmpi_get_varm_int_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], int *ip);
+
+int ncmpi_get_varm_float(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], float *ip);
+
+int ncmpi_get_varm_float_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], float *ip);
+
+int ncmpi_get_varm_double(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], double *ip);
+
+int ncmpi_get_varm_double_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], double *ip);
+
+int ncmpi_get_varm_longlong(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], long long *ip);
+
+int ncmpi_get_varm_longlong_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], long long *ip);
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_put_varm_uchar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const unsigned char *op);
+
+int ncmpi_put_varm_uchar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const unsigned char *op);
+
+int ncmpi_put_varm_ushort(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const unsigned short *op);
+
+int ncmpi_put_varm_ushort_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const unsigned short *op);
+
+int ncmpi_put_varm_uint(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const unsigned int *op);
+
+int ncmpi_put_varm_uint_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const unsigned int *op);
+
+int ncmpi_put_varm_long(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const long *op);
+
+int ncmpi_put_varm_long_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const long *op);
+
+int ncmpi_put_varm_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const unsigned long long *op);
+
+int ncmpi_put_varm_ulonglong_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], const unsigned long long *op);
+
+int ncmpi_get_varm_uchar(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], unsigned char *ip);
+
+int ncmpi_get_varm_uchar_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], unsigned char *ip);
+
+int ncmpi_get_varm_ushort(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], unsigned short *ip);
+
+int ncmpi_get_varm_ushort_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], unsigned short *ip);
+
+int ncmpi_get_varm_uint(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], unsigned int *ip);
+
+int ncmpi_get_varm_uint_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], unsigned int *ip);
+
+int ncmpi_get_varm_long(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], long *ip);
+
+int ncmpi_get_varm_long_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], long *ip);
+
+int ncmpi_get_varm_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], unsigned long long *ip);
+
+int ncmpi_get_varm_ulonglong_all(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[],
+                   const MPI_Offset imap[], unsigned long long *ip);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End {put,get}_varm */
+
+/* Begin of {put,get}_varn{kind} */
+
+int ncmpi_put_varn(int ncid, int varid, int num, MPI_Offset* const starts[],
+              MPI_Offset* const counts[], const void *buf, MPI_Offset bufcount,
+              MPI_Datatype buftype);
+
+int ncmpi_put_varn_all(int ncid, int varid, int num, MPI_Offset* const starts[],
+              MPI_Offset* const counts[], const void *buf, MPI_Offset bufcount,
+              MPI_Datatype buftype);
+
+int ncmpi_get_varn(int ncid, int varid, int num, MPI_Offset* const starts[],
+              MPI_Offset* const counts[],  void *buf, MPI_Offset bufcount,
+              MPI_Datatype buftype);
+
+int ncmpi_get_varn_all(int ncid, int varid, int num, MPI_Offset* const starts[],
+              MPI_Offset* const counts[],  void *buf, MPI_Offset bufcount,
+              MPI_Datatype buftype);
+
+int ncmpi_put_varn_text(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const char *buf);
+
+int ncmpi_put_varn_schar(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const signed char *buf);
+
+int ncmpi_put_varn_short(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const short *buf);
+
+int ncmpi_put_varn_int(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const int *buf);
+
+int ncmpi_put_varn_float(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const float *buf);
+
+int ncmpi_put_varn_double(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const double *buf);
+
+int ncmpi_put_varn_longlong(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const long long *buf);
+
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_put_varn_uchar(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const unsigned char *buf);
+
+int ncmpi_put_varn_ushort(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const unsigned short *buf);
+
+int ncmpi_put_varn_uint(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const unsigned int *buf);
+
+int ncmpi_put_varn_long(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const long *buf);
+
+int ncmpi_put_varn_ulonglong(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const unsigned long long *buf);
+
+/* End Skip Prototypes for Fortran binding */
+
+int ncmpi_put_varn_text_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const char *buf);
+
+int ncmpi_put_varn_schar_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const signed char *buf);
+
+int ncmpi_put_varn_short_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const short *buf);
+
+int ncmpi_put_varn_int_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const int *buf);
+
+int ncmpi_put_varn_float_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const float *buf);
+
+int ncmpi_put_varn_double_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const double *buf);
+
+int ncmpi_put_varn_longlong_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const long long *buf);
+
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_put_varn_uchar_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const unsigned char *buf);
+
+int ncmpi_put_varn_ushort_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const unsigned short *buf);
+
+int ncmpi_put_varn_uint_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const unsigned int *buf);
+
+int ncmpi_put_varn_long_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const long *buf);
+
+int ncmpi_put_varn_ulonglong_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+              const unsigned long long *buf);
+
+/* End Skip Prototypes for Fortran binding */
+
+int ncmpi_get_varn_text(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               char *buf);
+
+int ncmpi_get_varn_schar(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               signed char *buf);
+
+int ncmpi_get_varn_short(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               short *buf);
+
+int ncmpi_get_varn_int(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               int *buf);
+
+int ncmpi_get_varn_float(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               float *buf);
+
+int ncmpi_get_varn_double(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               double *buf);
+
+int ncmpi_get_varn_longlong(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long long *buf);
+
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_get_varn_uchar(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned char *buf);
+
+int ncmpi_get_varn_ushort(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned short *buf);
+
+int ncmpi_get_varn_uint(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned int *buf);
+
+int ncmpi_get_varn_long(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long *buf);
+
+int ncmpi_get_varn_ulonglong(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned long long *buf);
+
+/* End Skip Prototypes for Fortran binding */
+
+int ncmpi_get_varn_text_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               char *buf);
+
+int ncmpi_get_varn_schar_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               signed char *buf);
+
+int ncmpi_get_varn_short_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               short *buf);
+
+int ncmpi_get_varn_int_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               int *buf);
+
+int ncmpi_get_varn_float_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               float *buf);
+
+int ncmpi_get_varn_double_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               double *buf);
+
+int ncmpi_get_varn_longlong_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long long *buf);
+
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_get_varn_uchar_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned char *buf);
+
+int ncmpi_get_varn_ushort_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned short *buf);
+
+int ncmpi_get_varn_uint_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned int *buf);
+
+int ncmpi_get_varn_long_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long *buf);
+
+int ncmpi_get_varn_ulonglong_all(int ncid, int varid, int num,
+              MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned long long *buf);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End of {put,get}_varn{kind} */
+
+/* Begin {put,get}_vard */
+int ncmpi_get_vard(int ncid, int varid, MPI_Datatype filetype, void *buf,
+              MPI_Offset bufcount, MPI_Datatype buftype);
+int ncmpi_get_vard_all(int ncid, int varid, MPI_Datatype filetype, void *buf,
+              MPI_Offset bufcount, MPI_Datatype buftype);
+int ncmpi_put_vard(int ncid, int varid, MPI_Datatype filetype, const void *buf,
+              MPI_Offset bufcount, MPI_Datatype buftype);
+int ncmpi_put_vard_all(int ncid, int varid, MPI_Datatype filetype, const void *buf,
+              MPI_Offset bufcount, MPI_Datatype buftype);
+/* End of {put,get}_vard */
+
+/* Begin {mput,mget}_var */
+
+/* #################################################################### */
+/* Begin: more prototypes to be included for Fortran binding conversion */
+
+/* Begin non-blocking data access functions */
+
+int ncmpi_wait(int ncid, int count, int array_of_requests[],
+                   int array_of_statuses[]);
+
+int ncmpi_wait_all(int ncid, int count, int array_of_requests[],
+                   int array_of_statuses[]);
+
+int ncmpi_cancel(int ncid, int num, int *requests, int *statuses);
+
+int ncmpi_buffer_attach(int ncid, MPI_Offset bufsize);
+int ncmpi_buffer_detach(int ncid);
+int ncmpi_inq_buffer_usage(int ncid, MPI_Offset *usage);
+int ncmpi_inq_buffer_size(int ncid, MPI_Offset *buf_size);
+int ncmpi_inq_nreqs(int ncid, int *nreqs);
+
+/* Begin {iput,iget,bput}_var1 */
+
+int ncmpi_iput_var1(int ncid, int varid, const MPI_Offset index[],
+                    const void *buf, MPI_Offset bufcount,
+                    MPI_Datatype buftype, int *request);
+
+int ncmpi_iput_var1_text(int ncid, int varid, const MPI_Offset index[],
+                    const char *op, int *request);
+
+int ncmpi_iput_var1_schar(int ncid, int varid, const MPI_Offset index[],
+                    const signed char *op, int *request);
+
+int ncmpi_iput_var1_short(int ncid, int varid, const MPI_Offset index[],
+                    const short *op, int *request);
+
+int ncmpi_iput_var1_int(int ncid, int varid, const MPI_Offset index[],
+                    const int *op, int *request);
+
+int ncmpi_iput_var1_float(int ncid, int varid, const MPI_Offset index[],
+                    const float *op, int *request);
+
+int ncmpi_iput_var1_double(int ncid, int varid, const MPI_Offset index[],
+                    const double *op, int *request);
+
+int ncmpi_iput_var1_longlong(int ncid, int varid, const MPI_Offset index[],
+                    const long long *op, int *request);
+
+int ncmpi_iget_var1(int ncid, int varid, const MPI_Offset index[], void *buf,
+                    MPI_Offset bufcount, MPI_Datatype buftype, int *request);
+
+int ncmpi_iget_var1_schar(int ncid, int varid, const MPI_Offset index[],
+                    signed char *ip, int *request);
+
+int ncmpi_iget_var1_text(int ncid, int varid, const MPI_Offset index[],
+                    char *ip, int *request);
+
+int ncmpi_iget_var1_short(int ncid, int varid, const MPI_Offset index[],
+                    short *ip, int *request);
+
+int ncmpi_iget_var1_int(int ncid, int varid, const MPI_Offset index[],
+                    int *ip, int *request);
+
+int ncmpi_iget_var1_float(int ncid, int varid, const MPI_Offset index[],
+                    float *ip, int *request);
+
+int ncmpi_iget_var1_double(int ncid, int varid, const MPI_Offset index[],
+                    double *ip, int *request);
+
+int ncmpi_iget_var1_longlong(int ncid, int varid, const MPI_Offset index[],
+                    long long *ip, int *request);
+
+int ncmpi_bput_var1(int ncid, int varid, const MPI_Offset index[],
+                    const void *buf, MPI_Offset bufcount,
+                    MPI_Datatype buftype, int *request);
+
+int ncmpi_bput_var1_text(int ncid, int varid, const MPI_Offset index[],
+                    const char *op, int *request);
+
+int ncmpi_bput_var1_schar(int ncid, int varid, const MPI_Offset index[],
+                    const signed char *op, int *request);
+
+int ncmpi_bput_var1_short(int ncid, int varid, const MPI_Offset index[],
+                    const short *op, int *request);
+
+int ncmpi_bput_var1_int(int ncid, int varid, const MPI_Offset index[],
+                    const int *op, int *request);
+
+int ncmpi_bput_var1_float(int ncid, int varid, const MPI_Offset index[],
+                    const float *op, int *request);
+
+int ncmpi_bput_var1_double(int ncid, int varid, const MPI_Offset index[],
+                    const double *op, int *request);
+
+int ncmpi_bput_var1_longlong(int ncid, int varid, const MPI_Offset index[],
+                    const long long *op, int *request);
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_iput_var1_uchar(int ncid, int varid, const MPI_Offset index[],
+                    const unsigned char *op, int *request);
+
+int ncmpi_iput_var1_ushort(int ncid, int varid, const MPI_Offset index[],
+                    const unsigned short *op, int *request);
+
+int ncmpi_iput_var1_uint(int ncid, int varid, const MPI_Offset index[],
+                    const unsigned int *op, int *request);
+
+int ncmpi_iput_var1_long(int ncid, int varid, const MPI_Offset index[],
+                    const long *ip, int *request);
+
+int ncmpi_iput_var1_ulonglong(int ncid, int varid, const MPI_Offset index[],
+                    const unsigned long long *op, int *request);
+
+int ncmpi_iget_var1_uchar(int ncid, int varid, const MPI_Offset index[],
+                    unsigned char *ip, int *request);
+
+int ncmpi_iget_var1_ushort(int ncid, int varid, const MPI_Offset index[],
+                    unsigned short *ip, int *request);
+
+int ncmpi_iget_var1_uint(int ncid, int varid, const MPI_Offset index[],
+                    unsigned int *ip, int *request);
+
+int ncmpi_iget_var1_long(int ncid, int varid, const MPI_Offset index[],
+                    long *ip, int *request);
+
+int ncmpi_iget_var1_ulonglong(int ncid, int varid, const MPI_Offset index[],
+                    unsigned long long *ip, int *request);
+
+int ncmpi_bput_var1_uchar(int ncid, int varid, const MPI_Offset index[],
+                    const unsigned char *op, int *request);
+
+int ncmpi_bput_var1_ushort(int ncid, int varid, const MPI_Offset index[],
+                    const unsigned short *op, int *request);
+
+int ncmpi_bput_var1_uint(int ncid, int varid, const MPI_Offset index[],
+                    const unsigned int *op, int *request);
+
+int ncmpi_bput_var1_long(int ncid, int varid, const MPI_Offset index[],
+                    const long *ip, int *request);
+
+int ncmpi_bput_var1_ulonglong(int ncid, int varid, const MPI_Offset index[],
+                    const unsigned long long *op, int *request);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End {iput,iget,bput}_var1 */
+
+/* Begin {iput,iget,bput}_var */
+
+int ncmpi_iput_var(int ncid, int varid, const void *buf, MPI_Offset bufcount,
+                    MPI_Datatype buftype, int *request);
+
+int ncmpi_iput_var_schar(int ncid, int varid, const signed char *op,
+                    int *request);
+
+int ncmpi_iput_var_text(int ncid, int varid, const char *op, int *request);
+
+int ncmpi_iput_var_short(int ncid, int varid, const short *op, int *request);
+
+int ncmpi_iput_var_int(int ncid, int varid, const int *op, int *request);
+
+int ncmpi_iput_var_float(int ncid, int varid, const float *op, int *request);
+
+int ncmpi_iput_var_double(int ncid, int varid, const double *op, int *request);
+
+int ncmpi_iput_var_longlong(int ncid, int varid, const long long *op, int *request);
+
+int ncmpi_iget_var(int ncid, int varid, void *buf, MPI_Offset bufcount,
+                    MPI_Datatype buftype, int *request);
+
+int ncmpi_iget_var_schar(int ncid, int varid, signed char *ip, int *request);
+
+int ncmpi_iget_var_text(int ncid, int varid, char *ip, int *request);
+
+int ncmpi_iget_var_short(int ncid, int varid, short *ip, int *request);
+
+int ncmpi_iget_var_int(int ncid, int varid, int *ip, int *request);
+
+int ncmpi_iget_var_float(int ncid, int varid, float *ip, int *request);
+
+int ncmpi_iget_var_double(int ncid, int varid, double *ip, int *request);
+
+int ncmpi_iget_var_longlong(int ncid, int varid, long long *ip, int *request);
+
+int ncmpi_bput_var(int ncid, int varid, const void *buf, MPI_Offset bufcount,
+                    MPI_Datatype buftype, int *request);
+
+int ncmpi_bput_var_schar(int ncid, int varid, const signed char *op,
+                    int *request);
+
+int ncmpi_bput_var_text(int ncid, int varid, const char *op, int *request);
+
+int ncmpi_bput_var_short(int ncid, int varid, const short *op, int *request);
+
+int ncmpi_bput_var_int(int ncid, int varid, const int *op, int *request);
+
+int ncmpi_bput_var_float(int ncid, int varid, const float *op, int *request);
+
+int ncmpi_bput_var_double(int ncid, int varid, const double *op, int *request);
+
+int ncmpi_bput_var_longlong(int ncid, int varid, const long long *op, int *request);
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_iput_var_uchar(int ncid, int varid, const unsigned char *op,
+                    int *request);
+
+int ncmpi_iput_var_ushort(int ncid, int varid, const unsigned short *op,
+                    int *request);
+
+int ncmpi_iput_var_uint(int ncid, int varid, const unsigned int *op,
+                    int *request);
+
+int ncmpi_iput_var_long(int ncid, int varid, const long *op, int *request);
+
+int ncmpi_iput_var_ulonglong(int ncid, int varid, const unsigned long long *op,
+                    int *request);
+
+int ncmpi_iget_var_uchar(int ncid, int varid, unsigned char *ip, int *request);
+
+int ncmpi_iget_var_ushort(int ncid, int varid, unsigned short *ip, int *request);
+
+int ncmpi_iget_var_uint(int ncid, int varid, unsigned int *ip, int *request);
+
+int ncmpi_iget_var_long(int ncid, int varid, long *ip, int *request);
+
+int ncmpi_iget_var_ulonglong(int ncid, int varid, unsigned long long *ip, int *request);
+
+int ncmpi_bput_var_uchar(int ncid, int varid, const unsigned char *op,
+                    int *request);
+
+int ncmpi_bput_var_ushort(int ncid, int varid, const unsigned short *op,
+                    int *request);
+
+int ncmpi_bput_var_uint(int ncid, int varid, const unsigned int *op,
+                    int *request);
+
+int ncmpi_bput_var_long(int ncid, int varid, const long *op, int *request);
+
+int ncmpi_bput_var_ulonglong(int ncid, int varid, const unsigned long long *op,
+                    int *request);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End {iput,iget,bput}_var */
+
+/* Begin {iput,iget,bput}_vara */
+
+int ncmpi_iput_vara(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const void *buf,
+                    MPI_Offset bufcount, MPI_Datatype buftype, int *request);
+
+int ncmpi_iput_vara_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const signed char *op,
+                    int *request);
+
+int ncmpi_iput_vara_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const char *op, int *request);
+
+int ncmpi_iput_vara_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const short *op, int *request);
+
+int ncmpi_iput_vara_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const int *op, int *request);
+
+int ncmpi_iput_vara_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const float *op, int *request);
+
+int ncmpi_iput_vara_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const double *op, int *request);
+
+int ncmpi_iput_vara_longlong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const long long *op, int *request);
+
+int ncmpi_iget_vara(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], void *buf, MPI_Offset bufcount,
+                    MPI_Datatype buftype, int *request);
+
+int ncmpi_iget_vara_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], signed char *ip, int *request);
+
+int ncmpi_iget_vara_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], char *ip, int *request);
+
+int ncmpi_iget_vara_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], short *ip, int *request);
+
+int ncmpi_iget_vara_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], int *ip, int *request);
+
+int ncmpi_iget_vara_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], float *ip, int *request);
+
+int ncmpi_iget_vara_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], double *ip, int *request);
+
+int ncmpi_iget_vara_longlong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], long long *ip, int *request);
+
+int ncmpi_bput_vara(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const void *buf,
+                    MPI_Offset bufcount, MPI_Datatype buftype, int *request);
+
+int ncmpi_bput_vara_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const signed char *op,
+                    int *request);
+
+int ncmpi_bput_vara_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const char *op, int *request);
+
+int ncmpi_bput_vara_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const short *op, int *request);
+
+int ncmpi_bput_vara_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const int *op, int *request);
+
+int ncmpi_bput_vara_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const float *op, int *request);
+
+int ncmpi_bput_vara_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const double *op, int *request);
+
+int ncmpi_bput_vara_longlong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const long long *op, int *request);
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_iput_vara_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const unsigned char *op,
+                    int *request);
+
+int ncmpi_iput_vara_ushort(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const unsigned short *op,
+                    int *request);
+
+int ncmpi_iput_vara_uint(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const unsigned int *op,
+                    int *request);
+
+int ncmpi_iput_vara_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const long *op, int *request);
+
+int ncmpi_iput_vara_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const unsigned long long *op,
+                    int *request);
+
+int ncmpi_iget_vara_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], unsigned char *ip, int *request);
+
+int ncmpi_iget_vara_ushort(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], unsigned short *ip, int *request);
+
+int ncmpi_iget_vara_uint(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], unsigned int *ip, int *request);
+
+int ncmpi_iget_vara_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], long *ip, int *request);
+
+int ncmpi_iget_vara_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], unsigned long long *ip, int *request);
+
+int ncmpi_bput_vara_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const unsigned char *op,
+                    int *request);
+
+int ncmpi_bput_vara_ushort(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const unsigned short *op,
+                    int *request);
+
+int ncmpi_bput_vara_uint(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const unsigned int *op,
+                    int *request);
+
+int ncmpi_bput_vara_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const long *op, int *request);
+
+int ncmpi_bput_vara_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const unsigned long long *op,
+                    int *request);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End {iput,iget,bput}_vara */
+
+/* Begin {iput,iget,bput}_vars */
+
+int ncmpi_iput_vars(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const void *buf, MPI_Offset bufcount,
+                    MPI_Datatype buftype, int *request);
+
+int ncmpi_iput_vars_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const signed char *op, int *request);
+
+int ncmpi_iput_vars_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const char *op, int *request);
+
+int ncmpi_iput_vars_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const short *op, int *request);
+
+int ncmpi_iput_vars_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const int *op, int *request);
+
+int ncmpi_iput_vars_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const float *op, int *request);
+
+int ncmpi_iput_vars_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const double *op, int *request);
+
+int ncmpi_iput_vars_longlong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const long long *op, int *request);
+
+int ncmpi_iget_vars(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    void *buf, MPI_Offset bufcount, MPI_Datatype buftype,
+                    int *request);
+
+int ncmpi_iget_vars_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    signed char *ip, int *request);
+
+int ncmpi_iget_vars_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    char *ip, int *request);
+
+int ncmpi_iget_vars_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    short *ip, int *request);
+
+int ncmpi_iget_vars_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    int *ip, int *request);
+
+int ncmpi_iget_vars_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    float *ip, int *request);
+
+int ncmpi_iget_vars_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    double *ip, int *request);
+
+int ncmpi_iget_vars_longlong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    long long *ip, int *request);
+
+int ncmpi_bput_vars(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const void *buf, MPI_Offset bufcount,
+                    MPI_Datatype buftype, int *request);
+
+int ncmpi_bput_vars_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const signed char *op, int *request);
+
+int ncmpi_bput_vars_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const char *op, int *request);
+
+int ncmpi_bput_vars_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const short *op, int *request);
+
+int ncmpi_bput_vars_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const int *op, int *request);
+
+int ncmpi_bput_vars_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const float *op, int *request);
+
+int ncmpi_bput_vars_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const double *op, int *request);
+
+int ncmpi_bput_vars_longlong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const long long *op, int *request);
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_iput_vars_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const unsigned char *op, int *request);
+
+int ncmpi_iput_vars_ushort(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const unsigned short *op, int *request);
+
+int ncmpi_iput_vars_uint(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const unsigned int *op, int *request);
+
+int ncmpi_iput_vars_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const long *op, int *request);
+
+int ncmpi_iput_vars_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const unsigned long long *op, int *request);
+
+int ncmpi_iget_vars_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    unsigned char *ip, int *request);
+
+int ncmpi_iget_vars_ushort(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    unsigned short *ip, int *request);
+
+int ncmpi_iget_vars_uint(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    unsigned int *ip, int *request);
+
+int ncmpi_iget_vars_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    long *ip, int *request);
+
+int ncmpi_iget_vars_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    unsigned long long *ip, int *request);
+
+int ncmpi_bput_vars_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const unsigned char *op, int *request);
+
+int ncmpi_bput_vars_ushort(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const unsigned short *op, int *request);
+
+int ncmpi_bput_vars_uint(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const unsigned int *op, int *request);
+
+int ncmpi_bput_vars_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const long *op, int *request);
+
+int ncmpi_bput_vars_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const unsigned long long *op, int *request);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End {iput,iget,bput}_vars */
+
+/* Begin {iput,iget,bput}_varm */
+
+int ncmpi_iput_varm(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const void *buf,
+                    MPI_Offset bufcount, MPI_Datatype buftype, int *request);
+
+int ncmpi_iput_varm_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const signed char *op,
+                    int *request);
+
+int ncmpi_iput_varm_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const char *op, int *request);
+
+int ncmpi_iput_varm_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const short *op, int *request);
+
+int ncmpi_iput_varm_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const int *op, int *request);
+
+int ncmpi_iput_varm_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const float *op, int *request);
+
+int ncmpi_iput_varm_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const double *op, int *request);
+
+int ncmpi_iput_varm_longlong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const long long *op, int *request);
+
+int ncmpi_iget_varm(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], void *buf, MPI_Offset bufcount,
+                    MPI_Datatype buftype, int *request);
+
+int ncmpi_iget_varm_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], signed char *ip, int *request);
+
+int ncmpi_iget_varm_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], char *ip, int *request);
+
+int ncmpi_iget_varm_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], short *ip, int *request);
+
+int ncmpi_iget_varm_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], int *ip, int *request);
+
+int ncmpi_iget_varm_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], float *ip, int *request);
+
+int ncmpi_iget_varm_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], double *ip, int *request);
+
+int ncmpi_iget_varm_longlong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], long long *ip, int *request);
+
+int ncmpi_bput_varm(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const void *buf,
+                    MPI_Offset bufcount, MPI_Datatype buftype, int *request);
+
+int ncmpi_bput_varm_schar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const signed char *op,
+                    int *request);
+
+int ncmpi_bput_varm_text(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const char *op, int *request);
+
+int ncmpi_bput_varm_short(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const short *op, int *request);
+
+int ncmpi_bput_varm_int(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const int *op, int *request);
+
+int ncmpi_bput_varm_float(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const float *op, int *request);
+
+int ncmpi_bput_varm_double(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const double *op, int *request);
+
+int ncmpi_bput_varm_longlong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const long long *op, int *request);
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_iput_varm_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const unsigned char *op,
+                    int *request);
+
+int ncmpi_iput_varm_ushort(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const unsigned short *op,
+                    int *request);
+
+int ncmpi_iput_varm_uint(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const unsigned int *op,
+                    int *request);
+
+int ncmpi_iput_varm_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const long *op, int *request);
+
+int ncmpi_iput_varm_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const unsigned long long *op,
+                    int *request);
+
+int ncmpi_iget_varm_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], unsigned char *ip, int *request);
+
+int ncmpi_iget_varm_ushort(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], unsigned short *ip, int *request);
+
+int ncmpi_iget_varm_uint(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], unsigned int *ip, int *request);
+
+int ncmpi_iget_varm_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], long *ip, int *request);
+
+int ncmpi_iget_varm_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], unsigned long long *ip, int *request);
+
+int ncmpi_bput_varm_uchar(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const unsigned char *op,
+                    int *request);
+
+int ncmpi_bput_varm_ushort(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const unsigned short *op,
+                    int *request);
+
+int ncmpi_bput_varm_uint(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const unsigned int *op,
+                    int *request);
+
+int ncmpi_bput_varm_long(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const long *op, int *request);
+
+int ncmpi_bput_varm_ulonglong(int ncid, int varid, const MPI_Offset start[],
+                    const MPI_Offset count[], const MPI_Offset stride[],
+                    const MPI_Offset imap[], const unsigned long long *op,
+                    int *request);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End {iput,iget,bput}_varm */
+
+/* Begin of nonblocking {iput,iget}_varn{kind} */
+
+int ncmpi_iput_varn(int ncid, int varid, int num, MPI_Offset* const starts[],
+               MPI_Offset* const counts[], const void *buf, MPI_Offset bufcount,
+               MPI_Datatype buftype, int *request);
+
+int ncmpi_iget_varn(int ncid, int varid, int num, MPI_Offset* const starts[],
+               MPI_Offset* const counts[],  void *buf, MPI_Offset bufcount,
+               MPI_Datatype buftype, int *request);
+
+int ncmpi_iput_varn_text(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const char *buf, int *request);
+
+int ncmpi_iput_varn_schar(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const signed char *buf, int *request);
+
+int ncmpi_iput_varn_short(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const short *buf, int *request);
+
+int ncmpi_iput_varn_int(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const int *buf, int *request);
+
+int ncmpi_iput_varn_float(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const float *buf, int *request);
+
+int ncmpi_iput_varn_double(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const double *buf, int *request);
+
+int ncmpi_iput_varn_longlong(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const long long *buf, int *request);
+
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_iput_varn_uchar(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const unsigned char *buf, int *request);
+
+int ncmpi_iput_varn_ushort(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const unsigned short *buf, int *request);
+
+int ncmpi_iput_varn_uint(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const unsigned int *buf, int *request);
+
+int ncmpi_iput_varn_long(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const long *buf, int *request);
+
+int ncmpi_iput_varn_ulonglong(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const unsigned long long *buf, int *request);
+
+/* End Skip Prototypes for Fortran binding */
+
+int ncmpi_iget_varn_text(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               char *buf, int *request);
+
+int ncmpi_iget_varn_schar(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               signed char *buf, int *request);
+
+int ncmpi_iget_varn_short(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               short *buf, int *request);
+
+int ncmpi_iget_varn_int(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               int *buf, int *request);
+
+int ncmpi_iget_varn_float(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               float *buf, int *request);
+
+int ncmpi_iget_varn_double(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               double *buf, int *request);
+
+int ncmpi_iget_varn_longlong(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long long *buf, int *request);
+
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_iget_varn_uchar(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned char *buf, int *request);
+
+int ncmpi_iget_varn_ushort(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned short *buf, int *request);
+
+int ncmpi_iget_varn_uint(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned int *buf, int *request);
+
+int ncmpi_iget_varn_long(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long *buf, int *request);
+
+int ncmpi_iget_varn_ulonglong(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned long long *buf, int *request);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End of {iput,iget}_varn{kind} */
+
+/* Begin of nonblocking bput_varn{kind} */
+
+int ncmpi_bput_varn(int ncid, int varid, int num, MPI_Offset* const starts[],
+               MPI_Offset* const counts[], const void *buf, MPI_Offset bufcount,
+               MPI_Datatype buftype, int *request);
+
+int ncmpi_bput_varn_text(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const char *buf, int *request);
+
+int ncmpi_bput_varn_schar(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const signed char *buf, int *request);
+
+int ncmpi_bput_varn_short(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const short *buf, int *request);
+
+int ncmpi_bput_varn_int(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const int *buf, int *request);
+
+int ncmpi_bput_varn_float(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const float *buf, int *request);
+
+int ncmpi_bput_varn_double(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const double *buf, int *request);
+
+int ncmpi_bput_varn_longlong(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const long long *buf, int *request);
+
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip types: uchar, ubyte, ushort, uint, long, ulonglong string */
+
+int ncmpi_bput_varn_uchar(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const unsigned char *buf, int *request);
+
+int ncmpi_bput_varn_ushort(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const unsigned short *buf, int *request);
+
+int ncmpi_bput_varn_uint(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const unsigned int *buf, int *request);
+
+int ncmpi_bput_varn_long(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const long *buf, int *request);
+
+int ncmpi_bput_varn_ulonglong(int ncid, int varid, int num,
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               const unsigned long long *buf, int *request);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End of bput_varn{kind} */
+
+/* End non-blocking data access functions */
+
+/* Begin Skip Prototypes for Fortran binding */
+/* skip all mput/mget APIs as Fortran cannot handle array of buffers */
+
+int ncmpi_mput_var(int ncid, int num, int varids[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mput_var_all(int ncid, int num, int varids[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mput_var_text(int ncid, int num, int varids[],
+               char *bufs[]);
+
+int ncmpi_mput_var_schar(int ncid, int num, int varids[],
+               signed char *bufs[]);
+
+int ncmpi_mput_var_uchar(int ncid, int num, int varids[],
+               unsigned char *bufs[]);
+
+int ncmpi_mput_var_short(int ncid, int num, int varids[],
+               short *bufs[]);
+
+int ncmpi_mput_var_ushort(int ncid, int num, int varids[],
+               unsigned short *bufs[]);
+
+int ncmpi_mput_var_int(int ncid, int num, int varids[],
+               int *bufs[]);
+
+int ncmpi_mput_var_uint(int ncid, int num, int varids[],
+               unsigned int *bufs[]);
+
+int ncmpi_mput_var_long(int ncid, int num, int varids[],
+               long *bufs[]);
+
+int ncmpi_mput_var_float(int ncid, int num, int varids[],
+               float *bufs[]);
+
+int ncmpi_mput_var_double(int ncid, int num, int varids[],
+               double *bufs[]);
+
+int ncmpi_mput_var_longlong(int ncid, int num, int varids[],
+               long long *bufs[]);
+
+int ncmpi_mput_var_ulonglong(int ncid, int num, int varids[],
+               unsigned long long *bufs[]);
+
+
+int ncmpi_mput_var_text_all(int ncid, int num, int varids[],
+               char *bufs[]);
+
+int ncmpi_mput_var_schar_all(int ncid, int num, int varids[],
+               signed char *bufs[]);
+
+int ncmpi_mput_var_uchar_all(int ncid, int num, int varids[],
+               unsigned char *bufs[]);
+
+int ncmpi_mput_var_short_all(int ncid, int num, int varids[],
+               short *bufs[]);
+
+int ncmpi_mput_var_ushort_all(int ncid, int num, int varids[],
+               unsigned short *bufs[]);
+
+int ncmpi_mput_var_int_all(int ncid, int num, int varids[],
+               int *bufs[]);
+
+int ncmpi_mput_var_uint_all(int ncid, int num, int varids[],
+               unsigned int *bufs[]);
+
+int ncmpi_mput_var_long_all(int ncid, int num, int varids[],
+               long *bufs[]);
+
+int ncmpi_mput_var_float_all(int ncid, int num, int varids[],
+               float *bufs[]);
+
+int ncmpi_mput_var_double_all(int ncid, int num, int varids[],
+               double *bufs[]);
+
+int ncmpi_mput_var_longlong_all(int ncid, int num, int varids[],
+               long long *bufs[]);
+
+int ncmpi_mput_var_ulonglong_all(int ncid, int num, int varids[],
+               unsigned long long *bufs[]);
+
+
+int ncmpi_mput_var1(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mput_var1_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mput_var1_text(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], char *bufs[]);
+
+int ncmpi_mput_var1_schar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], signed char *bufs[]);
+
+int ncmpi_mput_var1_uchar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned char *bufs[]);
+
+int ncmpi_mput_var1_short(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], short *bufs[]);
+
+int ncmpi_mput_var1_ushort(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned short *bufs[]);
+
+int ncmpi_mput_var1_int(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], int *bufs[]);
+
+int ncmpi_mput_var1_uint(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned int *bufs[]);
+
+int ncmpi_mput_var1_long(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], long *bufs[]);
+
+int ncmpi_mput_var1_float(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], float *bufs[]);
+
+int ncmpi_mput_var1_double(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], double *bufs[]);
+
+int ncmpi_mput_var1_longlong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], long long *bufs[]);
+
+int ncmpi_mput_var1_ulonglong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned long long *bufs[]);
+
+
+int ncmpi_mput_var1_text_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], char *bufs[]);
+
+int ncmpi_mput_var1_schar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], signed char *bufs[]);
+
+int ncmpi_mput_var1_uchar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned char *bufs[]);
+
+int ncmpi_mput_var1_short_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], short *bufs[]);
+
+int ncmpi_mput_var1_ushort_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned short *bufs[]);
+
+int ncmpi_mput_var1_int_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], int *bufs[]);
+
+int ncmpi_mput_var1_uint_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned int *bufs[]);
+
+int ncmpi_mput_var1_long_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], long *bufs[]);
+
+int ncmpi_mput_var1_float_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], float *bufs[]);
+
+int ncmpi_mput_var1_double_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], double *bufs[]);
+
+int ncmpi_mput_var1_longlong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], long long *bufs[]);
+
+int ncmpi_mput_var1_ulonglong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned long long *bufs[]);
+
+
+int ncmpi_mput_vara(int ncid, int num, int varids[], MPI_Offset* const starts[],
+               MPI_Offset* const counts[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mput_vara_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               void *bufs[], MPI_Offset bufcounts[],
+               MPI_Datatype datatypes[]);
+
+int ncmpi_mput_vara_text(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               char *bufs[]);
+
+int ncmpi_mput_vara_schar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               signed char *bufs[]);
+
+int ncmpi_mput_vara_uchar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned char *bufs[]);
+
+int ncmpi_mput_vara_short(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               short *bufs[]);
+
+int ncmpi_mput_vara_ushort(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned short *bufs[]);
+
+int ncmpi_mput_vara_int(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               int *bufs[]);
+
+int ncmpi_mput_vara_uint(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned int *bufs[]);
+
+int ncmpi_mput_vara_long(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long *bufs[]);
+
+int ncmpi_mput_vara_float(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               float *bufs[]);
+
+int ncmpi_mput_vara_double(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               double *bufs[]);
+
+int ncmpi_mput_vara_longlong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long long *bufs[]);
+
+int ncmpi_mput_vara_ulonglong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned long long *bufs[]);
+
+
+int ncmpi_mput_vara_text_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               char *bufs[]);
+
+int ncmpi_mput_vara_schar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               signed char *bufs[]);
+
+int ncmpi_mput_vara_uchar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned char *bufs[]);
+
+int ncmpi_mput_vara_short_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               short *bufs[]);
+
+int ncmpi_mput_vara_ushort_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned short *bufs[]);
+
+int ncmpi_mput_vara_int_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               int *bufs[]);
+
+int ncmpi_mput_vara_uint_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned int *bufs[]);
+
+int ncmpi_mput_vara_long_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long *bufs[]);
+
+int ncmpi_mput_vara_float_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               float *bufs[]);
+
+int ncmpi_mput_vara_double_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               double *bufs[]);
+
+int ncmpi_mput_vara_longlong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long long *bufs[]);
+
+int ncmpi_mput_vara_ulonglong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned long long *bufs[]);
+
+
+int ncmpi_mput_vars(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mput_vars_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mput_vars_text(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], char *bufs[]);
+
+int ncmpi_mput_vars_schar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], signed char *bufs[]);
+
+int ncmpi_mput_vars_uchar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned char *bufs[]);
+
+int ncmpi_mput_vars_short(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], short *bufs[]);
+
+int ncmpi_mput_vars_ushort(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned short *bufs[]);
+
+int ncmpi_mput_vars_int(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], int *bufs[]);
+
+int ncmpi_mput_vars_uint(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned int *bufs[]);
+
+int ncmpi_mput_vars_long(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], long *bufs[]);
+
+int ncmpi_mput_vars_float(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], float *bufs[]);
+
+int ncmpi_mput_vars_double(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], double *bufs[]);
+
+int ncmpi_mput_vars_longlong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], long long *bufs[]);
+
+int ncmpi_mput_vars_ulonglong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned long long *bufs[]);
+
+
+int ncmpi_mput_vars_text_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], char *bufs[]);
+
+int ncmpi_mput_vars_schar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], signed char *bufs[]);
+
+int ncmpi_mput_vars_uchar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned char *bufs[]);
+
+int ncmpi_mput_vars_short_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], short *bufs[]);
+
+int ncmpi_mput_vars_ushort_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned short *bufs[]);
+
+int ncmpi_mput_vars_int_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], int *bufs[]);
+
+int ncmpi_mput_vars_uint_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned int *bufs[]);
+
+int ncmpi_mput_vars_long_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], long *bufs[]);
+
+int ncmpi_mput_vars_float_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], float *bufs[]);
+
+int ncmpi_mput_vars_double_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], double *bufs[]);
+
+int ncmpi_mput_vars_longlong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], long long *bufs[]);
+
+int ncmpi_mput_vars_ulonglong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned long long *bufs[]);
+
+
+int ncmpi_mput_varm(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               void *bufs[], MPI_Offset bufcounts[],
+               MPI_Datatype datatypes[]);
+
+int ncmpi_mput_varm_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               void *bufs[], MPI_Offset bufcounts[],
+               MPI_Datatype datatypes[]);
+
+int ncmpi_mput_varm_text(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               char *bufs[]);
+
+int ncmpi_mput_varm_schar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               signed char *bufs[]);
+
+int ncmpi_mput_varm_uchar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned char *bufs[]);
+
+int ncmpi_mput_varm_short(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               short *bufs[]);
+
+int ncmpi_mput_varm_ushort(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned short *bufs[]);
+
+int ncmpi_mput_varm_int(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               int *bufs[]);
+
+int ncmpi_mput_varm_uint(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned int *bufs[]);
+
+int ncmpi_mput_varm_long(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               long *bufs[]);
+
+int ncmpi_mput_varm_float(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               float *bufs[]);
+
+int ncmpi_mput_varm_double(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               double *bufs[]);
+
+int ncmpi_mput_varm_longlong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               long long *bufs[]);
+
+int ncmpi_mput_varm_ulonglong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned long long *bufs[]);
+
+
+int ncmpi_mput_varm_text_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               char *bufs[]);
+
+int ncmpi_mput_varm_schar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               signed char *bufs[]);
+
+int ncmpi_mput_varm_uchar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned char *bufs[]);
+
+int ncmpi_mput_varm_short_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               short *bufs[]);
+
+int ncmpi_mput_varm_ushort_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned short *bufs[]);
+
+int ncmpi_mput_varm_int_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               int *bufs[]);
+
+int ncmpi_mput_varm_uint_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned int *bufs[]);
+
+int ncmpi_mput_varm_long_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               long *bufs[]);
+
+int ncmpi_mput_varm_float_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               float *bufs[]);
+
+int ncmpi_mput_varm_double_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               double *bufs[]);
+
+int ncmpi_mput_varm_longlong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               long long *bufs[]);
+
+int ncmpi_mput_varm_ulonglong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned long long *bufs[]);
+
+
+int ncmpi_mget_var(int ncid, int num, int varids[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mget_var_all(int ncid, int num, int varids[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mget_var_text(int ncid, int num, int varids[],
+               char *bufs[]);
+
+int ncmpi_mget_var_schar(int ncid, int num, int varids[],
+               signed char *bufs[]);
+
+int ncmpi_mget_var_uchar(int ncid, int num, int varids[],
+               unsigned char *bufs[]);
+
+int ncmpi_mget_var_short(int ncid, int num, int varids[],
+               short *bufs[]);
+
+int ncmpi_mget_var_ushort(int ncid, int num, int varids[],
+               unsigned short *bufs[]);
+
+int ncmpi_mget_var_int(int ncid, int num, int varids[],
+               int *bufs[]);
+
+int ncmpi_mget_var_uint(int ncid, int num, int varids[],
+               unsigned int *bufs[]);
+
+int ncmpi_mget_var_long(int ncid, int num, int varids[],
+               long *bufs[]);
+
+int ncmpi_mget_var_float(int ncid, int num, int varids[],
+               float *bufs[]);
+
+int ncmpi_mget_var_double(int ncid, int num, int varids[],
+               double *bufs[]);
+
+int ncmpi_mget_var_longlong(int ncid, int num, int varids[],
+               long long *bufs[]);
+
+int ncmpi_mget_var_ulonglong(int ncid, int num, int varids[],
+               unsigned long long *bufs[]);
+
+
+int ncmpi_mget_var_text_all(int ncid, int num, int varids[],
+               char *bufs[]);
+
+int ncmpi_mget_var_schar_all(int ncid, int num, int varids[],
+               signed char *bufs[]);
+
+int ncmpi_mget_var_uchar_all(int ncid, int num, int varids[],
+               unsigned char *bufs[]);
+
+int ncmpi_mget_var_short_all(int ncid, int num, int varids[],
+               short *bufs[]);
+
+int ncmpi_mget_var_ushort_all(int ncid, int num, int varids[],
+               unsigned short *bufs[]);
+
+int ncmpi_mget_var_int_all(int ncid, int num, int varids[],
+               int *bufs[]);
+
+int ncmpi_mget_var_uint_all(int ncid, int num, int varids[],
+               unsigned int *bufs[]);
+
+int ncmpi_mget_var_long_all(int ncid, int num, int varids[],
+               long *bufs[]);
+
+int ncmpi_mget_var_float_all(int ncid, int num, int varids[],
+               float *bufs[]);
+
+int ncmpi_mget_var_double_all(int ncid, int num, int varids[],
+               double *bufs[]);
+
+int ncmpi_mget_var_longlong_all(int ncid, int num, int varids[],
+               long long *bufs[]);
+
+int ncmpi_mget_var_ulonglong_all(int ncid, int num, int varids[],
+               unsigned long long *bufs[]);
+
+
+int ncmpi_mget_var1(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mget_var1_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mget_var1_text(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], char *bufs[]);
+
+int ncmpi_mget_var1_schar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], signed char *bufs[]);
+
+int ncmpi_mget_var1_uchar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned char *bufs[]);
+
+int ncmpi_mget_var1_short(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], short *bufs[]);
+
+int ncmpi_mget_var1_ushort(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned short *bufs[]);
+
+int ncmpi_mget_var1_int(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], int *bufs[]);
+
+int ncmpi_mget_var1_uint(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned int *bufs[]);
+
+int ncmpi_mget_var1_long(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], long *bufs[]);
+
+int ncmpi_mget_var1_float(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], float *bufs[]);
+
+int ncmpi_mget_var1_double(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], double *bufs[]);
+
+int ncmpi_mget_var1_longlong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], long long *bufs[]);
+
+int ncmpi_mget_var1_ulonglong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned long long *bufs[]);
+
+
+int ncmpi_mget_var1_text_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], char *bufs[]);
+
+int ncmpi_mget_var1_schar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], signed char *bufs[]);
+
+int ncmpi_mget_var1_uchar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned char *bufs[]);
+
+int ncmpi_mget_var1_short_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], short *bufs[]);
+
+int ncmpi_mget_var1_ushort_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned short *bufs[]);
+
+int ncmpi_mget_var1_int_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], int *bufs[]);
+
+int ncmpi_mget_var1_uint_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned int *bufs[]);
+
+int ncmpi_mget_var1_long_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], long *bufs[]);
+
+int ncmpi_mget_var1_float_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], float *bufs[]);
+
+int ncmpi_mget_var1_double_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], double *bufs[]);
+
+int ncmpi_mget_var1_longlong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], long long *bufs[]);
+
+int ncmpi_mget_var1_ulonglong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], unsigned long long *bufs[]);
+
+
+int ncmpi_mget_vara(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               void *bufs[], MPI_Offset bufcounts[],
+               MPI_Datatype datatypes[]);
+
+int ncmpi_mget_vara_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               void *bufs[], MPI_Offset bufcounts[],
+               MPI_Datatype datatypes[]);
+
+int ncmpi_mget_vara_text(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               char *bufs[]);
+
+int ncmpi_mget_vara_schar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               signed char *bufs[]);
+
+int ncmpi_mget_vara_uchar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned char *bufs[]);
+
+int ncmpi_mget_vara_short(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               short *bufs[]);
+
+int ncmpi_mget_vara_ushort(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned short *bufs[]);
+
+int ncmpi_mget_vara_int(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               int *bufs[]);
+
+int ncmpi_mget_vara_uint(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned int *bufs[]);
+
+int ncmpi_mget_vara_long(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long *bufs[]);
+
+int ncmpi_mget_vara_float(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               float *bufs[]);
+
+int ncmpi_mget_vara_double(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               double *bufs[]);
+
+int ncmpi_mget_vara_longlong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long long *bufs[]);
+
+int ncmpi_mget_vara_ulonglong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned long long *bufs[]);
+
+
+int ncmpi_mget_vara_text_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               char *bufs[]);
+
+int ncmpi_mget_vara_schar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               signed char *bufs[]);
+
+int ncmpi_mget_vara_uchar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned char *bufs[]);
+
+int ncmpi_mget_vara_short_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               short *bufs[]);
+
+int ncmpi_mget_vara_ushort_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned short *bufs[]);
+
+int ncmpi_mget_vara_int_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               int *bufs[]);
+
+int ncmpi_mget_vara_uint_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned int *bufs[]);
+
+int ncmpi_mget_vara_long_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long *bufs[]);
+
+int ncmpi_mget_vara_float_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               float *bufs[]);
+
+int ncmpi_mget_vara_double_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               double *bufs[]);
+
+int ncmpi_mget_vara_longlong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               long long *bufs[]);
+
+int ncmpi_mget_vara_ulonglong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               unsigned long long *bufs[]);
+
+
+int ncmpi_mget_vars(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mget_vars_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], void *bufs[],
+               MPI_Offset bufcounts[], MPI_Datatype datatypes[]);
+
+int ncmpi_mget_vars_text(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], char *bufs[]);
+
+int ncmpi_mget_vars_schar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], signed char *bufs[]);
+
+int ncmpi_mget_vars_uchar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned char *bufs[]);
+
+int ncmpi_mget_vars_short(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], short *bufs[]);
+
+int ncmpi_mget_vars_ushort(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned short *bufs[]);
+
+int ncmpi_mget_vars_int(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], int *bufs[]);
+
+int ncmpi_mget_vars_uint(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned int *bufs[]);
+
+int ncmpi_mget_vars_long(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], long *bufs[]);
+
+int ncmpi_mget_vars_float(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], float *bufs[]);
+
+int ncmpi_mget_vars_double(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], double *bufs[]);
+
+int ncmpi_mget_vars_longlong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], long long *bufs[]);
+
+int ncmpi_mget_vars_ulonglong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned long long *bufs[]);
+
+
+int ncmpi_mget_vars_text_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], char *bufs[]);
+
+int ncmpi_mget_vars_schar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], signed char *bufs[]);
+
+int ncmpi_mget_vars_uchar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned char *bufs[]);
+
+int ncmpi_mget_vars_short_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], short *bufs[]);
+
+int ncmpi_mget_vars_ushort_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned short *bufs[]);
+
+int ncmpi_mget_vars_int_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], int *bufs[]);
+
+int ncmpi_mget_vars_uint_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned int *bufs[]);
+
+int ncmpi_mget_vars_long_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], long *bufs[]);
+
+int ncmpi_mget_vars_float_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], float *bufs[]);
+
+int ncmpi_mget_vars_double_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], double *bufs[]);
+
+int ncmpi_mget_vars_longlong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], long long *bufs[]);
+
+int ncmpi_mget_vars_ulonglong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], unsigned long long *bufs[]);
+
+
+int ncmpi_mget_varm(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               void *bufs[], MPI_Offset bufcounts[],
+               MPI_Datatype datatypes[]);
+
+int ncmpi_mget_varm_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               void *bufs[], MPI_Offset bufcounts[],
+               MPI_Datatype datatypes[]);
+
+int ncmpi_mget_varm_text(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               char *bufs[]);
+
+int ncmpi_mget_varm_schar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               signed char *bufs[]);
+
+int ncmpi_mget_varm_uchar(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned char *bufs[]);
+
+int ncmpi_mget_varm_short(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               short *bufs[]);
+
+int ncmpi_mget_varm_ushort(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned short *bufs[]);
+
+int ncmpi_mget_varm_int(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               int *bufs[]);
+
+int ncmpi_mget_varm_uint(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned int *bufs[]);
+
+int ncmpi_mget_varm_long(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               long *bufs[]);
+
+int ncmpi_mget_varm_float(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               float *bufs[]);
+
+int ncmpi_mget_varm_double(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               double *bufs[]);
+
+int ncmpi_mget_varm_longlong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               long long *bufs[]);
+
+int ncmpi_mget_varm_ulonglong(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned long long *bufs[]);
+
+
+int ncmpi_mget_varm_text_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               char *bufs[]);
+
+int ncmpi_mget_varm_schar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               signed char *bufs[]);
+
+int ncmpi_mget_varm_uchar_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned char *bufs[]);
+
+int ncmpi_mget_varm_short_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               short *bufs[]);
+
+int ncmpi_mget_varm_ushort_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned short *bufs[]);
+
+int ncmpi_mget_varm_int_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               int *bufs[]);
+
+int ncmpi_mget_varm_uint_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned int *bufs[]);
+
+int ncmpi_mget_varm_long_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               long *bufs[]);
+
+int ncmpi_mget_varm_float_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               float *bufs[]);
+
+int ncmpi_mget_varm_double_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               double *bufs[]);
+
+int ncmpi_mget_varm_longlong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               long long *bufs[]);
+
+int ncmpi_mget_varm_ulonglong_all(int ncid, int num, int varids[],
+               MPI_Offset* const starts[], MPI_Offset* const counts[],
+               MPI_Offset* const strides[], MPI_Offset* const imaps[],
+               unsigned long long *bufs[]);
+
+/* End Skip Prototypes for Fortran binding */
+
+/* End {mput,mget}_var */
+
+/* End: more prototypes to be included for Fortran binding conversion */
+/* ################################################################## */
+
+/* End Prototypes */
+
+
+/* These macros are defined in serial netcdf (3.5.0) for backwards
+ * compatibility with older netcdf code.   We aren't concerned with backwards
+ * compatibility, so if your code doesn't compile with parallel-netcdf, maybe
+ * this is why:
+ *
+ *
+ *  OLD NAME                 NEW NAME
+ *  ----------------------------------
+ *  FILL_BYTE       NC_FILL_BYTE
+ *  FILL_CHAR       NC_FILL_CHAR
+ *  FILL_SHORT      NC_FILL_SHORT
+ *  FILL_LONG       NC_FILL_INT
+ *  FILL_FLOAT      NC_FILL_FLOAT
+ *  FILL_DOUBLE     NC_FILL_DOUBLE
+ *
+ *  MAX_NC_DIMS     NC_MAX_DIMS
+ *  MAX_NC_ATTRS    NC_MAX_ATTRS
+ *  MAX_NC_VARS     NC_MAX_VARS
+ *  MAX_NC_NAME     NC_MAX_NAME
+ *  MAX_VAR_DIMS    NC_MAX_VAR_DIMS
+ */
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/src/lib/rnd.h b/src/lib/rnd.h
new file mode 100644
index 0000000..3a9c810
--- /dev/null
+++ b/src/lib/rnd.h
@@ -0,0 +1,19 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: rnd.h 2021 2015-04-09 20:29:40Z wkliao $ */
+#ifndef _RNDUP
+
+/* useful for aligning memory */
+#define	_RNDUP(x, unit)  ((((x) + (unit) - 1) / (unit)) * (unit))
+#define	_RNDDOWN(x, unit)  ((x) - ((x)%(unit)))
+
+/* #define M_RND_UNIT	(sizeof(double))
+ * SIZEOF_DOUBLE is defined in ncconfig.h
+ */
+#define M_RND_UNIT	SIZEOF_DOUBLE
+#define	M_RNDUP(x) _RNDUP(x, M_RND_UNIT)
+#define	M_RNDDOWN(x)  __RNDDOWN(x, M_RND_UNIT)
+
+#endif
diff --git a/src/lib/string.c b/src/lib/string.c
new file mode 100644
index 0000000..3665008
--- /dev/null
+++ b/src/lib/string.c
@@ -0,0 +1,351 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: string.c 2196 2015-11-27 22:31:05Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "rnd.h"
+#include "macro.h"
+
+
+/*
+ * Free string, and, if needed, its values.
+ * Formerly
+NC_free_string()
+ */
+inline void
+ncmpii_free_NC_string(NC_string *ncstrp)
+{
+    if (ncstrp==NULL) return;
+    /* ncstrp->cp is allocated as part of ncstrp object */
+    NCI_Free(ncstrp);
+}
+
+#ifdef _CONFORM_NETCDF_3_5_1
+/*
+ * For CDF-1, Verify that a name string is valid
+ * CDL syntax, eg, all the characters are
+ * alphanumeric, '-', '_', or '.'.
+ * Also permit ':', '@', '(', or ')' in names for chemists currently making
+ * use of these characters, but don't document until ncgen and ncdump can
+ * also handle these characters in names.
+ */
+static int
+ncmpii_NC_check_name_CDF1(const char *name)
+{
+    const char *cp = name;
+    assert(name != NULL);
+
+    if (*name == 0)
+        DEBUG_RETURN_ERROR(NC_EBADNAME) /* empty names disallowed */
+
+    for (; *cp != 0; cp++) {
+        int ch = *cp;
+        if (!isalnum(ch)) {
+            if (ch != '_' && ch != '-' && ch != '+' && ch != '.' &&
+                ch != ':' && ch != '@' && ch != '(' && ch != ')')
+                DEBUG_RETURN_ERROR(NC_EBADNAME)
+        }
+    }
+    if (cp - name > NC_MAX_NAME)
+        DEBUG_RETURN_ERROR(NC_EMAXNAME)
+
+    return NC_NOERR;
+}
+#endif
+
+static int ncmpii_NC_check_name_CDF2(const char *name);
+
+/*----< ncmpii_NC_check_name() >---------------------------------------------*/
+int
+ncmpii_NC_check_name(const char *name,
+                     int         file_ver) /* CDF version: 1, 2, or 5 */
+{
+    /* NetCDF4 has made CDF-1 no different from CDF-2 except the size of
+     * OFFSET (i.e. 32-bit vs. 64-bit integer. Both formats support extended
+     * names now.
+     */
+#ifdef _CONFORM_NETCDF_3_5_1
+    if (file_ver == 1)
+        return ncmpii_NC_check_name_CDF1(name);
+#endif
+
+    return ncmpii_NC_check_name_CDF2(name);
+}
+
+#include "utf8proc.h"
+
+/* There are 3 levels of UTF8 checking: 1=> (exact)validating 2=>relaxed
+   and 3=>very relaxed
+*/
+/* Use semi-relaxed check */
+#define UTF8_CHECK 2
+
+static int
+nextUTF8(const char* cp)
+{
+    /*  The goal here is to recognize the length of each
+	multibyte utf8 character sequence and skip it.
+        Again, we assume that every non-ascii character is legal.
+        We can define three possible tests of decreasing correctness
+        (in the sense that the least correct will allow some sequences that
+        are technically illegal UTF8).
+        As Regular expressions they are as follows:
+        1. most correct:
+            UTF8   ([\xC2-\xDF][\x80-\xBF])                       \
+                 | (\xE0[\xA0-\xBF][\x80-\xBF])                   \
+                 | ([\xE1-\xEC][\x80-\xBF][\x80-\xBF])            \
+                 | (\xED[\x80-\x9F][\x80-\xBF])                   \
+                 | ([\xEE-\xEF][\x80-\xBF][\x80-\xBF])            \
+                 | (\xF0[\x90-\xBF][\x80-\xBF][\x80-\xBF])        \
+                 | ([\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]) \
+                 | (\xF4[\x80-\x8F][\x80-\xBF][\x80-\xBF])        \
+
+        2. partially relaxed:
+            UTF8 ([\xC0-\xDF][\x80-\xBF])
+                 |([\xE0-\xEF][\x80-\xBF][\x80-\xBF])
+                 |([\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF])
+
+        3. The most relaxed version of UTF8:
+            UTF8 ([\xC0-\xD6].)|([\xE0-\xEF]..)|([\xF0-\xF7]...)
+
+        We use #2 here.
+
+	The tests are derived from the table at
+	    http://www.w3.org/2005/03/23-lex-U
+    */
+
+/* Define a test macro to test against a range */
+#define RANGE(c,lo,hi) (((uchar)c) >= lo && ((uchar)c) <= hi)
+/* Define a common RANGE */
+#define RANGE0(c) RANGE(c,0x80,0xBF)
+
+    int ch0;
+
+    int skip = -1; /* assume failed */
+
+    ch0 = (uchar)*cp;
+    if(ch0 <= 0x7f) skip = 1; /* remove ascii case */
+    else
+
+#if UTF8_CHECK == 2
+    /* Do relaxed validation check */
+    if(RANGE(ch0,0xC0,0XDF)) {/* 2-bytes, but check */
+        if(cp[1] != 0 && RANGE0(cp[1]))
+		skip = 2; /* two bytes */
+    } else if(RANGE(ch0,0xE0,0XEF)) {/* 3-bytes, but check */
+        if(cp[1] != 0 && RANGE0(cp[1]) && cp[2] != 0 && RANGE0(cp[1]))
+		skip = 3; /* three bytes */
+    } else if(RANGE(ch0,0xF0,0XF7)) {/* 3-bytes, but check */
+        if(cp[1] != 0 && RANGE0(cp[1]) && cp[2] != 0
+           && RANGE0(cp[1]) && cp[3] != 0 && RANGE0(cp[1]))
+		skip = 4; /* four bytes*/
+    }
+#elif UTF8_CHECK == 1
+    /* Do exact validation check */
+    if(RANGE(ch0,0xC2,0xDF)) {/* non-overlong 2-bytes */
+	int ch1 = (uchar)cp[1];
+	if(ch1 != 0 && RANGE0(ch1)) skip = 2;
+    } else if((ch0 == 0xE0)) {/* 3-bytes, not overlong */
+	int ch1 = (uchar)cp[1];
+	if(ch1 != 0 && RANGE(ch1,0xA0,0xBF)) {
+	    int ch2 = (uchar)cp[2];
+	    if(ch2 != 0 && RANGE0(ch2)) skip = 3;
+	}
+    } else if((ch0 == 0xED)) {/* 3-bytes minus surrogates */
+	int ch1 = (uchar)cp[1];
+	if(ch1 != 0 && RANGE(ch1,0x80,0x9f)) {
+	    int ch2 = (uchar)cp[2];
+	    if(ch2 != 0 && RANGE0(ch2)) skip = 3;
+	}
+    } else if(RANGE(ch0,0xE1,0xEC) || ch0 == 0xEE || ch0 == 0xEF) {
+	int ch1 = (uchar)cp[1];
+	if(ch1 != 0 && RANGE0(ch1)) {
+	    int ch2 = (uchar)cp[2];
+	    if(ch2 != 0 && RANGE0(ch2)) skip = 3;
+	}
+    } else if((ch0 == 0xF0)) {/* planes 1-3 */
+	int ch1 = (uchar)cp[1];
+	if(ch1 != 0 && RANGE(ch1,0x90,0xBF)) {
+	    int ch2 = (uchar)cp[2];
+	    if(ch2 != 0 && RANGE0(ch2)) {
+	        int ch3 = (uchar)cp[3];
+	        if(ch3 != 0 && RANGE0(ch3)) skip = 4;
+	    }
+	}
+    } else if((ch0 == 0xF4)) {/* plane 16 */
+	int ch1 = (uchar)cp[1];
+	if(ch1 != 0 && RANGE0(ch1)) {
+	    int ch2 = (uchar)cp[2];
+	    if(ch2 != 0 && RANGE0(ch2)) {
+	        int ch3 = (uchar)cp[3];
+	        if(ch3 != 0 && RANGE0(ch3)) skip = 4;
+	    }
+	}
+    } else if(RANGE(ch0,0xF1,0xF3)) { /* planes 4-15 */
+	int ch1 = (uchar)cp[1];
+	if(ch1 != 0 && RANGE0(ch1)) {
+	    int ch2 = (uchar)cp[2];
+	    if(ch2 != 0 && RANGE0(ch2)) {
+	        int ch3 = (uchar)cp[3];
+	        if(ch3 != 0 && RANGE0(ch3)) skip = 4;
+	    }
+	}
+    }
+#else
+#error "Must Define UTF8_CHECK as 1 or 2"
+#endif
+    return skip;
+}
+
+
+/*
+ * Verify that a name string is valid syntax.  The allowed name
+ * syntax (in RE form) is:
+ *
+ * ([a-zA-Z_]|{UTF8})([^\x00-\x1F\x7F/]|{UTF8})*
+ *
+ * where UTF8 represents a multibyte UTF-8 encoding.  Also, no
+ * trailing spaces are permitted in names.  This definition
+ * must be consistent with the one in ncgen.l.  We do not allow '/'
+ * because HDF5 does not permit slashes in names as slash is used as a
+ * group separator.  If UTF-8 is supported, then a multi-byte UTF-8
+ * character can occur anywhere within an identifier.  We later
+ * normalize UTF-8 strings to NFC to facilitate matching and queries.
+ */
+static int
+ncmpii_NC_check_name_CDF2(const char *name)
+{
+	int skip;
+	int ch;
+	const char *cp = name;
+	ssize_t utf8_stat;
+
+	assert(name != NULL);
+
+	if(*name == 0		/* empty names disallowed */
+	   || strchr(cp, '/'))	/* '/' can't be in a name */
+		DEBUG_RETURN_ERROR(NC_EBADNAME)
+
+	/* check validity of any UTF-8 */
+	utf8_stat = utf8proc_check((const unsigned char *)name);
+	if (utf8_stat < 0)
+	    DEBUG_RETURN_ERROR(NC_EBADNAME)
+
+	/* First char must be [a-z][A-Z][0-9]_ | UTF8 */
+	ch = (uchar)*cp;
+	if(ch <= 0x7f) {
+	    if(!('A' <= ch && ch <= 'Z')
+	       && !('a' <= ch && ch <= 'z')
+               && !('0' <= ch && ch <= '9')
+	       && ch != '_' )
+		DEBUG_RETURN_ERROR(NC_EBADNAME)
+	    cp++;
+	} else {
+	    if((skip = nextUTF8(cp)) < 0)
+		DEBUG_RETURN_ERROR(NC_EBADNAME)
+	    cp += skip;
+	}
+
+	while(*cp != 0) {
+	    ch = (uchar)*cp;
+	    /* handle simple 0x00-0x7f characters here */
+	    if(ch <= 0x7f) {
+                if( ch < ' ' || ch > 0x7E) /* control char or DEL */
+		  DEBUG_RETURN_ERROR(NC_EBADNAME)
+		cp++;
+	    } else {
+		if((skip = nextUTF8(cp)) < 0) DEBUG_RETURN_ERROR(NC_EBADNAME)
+		cp += skip;
+	    }
+	    if(cp - name > NC_MAX_NAME)
+		DEBUG_RETURN_ERROR(NC_EMAXNAME)
+	}
+	if(ch <= 0x7f && isspace(ch)) /* trailing spaces disallowed */
+	    DEBUG_RETURN_ERROR(NC_EBADNAME)
+	return NC_NOERR;
+}
+
+/*----< ncmpii_new_NC_string() >---------------------------------------------*/
+/*
+ * Allocate a NC_string structure large enough
+ * to hold slen characters.
+ * Formerly
+NC_new_string(count, str)
+ */
+NC_string *
+ncmpii_new_NC_string(size_t      slen,
+                     const char *str)
+{
+    /* str may not be NULL terminated */
+    NC_string *ncstrp;
+    size_t sizeof_NC_string = M_RNDUP(sizeof(NC_string));
+    size_t sz = slen + sizeof_NC_string + 1;
+    /* one char more space for NULL terminate char */
+
+#if 0
+    sz = _RNDUP(sz, X_ALIGN);
+#endif
+
+    ncstrp = (NC_string *) NCI_Calloc(sz, sizeof(char));
+    if (ncstrp == NULL) return NULL;
+
+    /* make space occupied by ncstrp->cp part of ncstrp */
+    ncstrp->nchars = (MPI_Offset)slen;
+    ncstrp->cp = (char *)ncstrp + sizeof_NC_string;
+
+    /* in PnetCDF, we want to make name->cp always NULL character terminated */
+    if (str != NULL && *str != '\0') {
+        strncpy(ncstrp->cp, str, slen);
+        ncstrp->cp[slen] = '\0';  /* NULL terminated */
+    }
+
+    return(ncstrp);
+}
+
+
+/*----< ncmpii_set_NC_string() >---------------------------------------------*/
+/*
+ * If possible, change the value of an NC_string to 'str'.
+ *
+ * Formerly
+NC_re_string()
+ */
+int
+ncmpii_set_NC_string(NC_string  *ncstrp,
+                     const char *str)
+{
+    size_t slen;
+
+    assert(str != NULL && *str != '\0');
+
+    slen = strlen(str);
+
+    if (ncstrp->nchars < (MPI_Offset)slen) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+
+    memcpy(ncstrp->cp, str, slen);
+
+    /* in PnetCDF, we want to make name->cp always NULL character terminated */
+    if (ncstrp->nchars > (MPI_Offset)slen)
+        memset(ncstrp->cp + slen, 0, (size_t)ncstrp->nchars - slen);
+
+    ncstrp->nchars = (MPI_Offset)slen;
+
+    return NC_NOERR;
+}
diff --git a/src/lib/subfile.c b/src/lib/subfile.c
new file mode 100644
index 0000000..ca909e8
--- /dev/null
+++ b/src/lib/subfile.c
@@ -0,0 +1,1109 @@
+/*
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: subfile.c 2196 2015-11-27 22:31:05Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+#include "subfile.h"
+#ifdef TAU_SSON
+#include <TAU.h>
+#endif
+#include <stdlib.h>
+#include "ncmpidtype.h"
+
+static int DEBUG = 1;
+enum {ONE, BALANCED};
+int min_ndims = 1;
+
+/* set default values for the following values */
+int delegate_scheme = BALANCED; /* default: any proc can be delegate proc */
+static int is_partitioned = 0;
+
+#define check_err(fn_name_)                                                     \
+    if (mpireturn != MPI_SUCCESS) {                                             \
+        errs++;                                                                 \
+        if (DEBUG) {                                                            \
+            int _len;                                                           \
+            char err_str_[MPI_MAX_ERROR_STRING];                                \
+            MPI_Error_string(mpireturn, err_str_, &_len);                       \
+            fprintf(stderr, #fn_name_ " failed at line %d, mpireturn=%d: %s\n", \
+                    __LINE__, mpireturn, err_str_);                             \
+        }                                                                       \
+    }                                                                           \
+
+#if 0
+static int ncmpii_itoa(int val, char* buf)
+{
+    const unsigned int radix = 10;
+
+    char* p;
+    unsigned int a;        /* every digit */
+    int len;
+    char* b;            /* start of the digit char */
+    char temp;
+    unsigned int u;
+
+    p = buf;
+
+    if (val < 0) {
+        *p++ = '-';
+        val = 0 - val;
+    }
+    u = (unsigned int)val;
+
+    b = p;
+
+    do {
+        a = u % radix;
+        u /= radix;
+
+        *p++ = a + '0';
+
+    } while (u > 0);
+
+    len = (int)(p - buf);
+
+    *p-- = 0;
+
+    /* swap */
+    do {
+        temp = *p;
+        *p = *b;
+        *b = temp;
+        --p;
+        ++b;
+    } while (b < p);
+
+    return len;
+}
+#endif
+
+int ncmpii_subfile_create(NC *ncp, int *ncidp)
+{
+    int myrank, nprocs, color, status=NC_NOERR, mpireturn;
+    char path_sf[1024];
+    double ratio;
+    MPI_Comm comm_sf;
+    MPI_Info info;
+
+    MPI_Info_create(&info);
+
+    MPI_Comm_rank(ncp->nciop->comm, &myrank);
+    MPI_Comm_size(ncp->nciop->comm, &nprocs);
+#ifdef SUBFILE_DEBUG
+    if (myrank == 0)
+      printf("%s: rank(%d): nprocs=%d, ncp->nc_num_subfiles=%d\n",
+           __func__, myrank, nprocs, ncp->nc_num_subfiles);
+#endif
+
+    /* split the orignial comm to subcomm */
+    if (nprocs > ncp->nc_num_subfiles) {
+        ratio = (double)nprocs/(double)(ncp->nc_num_subfiles);
+        color = (int)((double)myrank/ratio);
+    }
+    else
+        color = myrank%ncp->nc_num_subfiles;
+
+#ifdef SUBFILE_DEBUG
+    printf("rank(%d): color=%d\n", myrank, color);
+#endif
+    /* key = myrank/comm_size; */
+
+    /* TODO: fix error when using generated key value.
+     * for now, just passing 0 value. */
+    TRACE_COMM(MPI_Comm_split)(ncp->nciop->comm, color, myrank, &comm_sf);
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_Comm_split"); 
+
+    sprintf(path_sf, "%s.subfile_%i.%s", ncp->nciop->path, color, "nc");
+
+    /* MPI_Info_set(info, "romio_lustre_start_iodevice", offset);
+       MPI_Info_set(info, "striping_factor", "1");
+     */
+
+    status = ncmpi_create(comm_sf, path_sf, ncp->nciop->ioflags, info, ncidp);
+    if (status != NC_NOERR && myrank == 0)
+        fprintf(stderr, "%s: error in creating file(%s): %s\n",
+                __func__, path_sf, ncmpi_strerror(status));
+
+    MPI_Comm_free(&comm_sf);
+    MPI_Info_free(&info);
+
+    return status;
+}
+
+int
+ncmpii_subfile_open(NC *ncp, int *ncidp)
+{
+    int myrank, nprocs, color, status=NC_NOERR, mpireturn;
+    char path_sf[1024];
+    MPI_Comm comm_sf;
+    double ratio;
+
+    MPI_Comm_rank(ncp->nciop->comm, &myrank);
+    MPI_Comm_size(ncp->nciop->comm, &nprocs);
+#ifdef SUBFILE_DEBUG
+    if (myrank == 0)
+      printf("%s: rank(%d): nprocs=%d, ncp->nc_num_subfiles=%d\n", __func__,
+           myrank, nprocs, ncp->nc_num_subfiles);
+#endif
+
+    /* split the original comm to subcomm */
+    if (nprocs > ncp->nc_num_subfiles) {
+        ratio = (double)nprocs/(double)ncp->nc_num_subfiles;
+        color = (int)((double)myrank/ratio);
+    }
+    else
+        color = myrank%ncp->nc_num_subfiles;
+
+#ifdef SUBFILE_DEBUG
+    if (myrank == 0)
+      printf("%s: rank(%d): color=%d\n", __func__, myrank, color);
+#endif
+    /* key = myrank/comm_size; */
+
+    /* TODO: fix error when using generated key value.
+     * for now, just passing 0 value. */
+    TRACE_COMM(MPI_Comm_split)(ncp->nciop->comm, color, myrank, &comm_sf);
+    if (mpireturn != MPI_SUCCESS)
+        return ncmpii_handle_error(mpireturn, "MPI_Comm_split"); 
+
+    /* char path[1024], file[1024]; */
+    /* find_path_and_fname(ncp->nciop->path, path, file); */
+    sprintf(path_sf, "%s.subfile_%i.%s", ncp->nciop->path, color, "nc");
+    /* sprintf(path_sf, "%s%d/%s", path, color, file); */
+
+    status = ncmpi_open(comm_sf, path_sf, ncp->nciop->ioflags, MPI_INFO_NULL, ncidp);
+    if (status != NC_NOERR)
+        fprintf(stderr, "Error in file %s line %d: %s\n", __FILE__,__LINE__, ncmpi_strerror(status));
+
+    MPI_Comm_free(&comm_sf);
+    return status;
+}
+
+int ncmpii_subfile_close(NC *ncp)
+{
+    int status = NC_NOERR;
+    NC *ncp_sf;
+
+    status = ncmpii_NC_check_id(ncp->ncid_sf, &ncp_sf);
+    if (status != NC_NOERR)
+        return status;
+
+    status = ncmpii_close(ncp_sf);
+    if (status != NC_NOERR)
+        return status;
+
+    /* reset values to 0 */
+    is_partitioned = 0;
+
+    return status;
+}
+
+/*----< ncmpii_subfile_partition() >---------------------------------------*/
+int ncmpii_subfile_partition(NC *ncp, int *ncidp)
+{
+    int i, j, color, myrank, nprocs, status=NC_NOERR, num_subfiles;
+    NC *ncp_sf;
+    double ratio;
+
+    MPI_Comm_rank(ncp->nciop->comm, &myrank);
+    MPI_Comm_size(ncp->nciop->comm, &nprocs);
+#ifdef SUBFILE_DEBUG
+    if (myrank==0)  /* debug */
+    {
+        printf("rank(%d): is_partitioned=%d\n", myrank, is_partitioned);
+    }
+#endif
+    if (is_partitioned == 1) return NC_NOERR;
+
+    if (nprocs > ncp->nc_num_subfiles) {
+        ratio = (double)nprocs/(double)ncp->nc_num_subfiles;
+        color = (int)((double)myrank/ratio);
+    }
+    else
+        color = myrank%ncp->nc_num_subfiles;
+
+#ifdef SUBFILE_DEBUG
+    printf("%s: rank(%d): color=%d\n", __func__, myrank, color);
+#endif
+
+    /* check whether file is already partitioned */
+    /* this is to handle when app has multiple ncmpi_enddef() */
+    status = ncmpi_get_att_int(ncp->nciop->fd, NC_GLOBAL, "_PnetCDF_SubFiling.num_subfiles",
+                               &num_subfiles);
+
+    if (status == NC_ENOTATT) { /* if such attr doesn't exist */
+        status = ncmpii_subfile_create(ncp, ncidp);
+        TEST_HANDLE_ERR(status)
+
+        status = ncmpi_put_att_int(ncp->nciop->fd, NC_GLOBAL, "_PnetCDF_SubFiling.num_subfiles",
+                                   NC_INT, 1, &ncp->nc_num_subfiles);
+        TEST_HANDLE_ERR(status)
+    }
+    else if (status == NC_NOERR) { /* attr is already set */
+        assert(num_subfiles == ncp->nc_num_subfiles);
+    }
+    else /* other error */
+        return status;
+
+    /* TODO: ignore UNLIMITED dims */
+    /* NOTE: the following "for loop" should be before NC_begins() */
+    /* NOTE: ncp->vars.nalloc shouldn't be used for loop bound
+       because it will incremented by 4, not by 1 */
+    status = ncmpii_NC_check_id(ncp->ncid_sf, &ncp_sf);
+    TEST_HANDLE_ERR(status)
+
+    /* adjust the hints to be used by PnetCDF; use the same value in master */
+    ncp_sf->nciop->hints.h_align = ncp->nciop->hints.h_align;
+    ncp_sf->nciop->hints.v_align = ncp->nciop->hints.v_align;
+    ncp_sf->nciop->hints.r_align = ncp->nciop->hints.r_align;
+
+    for(i=0; i<ncp->vars.ndefined; i++) { /* traverse all variables */
+        NC_var **vpp = ncp->vars.value;
+        NC_dim **dpp = ncp->dims.value;
+
+        /* check attr for subfiles */
+        int par_dim_id = (IS_RECVAR(vpp[i])?1:0); /* default is the most significant dim excluding NC_UNLIMITED */
+
+        /* skip if the var is partitioned already */
+        if (vpp[i]->dimids == NULL) continue;
+
+        int par_dim_id_temp;
+        status = ncmpi_get_att_int(ncp->nciop->fd, i, "_PnetCDF_SubFiling.par_dim_id",
+                                   &par_dim_id_temp);
+        if (status == NC_NOERR) { /* if this attr exists */
+#ifdef SUBFILE_DEBUG
+            printf("par_dim_id_temp=%d\n", par_dim_id_temp);
+            printf("par_dim_id=%d\n", par_dim_id);
+#endif
+            /* convert par_dim_id to dim index defined in a var */
+            for (j=0; j<vpp[i]->ndims; j++)
+                if (vpp[i]->dimids[j] == par_dim_id_temp) {
+#ifdef SUBFILE_DEBUG
+                    if (myrank == 0)
+                        printf("dimids[%d]=%d\n", j, vpp[i]->dimids[j]);
+#endif
+                    par_dim_id = j;
+                    break;
+                }
+        }
+        else if (status != NC_ENOTATT) /* ignore if this attr does not exist */
+            return status; /* other kind of error */
+
+        if (par_dim_id < vpp[i]->ndims) {
+            status = ncmpi_put_att_int(ncp->nciop->fd, i, "_PnetCDF_SubFiling.par_dim_index",
+                                       NC_INT, 1, &par_dim_id);
+            TEST_HANDLE_ERR(status)
+        }
+
+#ifdef SUBFILE_DEBUG
+        if (myrank == 0)
+            printf ("%s: var(%s): size of partitioning dim (id=%d)=%d\n",
+                    __func__, (*vpp[i]).name->cp, par_dim_id,
+                    dpp[par_dim_id]->size);
+#endif
+        /* divide only when dim is partitionable */
+        /* 1. skip sizeof(par_dim_id) is smaller than num_subfiles */
+        /* 2. skip if ndims < min_ndims */
+        if ( (dpp[(*vpp[i]).dimids[par_dim_id]]->size)/(ncp->nc_num_subfiles) != 0 && (vpp[i]->ndims >= par_dim_id+1) && (vpp[i]->ndims >= min_ndims)) {
+            int varid, j, jj, k;
+            int var_ndims = vpp[i]->ndims; /* keep org ndims */
+            int dimids[var_ndims];
+            char *key[ncp->nc_num_subfiles][var_ndims];
+
+            for (jj=0; jj < ncp->nc_num_subfiles; jj++)
+                for (k=0; k<var_ndims; k++)
+                    key[jj][k] = (char*) NCI_Calloc((size_t)256, sizeof(char));
+
+            /* save original value ndims to attribute before making to 0 */
+            status = ncmpi_put_att_int(ncp->nciop->fd, i, "_PnetCDF_SubFiling.ndims_org", NC_INT, 1, &vpp[i]->ndims);
+            TEST_HANDLE_ERR(status)
+
+            int sf_range[ncp->nc_num_subfiles][var_ndims][3];
+
+            /* j: each dimension */
+            /* subfile: create a var with partitioned dim sizes */
+            for(j=0; j<var_ndims; j++) {
+                MPI_Offset dim_sz;
+                char str[80];
+                double x; /* = org dim size / num_subfiles */
+                int min, max;
+
+                dim_sz = dpp[vpp[i]->dimids[j]]->size; /* init both to org dim sz */
+                /* determine partition ratio */
+                x = (double)(dpp[vpp[i]->dimids[j]]->size)/(double)(ncp->nc_num_subfiles);
+
+                /* don't partition dim if dim size is less than ratio x */
+                if ((int)x < 1 && j == par_dim_id)
+                    continue;
+
+                /* don't need to check? */
+                if (j == par_dim_id)
+                {
+                    double xx = x*(double)color;
+                    double yy = x*(double)(color+1);
+                    min = (int)xx+(color==0||(xx-(int)xx==0.0)?0:1);
+                    max = (int)yy-(yy-(int)yy==0.0?1:0);
+                    if (max >= dpp[vpp[i]->dimids[j]]->size) max = dpp[vpp[i]->dimids[j]]->size-1;
+                    dim_sz = max-min+1;
+                }
+
+                /* name->cp is always NULL terminated, see ncmpii_new_NC_string() */
+                sprintf(str, "%s.%s", dpp[vpp[i]->dimids[j]]->name->cp,
+                        vpp[i]->name->cp);
+#ifdef SUBFILE_DEBUG
+                printf("rank(%d): new dim name = %s, dim_sz=%d\n", myrank, str, dim_sz);
+#endif
+                status = ncmpi_def_dim(ncp->ncid_sf, str, dim_sz, &dimids[j]);
+                TEST_HANDLE_ERR(status)
+
+                /* dpp_sf[color][j] = ncp_sf->dims.value[j]; */
+
+                for (jj=0; jj < ncp->nc_num_subfiles; jj++) {
+                    double xx, yy;
+                    sprintf(key[jj][j], "_PnetCDF_SubFiling.range(%s).subfile.%d", dpp[vpp[i]->dimids[j]]->name->cp, jj); /* dim name*/
+                    xx = x*(double)jj;
+                    min = (int)xx+(jj==0||(xx-(int)xx==0.0)?0:1);
+                    yy = x*(double)(jj+1);
+                    max = (int)yy-(yy-(int)yy==0.0?1:0);
+                    if (max >= dpp[vpp[i]->dimids[j]]->size) max = dpp[vpp[i]->dimids[j]]->size-1;
+#ifdef SUBFILE_DEBUG
+                    if (myrank == 0) printf("subfile(%d): min=%d, max=%d\n", jj, min, max);
+#endif
+                    if (j == par_dim_id) { /* partitioning dims? */
+                        sf_range[jj][j][0] = min;
+                        sf_range[jj][j][1] = max;
+                        sf_range[jj][j][2] = (max-min+1);;
+                    }
+                    else {
+                        sf_range[jj][j][0] = 0;
+                        sf_range[jj][j][2] = dpp[vpp[i]->dimids[j]]->size;
+                        sf_range[jj][j][1] = (dpp[vpp[i]->dimids[j]]->size!=0?(dpp[vpp[i]->dimids[j]]->size)-1:0);
+                    }
+                }
+            } /* for each dim */
+
+            /* master file: replace the original var with scalar var */
+            vpp[i]->dimids_org = (int*) NCI_Malloc((size_t)vpp[i]->ndims * SIZEOF_INT);
+            memcpy(vpp[i]->dimids_org, vpp[i]->dimids, (size_t)vpp[i]->ndims*SIZEOF_INT);
+            vpp[i]->ndims_org = vpp[i]->ndims;
+            vpp[i]->ndims = 0;
+            vpp[i]->dimids = (IS_RECVAR(vpp[i])?&vpp[i]->dimids[0]:NULL);
+            vpp[i]->len = vpp[i]->xsz; /* size of type  */
+            vpp[i]->shape = NULL;
+            vpp[i]->num_subfiles = ncp->nc_num_subfiles;
+
+            status = ncmpi_put_att_int(ncp->nciop->fd, i, "_PnetCDF_SubFiling.dimids_org",
+                                       NC_INT, vpp[i]->ndims_org, vpp[i]->dimids_org);
+            TEST_HANDLE_ERR(status)
+
+            status = ncmpi_put_att_int(ncp->nciop->fd, i, "_PnetCDF_SubFiling.num_subfiles",
+                                       NC_INT, 1, &ncp->nc_num_subfiles);
+            TEST_HANDLE_ERR(status)
+
+            for (jj=0; jj < ncp->nc_num_subfiles; jj++)
+                for (k=0; k < var_ndims; k++) {
+                    status = ncmpi_put_att_int(ncp->nciop->fd, i,
+                                               key[jj][k], NC_INT,
+                                               2, sf_range[jj][k]);
+                    TEST_HANDLE_ERR(status)
+                }
+
+            /* define a var with new dim */
+            status = ncmpi_def_var(ncp->ncid_sf, (*vpp[i]).name->cp,
+                                   vpp[i]->type, var_ndims, dimids, &varid);
+            TEST_HANDLE_ERR(status)
+
+            /* add an attribute about each dim's range in subfile */
+            /* varid: var id in subfile */
+            for (k=0; k<var_ndims; k++) {
+                status = ncmpi_put_att_int(ncp->ncid_sf, varid, key[color][k],
+                                           NC_INT, 2, sf_range[color][k]);
+                TEST_HANDLE_ERR(status)
+            }
+
+            /* deallocate buffers */
+            for (jj=0; jj < ncp->nc_num_subfiles; jj++)
+                for (k=0; k<var_ndims; k++)
+                    NCI_Free(key[jj][k]);
+
+            status = ncmpi_put_att_int(ncp->ncid_sf, varid, "_PnetCDF_SubFiling.subfile_index",
+                                       NC_INT, 1, &color);
+            TEST_HANDLE_ERR(status)
+        } /* end if() */
+    } /* for each variable */
+
+    is_partitioned = 1;
+
+    return NC_NOERR;
+}
+
+/*----< ncmpii_subfile_getput_vars() >---------------------------------------*/
+int
+ncmpii_subfile_getput_vars(NC               *ncp,
+                           NC_var           *varp,
+                           const MPI_Offset  start[],
+                           const MPI_Offset  count[],
+                           const MPI_Offset  stride[],
+                           void             *buf,
+                           MPI_Offset        bufcount,
+                           MPI_Datatype      buftype, /* data type of the buffer */
+                           int               rw_flag,
+                           int               io_method)
+{
+    int mpireturn, errs=0, status;
+    NC_subfile_access *my_req, *others_req;
+    int i, j, k, myrank, nprocs;
+    NC *ncp_sf;
+    int *count_my_req_per_proc, *count_others_req_per_proc;
+    int varid, varid_sf;
+    MPI_Offset *buf_count_my, *buf_count_others;
+    void **xbuf=NULL, *cbuf=NULL;
+    MPI_Request *requests=NULL;
+    MPI_Status *statuses=NULL;
+    int ndims_org = varp->ndims_org;
+    int color;
+    int nasyncios=0;
+
+    /* check whether start, count, and stride are valid */
+    status = NC_start_count_stride_ck(ncp, varp, start, count, stride, rw_flag);
+    if (status != NC_NOERR) return status;
+
+    MPI_Comm_rank(ncp->nciop->comm, &myrank);
+    MPI_Comm_size(ncp->nciop->comm, &nprocs);
+
+#ifdef SUBFILE_DEBUG
+    for (i=0; i<ndims_org; i++)
+        printf("rank(%d): %s: var(%s): start[%d]=%ld, count[%d]=%ld, stride[%d]=%ld, bufcount=%ld\n",
+               myrank, __func__, varp->name->cp, i, start[i], i, count[i], i,
+               ((stride != NULL)?stride[i]:1), bufcount);
+#endif
+
+    /* get ncp info for the subfile */
+    status = ncmpii_NC_check_id(ncp->ncid_sf, &ncp_sf);
+    TEST_HANDLE_ERR(status)
+
+    /* check attr for subfiles */
+    int par_dim_id = 0; /* default is the most significant dim */
+
+    status = ncmpi_inq_varid(ncp->nciop->fd, varp->name->cp, &varid);
+    TEST_HANDLE_ERR(status)
+
+    status = ncmpi_get_att_int(ncp->nciop->fd, varid, "_PnetCDF_SubFiling.par_dim_index",
+                               &par_dim_id);
+    TEST_HANDLE_ERR(status)
+#ifdef SUBFILE_DEBUG
+    if (myrank == 0)
+        printf("_PnetCDF_SubFiling.par_dim_index of %s = %d\n", varp->name->cp, par_dim_id);
+#endif
+    status = ncmpi_inq_varid(ncp_sf->nciop->fd, varp->name->cp, &varid_sf);
+    TEST_HANDLE_ERR(status)
+
+    status = ncmpi_get_att_int(ncp_sf->nciop->fd, varid_sf, "_PnetCDF_SubFiling.subfile_index",
+                               &color);
+    TEST_HANDLE_ERR(status)
+
+    count_my_req_per_proc = (int *)NCI_Calloc((size_t)nprocs, SIZEOF_INT);
+    count_others_req_per_proc = (int *)NCI_Calloc((size_t)nprocs, SIZEOF_INT);
+    buf_count_my = (MPI_Offset *)NCI_Calloc((size_t)nprocs, SIZEOF_MPI_OFFSET);
+    buf_count_others = (MPI_Offset *)NCI_Calloc((size_t)nprocs, SIZEOF_MPI_OFFSET);
+
+    /* TODO: shouldn't it be initialized to 0? */
+    for (i=0; i<nprocs; i++) {
+        buf_count_my[i] = 1;
+        buf_count_others[i] = 1;
+    }
+
+    /* allocate space for my_req */
+    my_req = (NC_subfile_access*) NCI_Calloc((size_t)nprocs, sizeof(NC_subfile_access));
+
+    /* init allocated my_req */
+    for (i=0; i<nprocs; i++) {
+        my_req[i].start = (MPI_Offset*)NCI_Malloc((size_t)(3 * ndims_org * SIZEOF_MPI_OFFSET));
+        my_req[i].count = my_req[i].start + ndims_org;
+        my_req[i].start_org = my_req[i].count + ndims_org;
+        /* init start/count to -1 */
+        for (j=0; j<ndims_org; j++) {
+            my_req[i].start[j] = -1;
+            my_req[i].count[j] = -1;
+            my_req[i].start_org[j] = -1;
+        }
+    }
+
+    /* i: for each subfile */
+    for (i=0; i<ncp->nc_num_subfiles; i++) {
+        int flag = 0; /* set to 1 if par_dim_id is partitioned, initially 0 */
+        double ratio = (double)nprocs/(double)ncp->nc_num_subfiles;
+        int aproc=-1; /* I/O delegate proc in subfile group */
+
+        if (delegate_scheme == BALANCED) {
+            double scaled, xx, yy;
+            int min, max;
+
+            xx = (ratio)*(double)i; /* i: each subfile */
+            min = (int)xx+(i==0||(xx-(int)xx==0.0)?0:1);
+            yy = (ratio)*(double)(i+1);
+            max = (int)yy-(yy-(int)yy==0.0?1:0);
+            if (max >= nprocs) max = nprocs-1;
+            /* scaled = (double)rand()/RAND_MAX; */
+            scaled = (double)myrank/ratio-(double)color;
+            aproc = (i==color)?myrank:(min+(max-min+1)*scaled);
+        }
+        else if (delegate_scheme == ONE)
+        {
+            double xx;
+            int min;
+            xx = (ratio)*(double)i;
+            min = (int)xx+(i==0||(xx-(int)xx==0.0)?0:1);
+            aproc = (i==color)?myrank:min;
+        }
+
+        /* check out of range? */
+        if (aproc >= nprocs)
+            aproc = nprocs-1;
+
+#ifdef SUBFILE_DEBUG
+        printf("rank(%d): color=%d, subfile=%d, aproc=%d\n", myrank, color, i, aproc);
+#endif
+
+        /* j: for each dim starting from par_dim_id in round-robin manner */
+        for (j=par_dim_id; j<par_dim_id+ndims_org; j++) {
+            int jx = j%ndims_org;
+            NC_dim *dimp = ncp_sf->dims.value[ncp_sf->vars.value[varid_sf]->dimids[jx]];
+            int sf_range[2];
+            int ii, jj, kk, stride_count;
+            char key[256], *org_dim_name;
+
+            org_dim_name = strtok(dimp->name->cp, ".");
+            sprintf(key, "_PnetCDF_SubFiling.range(%s).subfile.%d", org_dim_name, i); /* dim name*/
+#ifdef SUBFILE_DEBUG
+            if (myrank == 0) {
+                printf("rank(%d): org_dim_name=%s\n", myrank, org_dim_name);
+                printf("rank(%d): key=%s\n", myrank, key);
+            }
+#endif
+            /* should get range info from the master file */
+            status = ncmpi_get_att_int(ncp->nciop->fd, varid, key, sf_range);
+            TEST_HANDLE_ERR(status)
+
+#ifdef SUBFILE_DEBUG
+            /* if (myrank == 0) */
+                printf("rank(%d): ndims_org=%d, rstart=%d, rend=%d, start[%d]=%d, count[%d]=%d\n",
+                       myrank, ndims_org, sf_range[0], sf_range[1], jx, start[jx], jx, count[jx]);
+#endif
+            /* ii: traverse user's request range, incremented by stride count
+               jj: traverse subfile range, incrementing sequentially
+               kk: count belong to my subfile range */
+            ii=start[jx], jj=sf_range[0], kk=0;
+            stride_count = (stride == NULL?1:stride[jx]);
+            /* printf("stride_count[%d]=%d\n", jx, stride_count); */
+
+            /* TODO: if sf_range is 1, count[] value is incorrect
+               e.g., size of par_dim is 4 and the nproc is also 4 */
+            int is_unlimited_dim = sf_range[1]-sf_range[0];
+
+            /* skip the remaining dim if par_dim is not
+               intersected with user's request */
+            if (jx != par_dim_id && !flag) continue;
+
+            while (ii < (start[jx]+(count[jx]*stride_count)) &&
+                   jj <= (is_unlimited_dim==0?(count[jx]*stride_count-1):sf_range[1]))
+            {
+                if (ii < jj)
+                    ii+=stride_count;
+                else if (jj < ii)
+                    jj++;
+                else {
+#ifdef SUBFILE_DEBUG
+                    printf("rank(%d): var(%s): i=%d, j=%d, ii=%d, jj=%d, kk=%d, jx=%d\n", myrank, varp->name->cp, i, j, ii, jj, kk, jx);
+#endif
+                    if (kk == 0) {
+                        my_req[aproc].start[jx] = ii;
+#ifdef SUBFILE_DEBUG
+                        printf("rank(%d): var(%s): my_req[%d].start[%d]=%d\n",
+                               myrank, varp->name->cp, aproc, jx, ii);
+#endif
+                    }
+                    if (jx == par_dim_id) flag = 1;
+                    ii+=stride_count; jj++; kk++;
+                }
+
+            }
+            if (kk > 0 && flag == 1) my_req[aproc].count[jx] = kk;
+            /* adjust start offset based on subfile's range start.
+               otherwise, there will be an out of bound error during I/O */
+            if (my_req[aproc].start[jx] != -1) {
+                my_req[aproc].start_org[jx] = my_req[aproc].start[jx];
+                my_req[aproc].start[jx] -= sf_range[0];
+            }
+#ifdef SUBFILE_DEBUG
+            /* if (myrank == 0) */
+            {
+                printf("rank(%d): my_req[%d].start[%d]=%d\n", myrank, aproc,
+                       jx, my_req[aproc].start[jx]);
+                printf("rank(%d): my_req[%d].count[%d]=%d\n", myrank, aproc,
+                       jx, my_req[aproc].count[jx]);
+            }
+#endif
+        } /* for each dim, j */
+        if (my_req[aproc].start[0] == -1)
+            count_my_req_per_proc[aproc] = 0;
+        else
+            count_my_req_per_proc[aproc] = 1;
+    } /* for each subfile, i */
+
+#ifdef SUBFILE_DEBUG
+    for (i=0; i<ncp->nc_num_subfiles; i++) {
+        char str_st[100], str_st_org[100], str_ct[100], str_t1[10];
+        sprintf(str_st, ">> rank(%d): subfile(%d): var(%s): start(", myrank, i, varp->name->cp);
+        sprintf(str_ct, ">> rank(%d): subfile(%d): count(", myrank, i);
+        sprintf(str_st_org, "%d: start_org(", i);
+        for (j=0; j<ndims_org; j++) {
+            sprintf(str_t1, "%d", my_req[i].start[j]);
+            strcat(str_st, str_t1);
+            sprintf(str_t1, "%d", my_req[i].count[j]);
+            strcat(str_ct, str_t1);
+            sprintf(str_t1, "%d", my_req[i].start_org[j]);
+            strcat(str_st_org, str_t1);
+            if (j != (ndims_org-1)) {
+                strcat(str_st, ",");
+                strcat(str_ct, ",");
+                strcat(str_st_org, ",");
+            }
+
+        }
+        strcat(str_st, ")");
+        strcat(str_ct, ")");
+        strcat(str_st_org, ")");
+        printf("%s\n", str_st);
+        printf("%s\n", str_ct);
+        printf("%s\n", str_st_org);
+    }
+#endif
+
+    /* calculate buf_count based on subfile */
+    /* TODO: should do only when count_my_req_per_proc[myrank] != 0??? */
+    for (i=0; i<ndims_org; i++)
+        buf_count_my[myrank] *= my_req[myrank].count[i];
+
+    /* build other proc's request */
+    others_req = (NC_subfile_access *) NCI_Calloc((size_t)nprocs, sizeof(NC_subfile_access));
+    /* init allocated others_req */
+    for (i=0; i<nprocs; i++) {
+        others_req[i].start = (MPI_Offset *)NCI_Malloc((size_t)(3 * ndims_org * SIZEOF_MPI_OFFSET));
+        others_req[i].count = others_req[i].start + ndims_org;
+        others_req[i].start_org = others_req[i].count + ndims_org;
+        /* init start/count to -1 */
+        for (j=0; j<ndims_org; j++) {
+            others_req[i].start[j] = -1;
+            others_req[i].count[j] = -1;
+            others_req[i].start_org[j] = -1;
+        }
+    }
+
+#ifdef SUBFILE_DEBUG
+    for (i=0; i<nprocs && myrank==0; i++) {
+        printf("%d: count_my_req_per_proc[%d]=%d\n", myrank, i, count_my_req_per_proc[i]);
+        printf("%d: count_others_req_per_proc[%d]=%d\n", myrank, i, count_others_req_per_proc[i]);
+    }
+#endif
+
+#ifdef TAU_SSON
+    TAU_PHASE_CREATE_STATIC(t51, "SSON --- getput_vars MPI_Alltoall", "", TAU_USER);
+    TAU_PHASE_START(t51);
+#endif
+
+    TRACE_COMM(MPI_Alltoall)(count_my_req_per_proc, 1, MPI_INT, count_others_req_per_proc, 1, MPI_INT, ncp->nciop->comm);
+
+#ifdef TAU_SSON
+    TAU_PHASE_STOP(t51);
+#endif
+
+#ifdef SUBFILE_DEBUG
+    for (i=0; i<nprocs && myrank==0; i++) {
+        printf("=> %d: count_others_req_per_proc[%d]=%d\n", myrank, i, count_others_req_per_proc[i]);
+    }
+#endif
+
+    MPI_Offset buf_offset[nprocs];
+    for (i=0; i<nprocs; i++)
+        buf_offset[i] = 0;
+
+#ifdef SUBFILE_DEBUG
+    if (myrank == 0) printf("varname=%s: etype=0x%x, etype_size=%d\n", varp->name->cp, varp->type, varp->xsz);
+#endif
+
+    /* find the ptype (primitive MPI data type) from buftype
+     * el_size is the element size of ptype
+     * bnelems is the total number of ptype elements in the I/O buffer, buf
+     * fnelems is the number of nc variable elements in nc_type
+     * nbytes is the amount of read/write in bytes
+     */
+    MPI_Datatype ptype;
+    int el_size;
+    int isderived, buftype_is_contig;
+    MPI_Offset bnelems;
+
+    if (buftype == MPI_DATATYPE_NULL) {
+        /* In this case, bufcount is ignored and will be recalculated to match
+         * count[]. Note buf's data type must match the data type of
+         * variable defined in the file - no data conversion will be done.
+         */
+        bufcount = 1;
+        for (i=0; i<varp->ndims; i++) {
+            if (count[i] < 0)  /* no negative count[] */
+                DEBUG_RETURN_ERROR(NC_ENEGATIVECNT)
+            bufcount *= count[i];
+        }
+        /* assign buftype match with the variable's data type */
+        buftype = ncmpii_nc2mpitype(varp->type);
+    }
+
+    status = ncmpii_dtype_decode(buftype, &ptype, &el_size, &bnelems,
+                                 &isderived, &buftype_is_contig);
+    /* bnelems now is the number of ptype in a buftype */
+    TEST_HANDLE_ERR(status)
+
+#ifdef SUBFILE_DEBUG
+    MPI_Aint lb, extent;
+    MPI_Type_get_extent(buftype, &lb, &extent);
+    printf("rank(%d): var(%s): ptype=0x%x, el_size=%d, bnelems=%d, isderived=%d, buftype_is_contig=%d, lb=%d, extent=%d\n",
+           myrank, varp->name->cp, ptype, el_size, bnelems, isderived, buftype_is_contig, lb, extent);
+#endif
+
+    /* if buftype is non-contiguous, pack to contiguous buffer*/
+    /* NOTE: no conversion and byte swap are performed here
+       as they are done underneath layer */
+    if (!buftype_is_contig && bufcount > 0 && bnelems > 0) {
+        int position=0;
+        MPI_Offset outsize = bnelems * bufcount * el_size;
+        if (outsize  != (int)outsize) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        if (bufcount != (int)bufcount) DEBUG_RETURN_ERROR(NC_EINTOVERFLOW)
+        cbuf = NCI_Malloc((size_t)outsize);
+        if (rw_flag == WRITE_REQ)
+            MPI_Pack(buf, (int)bufcount, buftype, cbuf, (int)outsize,
+                     &position, MPI_COMM_SELF);
+    }
+    else
+        cbuf = (void *)buf;
+
+    MPI_Offset diff[ndims_org];
+    for (i=0; i < ndims_org; i++) {
+        MPI_Offset stride_count;
+        stride_count = (stride == NULL?1:stride[i]);
+        /* making diff is necessary?? */
+        diff[i] = ABS(my_req[myrank].start_org[i]-start[i])/stride_count;
+#ifdef SUBFILE_DEBUG
+        if (myrank == 0) printf("rank(%d): my_req[%d].start_org[%d]=%d, start[%d]=%d, diff[%d]=%lld\n", myrank,
+               myrank, i, my_req[myrank].start_org[i], i, start[i], i, diff[i]);
+#endif
+    }
+
+    for (i=0; i<ndims_org; i++) {
+        int l;
+        MPI_Offset tmp=1;
+        for (l=i+1; l < ndims_org ; l++) {
+            tmp *= my_req[myrank].count[l];
+        }
+        buf_offset[myrank] += tmp*diff[i];
+#ifdef SUBFILE_DEBUG
+        if (myrank == 0) printf("local: rank(%d): buf_offset[%d]=%d\n", myrank, myrank, buf_offset[myrank]);
+#endif
+    }
+
+    buf_offset[myrank] *= el_size;
+
+#ifdef SUBFILE_DEBUG
+    printf("rank(%d): buf_offset[%d]=%d, buf_count_my[%d]=%d\n", myrank,
+           myrank, buf_offset[myrank], myrank, buf_count_my[myrank]);
+
+    printf ("rank(%d): %s: var(%s)\n", myrank, __func__, varp->name->cp);
+    for (i=0; i<ndims_org; i++)
+        printf("my_req[%d].start[%d]=%ld, my_req[%d].count[%d]=%ld, my_req[%d].stride[%d]=%ld, bufcount=%ld\n",
+               myrank, i, my_req[myrank].start[i], myrank, i,
+               my_req[myrank].count[i], myrank, i,
+               ((stride != NULL)?stride[i]:1), bufcount);
+#endif
+
+    int *array_of_requests;
+    int *array_of_statuses;
+    /* TODO: each proc can't get more than nprocs-1?? */
+    array_of_requests = (int *)NCI_Malloc((size_t)nprocs * SIZEOF_INT);
+    for (i=0; i<nprocs; i++)
+        array_of_requests[i] = NC_REQ_NULL;
+
+#ifdef SUBFILE_DEBUG
+    printf("buf_count_my[%d]=%d\n", myrank, buf_count_my[myrank]);
+#endif
+    /* doing my portion of I/O */
+    if (count_my_req_per_proc[myrank] != 0) {
+        status = ncmpii_igetput_varm(ncp_sf,
+                                     ncp_sf->vars.value[varid_sf],
+                                     my_req[myrank].start,
+                                     my_req[myrank].count,
+                                     stride,
+                                     NULL,
+                                     (char*)cbuf+buf_offset[myrank],
+                                     buf_count_my[myrank],
+                                     (!buftype_is_contig?ptype:buftype),
+                                     &array_of_requests[nasyncios++],
+                                     rw_flag,
+                                     0, 0);
+        TEST_HANDLE_ERR(status)
+    }
+#ifdef SUBFILE_DEBUG
+    printf("rank(%d): var(%s): pushed local I/O to async calls...\n", myrank, varp->name->cp);
+#endif
+
+    /* doing other proc's request to my subfile
+       TODO: each proc can't get more than nprocs?? */
+    requests = (MPI_Request *)NCI_Malloc((size_t)nprocs*2*sizeof(MPI_Request));
+
+    j = 0;
+#ifdef TAU_SSON
+    TAU_PHASE_CREATE_STATIC(t52, "SSON --- getput_vars: exch count_my_req", "", TAU_USER);
+    TAU_PHASE_START(t52);
+#endif
+    /* TODO: need to exchange count_my_req_per_proc? */
+    count_others_req_per_proc[myrank] = count_my_req_per_proc[myrank];
+
+    for (i=0; i<nprocs; i++)
+        if (count_my_req_per_proc[i] != 0 && i != myrank)
+            TRACE_COMM(MPI_Irecv)(&count_others_req_per_proc[i], 1, MPI_INT, i, i+myrank, ncp->nciop->comm, &requests[j++]);
+
+    for (i=0; i<nprocs; i++)
+        if (count_others_req_per_proc[i] != 0 && i != myrank)
+            TRACE_COMM(MPI_Isend)(&count_my_req_per_proc[i], 1, MPI_INT, i, i+myrank, ncp->nciop->comm, &requests[j++]);
+
+    statuses = (MPI_Status *)NCI_Malloc((size_t)j*sizeof(MPI_Status));
+    TRACE_COMM(MPI_Waitall)(j, requests, statuses);
+#ifdef TAU_SSON
+    TAU_PHASE_STOP(t52);
+#endif
+    check_err(MPI_Waitall);
+    NCI_Free(statuses);
+    NCI_Free(requests);
+
+    j = 0;
+    requests = (MPI_Request *)NCI_Malloc((size_t)nprocs*2*sizeof(MPI_Request));
+
+#ifdef TAU_SSON
+    TAU_PHASE_CREATE_STATIC(t53, "SSON --- getput_vars: exch start,count,", "", TAU_USER);
+    TAU_PHASE_START(t53);
+#endif
+    /* when dest rank == myrank */
+    if (count_others_req_per_proc[myrank] > 0)
+        memcpy(others_req[myrank].start, my_req[myrank].start,
+               (size_t)ndims_org * 3 * SIZEOF_MPI_OFFSET);
+
+    /* exchange my_req's and others_req's start[], count[], and start_org[] */
+    for (i=0; i<nprocs; i++) {
+        if (count_others_req_per_proc[i] != 0 && i != myrank)
+            /* MPI_Offset == MPI_LONG_LONG_INT */
+            TRACE_COMM(MPI_Irecv)(others_req[i].start, 3*ndims_org, MPI_LONG_LONG_INT, i,
+                      i+myrank, ncp->nciop->comm, &requests[j++]);
+    }
+    for (i=0; i<nprocs; i++) {
+        if (count_my_req_per_proc[i] != 0 && i != myrank)
+            TRACE_COMM(MPI_Isend)(my_req[i].start, 3 * ndims_org, MPI_LONG_LONG_INT, i,
+                      i+myrank, ncp->nciop->comm, &requests[j++]);
+    }
+
+    statuses = (MPI_Status *)NCI_Malloc((size_t)j*sizeof(MPI_Status));
+    TRACE_COMM(MPI_Waitall)(j, requests, statuses);
+    NCI_Free(statuses);
+    NCI_Free(requests);
+
+#ifdef TAU_SSON
+    TAU_PHASE_STOP(t53);
+#endif
+    check_err(MPI_Waitall);
+
+#ifdef SUBFILE_DEBUG
+    /* DEBUG: print out others_req.{start,count} */
+    for (i=0; i<nprocs && myrank == 0; i++) {
+        char str_st[100], str_st_org[100], str_ct[100], str_t1[10];
+        sprintf(str_st, "%d: others.start(", i);
+        sprintf(str_ct, "%d: others.count(", i);
+        sprintf(str_st_org, "%d: others.start_org(", i);
+
+        for (j=0; j<ndims_org; j++) {
+            sprintf(str_t1, "%d", others_req[i].start[j]);
+            strcat(str_st, str_t1);
+            sprintf(str_t1, "%d", others_req[i].count[j]);
+            strcat(str_ct, str_t1);
+            sprintf(str_t1, "%d", others_req[i].start_org[j]);
+            strcat(str_st_org, str_t1);
+            if (j != (ndims_org-1)) {
+                strcat(str_st, ",");
+                strcat(str_ct, ",");
+                strcat(str_st_org, ",");
+            }
+
+        }
+        strcat(str_st, ")");
+        strcat(str_ct, ")");
+        strcat(str_st_org, ")");
+        printf("%s\n", str_st);
+        printf("%s\n", str_ct);
+        printf("%s\n", str_st_org);
+    }
+#endif
+
+    j = 0;
+    requests = (MPI_Request *)NCI_Malloc((size_t)nprocs*2*sizeof(MPI_Request));
+
+    xbuf = (void**)NCI_Calloc((size_t)nprocs, sizeof(void *));
+
+#ifdef TAU_SSON
+    TAU_PHASE_CREATE_STATIC(t54, "SSON --- getput_vars: exch buf", "", TAU_USER);
+    TAU_PHASE_START(t54);
+#endif
+
+    for (i=0; i<nprocs; i++) {
+        /* xbuf[i] = NULL; */
+        buf_count_others[i] = 1;
+        if (count_others_req_per_proc[i] != 0 && i != myrank) {
+            for (k=0; k<ndims_org; k++) {
+                buf_count_others[i] *= others_req[i].count[k];
+            }
+#ifdef SUBFILE_DEBUG
+            printf("rank(%d): recv from rank %d: buf_count_others[%d]=%d\n", myrank, i, i, buf_count_others[i]);
+#endif
+            xbuf[i] = (void*)NCI_Calloc((size_t)buf_count_others[i], (size_t)el_size);
+            TRACE_COMM(MPI_Irecv)(xbuf[i], buf_count_others[i], (!buftype_is_contig?ptype:buftype), i, i+myrank, ncp->nciop->comm, &requests[j++]);
+        }
+    }
+
+    for (i=0; i<nprocs; i++) {
+        buf_count_my[i] = 1;
+        if (count_my_req_per_proc[i] != 0 && i != myrank) {
+            MPI_Offset diff[ndims_org];
+            for (k=0; k < ndims_org; k++) {
+                int l;
+                MPI_Offset stride_count, tmp=1;
+
+                stride_count = (stride == NULL?1:stride[k]);
+                diff[k] = ABS(my_req[i].start_org[k]-start[k])/stride_count;
+
+                for (l=k+1; l < ndims_org; l++)
+                    tmp *= my_req[i].count[l];
+
+                buf_offset[i] += tmp*diff[k];
+#ifdef SUBFILE_DEBUG
+                if (myrank == 0) printf("rank(%d): subfile(%d): diff[%d]=%d\n", myrank, i, k, diff[k]);
+#endif
+            }
+
+            buf_offset[i] *= el_size;
+
+            for (k=0; k<ndims_org; k++) {
+                buf_count_my[i] *= my_req[i].count[k];
+            }
+#ifdef SUBFILE_DEBUG
+            printf("rank(%d): send to rank %d: buf_offset[%d]=%d, buf_count_my[%d]=%d\n", myrank, i, i, buf_offset[i], i, buf_count_my[i]);
+#endif
+
+            TRACE_COMM(MPI_Isend)((char*)cbuf+buf_offset[i], buf_count_my[i], (!buftype_is_contig?ptype:buftype), i, i+myrank, ncp->nciop->comm, &requests[j++]);
+        } /* end if() */
+    } /* end for() */
+
+    statuses = (MPI_Status *)NCI_Malloc((size_t)j * sizeof(MPI_Status));
+    TRACE_COMM(MPI_Waitall)(j, requests, statuses);
+    NCI_Free(statuses);
+    NCI_Free(requests);
+
+#ifdef TAU_SSON
+    TAU_PHASE_STOP(t54);
+#endif
+    check_err(MPI_Waitall);
+
+#ifdef TAU_SSON
+    TAU_PHASE_CREATE_STATIC(t55, "SSON --- getput_vars igetput", "", TAU_USER);
+    TAU_PHASE_START(t55);
+#endif
+
+    for (i=0; i<nprocs; i++) {
+        if (count_others_req_per_proc[i] != 0 && i != myrank) {
+            status = ncmpii_igetput_varm(ncp_sf,
+                                         ncp_sf->vars.value[varid_sf],
+                                         others_req[i].start,
+                                         others_req[i].count,
+                                         stride,
+                                         NULL,
+                                         xbuf[i],
+                                         buf_count_others[i],
+                                         (!buftype_is_contig?ptype:buftype),
+                                         &array_of_requests[nasyncios++],
+                                         rw_flag,
+                                         0, 0);
+            TEST_HANDLE_ERR(status)
+        }
+    }
+#ifdef TAU_SSON
+    TAU_PHASE_STOP(t55);
+#endif
+
+#ifdef SUBFILE_DEBUG
+    printf("rank(%d): nasyncios=%d\n", myrank, nasyncios);
+#endif
+
+#ifdef TAU_SSON
+    TAU_PHASE_CREATE_STATIC(t56, "SSON --- getput_vars ncmpi_wait_all", "", TAU_USER);
+    TAU_PHASE_START(t56);
+#endif
+    /*
+    double stime, wait_time;
+    stime = MPI_Wtime();
+    */
+    array_of_statuses = (int *)NCI_Malloc((size_t)nasyncios * SIZEOF_INT);
+    status = ncmpii_wait(ncp_sf, COLL_IO, nasyncios, array_of_requests, array_of_statuses);
+    TEST_HANDLE_ERR(status)
+    NCI_Free(array_of_statuses);
+    NCI_Free(array_of_requests);
+
+    /*
+    int pending_nreqs;
+    status = ncmpi_inq_nreqs(ncp->nciop->fd, &pending_nreqs);
+    printf("myrank(%d): pending_nreqs=%d\n", myrank, pending_nreqs);
+    wait_time = MPI_Wtime() - stime;
+    printf("myrank(%d): ncmpii_wait time = %f\n", myrank, wait_time);
+    */
+#ifdef TAU_SSON
+    TAU_PHASE_STOP(t56);
+#endif
+
+#ifdef SUBFILE_DEBUG
+    printf("rank(%d): var(%s): after ncmpi_wait_all()\n", myrank, varp->name->cp);
+#endif
+
+    /* MPI_Barrier(ncp->nciop->comm); */
+
+    /* free all allocated memories */
+
+    for(i=0; i<nprocs; i++)
+        if (xbuf[i] != NULL) NCI_Free(xbuf[i]);
+    NCI_Free(xbuf);
+
+    if (cbuf != NULL && cbuf != buf) {
+        NCI_Free(cbuf);
+    }
+
+    NCI_Free(count_my_req_per_proc);
+    NCI_Free(count_others_req_per_proc);
+    NCI_Free(buf_count_my);
+    NCI_Free(buf_count_others);
+
+    for (i=0; i<nprocs; i++) {
+        NCI_Free(my_req[i].start);
+        NCI_Free(others_req[i].start);
+    }
+    NCI_Free(my_req);
+    NCI_Free(others_req);
+
+    return status;
+}
diff --git a/src/lib/subfile.h b/src/lib/subfile.h
new file mode 100644
index 0000000..7e209ef
--- /dev/null
+++ b/src/lib/subfile.h
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: subfile.h 2021 2015-04-09 20:29:40Z wkliao $ */
+#ifndef SUBFILE_H
+#define SUBFILE_H
+
+#include "pnetcdf.h"
+#include "nc.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "macro.h"
+
+/* structure for storing access info of this process's request
+   to the subfiles on all other processes, and vice-versa. used
+   as array of structures indexed by subfile index. */
+typedef struct {
+    MPI_Offset *start;
+    MPI_Offset *count;
+    MPI_Offset *start_org;
+} NC_subfile_access;
+
+#define CEIL(x) ( (x - (int)x)==0 ? (int)x : (int)x+1 )
+#define FLOOR(x) ( (x - (int)x)==0 ? (int)x : (int)x-1 )
+#define ROUND(x) ( x >= 0 ? (int)(x+0.5) : (int)(x-0.5) )
+#define ABS(a) (((a) < 0) ? -(a) : (a))
+
+#define TEST_HANDLE_ERR(status)                                        \
+    if ((status) != NC_NOERR) {                                        \
+        printf("Error at file %s line %d (%s)\n", __FILE__, __LINE__,  \
+               ncmpi_strerror((status)) );                             \
+        return status;                                                 \
+    }
+
+extern int ncmpii_subfile_create(NC *ncp, int *ncidp);
+
+extern int ncmpii_subfile_open(NC *ncp, int *ncidp);
+
+extern int ncmpii_subfile_close(NC *ncp);
+
+extern int ncmpii_subfile_partition(NC *ncp, int *ncidp);
+
+extern int ncmpii_subfile_getput_vars(NC *ncp, NC_var *varp, const MPI_Offset start[],
+                               const MPI_Offset count[], const MPI_Offset  stride[],
+                               void *buf, MPI_Offset bufcount,
+                               MPI_Datatype buftype, int rw_flag, int io_method);
+
+#endif /* end of SUBFILE_H */
diff --git a/src/lib/utf8proc.c b/src/lib/utf8proc.c
new file mode 100644
index 0000000..756a10b
--- /dev/null
+++ b/src/lib/utf8proc.c
@@ -0,0 +1,600 @@
+/*
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: utf8proc.c 2220 2015-12-11 23:07:44Z wkliao $ */
+
+/*
+ *  Copyright (c) 2006-2007 Jan Behrens, FlexiGuided GmbH, Berlin
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a
+ *  copy of this software and associated documentation files (the "Software"),
+ *  to deal in the Software without restriction, including without limitation
+ *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ *  and/or sell copies of the Software, and to permit persons to whom the
+ *  Software is furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in
+ *  all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *  DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ *  This library contains derived data from a modified version of the
+ *  Unicode data files.
+ *
+ *  The original data files are available at
+ *  http://www.unicode.org/Public/UNIDATA/
+ *
+ *  Please notice the copyright statement in the file "utf8proc_data.c".
+ */
+
+
+/*
+ *  File name:    utf8proc.c
+ *  Version:      1.1.1
+ *  Last changed: 2007-07-22
+ *
+ *  Description:
+ *  Implementation of libutf8proc.
+ */
+
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include "utf8proc.h"
+#include "utf8proc_data.h"
+
+const int8_t utf8proc_utf8class[256] = {
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+  4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+#define UTF8PROC_HANGUL_SBASE 0xAC00
+#define UTF8PROC_HANGUL_LBASE 0x1100
+#define UTF8PROC_HANGUL_VBASE 0x1161
+#define UTF8PROC_HANGUL_TBASE 0x11A7
+#define UTF8PROC_HANGUL_LCOUNT 19
+#define UTF8PROC_HANGUL_VCOUNT 21
+#define UTF8PROC_HANGUL_TCOUNT 28
+#define UTF8PROC_HANGUL_NCOUNT 588
+#define UTF8PROC_HANGUL_SCOUNT 11172
+/*// END is exclusive*/
+#define UTF8PROC_HANGUL_L_START  0x1100
+#define UTF8PROC_HANGUL_L_END    0x115A
+#define UTF8PROC_HANGUL_L_FILLER 0x115F
+#define UTF8PROC_HANGUL_V_START  0x1160
+#define UTF8PROC_HANGUL_V_END    0x11A3
+#define UTF8PROC_HANGUL_T_START  0x11A8
+#define UTF8PROC_HANGUL_T_END    0x11FA
+#define UTF8PROC_HANGUL_S_START  0xAC00
+#define UTF8PROC_HANGUL_S_END    0xD7A4
+
+
+#define UTF8PROC_BOUNDCLASS_START    0
+#define UTF8PROC_BOUNDCLASS_OTHER    1
+#define UTF8PROC_BOUNDCLASS_CR       2
+#define UTF8PROC_BOUNDCLASS_LF       3
+#define UTF8PROC_BOUNDCLASS_CONTROL  4
+#define UTF8PROC_BOUNDCLASS_EXTEND   5
+#define UTF8PROC_BOUNDCLASS_L        6
+#define UTF8PROC_BOUNDCLASS_V        7
+#define UTF8PROC_BOUNDCLASS_T        8
+#define UTF8PROC_BOUNDCLASS_LV       9
+#define UTF8PROC_BOUNDCLASS_LVT     10
+
+
+const char *utf8proc_errmsg(ssize_t errcode) {
+  switch (errcode) {
+    case UTF8PROC_ERROR_NOMEM:
+    return "Memory for processing UTF-8 data could not be allocated.";
+    case UTF8PROC_ERROR_OVERFLOW:
+    return "UTF-8 string is too long to be processed.";
+    case UTF8PROC_ERROR_INVALIDUTF8:
+    return "Invalid UTF-8 string";
+    case UTF8PROC_ERROR_NOTASSIGNED:
+    return "Unassigned Unicode code point found in UTF-8 string.";
+    case UTF8PROC_ERROR_INVALIDOPTS:
+    return "Invalid options for UTF-8 processing chosen.";
+    default:
+    return "An unknown error occurred while processing UTF-8 data.";
+  }
+}
+
+ssize_t utf8proc_iterate(
+  const uint8_t *str, ssize_t slen, int32_t *dst
+) {
+  int length;
+  int i;
+  int32_t uc = -1;
+  *dst = -1;
+  if (!slen) return 0;
+  length = utf8proc_utf8class[str[0]];
+  if (!length) return UTF8PROC_ERROR_INVALIDUTF8;
+  if (slen >= 0 && length > slen) return UTF8PROC_ERROR_INVALIDUTF8;
+  for (i=1; i<length; i++) {
+    if ((str[i] & 0xC0) != 0x80) return UTF8PROC_ERROR_INVALIDUTF8;
+  }
+  switch (length) {
+    case 1:
+    uc = str[0];
+    break;
+    case 2:
+    uc = ((str[0] & 0x1F) <<  6) + (str[1] & 0x3F);
+    if (uc < 0x80) uc = -1;
+    break;
+    case 3:
+    uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) <<  6)
+      + (str[2] & 0x3F);
+    if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000) ||
+      (uc >= 0xFDD0 && uc < 0xFDF0)) uc = -1;
+    break;
+    case 4:
+    uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12)
+      + ((str[2] & 0x3F) <<  6) + (str[3] & 0x3F);
+    if (uc < 0x10000 || uc >= 0x110000) uc = -1;
+    break;
+  }
+  if (uc < 0 || ((uc & 0xFFFF) >= 0xFFFE))
+    return UTF8PROC_ERROR_INVALIDUTF8;
+  *dst = uc;
+  return length;
+}
+
+bool utf8proc_codepoint_valid(int32_t uc) {
+  if (uc < 0 || uc >= 0x110000 ||
+    ((uc & 0xFFFF) >= 0xFFFE) || (uc >= 0xD800 && uc < 0xE000) ||
+    (uc >= 0xFDD0 && uc < 0xFDF0)) return false;
+  else return true;
+}
+
+ssize_t utf8proc_encode_char(int32_t uc, uint8_t *dst) {
+  if (uc < 0x00) {
+    return 0;
+  } else if (uc < 0x80) {
+    dst[0] = (uint8_t)uc;
+    return 1;
+  } else if (uc < 0x800) {
+    dst[0] = (uint8_t)(0xC0 + (uc >> 6));
+    dst[1] = (uint8_t)(0x80 + (uc & 0x3F));
+    return 2;
+  } else if (uc == 0xFFFF) {
+    dst[0] = 0xFF;
+    return 1;
+  } else if (uc == 0xFFFE) {
+    dst[0] = 0xFE;
+    return 1;
+  } else if (uc < 0x10000) {
+    dst[0] = (uint8_t)(0xE0 + (uc >> 12));
+    dst[1] = (uint8_t)(0x80 + ((uc >> 6) & 0x3F));
+    dst[2] = (uint8_t)(0x80 + (uc & 0x3F));
+    return 3;
+  } else if (uc < 0x110000) {
+    dst[0] = (uint8_t)(0xF0 + (uc >> 18));
+    dst[1] = (uint8_t)(0x80 + ((uc >> 12) & 0x3F));
+    dst[2] = (uint8_t)(0x80 + ((uc >> 6) & 0x3F));
+    dst[3] = (uint8_t)(0x80 + (uc & 0x3F));
+    return 4;
+  } else return 0;
+}
+
+const utf8proc_property_t *utf8proc_get_property(int32_t uc) {
+  /*  // ASSERT: uc >= 0 && uc < 0x110000*/
+  return utf8proc_properties + (
+    utf8proc_stage2table[
+      utf8proc_stage1table[uc >> 8] + (uc & 0xFF)
+    ]
+  );
+}
+
+#define utf8proc_decompose_lump(replacement_uc) \
+  return utf8proc_decompose_char((replacement_uc), dst, bufsize, \
+  options & ~UTF8PROC_LUMP, last_boundclass)
+
+ssize_t utf8proc_decompose_char(int32_t uc, int32_t *dst, ssize_t bufsize,
+    int options, int *last_boundclass) {
+  /*// ASSERT: uc >= 0 && uc < 0x110000*/
+  const utf8proc_property_t *property;
+  utf8proc_propval_t category;
+  int32_t hangul_sindex;
+  property = utf8proc_get_property(uc);
+  category = property->category;
+  hangul_sindex = uc - UTF8PROC_HANGUL_SBASE;
+  if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) {
+    if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT) {
+      int32_t hangul_tindex;
+      if (bufsize >= 1) {
+        dst[0] = UTF8PROC_HANGUL_LBASE +
+          hangul_sindex / UTF8PROC_HANGUL_NCOUNT;
+        if (bufsize >= 2) dst[1] = UTF8PROC_HANGUL_VBASE +
+          (hangul_sindex % UTF8PROC_HANGUL_NCOUNT) / UTF8PROC_HANGUL_TCOUNT;
+      }
+      hangul_tindex = hangul_sindex % UTF8PROC_HANGUL_TCOUNT;
+      if (!hangul_tindex) return 2;
+      if (bufsize >= 3) dst[2] = UTF8PROC_HANGUL_TBASE + hangul_tindex;
+      return 3;
+    }
+  }
+  if (options & UTF8PROC_REJECTNA) {
+    if (!category) return UTF8PROC_ERROR_NOTASSIGNED;
+  }
+  if (options & UTF8PROC_IGNORE) {
+    if (property->ignorable) return 0;
+  }
+  if (options & UTF8PROC_LUMP) {
+    if (category == UTF8PROC_CATEGORY_ZS) utf8proc_decompose_lump(0x0020);
+    if (uc == 0x2018 || uc == 0x2019 || uc == 0x02BC || uc == 0x02C8)
+      utf8proc_decompose_lump(0x0027);
+    if (category == UTF8PROC_CATEGORY_PD || uc == 0x2212)
+      utf8proc_decompose_lump(0x002D);
+    if (uc == 0x2044 || uc == 0x2215) utf8proc_decompose_lump(0x002F);
+    if (uc == 0x2236) utf8proc_decompose_lump(0x003A);
+    if (uc == 0x2039 || uc == 0x2329 || uc == 0x3008)
+      utf8proc_decompose_lump(0x003C);
+    if (uc == 0x203A || uc == 0x232A || uc == 0x3009)
+      utf8proc_decompose_lump(0x003E);
+    if (uc == 0x2216) utf8proc_decompose_lump(0x005C);
+    if (uc == 0x02C4 || uc == 0x02C6 || uc == 0x2038 || uc == 0x2303)
+      utf8proc_decompose_lump(0x005E);
+    if (category == UTF8PROC_CATEGORY_PC || uc == 0x02CD)
+      utf8proc_decompose_lump(0x005F);
+    if (uc == 0x02CB) utf8proc_decompose_lump(0x0060);
+    if (uc == 0x2223) utf8proc_decompose_lump(0x007C);
+    if (uc == 0x223C) utf8proc_decompose_lump(0x007E);
+    if ((options & UTF8PROC_NLF2LS) && (options & UTF8PROC_NLF2PS)) {
+      if (category == UTF8PROC_CATEGORY_ZL ||
+          category == UTF8PROC_CATEGORY_ZP)
+        utf8proc_decompose_lump(0x000A);
+    }
+  }
+  if (options & UTF8PROC_STRIPMARK) {
+    if (category == UTF8PROC_CATEGORY_MN ||
+      category == UTF8PROC_CATEGORY_MC ||
+      category == UTF8PROC_CATEGORY_ME) return 0;
+  }
+  if (options & UTF8PROC_CASEFOLD) {
+    if (property->casefold_mapping) {
+      const int32_t *casefold_entry;
+      ssize_t written = 0;
+      for (casefold_entry = property->casefold_mapping;
+          *casefold_entry >= 0; casefold_entry++) {
+        written += utf8proc_decompose_char(*casefold_entry, dst+written,
+          (bufsize > written) ? (bufsize - written) : 0, options,
+          last_boundclass);
+        if (written < 0) return UTF8PROC_ERROR_OVERFLOW;
+      }
+      return written;
+    }
+  }
+  if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) {
+    if (property->decomp_mapping &&
+        (!property->decomp_type || (options & UTF8PROC_COMPAT))) {
+      const int32_t *decomp_entry;
+      ssize_t written = 0;
+      for (decomp_entry = property->decomp_mapping;
+          *decomp_entry >= 0; decomp_entry++) {
+        written += utf8proc_decompose_char(*decomp_entry, dst+written,
+          (bufsize > written) ? (bufsize - written) : 0, options,
+        last_boundclass);
+        if (written < 0) return UTF8PROC_ERROR_OVERFLOW;
+      }
+      return written;
+    }
+  }
+  if (options & UTF8PROC_CHARBOUND) {
+    bool boundary;
+    int tbc, lbc;
+    tbc =
+      (uc == 0x000D) ? UTF8PROC_BOUNDCLASS_CR :
+      (uc == 0x000A) ? UTF8PROC_BOUNDCLASS_LF :
+      ((category == UTF8PROC_CATEGORY_ZL ||
+        category == UTF8PROC_CATEGORY_ZP ||
+        category == UTF8PROC_CATEGORY_CC ||
+        category == UTF8PROC_CATEGORY_CF) &&
+        !(uc == 0x200C || uc == 0x200D)) ? UTF8PROC_BOUNDCLASS_CONTROL :
+      property->extend ? UTF8PROC_BOUNDCLASS_EXTEND :
+      ((uc >= UTF8PROC_HANGUL_L_START && uc < UTF8PROC_HANGUL_L_END) ||
+        uc == UTF8PROC_HANGUL_L_FILLER) ? UTF8PROC_BOUNDCLASS_L :
+      (uc >= UTF8PROC_HANGUL_V_START && uc < UTF8PROC_HANGUL_V_END) ?
+        UTF8PROC_BOUNDCLASS_V :
+      (uc >= UTF8PROC_HANGUL_T_START && uc < UTF8PROC_HANGUL_T_END) ?
+        UTF8PROC_BOUNDCLASS_T :
+      (uc >= UTF8PROC_HANGUL_S_START && uc < UTF8PROC_HANGUL_S_END) ? (
+        ((uc-UTF8PROC_HANGUL_SBASE) % UTF8PROC_HANGUL_TCOUNT == 0) ?
+          UTF8PROC_BOUNDCLASS_LV : UTF8PROC_BOUNDCLASS_LVT
+      ) :
+      UTF8PROC_BOUNDCLASS_OTHER;
+    lbc = *last_boundclass;
+    boundary =
+      (tbc == UTF8PROC_BOUNDCLASS_EXTEND) ? false :
+      (lbc == UTF8PROC_BOUNDCLASS_START) ? true :
+      (lbc == UTF8PROC_BOUNDCLASS_CR &&
+       tbc == UTF8PROC_BOUNDCLASS_LF) ? false :
+      (lbc == UTF8PROC_BOUNDCLASS_CONTROL) ? true :
+      (tbc == UTF8PROC_BOUNDCLASS_CONTROL) ? true :
+      (lbc == UTF8PROC_BOUNDCLASS_L &&
+       (tbc == UTF8PROC_BOUNDCLASS_L ||
+        tbc == UTF8PROC_BOUNDCLASS_V ||
+        tbc == UTF8PROC_BOUNDCLASS_LV ||
+        tbc == UTF8PROC_BOUNDCLASS_LVT)) ? false :
+      ((lbc == UTF8PROC_BOUNDCLASS_LV ||
+        lbc == UTF8PROC_BOUNDCLASS_V) &&
+       (tbc == UTF8PROC_BOUNDCLASS_V ||
+        tbc == UTF8PROC_BOUNDCLASS_T)) ? false :
+      ((lbc == UTF8PROC_BOUNDCLASS_LVT ||
+        lbc == UTF8PROC_BOUNDCLASS_T) &&
+       tbc == UTF8PROC_BOUNDCLASS_T) ? false :
+       true;
+    *last_boundclass = tbc;
+    if (boundary) {
+      if (bufsize >= 1) dst[0] = 0xFFFF;
+      if (bufsize >= 2) dst[1] = uc;
+      return 2;
+    }
+  }
+  if (bufsize >= 1) *dst = uc;
+  return 1;
+}
+
+ssize_t utf8proc_decompose(
+  const uint8_t *str, ssize_t slen,
+  int32_t *buffer, ssize_t bufsize, int options
+) {
+  /*// slen will be ignored, if UTF8PROC_NULLTERM is set in options*/
+  ssize_t wpos = 0;
+  if ((options & UTF8PROC_COMPOSE) && (options & UTF8PROC_DECOMPOSE))
+    return UTF8PROC_ERROR_INVALIDOPTS;
+  if ((options & UTF8PROC_STRIPMARK) &&
+      !(options & UTF8PROC_COMPOSE) && !(options & UTF8PROC_DECOMPOSE))
+    return UTF8PROC_ERROR_INVALIDOPTS;
+  {
+    int32_t uc;
+    ssize_t rpos = 0;
+    ssize_t decomp_result;
+    int boundclass = UTF8PROC_BOUNDCLASS_START;
+    while (1) {
+      if (options & UTF8PROC_NULLTERM) {
+        rpos += utf8proc_iterate(str + rpos, -1, &uc);
+        /* checking of return value is not necessary,
+	   as 'uc' is < 0 in case of error. */
+        if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8;
+        if (rpos < 0) return UTF8PROC_ERROR_OVERFLOW;
+        if (uc == 0) break;
+      } else {
+        if (rpos >= slen) break;
+        rpos += utf8proc_iterate(str + rpos, slen - rpos, &uc);
+        if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8;
+      }
+      decomp_result = utf8proc_decompose_char(
+        uc, buffer + wpos, (bufsize > wpos) ? (bufsize - wpos) : 0, options,
+        &boundclass
+      );
+      if (decomp_result < 0) return decomp_result;
+      wpos += decomp_result;
+      /*      // prohibiting integer overflows due to too long strings:*/
+      if (wpos < 0 || wpos > SSIZE_MAX/sizeof(int32_t)/2)
+        return UTF8PROC_ERROR_OVERFLOW;
+    }
+  }
+  if ((options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) && bufsize >= wpos) {
+    ssize_t pos = 0;
+    while (pos < wpos-1) {
+      int32_t uc1, uc2;
+      const utf8proc_property_t *property1, *property2;
+      uc1 = buffer[pos];
+      uc2 = buffer[pos+1];
+      property1 = utf8proc_get_property(uc1);
+      property2 = utf8proc_get_property(uc2);
+      if (property1->combining_class > property2->combining_class &&
+          property2->combining_class > 0) {
+        buffer[pos] = uc2;
+        buffer[pos+1] = uc1;
+        if (pos > 0) pos--; else pos++;
+      } else {
+        pos++;
+      }
+    }
+  }
+  return wpos;
+}
+
+ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options) {
+  /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored
+     ASSERT: 'buffer' has one spare byte of free space at the end! */
+  if (options & (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS | UTF8PROC_STRIPCC)) {
+    ssize_t rpos;
+    ssize_t wpos = 0;
+    int32_t uc;
+    for (rpos = 0; rpos < length; rpos++) {
+      uc = buffer[rpos];
+      if (uc == 0x000D && rpos < length-1 && buffer[rpos+1] == 0x000A) rpos++;
+      if (uc == 0x000A || uc == 0x000D || uc == 0x0085 ||
+          ((options & UTF8PROC_STRIPCC) && (uc == 0x000B || uc == 0x000C))) {
+        if (options & UTF8PROC_NLF2LS) {
+          if (options & UTF8PROC_NLF2PS) {
+            buffer[wpos++] = 0x000A;
+          } else {
+            buffer[wpos++] = 0x2028;
+          }
+        } else {
+          if (options & UTF8PROC_NLF2PS) {
+            buffer[wpos++] = 0x2029;
+          } else {
+            buffer[wpos++] = 0x0020;
+          }
+        }
+      } else if ((options & UTF8PROC_STRIPCC) &&
+          (uc < 0x0020 || (uc >= 0x007F && uc < 0x00A0))) {
+        if (uc == 0x0009) buffer[wpos++] = 0x0020;
+      } else {
+        buffer[wpos++] = uc;
+      }
+    }
+    length = wpos;
+  }
+  if (options & UTF8PROC_COMPOSE) {
+    int32_t *starter = NULL;
+    int32_t current_char;
+    const utf8proc_property_t *starter_property = NULL, *current_property;
+    utf8proc_propval_t max_combining_class = -1;
+    ssize_t rpos;
+    ssize_t wpos = 0;
+    int32_t composition;
+    for (rpos = 0; rpos < length; rpos++) {
+      current_char = buffer[rpos];
+      current_property = utf8proc_get_property(current_char);
+      if (starter && current_property->combining_class > max_combining_class) {
+	/*        // combination perhaps possible*/
+        int32_t hangul_lindex;
+        int32_t hangul_sindex;
+        hangul_lindex = *starter - UTF8PROC_HANGUL_LBASE;
+        if (hangul_lindex >= 0 && hangul_lindex < UTF8PROC_HANGUL_LCOUNT) {
+          int32_t hangul_vindex;
+          hangul_vindex = current_char - UTF8PROC_HANGUL_VBASE;
+          if (hangul_vindex >= 0 && hangul_vindex < UTF8PROC_HANGUL_VCOUNT) {
+            *starter = UTF8PROC_HANGUL_SBASE +
+              (hangul_lindex * UTF8PROC_HANGUL_VCOUNT + hangul_vindex) *
+              UTF8PROC_HANGUL_TCOUNT;
+            starter_property = NULL;
+            continue;
+          }
+        }
+        hangul_sindex = *starter - UTF8PROC_HANGUL_SBASE;
+        if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT &&
+            (hangul_sindex % UTF8PROC_HANGUL_TCOUNT) == 0) {
+          int32_t hangul_tindex;
+          hangul_tindex = current_char - UTF8PROC_HANGUL_TBASE;
+          if (hangul_tindex >= 0 && hangul_tindex < UTF8PROC_HANGUL_TCOUNT) {
+            *starter += hangul_tindex;
+            starter_property = NULL;
+            continue;
+          }
+        }
+        if (!starter_property) {
+          starter_property = utf8proc_get_property(*starter);
+        }
+        if (starter_property->comb1st_index >= 0 &&
+            current_property->comb2nd_index >= 0) {
+          composition = utf8proc_combinations[
+            starter_property->comb1st_index +
+            current_property->comb2nd_index
+          ];
+          if (composition >= 0 && (!(options & UTF8PROC_STABLE) ||
+              !(utf8proc_get_property(composition)->comp_exclusion))) {
+            *starter = composition;
+            starter_property = NULL;
+            continue;
+          }
+        }
+      }
+      buffer[wpos] = current_char;
+      if (current_property->combining_class) {
+        if (current_property->combining_class > max_combining_class) {
+          max_combining_class = current_property->combining_class;
+        }
+      } else {
+        starter = buffer + wpos;
+        starter_property = NULL;
+        max_combining_class = -1;
+      }
+      wpos++;
+    }
+    length = wpos;
+  }
+  {
+    ssize_t rpos, wpos = 0;
+    int32_t uc;
+    for (rpos = 0; rpos < length; rpos++) {
+      uc = buffer[rpos];
+      wpos += utf8proc_encode_char(uc, ((uint8_t *)buffer) + wpos);
+    }
+    ((uint8_t *)buffer)[wpos] = 0;
+    return wpos;
+  }
+}
+
+ssize_t utf8proc_map(
+  const uint8_t *str, ssize_t slen, uint8_t **dstptr, int options
+) {
+  int32_t *buffer;
+  ssize_t result;
+  *dstptr = NULL;
+  result = utf8proc_decompose(str, slen, NULL, 0, options);
+  if (result < 0) return result;
+  buffer = (int32_t*)malloc(((size_t)result) * sizeof(int32_t) + 1);
+  if (!buffer) return UTF8PROC_ERROR_NOMEM;
+  result = utf8proc_decompose(str, slen, buffer, result, options);
+  if (result < 0) {
+    free(buffer);
+    return result;
+  }
+  result = utf8proc_reencode(buffer, result, options);
+  if (result < 0) {
+    free(buffer);
+    return result;
+  }
+  {
+    int32_t *newptr;
+    newptr = (int32_t*) realloc(buffer, (size_t)result+1);
+    if (newptr) buffer = newptr;
+  }
+  *dstptr = (uint8_t *)buffer;
+  return result;
+}
+
+uint8_t *utf8proc_NFD(const uint8_t *str) {
+  uint8_t *retval;
+  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
+    UTF8PROC_DECOMPOSE);
+  return retval;
+}
+
+uint8_t *utf8proc_NFC(const uint8_t *str) {
+  uint8_t *retval;
+  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
+    UTF8PROC_COMPOSE);
+  return retval;
+}
+
+uint8_t *utf8proc_NFKD(const uint8_t *str) {
+  uint8_t *retval;
+  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
+    UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT);
+  return retval;
+}
+
+uint8_t *utf8proc_NFKC(const uint8_t *str) {
+  uint8_t *retval;
+  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
+    UTF8PROC_COMPOSE | UTF8PROC_COMPAT);
+  return retval;
+}
+
+ssize_t utf8proc_check(const uint8_t *str) {
+  ssize_t result;
+  result = utf8proc_decompose(str, 0, NULL, 0,
+			      UTF8PROC_NULLTERM | UTF8PROC_STABLE);
+  return result;
+}
diff --git a/src/lib/utf8proc.h b/src/lib/utf8proc.h
new file mode 100644
index 0000000..41ae4ec
--- /dev/null
+++ b/src/lib/utf8proc.h
@@ -0,0 +1,407 @@
+/*
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: utf8proc.h 2220 2015-12-11 23:07:44Z wkliao $ */
+
+/*
+ *  Copyright (c) 2006-2007 Jan Behrens, FlexiGuided GmbH, Berlin
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a
+ *  copy of this software and associated documentation files (the "Software"),
+ *  to deal in the Software without restriction, including without limitation
+ *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ *  and/or sell copies of the Software, and to permit persons to whom the
+ *  Software is furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in
+ *  all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *  DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ *  File name:    utf8proc.h
+ *  Version:      1.1.1
+ *  Last changed: 2007-07-22
+ *  Changed 2008-05-16 by rkr to add config.h and replacement for stdbool.h
+ *                            for pre-C99 compilers that don't support bool.
+ *  Changed 2008-06-05 by rkr to add utf8proc_check(str, options) function for
+ *                            for just checking UTF-8 validity
+ *  Description:
+ *  Header files for libutf8proc, which is a mapping tool for UTF-8 strings
+ *  with following features:
+ *  - decomposing and composing of strings
+ *  - replacing compatibility characters with their equivalents
+ *  - stripping of "default ignorable characters"
+ *    like SOFT-HYPHEN or ZERO-WIDTH-SPACE
+ *  - folding of certain characters for string comparison
+ *    (e.g. HYPHEN U+2010 and MINUS U+2212 to ASCII "-")
+ *    (see "LUMP" option)
+ *  - optional rejection of strings containing non-assigned code points
+ *  - stripping of control characters
+ *  - stripping of character marks (accents, etc.)
+ *  - transformation of LF, CRLF, CR and NEL to line-feed (LF)
+ *    or to the unicode chararacters for paragraph separation (PS)
+ *    or line separation (LS).
+ *  - unicode case folding (for case insensitive string comparisons)
+ *  - rejection of illegal UTF-8 data
+ *    (i.e. UTF-8 encoded UTF-16 surrogates)
+ *  - support for korean hangul characters
+ *  Unicode Version 5.0.0 is supported.
+ */
+
+
+#ifndef UTF8PROC_H
+#define UTF8PROC_H
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+#include <stdbool.h>
+#else
+# if ! HAVE__BOOL
+#  ifdef __cplusplus
+typedef bool _Bool;
+#  else
+typedef unsigned char _Bool;
+#  endif
+# endif
+#ifndef _Bool
+# define bool _Bool
+#endif
+# define false 0
+# define true 1
+# define __bool_true_false_are_defined 1
+#endif
+#include <sys/types.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#elif defined(_MSC_VER) && defined(HAVE_STDINT_H)
+#include <stdint.h>
+#else /* HAVE_INTTYPES_H */
+#include <pstdint.h>
+#endif /* HAVE_INTTYPES_H */
+#include <limits.h>
+
+#ifndef HAVE_SSIZE_T
+#define ssize_t int
+#endif
+
+#ifndef SSIZE_MAX
+#define SSIZE_MAX (SIZE_MAX/2)
+#endif
+
+#define UTF8PROC_NULLTERM  (1<<0)
+#define UTF8PROC_STABLE    (1<<1)
+#define UTF8PROC_COMPAT    (1<<2)
+#define UTF8PROC_COMPOSE   (1<<3)
+#define UTF8PROC_DECOMPOSE (1<<4)
+#define UTF8PROC_IGNORE    (1<<5)
+#define UTF8PROC_REJECTNA  (1<<6)
+#define UTF8PROC_NLF2LS    (1<<7)
+#define UTF8PROC_NLF2PS    (1<<8)
+#define UTF8PROC_NLF2LF    (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS)
+#define UTF8PROC_STRIPCC   (1<<9)
+#define UTF8PROC_CASEFOLD  (1<<10)
+#define UTF8PROC_CHARBOUND (1<<11)
+#define UTF8PROC_LUMP      (1<<12)
+#define UTF8PROC_STRIPMARK (1<<13)
+/*
+ *  Flags being regarded by several functions in the library:
+ *  NULLTERM:  The given UTF-8 input is NULL terminated.
+ *  STABLE:    Unicode Versioning Stability has to be respected.
+ *  COMPAT:    Compatibility decomposition
+ *             (i.e. formatting information is lost)
+ *  COMPOSE:   Return a result with composed characters.
+ *  DECOMPOSE: Return a result with decomposed characters.
+ *  IGNORE:    Strip "default ignorable characters"
+ *  REJECTNA:  Return an error, if the input contains unassigned
+ *             code points.
+ *  NLF2LS:    Indicating that NLF-sequences (LF, CRLF, CR, NEL) are
+ *             representing a line break, and should be converted to the
+ *             unicode character for line separation (LS).
+ *  NLF2PS:    Indicating that NLF-sequences are representing a paragraph
+ *             break, and should be converted to the unicode character for
+ *             paragraph separation (PS).
+ *  NLF2LF:    Indicating that the meaning of NLF-sequences is unknown.
+ *  STRIPCC:   Strips and/or convers control characters.
+ *             NLF-sequences are transformed into space, except if one of
+ *             the NLF2LS/PS/LF options is given.
+ *             HorizontalTab (HT) and FormFeed (FF) are treated as a
+ *             NLF-sequence in this case.
+ *             All other control characters are simply removed.
+ *  CASEFOLD:  Performs unicode case folding, to be able to do a
+ *             case-insensitive string comparison.
+ *  CHARBOUND: Inserts 0xFF bytes at the beginning of each sequence which
+ *             is representing a single grapheme cluster (see UAX#29).
+ *  LUMP:      Lumps certain characters together
+ *             (e.g. HYPHEN U+2010 and MINUS U+2212 to ASCII "-").
+ *             (See lump.txt for details.)
+ *             If NLF2LF is set, this includes a transformation of
+ *             paragraph and line separators to ASCII line-feed (LF).
+ *  STRIPMARK: Strips all character markings
+ *             (non-spacing, spacing and enclosing) (i.e. accents)
+ *             NOTE: this option works only with COMPOSE or DECOMPOSE
+ */
+
+#define UTF8PROC_ERROR_NOMEM -1
+#define UTF8PROC_ERROR_OVERFLOW -2
+#define UTF8PROC_ERROR_INVALIDUTF8 -3
+#define UTF8PROC_ERROR_NOTASSIGNED -4
+#define UTF8PROC_ERROR_INVALIDOPTS -5
+/*
+ *  Error codes being returned by almost all functions:
+ *  ERROR_NOMEM:       Memory could not be allocated.
+ *  ERROR_OVERFLOW:    The given string is too long to be processed.
+ *  ERROR_INVALIDUTF8: The given string is not a legal UTF-8 string.
+ *  ERROR_NOTASSIGNED: The REJECTNA flag was set,
+ *                     and an unassigned code point was found.
+ *  ERROR_INVALIDOPTS: Invalid options have been used.
+ */
+
+typedef int16_t utf8proc_propval_t;
+typedef struct utf8proc_property_struct {
+  utf8proc_propval_t category;
+  utf8proc_propval_t combining_class;
+  utf8proc_propval_t bidi_class;
+  utf8proc_propval_t decomp_type;
+  const int32_t *decomp_mapping;
+  unsigned bidi_mirrored:1;
+  int32_t uppercase_mapping;
+  int32_t lowercase_mapping;
+  int32_t titlecase_mapping;
+  int32_t comb1st_index;
+  int32_t comb2nd_index;
+  unsigned comp_exclusion:1;
+  unsigned ignorable:1;
+  unsigned control_boundary:1;
+  unsigned extend:1;
+  const int32_t *casefold_mapping;
+} utf8proc_property_t;
+
+#define UTF8PROC_CATEGORY_LU  1
+#define UTF8PROC_CATEGORY_LL  2
+#define UTF8PROC_CATEGORY_LT  3
+#define UTF8PROC_CATEGORY_LM  4
+#define UTF8PROC_CATEGORY_LO  5
+#define UTF8PROC_CATEGORY_MN  6
+#define UTF8PROC_CATEGORY_MC  7
+#define UTF8PROC_CATEGORY_ME  8
+#define UTF8PROC_CATEGORY_ND  9
+#define UTF8PROC_CATEGORY_NL 10
+#define UTF8PROC_CATEGORY_NO 11
+#define UTF8PROC_CATEGORY_PC 12
+#define UTF8PROC_CATEGORY_PD 13
+#define UTF8PROC_CATEGORY_PS 14
+#define UTF8PROC_CATEGORY_PE 15
+#define UTF8PROC_CATEGORY_PI 16
+#define UTF8PROC_CATEGORY_PF 17
+#define UTF8PROC_CATEGORY_PO 18
+#define UTF8PROC_CATEGORY_SM 19
+#define UTF8PROC_CATEGORY_SC 20
+#define UTF8PROC_CATEGORY_SK 21
+#define UTF8PROC_CATEGORY_SO 22
+#define UTF8PROC_CATEGORY_ZS 23
+#define UTF8PROC_CATEGORY_ZL 24
+#define UTF8PROC_CATEGORY_ZP 25
+#define UTF8PROC_CATEGORY_CC 26
+#define UTF8PROC_CATEGORY_CF 27
+#define UTF8PROC_CATEGORY_CS 28
+#define UTF8PROC_CATEGORY_CO 29
+#define UTF8PROC_CATEGORY_CN 30
+#define UTF8PROC_BIDI_CLASS_L    1
+#define UTF8PROC_BIDI_CLASS_LRE  2
+#define UTF8PROC_BIDI_CLASS_LRO  3
+#define UTF8PROC_BIDI_CLASS_R    4
+#define UTF8PROC_BIDI_CLASS_AL   5
+#define UTF8PROC_BIDI_CLASS_RLE  6
+#define UTF8PROC_BIDI_CLASS_RLO  7
+#define UTF8PROC_BIDI_CLASS_PDF  8
+#define UTF8PROC_BIDI_CLASS_EN   9
+#define UTF8PROC_BIDI_CLASS_ES  10
+#define UTF8PROC_BIDI_CLASS_ET  11
+#define UTF8PROC_BIDI_CLASS_AN  12
+#define UTF8PROC_BIDI_CLASS_CS  13
+#define UTF8PROC_BIDI_CLASS_NSM 14
+#define UTF8PROC_BIDI_CLASS_BN  15
+#define UTF8PROC_BIDI_CLASS_B   16
+#define UTF8PROC_BIDI_CLASS_S   17
+#define UTF8PROC_BIDI_CLASS_WS  18
+#define UTF8PROC_BIDI_CLASS_ON  19
+#define UTF8PROC_DECOMP_TYPE_FONT      1
+#define UTF8PROC_DECOMP_TYPE_NOBREAK   2
+#define UTF8PROC_DECOMP_TYPE_INITIAL   3
+#define UTF8PROC_DECOMP_TYPE_MEDIAL    4
+#define UTF8PROC_DECOMP_TYPE_FINAL     5
+#define UTF8PROC_DECOMP_TYPE_ISOLATED  6
+#define UTF8PROC_DECOMP_TYPE_CIRCLE    7
+#define UTF8PROC_DECOMP_TYPE_SUPER     8
+#define UTF8PROC_DECOMP_TYPE_SUB       9
+#define UTF8PROC_DECOMP_TYPE_VERTICAL 10
+#define UTF8PROC_DECOMP_TYPE_WIDE     11
+#define UTF8PROC_DECOMP_TYPE_NARROW   12
+#define UTF8PROC_DECOMP_TYPE_SMALL    13
+#define UTF8PROC_DECOMP_TYPE_SQUARE   14
+#define UTF8PROC_DECOMP_TYPE_FRACTION 15
+#define UTF8PROC_DECOMP_TYPE_COMPAT   16
+
+extern const int8_t utf8proc_utf8class[256];
+
+const char *utf8proc_errmsg(ssize_t errcode);
+/*
+ *  Returns a static error string for the given error code.
+ */
+
+ssize_t utf8proc_iterate(const uint8_t *str, ssize_t strlen, int32_t *dst);
+/*
+ *  Reads a single char from the UTF-8 sequence being pointed to by 'str'.
+ *  The maximum number of bytes read is 'strlen', unless 'strlen' is
+ *  negative.
+ *  If a valid unicode char could be read, it is stored in the variable
+ *  being pointed to by 'dst', otherwise that variable will be set to -1.
+ *  In case of success the number of bytes read is returned, otherwise a
+ *  negative error code is returned.
+ */
+
+bool utf8proc_codepoint_valid(int32_t uc);
+/*
+ *  Returns 1, if the given unicode code-point is valid, otherwise 0.
+ */
+
+ssize_t utf8proc_encode_char(int32_t uc, uint8_t *dst);
+/*
+ *  Encodes the unicode char with the code point 'uc' as an UTF-8 string in
+ *  the byte array being pointed to by 'dst'. This array has to be at least
+ *  4 bytes long.
+ *  In case of success the number of bytes written is returned,
+ *  otherwise 0.
+ *  This function does not check if 'uc' is a valid unicode code point.
+ */
+
+const utf8proc_property_t *utf8proc_get_property(int32_t uc);
+/*
+ *  Returns a pointer to a (constant) struct containing information about
+ *  the unicode char with the given code point 'uc'.
+ *  If the character is not existent a pointer to a special struct is
+ *  returned, where 'category' is a NULL pointer.
+ *  WARNING: The parameter 'uc' has to be in the range of 0x0000 to
+ *           0x10FFFF, otherwise the program might crash!
+ */
+
+ssize_t utf8proc_decompose_char(
+  int32_t uc, int32_t *dst, ssize_t bufsize,
+  int options, int *last_boundclass
+);
+/*
+ *  Writes a decomposition of the unicode char 'uc' into the array being
+ *  pointed to by 'dst'.
+ *  Following flags in the 'options' field are regarded:
+ *  REJECTNA:  an unassigned unicode code point leads to an error
+ *  IGNORE:    "default ignorable" chars are stripped
+ *  CASEFOLD:  unicode casefolding is applied
+ *  COMPAT:    replace certain characters with their
+ *             compatibility decomposition
+ *  CHARBOUND: Inserts 0xFF bytes before each grapheme cluster
+ *  LUMP:      lumps certain different characters together
+ *  STRIPMARK: removes all character marks
+ *  The pointer 'last_boundclass' has to point to an integer variable which
+ *  is storing the last character boundary class, if the CHARBOUND option
+ *  is used.
+ *  In case of success the number of chars written is returned,
+ *  in case of an error, a negative error code is returned.
+ *  If the number of written chars would be bigger than 'bufsize',
+ *  the buffer (up to 'bufsize') has inpredictable data, and the needed
+ *  buffer size is returned.
+ *  WARNING: The parameter 'uc' has to be in the range of 0x0000 to
+ *           0x10FFFF, otherwise the program might crash!
+ */
+
+ssize_t utf8proc_decompose(
+  const uint8_t *str, ssize_t strlen,
+  int32_t *buffer, ssize_t bufsize, int options
+);
+/*
+ *  Does the same as 'utf8proc_decompose_char', but acts on a whole UTF-8
+ *  string, and orders the decomposed sequences correctly.
+ *  If the NULLTERM flag in 'options' is set, processing will be stopped,
+ *  when a NULL byte is encounted, otherwise 'strlen' bytes are processed.
+ *  The result in form of unicode code points is written into the buffer
+ *  being pointed to by 'buffer', having the length of 'bufsize' entries.
+ *  In case of success the number of chars written is returned,
+ *  in case of an error, a negative error code is returned.
+ *  If the number of written chars would be bigger than 'bufsize',
+ *  the buffer (up to 'bufsize') has inpredictable data, and the needed
+ *  buffer size is returned.
+ */
+
+ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options);
+/*
+ *  Reencodes the sequence of unicode characters given by the pointer
+ *  'buffer' and 'length' as UTF-8.
+ *  The result is stored in the same memory area where the data is read.
+ *  Following flags in the 'options' field are regarded:
+ *  NLF2LS:  converts LF, CRLF, CR and NEL into LS
+ *  NLF2PS:  converts LF, CRLF, CR and NEL into PS
+ *  NLF2LF:  converts LF, CRLF, CR and NEL into LF
+ *  STRIPCC: strips or converts all non-affected control characters
+ *  COMPOSE: tries to combine decomposed characters into composite
+ *           characters
+ *  STABLE:  prohibits combining characters which would violate
+ *           the unicode versioning stability
+ *  In case of success the length of the resulting UTF-8 string is
+ *  returned, otherwise a negative error code is returned.
+ *  WARNING: The amount of free space being pointed to by 'buffer', has to
+ *           exceed the amount of the input data by one byte, and the
+ *           entries of the array pointed to by 'str' have to be in the
+ *           range of 0x0000 to 0x10FFFF, otherwise the program might
+ *           crash!
+ */
+
+ssize_t utf8proc_map(
+  const uint8_t *str, ssize_t strlen, uint8_t **dstptr, int options
+);
+/*
+ *  Maps the given UTF-8 string being pointed to by 'str' to a new UTF-8
+ *  string, which is allocated dynamically, and afterwards pointed to by
+ *  the pointer being pointed to by 'dstptr'.
+ *  If the NULLTERM flag in the 'options' field is set, the length is
+ *  determined by a NULL terminator, otherwise the parameter 'strlen' is
+ *  evaluated to determine the string length, but in any case the result
+ *  will be NULL terminated (though it might contain NULL characters
+ *  before). Other flags in the 'options' field are passed to the functions
+ *  defined above, and regarded as described.
+ *  In case of success the length of the new string is returned,
+ *  otherwise a negative error code is returned.
+ *  NOTICE: The memory of the new UTF-8 string will have been allocated with
+ *          'malloc', and has theirfore to be freed with 'free'.
+ */
+
+uint8_t *utf8proc_NFD(const uint8_t *str);
+uint8_t *utf8proc_NFC(const uint8_t *str);
+uint8_t *utf8proc_NFKD(const uint8_t *str);
+uint8_t *utf8proc_NFKC(const uint8_t *str);
+/*
+ *  Returns a pointer to newly allocated memory of a NFD, NFC, NFKD or NFKC
+ *  normalized version of the null-terminated string 'str'.
+ */
+
+ssize_t utf8proc_check(const uint8_t *str);
+/*
+ * Just checks UTF-8 string for validity, returns 0 if valid or one of
+ * the negative UTF8PROC_ERROR_* codes if invalid or memory exhausted
+ * checking.  Assumes null-terminated string str and UTF8PROC_STABLE
+ * option.
+ */
+
+#endif
+
diff --git a/src/lib/utf8proc_data.h b/src/lib/utf8proc_data.h
new file mode 100644
index 0000000..475be23
--- /dev/null
+++ b/src/lib/utf8proc_data.h
@@ -0,0 +1,13389 @@
+/*
+ *  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: utf8proc_data.h 1468 2013-10-26 16:53:18Z wkliao $ */
+
+/*
+ *  This file contains derived data from a modified version of the
+ *  Unicode data files.
+ *
+ *  The original data files are available at
+ *  http://www.unicode.org/Public/UNIDATA/
+ *
+ *
+ *  COPYRIGHT AND PERMISSION NOTICE
+ *
+ *  Copyright (c) 1991-2007 Unicode, Inc. All rights reserved. Distributed
+ *  under the Terms of Use in http://www.unicode.org/copyright.html.
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a
+ *  copy of the Unicode data files and any associated documentation (the "Data
+ *  Files") or Unicode software and any associated documentation (the
+ *  "Software") to deal in the Data Files or Software without restriction,
+ *  including without limitation the rights to use, copy, modify, merge,
+ *  publish, distribute, and/or sell copies of the Data Files or Software, and
+ *  to permit persons to whom the Data Files or Software are furnished to do
+ *  so, provided that (a) the above copyright notice(s) and this permission
+ *  notice appear with all copies of the Data Files or Software, (b) both the
+ *  above copyright notice(s) and this permission notice appear in associated
+ *  documentation, and (c) there is clear notice in each modified Data File or
+ *  in the Software as well as in the documentation associated with the Data
+ *  File(s) or Software that the data or software has been modified.
+ *
+ *  THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ *  KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
+ *  THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
+ *  INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR
+ *  CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ *  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ *  TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ *  PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+ *
+ *  Except as contained in this notice, the name of a copyright holder shall
+ *  not be used in advertising or otherwise to promote the sale, use or other
+ *  dealings in these Data Files or Software without prior written
+ *  authorization of the copyright holder.
+ */
+
+
+const int32_t utf8proc_sequences[] = {
+  97, -1, 98, -1, 99, -1, 100, 
+  -1, 101, -1, 102, -1, 103, -1, 104, 
+  -1, 105, -1, 106, -1, 107, -1, 108, 
+  -1, 109, -1, 110, -1, 111, -1, 112, 
+  -1, 113, -1, 114, -1, 115, -1, 116, 
+  -1, 117, -1, 118, -1, 119, -1, 120, 
+  -1, 121, -1, 122, -1, 32, -1, 32, 
+  776, -1, 32, 772, -1, 50, -1, 51, 
+  -1, 32, 769, -1, 956, -1, 32, 807, 
+  -1, 49, -1, 49, 8260, 52, -1, 49, 
+  8260, 50, -1, 51, 8260, 52, -1, 65, 
+  768, -1, 224, -1, 65, 769, -1, 225, 
+  -1, 65, 770, -1, 226, -1, 65, 771, 
+  -1, 227, -1, 65, 776, -1, 228, -1, 
+  65, 778, -1, 229, -1, 230, -1, 67, 
+  807, -1, 231, -1, 69, 768, -1, 232, 
+  -1, 69, 769, -1, 233, -1, 69, 770, 
+  -1, 234, -1, 69, 776, -1, 235, -1, 
+  73, 768, -1, 236, -1, 73, 769, -1, 
+  237, -1, 73, 770, -1, 238, -1, 73, 
+  776, -1, 239, -1, 240, -1, 78, 771, 
+  -1, 241, -1, 79, 768, -1, 242, -1, 
+  79, 769, -1, 243, -1, 79, 770, -1, 
+  244, -1, 79, 771, -1, 245, -1, 79, 
+  776, -1, 246, -1, 248, -1, 85, 768, 
+  -1, 249, -1, 85, 769, -1, 250, -1, 
+  85, 770, -1, 251, -1, 85, 776, -1, 
+  252, -1, 89, 769, -1, 253, -1, 254, 
+  -1, 115, 115, -1, 97, 768, -1, 97, 
+  769, -1, 97, 770, -1, 97, 771, -1, 
+  97, 776, -1, 97, 778, -1, 99, 807, 
+  -1, 101, 768, -1, 101, 769, -1, 101, 
+  770, -1, 101, 776, -1, 105, 768, -1, 
+  105, 769, -1, 105, 770, -1, 105, 776, 
+  -1, 110, 771, -1, 111, 768, -1, 111, 
+  769, -1, 111, 770, -1, 111, 771, -1, 
+  111, 776, -1, 117, 768, -1, 117, 769, 
+  -1, 117, 770, -1, 117, 776, -1, 121, 
+  769, -1, 121, 776, -1, 65, 772, -1, 
+  257, -1, 97, 772, -1, 65, 774, -1, 
+  259, -1, 97, 774, -1, 65, 808, -1, 
+  261, -1, 97, 808, -1, 67, 769, -1, 
+  263, -1, 99, 769, -1, 67, 770, -1, 
+  265, -1, 99, 770, -1, 67, 775, -1, 
+  267, -1, 99, 775, -1, 67, 780, -1, 
+  269, -1, 99, 780, -1, 68, 780, -1, 
+  271, -1, 100, 780, -1, 273, -1, 69, 
+  772, -1, 275, -1, 101, 772, -1, 69, 
+  774, -1, 277, -1, 101, 774, -1, 69, 
+  775, -1, 279, -1, 101, 775, -1, 69, 
+  808, -1, 281, -1, 101, 808, -1, 69, 
+  780, -1, 283, -1, 101, 780, -1, 71, 
+  770, -1, 285, -1, 103, 770, -1, 71, 
+  774, -1, 287, -1, 103, 774, -1, 71, 
+  775, -1, 289, -1, 103, 775, -1, 71, 
+  807, -1, 291, -1, 103, 807, -1, 72, 
+  770, -1, 293, -1, 104, 770, -1, 295, 
+  -1, 73, 771, -1, 297, -1, 105, 771, 
+  -1, 73, 772, -1, 299, -1, 105, 772, 
+  -1, 73, 774, -1, 301, -1, 105, 774, 
+  -1, 73, 808, -1, 303, -1, 105, 808, 
+  -1, 73, 775, -1, 105, 775, -1, 73, 
+  74, -1, 307, -1, 105, 106, -1, 74, 
+  770, -1, 309, -1, 106, 770, -1, 75, 
+  807, -1, 311, -1, 107, 807, -1, 76, 
+  769, -1, 314, -1, 108, 769, -1, 76, 
+  807, -1, 316, -1, 108, 807, -1, 76, 
+  780, -1, 318, -1, 108, 780, -1, 76, 
+  183, -1, 320, -1, 108, 183, -1, 322, 
+  -1, 78, 769, -1, 324, -1, 110, 769, 
+  -1, 78, 807, -1, 326, -1, 110, 807, 
+  -1, 78, 780, -1, 328, -1, 110, 780, 
+  -1, 700, 110, -1, 331, -1, 79, 772, 
+  -1, 333, -1, 111, 772, -1, 79, 774, 
+  -1, 335, -1, 111, 774, -1, 79, 779, 
+  -1, 337, -1, 111, 779, -1, 339, -1, 
+  82, 769, -1, 341, -1, 114, 769, -1, 
+  82, 807, -1, 343, -1, 114, 807, -1, 
+  82, 780, -1, 345, -1, 114, 780, -1, 
+  83, 769, -1, 347, -1, 115, 769, -1, 
+  83, 770, -1, 349, -1, 115, 770, -1, 
+  83, 807, -1, 351, -1, 115, 807, -1, 
+  83, 780, -1, 353, -1, 115, 780, -1, 
+  84, 807, -1, 355, -1, 116, 807, -1, 
+  84, 780, -1, 357, -1, 116, 780, -1, 
+  359, -1, 85, 771, -1, 361, -1, 117, 
+  771, -1, 85, 772, -1, 363, -1, 117, 
+  772, -1, 85, 774, -1, 365, -1, 117, 
+  774, -1, 85, 778, -1, 367, -1, 117, 
+  778, -1, 85, 779, -1, 369, -1, 117, 
+  779, -1, 85, 808, -1, 371, -1, 117, 
+  808, -1, 87, 770, -1, 373, -1, 119, 
+  770, -1, 89, 770, -1, 375, -1, 121, 
+  770, -1, 89, 776, -1, 255, -1, 90, 
+  769, -1, 378, -1, 122, 769, -1, 90, 
+  775, -1, 380, -1, 122, 775, -1, 90, 
+  780, -1, 382, -1, 122, 780, -1, 595, 
+  -1, 387, -1, 389, -1, 596, -1, 392, 
+  -1, 598, -1, 599, -1, 396, -1, 477, 
+  -1, 601, -1, 603, -1, 402, -1, 608, 
+  -1, 611, -1, 617, -1, 616, -1, 409, 
+  -1, 623, -1, 626, -1, 629, -1, 79, 
+  795, -1, 417, -1, 111, 795, -1, 419, 
+  -1, 421, -1, 640, -1, 424, -1, 643, 
+  -1, 429, -1, 648, -1, 85, 795, -1, 
+  432, -1, 117, 795, -1, 650, -1, 651, 
+  -1, 436, -1, 438, -1, 658, -1, 441, 
+  -1, 445, -1, 68, 381, -1, 454, -1, 
+  68, 382, -1, 100, 382, -1, 76, 74, 
+  -1, 457, -1, 76, 106, -1, 108, 106, 
+  -1, 78, 74, -1, 460, -1, 78, 106, 
+  -1, 110, 106, -1, 65, 780, -1, 462, 
+  -1, 97, 780, -1, 73, 780, -1, 464, 
+  -1, 105, 780, -1, 79, 780, -1, 466, 
+  -1, 111, 780, -1, 85, 780, -1, 468, 
+  -1, 117, 780, -1, 220, 772, -1, 470, 
+  -1, 252, 772, -1, 220, 769, -1, 472, 
+  -1, 252, 769, -1, 220, 780, -1, 474, 
+  -1, 252, 780, -1, 220, 768, -1, 476, 
+  -1, 252, 768, -1, 196, 772, -1, 479, 
+  -1, 228, 772, -1, 550, 772, -1, 481, 
+  -1, 551, 772, -1, 198, 772, -1, 483, 
+  -1, 230, 772, -1, 485, -1, 71, 780, 
+  -1, 487, -1, 103, 780, -1, 75, 780, 
+  -1, 489, -1, 107, 780, -1, 79, 808, 
+  -1, 491, -1, 111, 808, -1, 490, 772, 
+  -1, 493, -1, 491, 772, -1, 439, 780, 
+  -1, 495, -1, 658, 780, -1, 106, 780, 
+  -1, 68, 90, -1, 499, -1, 68, 122, 
+  -1, 100, 122, -1, 71, 769, -1, 501, 
+  -1, 103, 769, -1, 405, -1, 447, -1, 
+  78, 768, -1, 505, -1, 110, 768, -1, 
+  197, 769, -1, 507, -1, 229, 769, -1, 
+  198, 769, -1, 509, -1, 230, 769, -1, 
+  216, 769, -1, 511, -1, 248, 769, -1, 
+  65, 783, -1, 513, -1, 97, 783, -1, 
+  65, 785, -1, 515, -1, 97, 785, -1, 
+  69, 783, -1, 517, -1, 101, 783, -1, 
+  69, 785, -1, 519, -1, 101, 785, -1, 
+  73, 783, -1, 521, -1, 105, 783, -1, 
+  73, 785, -1, 523, -1, 105, 785, -1, 
+  79, 783, -1, 525, -1, 111, 783, -1, 
+  79, 785, -1, 527, -1, 111, 785, -1, 
+  82, 783, -1, 529, -1, 114, 783, -1, 
+  82, 785, -1, 531, -1, 114, 785, -1, 
+  85, 783, -1, 533, -1, 117, 783, -1, 
+  85, 785, -1, 535, -1, 117, 785, -1, 
+  83, 806, -1, 537, -1, 115, 806, -1, 
+  84, 806, -1, 539, -1, 116, 806, -1, 
+  541, -1, 72, 780, -1, 543, -1, 104, 
+  780, -1, 414, -1, 547, -1, 549, -1, 
+  65, 775, -1, 551, -1, 97, 775, -1, 
+  69, 807, -1, 553, -1, 101, 807, -1, 
+  214, 772, -1, 555, -1, 246, 772, -1, 
+  213, 772, -1, 557, -1, 245, 772, -1, 
+  79, 775, -1, 559, -1, 111, 775, -1, 
+  558, 772, -1, 561, -1, 559, 772, -1, 
+  89, 772, -1, 563, -1, 121, 772, -1, 
+  11365, -1, 572, -1, 410, -1, 11366, -1, 
+  578, -1, 384, -1, 649, -1, 652, -1, 
+  583, -1, 585, -1, 587, -1, 589, -1, 
+  591, -1, 614, -1, 633, -1, 635, -1, 
+  641, -1, 32, 774, -1, 32, 775, -1, 
+  32, 778, -1, 32, 808, -1, 32, 771, 
+  -1, 32, 779, -1, 661, -1, 768, -1, 
+  769, -1, 787, -1, 776, 769, -1, 953, 
+  -1, 697, -1, 32, 837, -1, 59, -1, 
+  168, 769, -1, 913, 769, -1, 940, -1, 
+  183, -1, 917, 769, -1, 941, -1, 919, 
+  769, -1, 942, -1, 921, 769, -1, 943, 
+  -1, 927, 769, -1, 972, -1, 933, 769, 
+  -1, 973, -1, 937, 769, -1, 974, -1, 
+  970, 769, -1, 953, 776, 769, -1, 945, 
+  -1, 946, -1, 947, -1, 948, -1, 949, 
+  -1, 950, -1, 951, -1, 952, -1, 954, 
+  -1, 955, -1, 957, -1, 958, -1, 959, 
+  -1, 960, -1, 961, -1, 963, -1, 964, 
+  -1, 965, -1, 966, -1, 967, -1, 968, 
+  -1, 969, -1, 921, 776, -1, 970, -1, 
+  933, 776, -1, 971, -1, 945, 769, -1, 
+  949, 769, -1, 951, 769, -1, 953, 769, 
+  -1, 971, 769, -1, 965, 776, 769, -1, 
+  953, 776, -1, 965, 776, -1, 959, 769, 
+  -1, 965, 769, -1, 969, 769, -1, 933, 
+  -1, 978, 769, -1, 978, 776, -1, 985, 
+  -1, 987, -1, 989, -1, 991, -1, 993, 
+  -1, 995, -1, 997, -1, 999, -1, 1001, 
+  -1, 1003, -1, 1005, -1, 1007, -1, 962, 
+  -1, 920, -1, 1016, -1, 931, -1, 1010, 
+  -1, 1019, -1, 891, -1, 892, -1, 893, 
+  -1, 1045, 768, -1, 1104, -1, 1045, 776, 
+  -1, 1105, -1, 1106, -1, 1043, 769, -1, 
+  1107, -1, 1108, -1, 1109, -1, 1110, -1, 
+  1030, 776, -1, 1111, -1, 1112, -1, 1113, 
+  -1, 1114, -1, 1115, -1, 1050, 769, -1, 
+  1116, -1, 1048, 768, -1, 1117, -1, 1059, 
+  774, -1, 1118, -1, 1119, -1, 1072, -1, 
+  1073, -1, 1074, -1, 1075, -1, 1076, -1, 
+  1077, -1, 1078, -1, 1079, -1, 1080, -1, 
+  1048, 774, -1, 1081, -1, 1082, -1, 1083, 
+  -1, 1084, -1, 1085, -1, 1086, -1, 1087, 
+  -1, 1088, -1, 1089, -1, 1090, -1, 1091, 
+  -1, 1092, -1, 1093, -1, 1094, -1, 1095, 
+  -1, 1096, -1, 1097, -1, 1098, -1, 1099, 
+  -1, 1100, -1, 1101, -1, 1102, -1, 1103, 
+  -1, 1080, 774, -1, 1077, 768, -1, 1077, 
+  776, -1, 1075, 769, -1, 1110, 776, -1, 
+  1082, 769, -1, 1080, 768, -1, 1091, 774, 
+  -1, 1121, -1, 1123, -1, 1125, -1, 1127, 
+  -1, 1129, -1, 1131, -1, 1133, -1, 1135, 
+  -1, 1137, -1, 1139, -1, 1141, -1, 1140, 
+  783, -1, 1143, -1, 1141, 783, -1, 1145, 
+  -1, 1147, -1, 1149, -1, 1151, -1, 1153, 
+  -1, 1163, -1, 1165, -1, 1167, -1, 1169, 
+  -1, 1171, -1, 1173, -1, 1175, -1, 1177, 
+  -1, 1179, -1, 1181, -1, 1183, -1, 1185, 
+  -1, 1187, -1, 1189, -1, 1191, -1, 1193, 
+  -1, 1195, -1, 1197, -1, 1199, -1, 1201, 
+  -1, 1203, -1, 1205, -1, 1207, -1, 1209, 
+  -1, 1211, -1, 1213, -1, 1215, -1, 1231, 
+  -1, 1046, 774, -1, 1218, -1, 1078, 774, 
+  -1, 1220, -1, 1222, -1, 1224, -1, 1226, 
+  -1, 1228, -1, 1230, -1, 1040, 774, -1, 
+  1233, -1, 1072, 774, -1, 1040, 776, -1, 
+  1235, -1, 1072, 776, -1, 1237, -1, 1045, 
+  774, -1, 1239, -1, 1077, 774, -1, 1241, 
+  -1, 1240, 776, -1, 1243, -1, 1241, 776, 
+  -1, 1046, 776, -1, 1245, -1, 1078, 776, 
+  -1, 1047, 776, -1, 1247, -1, 1079, 776, 
+  -1, 1249, -1, 1048, 772, -1, 1251, -1, 
+  1080, 772, -1, 1048, 776, -1, 1253, -1, 
+  1080, 776, -1, 1054, 776, -1, 1255, -1, 
+  1086, 776, -1, 1257, -1, 1256, 776, -1, 
+  1259, -1, 1257, 776, -1, 1069, 776, -1, 
+  1261, -1, 1101, 776, -1, 1059, 772, -1, 
+  1263, -1, 1091, 772, -1, 1059, 776, -1, 
+  1265, -1, 1091, 776, -1, 1059, 779, -1, 
+  1267, -1, 1091, 779, -1, 1063, 776, -1, 
+  1269, -1, 1095, 776, -1, 1271, -1, 1067, 
+  776, -1, 1273, -1, 1099, 776, -1, 1275, 
+  -1, 1277, -1, 1279, -1, 1281, -1, 1283, 
+  -1, 1285, -1, 1287, -1, 1289, -1, 1291, 
+  -1, 1293, -1, 1295, -1, 1297, -1, 1299, 
+  -1, 1377, -1, 1378, -1, 1379, -1, 1380, 
+  -1, 1381, -1, 1382, -1, 1383, -1, 1384, 
+  -1, 1385, -1, 1386, -1, 1387, -1, 1388, 
+  -1, 1389, -1, 1390, -1, 1391, -1, 1392, 
+  -1, 1393, -1, 1394, -1, 1395, -1, 1396, 
+  -1, 1397, -1, 1398, -1, 1399, -1, 1400, 
+  -1, 1401, -1, 1402, -1, 1403, -1, 1404, 
+  -1, 1405, -1, 1406, -1, 1407, -1, 1408, 
+  -1, 1409, -1, 1410, -1, 1411, -1, 1412, 
+  -1, 1413, -1, 1414, -1, 1381, 1410, -1, 
+  1575, 1619, -1, 1575, 1620, -1, 1608, 1620, 
+  -1, 1575, 1621, -1, 1610, 1620, -1, 1575, 
+  1652, -1, 1608, 1652, -1, 1735, 1652, -1, 
+  1610, 1652, -1, 1749, 1620, -1, 1729, 1620, 
+  -1, 1746, 1620, -1, 2344, 2364, -1, 2352, 
+  2364, -1, 2355, 2364, -1, 2325, 2364, -1, 
+  2326, 2364, -1, 2327, 2364, -1, 2332, 2364, 
+  -1, 2337, 2364, -1, 2338, 2364, -1, 2347, 
+  2364, -1, 2351, 2364, -1, 2503, 2494, -1, 
+  2503, 2519, -1, 2465, 2492, -1, 2466, 2492, 
+  -1, 2479, 2492, -1, 2610, 2620, -1, 2616, 
+  2620, -1, 2582, 2620, -1, 2583, 2620, -1, 
+  2588, 2620, -1, 2603, 2620, -1, 2887, 2902, 
+  -1, 2887, 2878, -1, 2887, 2903, -1, 2849, 
+  2876, -1, 2850, 2876, -1, 2962, 3031, -1, 
+  3014, 3006, -1, 3015, 3006, -1, 3014, 3031, 
+  -1, 3142, 3158, -1, 3263, 3285, -1, 3270, 
+  3285, -1, 3270, 3286, -1, 3270, 3266, -1, 
+  3274, 3285, -1, 3398, 3390, -1, 3399, 3390, 
+  -1, 3398, 3415, -1, 3545, 3530, -1, 3545, 
+  3535, -1, 3548, 3530, -1, 3545, 3551, -1, 
+  3661, 3634, -1, 3789, 3762, -1, 3755, 3737, 
+  -1, 3755, 3745, -1, 3851, -1, 3906, 4023, 
+  -1, 3916, 4023, -1, 3921, 4023, -1, 3926, 
+  4023, -1, 3931, 4023, -1, 3904, 4021, -1, 
+  3953, 3954, -1, 3953, 3956, -1, 4018, 3968, 
+  -1, 4018, 3969, -1, 4019, 3968, -1, 4019, 
+  3969, -1, 3953, 3968, -1, 3986, 4023, -1, 
+  3996, 4023, -1, 4001, 4023, -1, 4006, 4023, 
+  -1, 4011, 4023, -1, 3984, 4021, -1, 4133, 
+  4142, -1, 11520, -1, 11521, -1, 11522, -1, 
+  11523, -1, 11524, -1, 11525, -1, 11526, -1, 
+  11527, -1, 11528, -1, 11529, -1, 11530, -1, 
+  11531, -1, 11532, -1, 11533, -1, 11534, -1, 
+  11535, -1, 11536, -1, 11537, -1, 11538, -1, 
+  11539, -1, 11540, -1, 11541, -1, 11542, -1, 
+  11543, -1, 11544, -1, 11545, -1, 11546, -1, 
+  11547, -1, 11548, -1, 11549, -1, 11550, -1, 
+  11551, -1, 11552, -1, 11553, -1, 11554, -1, 
+  11555, -1, 11556, -1, 11557, -1, 4316, -1, 
+  6917, 6965, -1, 6919, 6965, -1, 6921, 6965, 
+  -1, 6923, 6965, -1, 6925, 6965, -1, 6929, 
+  6965, -1, 6970, 6965, -1, 6972, 6965, -1, 
+  6974, 6965, -1, 6975, 6965, -1, 6978, 6965, 
+  -1, 65, -1, 198, -1, 66, -1, 68, 
+  -1, 69, -1, 398, -1, 71, -1, 72, 
+  -1, 73, -1, 74, -1, 75, -1, 76, 
+  -1, 77, -1, 78, -1, 79, -1, 546, 
+  -1, 80, -1, 82, -1, 84, -1, 85, 
+  -1, 87, -1, 592, -1, 593, -1, 7426, 
+  -1, 604, -1, 7446, -1, 7447, -1, 7453, 
+  -1, 7461, -1, 594, -1, 597, -1, 607, 
+  -1, 609, -1, 613, -1, 618, -1, 7547, 
+  -1, 669, -1, 621, -1, 7557, -1, 671, 
+  -1, 625, -1, 624, -1, 627, -1, 628, 
+  -1, 632, -1, 642, -1, 427, -1, 7452, 
+  -1, 656, -1, 657, -1, 65, 805, -1, 
+  7681, -1, 97, 805, -1, 66, 775, -1, 
+  7683, -1, 98, 775, -1, 66, 803, -1, 
+  7685, -1, 98, 803, -1, 66, 817, -1, 
+  7687, -1, 98, 817, -1, 199, 769, -1, 
+  7689, -1, 231, 769, -1, 68, 775, -1, 
+  7691, -1, 100, 775, -1, 68, 803, -1, 
+  7693, -1, 100, 803, -1, 68, 817, -1, 
+  7695, -1, 100, 817, -1, 68, 807, -1, 
+  7697, -1, 100, 807, -1, 68, 813, -1, 
+  7699, -1, 100, 813, -1, 274, 768, -1, 
+  7701, -1, 275, 768, -1, 274, 769, -1, 
+  7703, -1, 275, 769, -1, 69, 813, -1, 
+  7705, -1, 101, 813, -1, 69, 816, -1, 
+  7707, -1, 101, 816, -1, 552, 774, -1, 
+  7709, -1, 553, 774, -1, 70, 775, -1, 
+  7711, -1, 102, 775, -1, 71, 772, -1, 
+  7713, -1, 103, 772, -1, 72, 775, -1, 
+  7715, -1, 104, 775, -1, 72, 803, -1, 
+  7717, -1, 104, 803, -1, 72, 776, -1, 
+  7719, -1, 104, 776, -1, 72, 807, -1, 
+  7721, -1, 104, 807, -1, 72, 814, -1, 
+  7723, -1, 104, 814, -1, 73, 816, -1, 
+  7725, -1, 105, 816, -1, 207, 769, -1, 
+  7727, -1, 239, 769, -1, 75, 769, -1, 
+  7729, -1, 107, 769, -1, 75, 803, -1, 
+  7731, -1, 107, 803, -1, 75, 817, -1, 
+  7733, -1, 107, 817, -1, 76, 803, -1, 
+  7735, -1, 108, 803, -1, 7734, 772, -1, 
+  7737, -1, 7735, 772, -1, 76, 817, -1, 
+  7739, -1, 108, 817, -1, 76, 813, -1, 
+  7741, -1, 108, 813, -1, 77, 769, -1, 
+  7743, -1, 109, 769, -1, 77, 775, -1, 
+  7745, -1, 109, 775, -1, 77, 803, -1, 
+  7747, -1, 109, 803, -1, 78, 775, -1, 
+  7749, -1, 110, 775, -1, 78, 803, -1, 
+  7751, -1, 110, 803, -1, 78, 817, -1, 
+  7753, -1, 110, 817, -1, 78, 813, -1, 
+  7755, -1, 110, 813, -1, 213, 769, -1, 
+  7757, -1, 245, 769, -1, 213, 776, -1, 
+  7759, -1, 245, 776, -1, 332, 768, -1, 
+  7761, -1, 333, 768, -1, 332, 769, -1, 
+  7763, -1, 333, 769, -1, 80, 769, -1, 
+  7765, -1, 112, 769, -1, 80, 775, -1, 
+  7767, -1, 112, 775, -1, 82, 775, -1, 
+  7769, -1, 114, 775, -1, 82, 803, -1, 
+  7771, -1, 114, 803, -1, 7770, 772, -1, 
+  7773, -1, 7771, 772, -1, 82, 817, -1, 
+  7775, -1, 114, 817, -1, 83, 775, -1, 
+  7777, -1, 115, 775, -1, 83, 803, -1, 
+  7779, -1, 115, 803, -1, 346, 775, -1, 
+  7781, -1, 347, 775, -1, 352, 775, -1, 
+  7783, -1, 353, 775, -1, 7778, 775, -1, 
+  7785, -1, 7779, 775, -1, 84, 775, -1, 
+  7787, -1, 116, 775, -1, 84, 803, -1, 
+  7789, -1, 116, 803, -1, 84, 817, -1, 
+  7791, -1, 116, 817, -1, 84, 813, -1, 
+  7793, -1, 116, 813, -1, 85, 804, -1, 
+  7795, -1, 117, 804, -1, 85, 816, -1, 
+  7797, -1, 117, 816, -1, 85, 813, -1, 
+  7799, -1, 117, 813, -1, 360, 769, -1, 
+  7801, -1, 361, 769, -1, 362, 776, -1, 
+  7803, -1, 363, 776, -1, 86, 771, -1, 
+  7805, -1, 118, 771, -1, 86, 803, -1, 
+  7807, -1, 118, 803, -1, 87, 768, -1, 
+  7809, -1, 119, 768, -1, 87, 769, -1, 
+  7811, -1, 119, 769, -1, 87, 776, -1, 
+  7813, -1, 119, 776, -1, 87, 775, -1, 
+  7815, -1, 119, 775, -1, 87, 803, -1, 
+  7817, -1, 119, 803, -1, 88, 775, -1, 
+  7819, -1, 120, 775, -1, 88, 776, -1, 
+  7821, -1, 120, 776, -1, 89, 775, -1, 
+  7823, -1, 121, 775, -1, 90, 770, -1, 
+  7825, -1, 122, 770, -1, 90, 803, -1, 
+  7827, -1, 122, 803, -1, 90, 817, -1, 
+  7829, -1, 122, 817, -1, 104, 817, -1, 
+  116, 776, -1, 119, 778, -1, 121, 778, 
+  -1, 97, 702, -1, 383, 775, -1, 65, 
+  803, -1, 7841, -1, 97, 803, -1, 65, 
+  777, -1, 7843, -1, 97, 777, -1, 194, 
+  769, -1, 7845, -1, 226, 769, -1, 194, 
+  768, -1, 7847, -1, 226, 768, -1, 194, 
+  777, -1, 7849, -1, 226, 777, -1, 194, 
+  771, -1, 7851, -1, 226, 771, -1, 7840, 
+  770, -1, 7853, -1, 7841, 770, -1, 258, 
+  769, -1, 7855, -1, 259, 769, -1, 258, 
+  768, -1, 7857, -1, 259, 768, -1, 258, 
+  777, -1, 7859, -1, 259, 777, -1, 258, 
+  771, -1, 7861, -1, 259, 771, -1, 7840, 
+  774, -1, 7863, -1, 7841, 774, -1, 69, 
+  803, -1, 7865, -1, 101, 803, -1, 69, 
+  777, -1, 7867, -1, 101, 777, -1, 69, 
+  771, -1, 7869, -1, 101, 771, -1, 202, 
+  769, -1, 7871, -1, 234, 769, -1, 202, 
+  768, -1, 7873, -1, 234, 768, -1, 202, 
+  777, -1, 7875, -1, 234, 777, -1, 202, 
+  771, -1, 7877, -1, 234, 771, -1, 7864, 
+  770, -1, 7879, -1, 7865, 770, -1, 73, 
+  777, -1, 7881, -1, 105, 777, -1, 73, 
+  803, -1, 7883, -1, 105, 803, -1, 79, 
+  803, -1, 7885, -1, 111, 803, -1, 79, 
+  777, -1, 7887, -1, 111, 777, -1, 212, 
+  769, -1, 7889, -1, 244, 769, -1, 212, 
+  768, -1, 7891, -1, 244, 768, -1, 212, 
+  777, -1, 7893, -1, 244, 777, -1, 212, 
+  771, -1, 7895, -1, 244, 771, -1, 7884, 
+  770, -1, 7897, -1, 7885, 770, -1, 416, 
+  769, -1, 7899, -1, 417, 769, -1, 416, 
+  768, -1, 7901, -1, 417, 768, -1, 416, 
+  777, -1, 7903, -1, 417, 777, -1, 416, 
+  771, -1, 7905, -1, 417, 771, -1, 416, 
+  803, -1, 7907, -1, 417, 803, -1, 85, 
+  803, -1, 7909, -1, 117, 803, -1, 85, 
+  777, -1, 7911, -1, 117, 777, -1, 431, 
+  769, -1, 7913, -1, 432, 769, -1, 431, 
+  768, -1, 7915, -1, 432, 768, -1, 431, 
+  777, -1, 7917, -1, 432, 777, -1, 431, 
+  771, -1, 7919, -1, 432, 771, -1, 431, 
+  803, -1, 7921, -1, 432, 803, -1, 89, 
+  768, -1, 7923, -1, 121, 768, -1, 89, 
+  803, -1, 7925, -1, 121, 803, -1, 89, 
+  777, -1, 7927, -1, 121, 777, -1, 89, 
+  771, -1, 7929, -1, 121, 771, -1, 945, 
+  787, -1, 945, 788, -1, 7936, 768, -1, 
+  7937, 768, -1, 7936, 769, -1, 7937, 769, 
+  -1, 7936, 834, -1, 7937, 834, -1, 913, 
+  787, -1, 7936, -1, 913, 788, -1, 7937, 
+  -1, 7944, 768, -1, 7938, -1, 7945, 768, 
+  -1, 7939, -1, 7944, 769, -1, 7940, -1, 
+  7945, 769, -1, 7941, -1, 7944, 834, -1, 
+  7942, -1, 7945, 834, -1, 7943, -1, 949, 
+  787, -1, 949, 788, -1, 7952, 768, -1, 
+  7953, 768, -1, 7952, 769, -1, 7953, 769, 
+  -1, 917, 787, -1, 7952, -1, 917, 788, 
+  -1, 7953, -1, 7960, 768, -1, 7954, -1, 
+  7961, 768, -1, 7955, -1, 7960, 769, -1, 
+  7956, -1, 7961, 769, -1, 7957, -1, 951, 
+  787, -1, 951, 788, -1, 7968, 768, -1, 
+  7969, 768, -1, 7968, 769, -1, 7969, 769, 
+  -1, 7968, 834, -1, 7969, 834, -1, 919, 
+  787, -1, 7968, -1, 919, 788, -1, 7969, 
+  -1, 7976, 768, -1, 7970, -1, 7977, 768, 
+  -1, 7971, -1, 7976, 769, -1, 7972, -1, 
+  7977, 769, -1, 7973, -1, 7976, 834, -1, 
+  7974, -1, 7977, 834, -1, 7975, -1, 953, 
+  787, -1, 953, 788, -1, 7984, 768, -1, 
+  7985, 768, -1, 7984, 769, -1, 7985, 769, 
+  -1, 7984, 834, -1, 7985, 834, -1, 921, 
+  787, -1, 7984, -1, 921, 788, -1, 7985, 
+  -1, 7992, 768, -1, 7986, -1, 7993, 768, 
+  -1, 7987, -1, 7992, 769, -1, 7988, -1, 
+  7993, 769, -1, 7989, -1, 7992, 834, -1, 
+  7990, -1, 7993, 834, -1, 7991, -1, 959, 
+  787, -1, 959, 788, -1, 8000, 768, -1, 
+  8001, 768, -1, 8000, 769, -1, 8001, 769, 
+  -1, 927, 787, -1, 8000, -1, 927, 788, 
+  -1, 8001, -1, 8008, 768, -1, 8002, -1, 
+  8009, 768, -1, 8003, -1, 8008, 769, -1, 
+  8004, -1, 8009, 769, -1, 8005, -1, 965, 
+  787, -1, 965, 788, -1, 8016, 768, -1, 
+  965, 787, 768, -1, 8017, 768, -1, 8016, 
+  769, -1, 965, 787, 769, -1, 8017, 769, 
+  -1, 8016, 834, -1, 965, 787, 834, -1, 
+  8017, 834, -1, 933, 788, -1, 8017, -1, 
+  8025, 768, -1, 8019, -1, 8025, 769, -1, 
+  8021, -1, 8025, 834, -1, 8023, -1, 969, 
+  787, -1, 969, 788, -1, 8032, 768, -1, 
+  8033, 768, -1, 8032, 769, -1, 8033, 769, 
+  -1, 8032, 834, -1, 8033, 834, -1, 937, 
+  787, -1, 8032, -1, 937, 788, -1, 8033, 
+  -1, 8040, 768, -1, 8034, -1, 8041, 768, 
+  -1, 8035, -1, 8040, 769, -1, 8036, -1, 
+  8041, 769, -1, 8037, -1, 8040, 834, -1, 
+  8038, -1, 8041, 834, -1, 8039, -1, 945, 
+  768, -1, 949, 768, -1, 951, 768, -1, 
+  953, 768, -1, 959, 768, -1, 965, 768, 
+  -1, 969, 768, -1, 7936, 837, -1, 7936, 
+  953, -1, 7937, 837, -1, 7937, 953, -1, 
+  7938, 837, -1, 7938, 953, -1, 7939, 837, 
+  -1, 7939, 953, -1, 7940, 837, -1, 7940, 
+  953, -1, 7941, 837, -1, 7941, 953, -1, 
+  7942, 837, -1, 7942, 953, -1, 7943, 837, 
+  -1, 7943, 953, -1, 7944, 837, -1, 8064, 
+  -1, 7945, 837, -1, 8065, -1, 7946, 837, 
+  -1, 8066, -1, 7947, 837, -1, 8067, -1, 
+  7948, 837, -1, 8068, -1, 7949, 837, -1, 
+  8069, -1, 7950, 837, -1, 8070, -1, 7951, 
+  837, -1, 8071, -1, 7968, 837, -1, 7968, 
+  953, -1, 7969, 837, -1, 7969, 953, -1, 
+  7970, 837, -1, 7970, 953, -1, 7971, 837, 
+  -1, 7971, 953, -1, 7972, 837, -1, 7972, 
+  953, -1, 7973, 837, -1, 7973, 953, -1, 
+  7974, 837, -1, 7974, 953, -1, 7975, 837, 
+  -1, 7975, 953, -1, 7976, 837, -1, 8080, 
+  -1, 7977, 837, -1, 8081, -1, 7978, 837, 
+  -1, 8082, -1, 7979, 837, -1, 8083, -1, 
+  7980, 837, -1, 8084, -1, 7981, 837, -1, 
+  8085, -1, 7982, 837, -1, 8086, -1, 7983, 
+  837, -1, 8087, -1, 8032, 837, -1, 8032, 
+  953, -1, 8033, 837, -1, 8033, 953, -1, 
+  8034, 837, -1, 8034, 953, -1, 8035, 837, 
+  -1, 8035, 953, -1, 8036, 837, -1, 8036, 
+  953, -1, 8037, 837, -1, 8037, 953, -1, 
+  8038, 837, -1, 8038, 953, -1, 8039, 837, 
+  -1, 8039, 953, -1, 8040, 837, -1, 8096, 
+  -1, 8041, 837, -1, 8097, -1, 8042, 837, 
+  -1, 8098, -1, 8043, 837, -1, 8099, -1, 
+  8044, 837, -1, 8100, -1, 8045, 837, -1, 
+  8101, -1, 8046, 837, -1, 8102, -1, 8047, 
+  837, -1, 8103, -1, 945, 774, -1, 945, 
+  772, -1, 8048, 837, -1, 8048, 953, -1, 
+  945, 837, -1, 945, 953, -1, 940, 837, 
+  -1, 940, 953, -1, 945, 834, -1, 8118, 
+  837, -1, 945, 834, 953, -1, 913, 774, 
+  -1, 8112, -1, 913, 772, -1, 8113, -1, 
+  913, 768, -1, 8048, -1, 902, -1, 8049, 
+  -1, 913, 837, -1, 8115, -1, 32, 787, 
+  -1, 32, 834, -1, 168, 834, -1, 8052, 
+  837, -1, 8052, 953, -1, 951, 837, -1, 
+  951, 953, -1, 942, 837, -1, 942, 953, 
+  -1, 951, 834, -1, 8134, 837, -1, 951, 
+  834, 953, -1, 917, 768, -1, 8050, -1, 
+  904, -1, 8051, -1, 919, 768, -1, 8052, 
+  -1, 905, -1, 8053, -1, 919, 837, -1, 
+  8131, -1, 8127, 768, -1, 8127, 769, -1, 
+  8127, 834, -1, 953, 774, -1, 953, 772, 
+  -1, 970, 768, -1, 953, 776, 768, -1, 
+  912, -1, 953, 834, -1, 970, 834, -1, 
+  953, 776, 834, -1, 921, 774, -1, 8144, 
+  -1, 921, 772, -1, 8145, -1, 921, 768, 
+  -1, 8054, -1, 906, -1, 8055, -1, 8190, 
+  768, -1, 8190, 769, -1, 8190, 834, -1, 
+  965, 774, -1, 965, 772, -1, 971, 768, 
+  -1, 965, 776, 768, -1, 944, -1, 961, 
+  787, -1, 961, 788, -1, 965, 834, -1, 
+  971, 834, -1, 965, 776, 834, -1, 933, 
+  774, -1, 8160, -1, 933, 772, -1, 8161, 
+  -1, 933, 768, -1, 8058, -1, 910, -1, 
+  8059, -1, 929, 788, -1, 8165, -1, 168, 
+  768, -1, 901, -1, 96, -1, 8060, 837, 
+  -1, 8060, 953, -1, 969, 837, -1, 969, 
+  953, -1, 974, 837, -1, 974, 953, -1, 
+  969, 834, -1, 8182, 837, -1, 969, 834, 
+  953, -1, 927, 768, -1, 8056, -1, 908, 
+  -1, 8057, -1, 937, 768, -1, 8060, -1, 
+  911, -1, 8061, -1, 937, 837, -1, 8179, 
+  -1, 180, -1, 32, 788, -1, 8194, -1, 
+  8195, -1, 8208, -1, 32, 819, -1, 46, 
+  -1, 46, 46, -1, 46, 46, 46, -1, 
+  8242, 8242, -1, 8242, 8242, 8242, -1, 8245, 
+  8245, -1, 8245, 8245, 8245, -1, 33, 33, 
+  -1, 32, 773, -1, 63, 63, -1, 63, 
+  33, -1, 33, 63, -1, 8242, 8242, 8242, 
+  8242, -1, 48, -1, 52, -1, 53, -1, 
+  54, -1, 55, -1, 56, -1, 57, -1, 
+  43, -1, 8722, -1, 61, -1, 40, -1, 
+  41, -1, 82, 115, -1, 97, 47, 99, 
+  -1, 97, 47, 115, -1, 67, -1, 176, 
+  67, -1, 99, 47, 111, -1, 99, 47, 
+  117, -1, 400, -1, 176, 70, -1, 78, 
+  111, -1, 81, -1, 83, 77, -1, 84, 
+  69, 76, -1, 84, 77, -1, 90, -1, 
+  937, -1, 197, -1, 70, -1, 8526, -1, 
+  1488, -1, 1489, -1, 1490, -1, 1491, -1, 
+  70, 65, 88, -1, 915, -1, 928, -1, 
+  8721, -1, 49, 8260, 51, -1, 50, 8260, 
+  51, -1, 49, 8260, 53, -1, 50, 8260, 
+  53, -1, 51, 8260, 53, -1, 52, 8260, 
+  53, -1, 49, 8260, 54, -1, 53, 8260, 
+  54, -1, 49, 8260, 56, -1, 51, 8260, 
+  56, -1, 53, 8260, 56, -1, 55, 8260, 
+  56, -1, 49, 8260, -1, 8560, -1, 73, 
+  73, -1, 8561, -1, 73, 73, 73, -1, 
+  8562, -1, 73, 86, -1, 8563, -1, 86, 
+  -1, 8564, -1, 86, 73, -1, 8565, -1, 
+  86, 73, 73, -1, 8566, -1, 86, 73, 
+  73, 73, -1, 8567, -1, 73, 88, -1, 
+  8568, -1, 88, -1, 8569, -1, 88, 73, 
+  -1, 8570, -1, 88, 73, 73, -1, 8571, 
+  -1, 8572, -1, 8573, -1, 8574, -1, 8575, 
+  -1, 105, 105, -1, 105, 105, 105, -1, 
+  105, 118, -1, 118, 105, -1, 118, 105, 
+  105, -1, 118, 105, 105, 105, -1, 105, 
+  120, -1, 120, 105, -1, 120, 105, 105, 
+  -1, 8580, -1, 8592, 824, -1, 8594, 824, 
+  -1, 8596, 824, -1, 8656, 824, -1, 8660, 
+  824, -1, 8658, 824, -1, 8707, 824, -1, 
+  8712, 824, -1, 8715, 824, -1, 8739, 824, 
+  -1, 8741, 824, -1, 8747, 8747, -1, 8747, 
+  8747, 8747, -1, 8750, 8750, -1, 8750, 8750, 
+  8750, -1, 8764, 824, -1, 8771, 824, -1, 
+  8773, 824, -1, 8776, 824, -1, 61, 824, 
+  -1, 8801, 824, -1, 8781, 824, -1, 60, 
+  824, -1, 62, 824, -1, 8804, 824, -1, 
+  8805, 824, -1, 8818, 824, -1, 8819, 824, 
+  -1, 8822, 824, -1, 8823, 824, -1, 8826, 
+  824, -1, 8827, 824, -1, 8834, 824, -1, 
+  8835, 824, -1, 8838, 824, -1, 8839, 824, 
+  -1, 8866, 824, -1, 8872, 824, -1, 8873, 
+  824, -1, 8875, 824, -1, 8828, 824, -1, 
+  8829, 824, -1, 8849, 824, -1, 8850, 824, 
+  -1, 8882, 824, -1, 8883, 824, -1, 8884, 
+  824, -1, 8885, 824, -1, 12296, -1, 12297, 
+  -1, 49, 48, -1, 49, 49, -1, 49, 
+  50, -1, 49, 51, -1, 49, 52, -1, 
+  49, 53, -1, 49, 54, -1, 49, 55, 
+  -1, 49, 56, -1, 49, 57, -1, 50, 
+  48, -1, 40, 49, 41, -1, 40, 50, 
+  41, -1, 40, 51, 41, -1, 40, 52, 
+  41, -1, 40, 53, 41, -1, 40, 54, 
+  41, -1, 40, 55, 41, -1, 40, 56, 
+  41, -1, 40, 57, 41, -1, 40, 49, 
+  48, 41, -1, 40, 49, 49, 41, -1, 
+  40, 49, 50, 41, -1, 40, 49, 51, 
+  41, -1, 40, 49, 52, 41, -1, 40, 
+  49, 53, 41, -1, 40, 49, 54, 41, 
+  -1, 40, 49, 55, 41, -1, 40, 49, 
+  56, 41, -1, 40, 49, 57, 41, -1, 
+  40, 50, 48, 41, -1, 49, 46, -1, 
+  50, 46, -1, 51, 46, -1, 52, 46, 
+  -1, 53, 46, -1, 54, 46, -1, 55, 
+  46, -1, 56, 46, -1, 57, 46, -1, 
+  49, 48, 46, -1, 49, 49, 46, -1, 
+  49, 50, 46, -1, 49, 51, 46, -1, 
+  49, 52, 46, -1, 49, 53, 46, -1, 
+  49, 54, 46, -1, 49, 55, 46, -1, 
+  49, 56, 46, -1, 49, 57, 46, -1, 
+  50, 48, 46, -1, 40, 97, 41, -1, 
+  40, 98, 41, -1, 40, 99, 41, -1, 
+  40, 100, 41, -1, 40, 101, 41, -1, 
+  40, 102, 41, -1, 40, 103, 41, -1, 
+  40, 104, 41, -1, 40, 105, 41, -1, 
+  40, 106, 41, -1, 40, 107, 41, -1, 
+  40, 108, 41, -1, 40, 109, 41, -1, 
+  40, 110, 41, -1, 40, 111, 41, -1, 
+  40, 112, 41, -1, 40, 113, 41, -1, 
+  40, 114, 41, -1, 40, 115, 41, -1, 
+  40, 116, 41, -1, 40, 117, 41, -1, 
+  40, 118, 41, -1, 40, 119, 41, -1, 
+  40, 120, 41, -1, 40, 121, 41, -1, 
+  40, 122, 41, -1, 9424, -1, 9425, -1, 
+  9426, -1, 9427, -1, 9428, -1, 9429, -1, 
+  9430, -1, 9431, -1, 9432, -1, 9433, -1, 
+  9434, -1, 9435, -1, 9436, -1, 9437, -1, 
+  9438, -1, 9439, -1, 9440, -1, 9441, -1, 
+  83, -1, 9442, -1, 9443, -1, 9444, -1, 
+  9445, -1, 9446, -1, 9447, -1, 89, -1, 
+  9448, -1, 9449, -1, 8747, 8747, 8747, 8747, 
+  -1, 58, 58, 61, -1, 61, 61, -1, 
+  61, 61, 61, -1, 10973, 824, -1, 11312, 
+  -1, 11313, -1, 11314, -1, 11315, -1, 11316, 
+  -1, 11317, -1, 11318, -1, 11319, -1, 11320, 
+  -1, 11321, -1, 11322, -1, 11323, -1, 11324, 
+  -1, 11325, -1, 11326, -1, 11327, -1, 11328, 
+  -1, 11329, -1, 11330, -1, 11331, -1, 11332, 
+  -1, 11333, -1, 11334, -1, 11335, -1, 11336, 
+  -1, 11337, -1, 11338, -1, 11339, -1, 11340, 
+  -1, 11341, -1, 11342, -1, 11343, -1, 11344, 
+  -1, 11345, -1, 11346, -1, 11347, -1, 11348, 
+  -1, 11349, -1, 11350, -1, 11351, -1, 11352, 
+  -1, 11353, -1, 11354, -1, 11355, -1, 11356, 
+  -1, 11357, -1, 11358, -1, 11361, -1, 619, 
+  -1, 7549, -1, 637, -1, 11368, -1, 11370, 
+  -1, 11372, -1, 11382, -1, 11393, -1, 11395, 
+  -1, 11397, -1, 11399, -1, 11401, -1, 11403, 
+  -1, 11405, -1, 11407, -1, 11409, -1, 11411, 
+  -1, 11413, -1, 11415, -1, 11417, -1, 11419, 
+  -1, 11421, -1, 11423, -1, 11425, -1, 11427, 
+  -1, 11429, -1, 11431, -1, 11433, -1, 11435, 
+  -1, 11437, -1, 11439, -1, 11441, -1, 11443, 
+  -1, 11445, -1, 11447, -1, 11449, -1, 11451, 
+  -1, 11453, -1, 11455, -1, 11457, -1, 11459, 
+  -1, 11461, -1, 11463, -1, 11465, -1, 11467, 
+  -1, 11469, -1, 11471, -1, 11473, -1, 11475, 
+  -1, 11477, -1, 11479, -1, 11481, -1, 11483, 
+  -1, 11485, -1, 11487, -1, 11489, -1, 11491, 
+  -1, 11617, -1, 27597, -1, 40863, -1, 19968, 
+  -1, 20008, -1, 20022, -1, 20031, -1, 20057, 
+  -1, 20101, -1, 20108, -1, 20128, -1, 20154, 
+  -1, 20799, -1, 20837, -1, 20843, -1, 20866, 
+  -1, 20886, -1, 20907, -1, 20960, -1, 20981, 
+  -1, 20992, -1, 21147, -1, 21241, -1, 21269, 
+  -1, 21274, -1, 21304, -1, 21313, -1, 21340, 
+  -1, 21353, -1, 21378, -1, 21430, -1, 21448, 
+  -1, 21475, -1, 22231, -1, 22303, -1, 22763, 
+  -1, 22786, -1, 22794, -1, 22805, -1, 22823, 
+  -1, 22899, -1, 23376, -1, 23424, -1, 23544, 
+  -1, 23567, -1, 23586, -1, 23608, -1, 23662, 
+  -1, 23665, -1, 24027, -1, 24037, -1, 24049, 
+  -1, 24062, -1, 24178, -1, 24186, -1, 24191, 
+  -1, 24308, -1, 24318, -1, 24331, -1, 24339, 
+  -1, 24400, -1, 24417, -1, 24435, -1, 24515, 
+  -1, 25096, -1, 25142, -1, 25163, -1, 25903, 
+  -1, 25908, -1, 25991, -1, 26007, -1, 26020, 
+  -1, 26041, -1, 26080, -1, 26085, -1, 26352, 
+  -1, 26376, -1, 26408, -1, 27424, -1, 27490, 
+  -1, 27513, -1, 27571, -1, 27595, -1, 27604, 
+  -1, 27611, -1, 27663, -1, 27668, -1, 27700, 
+  -1, 28779, -1, 29226, -1, 29238, -1, 29243, 
+  -1, 29247, -1, 29255, -1, 29273, -1, 29275, 
+  -1, 29356, -1, 29572, -1, 29577, -1, 29916, 
+  -1, 29926, -1, 29976, -1, 29983, -1, 29992, 
+  -1, 30000, -1, 30091, -1, 30098, -1, 30326, 
+  -1, 30333, -1, 30382, -1, 30399, -1, 30446, 
+  -1, 30683, -1, 30690, -1, 30707, -1, 31034, 
+  -1, 31160, -1, 31166, -1, 31348, -1, 31435, 
+  -1, 31481, -1, 31859, -1, 31992, -1, 32566, 
+  -1, 32593, -1, 32650, -1, 32701, -1, 32769, 
+  -1, 32780, -1, 32786, -1, 32819, -1, 32895, 
+  -1, 32905, -1, 33251, -1, 33258, -1, 33267, 
+  -1, 33276, -1, 33292, -1, 33307, -1, 33311, 
+  -1, 33390, -1, 33394, -1, 33400, -1, 34381, 
+  -1, 34411, -1, 34880, -1, 34892, -1, 34915, 
+  -1, 35198, -1, 35211, -1, 35282, -1, 35328, 
+  -1, 35895, -1, 35910, -1, 35925, -1, 35960, 
+  -1, 35997, -1, 36196, -1, 36208, -1, 36275, 
+  -1, 36523, -1, 36554, -1, 36763, -1, 36784, 
+  -1, 36789, -1, 37009, -1, 37193, -1, 37318, 
+  -1, 37324, -1, 37329, -1, 38263, -1, 38272, 
+  -1, 38428, -1, 38582, -1, 38585, -1, 38632, 
+  -1, 38737, -1, 38750, -1, 38754, -1, 38761, 
+  -1, 38859, -1, 38893, -1, 38899, -1, 38913, 
+  -1, 39080, -1, 39131, -1, 39135, -1, 39318, 
+  -1, 39321, -1, 39340, -1, 39592, -1, 39640, 
+  -1, 39647, -1, 39717, -1, 39727, -1, 39730, 
+  -1, 39740, -1, 39770, -1, 40165, -1, 40565, 
+  -1, 40575, -1, 40613, -1, 40635, -1, 40643, 
+  -1, 40653, -1, 40657, -1, 40697, -1, 40701, 
+  -1, 40718, -1, 40723, -1, 40736, -1, 40763, 
+  -1, 40778, -1, 40786, -1, 40845, -1, 40860, 
+  -1, 40864, -1, 12306, -1, 21316, -1, 21317, 
+  -1, 12363, 12441, -1, 12365, 12441, -1, 12367, 
+  12441, -1, 12369, 12441, -1, 12371, 12441, -1, 
+  12373, 12441, -1, 12375, 12441, -1, 12377, 12441, 
+  -1, 12379, 12441, -1, 12381, 12441, -1, 12383, 
+  12441, -1, 12385, 12441, -1, 12388, 12441, -1, 
+  12390, 12441, -1, 12392, 12441, -1, 12399, 12441, 
+  -1, 12399, 12442, -1, 12402, 12441, -1, 12402, 
+  12442, -1, 12405, 12441, -1, 12405, 12442, -1, 
+  12408, 12441, -1, 12408, 12442, -1, 12411, 12441, 
+  -1, 12411, 12442, -1, 12358, 12441, -1, 32, 
+  12441, -1, 32, 12442, -1, 12445, 12441, -1, 
+  12424, 12426, -1, 12459, 12441, -1, 12461, 12441, 
+  -1, 12463, 12441, -1, 12465, 12441, -1, 12467, 
+  12441, -1, 12469, 12441, -1, 12471, 12441, -1, 
+  12473, 12441, -1, 12475, 12441, -1, 12477, 12441, 
+  -1, 12479, 12441, -1, 12481, 12441, -1, 12484, 
+  12441, -1, 12486, 12441, -1, 12488, 12441, -1, 
+  12495, 12441, -1, 12495, 12442, -1, 12498, 12441, 
+  -1, 12498, 12442, -1, 12501, 12441, -1, 12501, 
+  12442, -1, 12504, 12441, -1, 12504, 12442, -1, 
+  12507, 12441, -1, 12507, 12442, -1, 12454, 12441, 
+  -1, 12527, 12441, -1, 12528, 12441, -1, 12529, 
+  12441, -1, 12530, 12441, -1, 12541, 12441, -1, 
+  12467, 12488, -1, 4352, -1, 4353, -1, 4522, 
+  -1, 4354, -1, 4524, -1, 4525, -1, 4355, 
+  -1, 4356, -1, 4357, -1, 4528, -1, 4529, 
+  -1, 4530, -1, 4531, -1, 4532, -1, 4533, 
+  -1, 4378, -1, 4358, -1, 4359, -1, 4360, 
+  -1, 4385, -1, 4361, -1, 4362, -1, 4363, 
+  -1, 4364, -1, 4365, -1, 4366, -1, 4367, 
+  -1, 4368, -1, 4369, -1, 4370, -1, 4449, 
+  -1, 4450, -1, 4451, -1, 4452, -1, 4453, 
+  -1, 4454, -1, 4455, -1, 4456, -1, 4457, 
+  -1, 4458, -1, 4459, -1, 4460, -1, 4461, 
+  -1, 4462, -1, 4463, -1, 4464, -1, 4465, 
+  -1, 4466, -1, 4467, -1, 4468, -1, 4469, 
+  -1, 4448, -1, 4372, -1, 4373, -1, 4551, 
+  -1, 4552, -1, 4556, -1, 4558, -1, 4563, 
+  -1, 4567, -1, 4569, -1, 4380, -1, 4573, 
+  -1, 4575, -1, 4381, -1, 4382, -1, 4384, 
+  -1, 4386, -1, 4387, -1, 4391, -1, 4393, 
+  -1, 4395, -1, 4396, -1, 4397, -1, 4398, 
+  -1, 4399, -1, 4402, -1, 4406, -1, 4416, 
+  -1, 4423, -1, 4428, -1, 4593, -1, 4594, 
+  -1, 4439, -1, 4440, -1, 4441, -1, 4484, 
+  -1, 4485, -1, 4488, -1, 4497, -1, 4498, 
+  -1, 4500, -1, 4510, -1, 4513, -1, 19977, 
+  -1, 22235, -1, 19978, -1, 20013, -1, 19979, 
+  -1, 30002, -1, 19993, -1, 19969, -1, 22825, 
+  -1, 22320, -1, 40, 4352, 41, -1, 40, 
+  4354, 41, -1, 40, 4355, 41, -1, 40, 
+  4357, 41, -1, 40, 4358, 41, -1, 40, 
+  4359, 41, -1, 40, 4361, 41, -1, 40, 
+  4363, 41, -1, 40, 4364, 41, -1, 40, 
+  4366, 41, -1, 40, 4367, 41, -1, 40, 
+  4368, 41, -1, 40, 4369, 41, -1, 40, 
+  4370, 41, -1, 40, 4352, 4449, 41, -1, 
+  40, 4354, 4449, 41, -1, 40, 4355, 4449, 
+  41, -1, 40, 4357, 4449, 41, -1, 40, 
+  4358, 4449, 41, -1, 40, 4359, 4449, 41, 
+  -1, 40, 4361, 4449, 41, -1, 40, 4363, 
+  4449, 41, -1, 40, 4364, 4449, 41, -1, 
+  40, 4366, 4449, 41, -1, 40, 4367, 4449, 
+  41, -1, 40, 4368, 4449, 41, -1, 40, 
+  4369, 4449, 41, -1, 40, 4370, 4449, 41, 
+  -1, 40, 4364, 4462, 41, -1, 40, 4363, 
+  4457, 4364, 4453, 4523, 41, -1, 40, 4363, 
+  4457, 4370, 4462, 41, -1, 40, 19968, 41, 
+  -1, 40, 20108, 41, -1, 40, 19977, 41, 
+  -1, 40, 22235, 41, -1, 40, 20116, 41, 
+  -1, 40, 20845, 41, -1, 40, 19971, 41, 
+  -1, 40, 20843, 41, -1, 40, 20061, 41, 
+  -1, 40, 21313, 41, -1, 40, 26376, 41, 
+  -1, 40, 28779, 41, -1, 40, 27700, 41, 
+  -1, 40, 26408, 41, -1, 40, 37329, 41, 
+  -1, 40, 22303, 41, -1, 40, 26085, 41, 
+  -1, 40, 26666, 41, -1, 40, 26377, 41, 
+  -1, 40, 31038, 41, -1, 40, 21517, 41, 
+  -1, 40, 29305, 41, -1, 40, 36001, 41, 
+  -1, 40, 31069, 41, -1, 40, 21172, 41, 
+  -1, 40, 20195, 41, -1, 40, 21628, 41, 
+  -1, 40, 23398, 41, -1, 40, 30435, 41, 
+  -1, 40, 20225, 41, -1, 40, 36039, 41, 
+  -1, 40, 21332, 41, -1, 40, 31085, 41, 
+  -1, 40, 20241, 41, -1, 40, 33258, 41, 
+  -1, 40, 33267, 41, -1, 80, 84, 69, 
+  -1, 50, 49, -1, 50, 50, -1, 50, 
+  51, -1, 50, 52, -1, 50, 53, -1, 
+  50, 54, -1, 50, 55, -1, 50, 56, 
+  -1, 50, 57, -1, 51, 48, -1, 51, 
+  49, -1, 51, 50, -1, 51, 51, -1, 
+  51, 52, -1, 51, 53, -1, 4352, 4449, 
+  -1, 4354, 4449, -1, 4355, 4449, -1, 4357, 
+  4449, -1, 4358, 4449, -1, 4359, 4449, -1, 
+  4361, 4449, -1, 4363, 4449, -1, 4364, 4449, 
+  -1, 4366, 4449, -1, 4367, 4449, -1, 4368, 
+  4449, -1, 4369, 4449, -1, 4370, 4449, -1, 
+  4366, 4449, 4535, 4352, 4457, -1, 4364, 4462, 
+  4363, 4468, -1, 4363, 4462, -1, 20116, -1, 
+  20845, -1, 19971, -1, 20061, -1, 26666, -1, 
+  26377, -1, 31038, -1, 21517, -1, 29305, -1, 
+  36001, -1, 31069, -1, 21172, -1, 31192, -1, 
+  30007, -1, 36969, -1, 20778, -1, 21360, -1, 
+  27880, -1, 38917, -1, 20241, -1, 20889, -1, 
+  27491, -1, 24038, -1, 21491, -1, 21307, -1, 
+  23447, -1, 23398, -1, 30435, -1, 20225, -1, 
+  36039, -1, 21332, -1, 22812, -1, 51, 54, 
+  -1, 51, 55, -1, 51, 56, -1, 51, 
+  57, -1, 52, 48, -1, 52, 49, -1, 
+  52, 50, -1, 52, 51, -1, 52, 52, 
+  -1, 52, 53, -1, 52, 54, -1, 52, 
+  55, -1, 52, 56, -1, 52, 57, -1, 
+  53, 48, -1, 49, 26376, -1, 50, 26376, 
+  -1, 51, 26376, -1, 52, 26376, -1, 53, 
+  26376, -1, 54, 26376, -1, 55, 26376, -1, 
+  56, 26376, -1, 57, 26376, -1, 49, 48, 
+  26376, -1, 49, 49, 26376, -1, 49, 50, 
+  26376, -1, 72, 103, -1, 101, 114, 103, 
+  -1, 101, 86, -1, 76, 84, 68, -1, 
+  12450, -1, 12452, -1, 12454, -1, 12456, -1, 
+  12458, -1, 12459, -1, 12461, -1, 12463, -1, 
+  12465, -1, 12467, -1, 12469, -1, 12471, -1, 
+  12473, -1, 12475, -1, 12477, -1, 12479, -1, 
+  12481, -1, 12484, -1, 12486, -1, 12488, -1, 
+  12490, -1, 12491, -1, 12492, -1, 12493, -1, 
+  12494, -1, 12495, -1, 12498, -1, 12501, -1, 
+  12504, -1, 12507, -1, 12510, -1, 12511, -1, 
+  12512, -1, 12513, -1, 12514, -1, 12516, -1, 
+  12518, -1, 12520, -1, 12521, -1, 12522, -1, 
+  12523, -1, 12524, -1, 12525, -1, 12527, -1, 
+  12528, -1, 12529, -1, 12530, -1, 12450, 12497, 
+  12540, 12488, -1, 12450, 12523, 12501, 12449, -1, 
+  12450, 12531, 12506, 12450, -1, 12450, 12540, 12523, 
+  -1, 12452, 12491, 12531, 12464, -1, 12452, 12531, 
+  12481, -1, 12454, 12457, 12531, -1, 12456, 12473, 
+  12463, 12540, 12489, -1, 12456, 12540, 12459, 12540, 
+  -1, 12458, 12531, 12473, -1, 12458, 12540, 12512, 
+  -1, 12459, 12452, 12522, -1, 12459, 12521, 12483, 
+  12488, -1, 12459, 12525, 12522, 12540, -1, 12460, 
+  12525, 12531, -1, 12460, 12531, 12510, -1, 12462, 
+  12460, -1, 12462, 12491, 12540, -1, 12461, 12517, 
+  12522, 12540, -1, 12462, 12523, 12480, 12540, -1, 
+  12461, 12525, -1, 12461, 12525, 12464, 12521, 12512, 
+  -1, 12461, 12525, 12513, 12540, 12488, 12523, -1, 
+  12461, 12525, 12527, 12483, 12488, -1, 12464, 12521, 
+  12512, -1, 12464, 12521, 12512, 12488, 12531, -1, 
+  12463, 12523, 12476, 12452, 12525, -1, 12463, 12525, 
+  12540, 12493, -1, 12465, 12540, 12473, -1, 12467, 
+  12523, 12490, -1, 12467, 12540, 12509, -1, 12469, 
+  12452, 12463, 12523, -1, 12469, 12531, 12481, 12540, 
+  12512, -1, 12471, 12522, 12531, 12464, -1, 12475, 
+  12531, 12481, -1, 12475, 12531, 12488, -1, 12480, 
+  12540, 12473, -1, 12487, 12471, -1, 12489, 12523, 
+  -1, 12488, 12531, -1, 12490, 12494, -1, 12494, 
+  12483, 12488, -1, 12495, 12452, 12484, -1, 12497, 
+  12540, 12475, 12531, 12488, -1, 12497, 12540, 12484, 
+  -1, 12496, 12540, 12524, 12523, -1, 12500, 12450, 
+  12473, 12488, 12523, -1, 12500, 12463, 12523, -1, 
+  12500, 12467, -1, 12499, 12523, -1, 12501, 12449, 
+  12521, 12483, 12489, -1, 12501, 12451, 12540, 12488, 
+  -1, 12502, 12483, 12471, 12455, 12523, -1, 12501, 
+  12521, 12531, -1, 12504, 12463, 12479, 12540, 12523, 
+  -1, 12506, 12477, -1, 12506, 12491, 12498, -1, 
+  12504, 12523, 12484, -1, 12506, 12531, 12473, -1, 
+  12506, 12540, 12472, -1, 12505, 12540, 12479, -1, 
+  12509, 12452, 12531, 12488, -1, 12508, 12523, 12488, 
+  -1, 12507, 12531, -1, 12509, 12531, 12489, -1, 
+  12507, 12540, 12523, -1, 12507, 12540, 12531, -1, 
+  12510, 12452, 12463, 12525, -1, 12510, 12452, 12523, 
+  -1, 12510, 12483, 12495, -1, 12510, 12523, 12463, 
+  -1, 12510, 12531, 12471, 12519, 12531, -1, 12511, 
+  12463, 12525, 12531, -1, 12511, 12522, -1, 12511, 
+  12522, 12496, 12540, 12523, -1, 12513, 12460, -1, 
+  12513, 12460, 12488, 12531, -1, 12513, 12540, 12488, 
+  12523, -1, 12516, 12540, 12489, -1, 12516, 12540, 
+  12523, -1, 12518, 12450, 12531, -1, 12522, 12483, 
+  12488, 12523, -1, 12522, 12521, -1, 12523, 12500, 
+  12540, -1, 12523, 12540, 12502, 12523, -1, 12524, 
+  12512, -1, 12524, 12531, 12488, 12466, 12531, -1, 
+  12527, 12483, 12488, -1, 48, 28857, -1, 49, 
+  28857, -1, 50, 28857, -1, 51, 28857, -1, 
+  52, 28857, -1, 53, 28857, -1, 54, 28857, 
+  -1, 55, 28857, -1, 56, 28857, -1, 57, 
+  28857, -1, 49, 48, 28857, -1, 49, 49, 
+  28857, -1, 49, 50, 28857, -1, 49, 51, 
+  28857, -1, 49, 52, 28857, -1, 49, 53, 
+  28857, -1, 49, 54, 28857, -1, 49, 55, 
+  28857, -1, 49, 56, 28857, -1, 49, 57, 
+  28857, -1, 50, 48, 28857, -1, 50, 49, 
+  28857, -1, 50, 50, 28857, -1, 50, 51, 
+  28857, -1, 50, 52, 28857, -1, 104, 80, 
+  97, -1, 100, 97, -1, 65, 85, -1, 
+  98, 97, 114, -1, 111, 86, -1, 112, 
+  99, -1, 100, 109, -1, 100, 109, 178, 
+  -1, 100, 109, 179, -1, 73, 85, -1, 
+  24179, 25104, -1, 26157, 21644, -1, 22823, 27491, 
+  -1, 26126, 27835, -1, 26666, 24335, 20250, 31038, 
+  -1, 112, 65, -1, 110, 65, -1, 956, 
+  65, -1, 109, 65, -1, 107, 65, -1, 
+  75, 66, -1, 77, 66, -1, 71, 66, 
+  -1, 99, 97, 108, -1, 107, 99, 97, 
+  108, -1, 112, 70, -1, 110, 70, -1, 
+  956, 70, -1, 956, 103, -1, 109, 103, 
+  -1, 107, 103, -1, 72, 122, -1, 107, 
+  72, 122, -1, 77, 72, 122, -1, 71, 
+  72, 122, -1, 84, 72, 122, -1, 956, 
+  8467, -1, 109, 8467, -1, 100, 8467, -1, 
+  107, 8467, -1, 102, 109, -1, 110, 109, 
+  -1, 956, 109, -1, 109, 109, -1, 99, 
+  109, -1, 107, 109, -1, 109, 109, 178, 
+  -1, 99, 109, 178, -1, 109, 178, -1, 
+  107, 109, 178, -1, 109, 109, 179, -1, 
+  99, 109, 179, -1, 109, 179, -1, 107, 
+  109, 179, -1, 109, 8725, 115, -1, 109, 
+  8725, 115, 178, -1, 80, 97, -1, 107, 
+  80, 97, -1, 77, 80, 97, -1, 71, 
+  80, 97, -1, 114, 97, 100, -1, 114, 
+  97, 100, 8725, 115, -1, 114, 97, 100, 
+  8725, 115, 178, -1, 112, 115, -1, 110, 
+  115, -1, 956, 115, -1, 109, 115, -1, 
+  112, 86, -1, 110, 86, -1, 956, 86, 
+  -1, 109, 86, -1, 107, 86, -1, 77, 
+  86, -1, 112, 87, -1, 110, 87, -1, 
+  956, 87, -1, 109, 87, -1, 107, 87, 
+  -1, 77, 87, -1, 107, 937, -1, 77, 
+  937, -1, 97, 46, 109, 46, -1, 66, 
+  113, -1, 99, 99, -1, 99, 100, -1, 
+  67, 8725, 107, 103, -1, 67, 111, 46, 
+  -1, 100, 66, -1, 71, 121, -1, 104, 
+  97, -1, 72, 80, -1, 105, 110, -1, 
+  75, 75, -1, 75, 77, -1, 107, 116, 
+  -1, 108, 109, -1, 108, 110, -1, 108, 
+  111, 103, -1, 108, 120, -1, 109, 98, 
+  -1, 109, 105, 108, -1, 109, 111, 108, 
+  -1, 80, 72, -1, 112, 46, 109, 46, 
+  -1, 80, 80, 77, -1, 80, 82, -1, 
+  115, 114, -1, 83, 118, -1, 87, 98, 
+  -1, 86, 8725, 109, -1, 65, 8725, 109, 
+  -1, 49, 26085, -1, 50, 26085, -1, 51, 
+  26085, -1, 52, 26085, -1, 53, 26085, -1, 
+  54, 26085, -1, 55, 26085, -1, 56, 26085, 
+  -1, 57, 26085, -1, 49, 48, 26085, -1, 
+  49, 49, 26085, -1, 49, 50, 26085, -1, 
+  49, 51, 26085, -1, 49, 52, 26085, -1, 
+  49, 53, 26085, -1, 49, 54, 26085, -1, 
+  49, 55, 26085, -1, 49, 56, 26085, -1, 
+  49, 57, 26085, -1, 50, 48, 26085, -1, 
+  50, 49, 26085, -1, 50, 50, 26085, -1, 
+  50, 51, 26085, -1, 50, 52, 26085, -1, 
+  50, 53, 26085, -1, 50, 54, 26085, -1, 
+  50, 55, 26085, -1, 50, 56, 26085, -1, 
+  50, 57, 26085, -1, 51, 48, 26085, -1, 
+  51, 49, 26085, -1, 103, 97, 108, -1, 
+  35912, -1, 26356, -1, 36040, -1, 28369, -1, 
+  20018, -1, 21477, -1, 22865, -1, 21895, -1, 
+  22856, -1, 25078, -1, 30313, -1, 32645, -1, 
+  34367, -1, 34746, -1, 35064, -1, 37007, -1, 
+  27138, -1, 27931, -1, 28889, -1, 29662, -1, 
+  33853, -1, 37226, -1, 39409, -1, 20098, -1, 
+  21365, -1, 27396, -1, 29211, -1, 34349, -1, 
+  40478, -1, 23888, -1, 28651, -1, 34253, -1, 
+  35172, -1, 25289, -1, 33240, -1, 34847, -1, 
+  24266, -1, 26391, -1, 28010, -1, 29436, -1, 
+  37070, -1, 20358, -1, 20919, -1, 21214, -1, 
+  25796, -1, 27347, -1, 29200, -1, 30439, -1, 
+  34310, -1, 34396, -1, 36335, -1, 38706, -1, 
+  39791, -1, 40442, -1, 30860, -1, 31103, -1, 
+  32160, -1, 33737, -1, 37636, -1, 35542, -1, 
+  22751, -1, 24324, -1, 31840, -1, 32894, -1, 
+  29282, -1, 30922, -1, 36034, -1, 38647, -1, 
+  22744, -1, 23650, -1, 27155, -1, 28122, -1, 
+  28431, -1, 32047, -1, 32311, -1, 38475, -1, 
+  21202, -1, 32907, -1, 20956, -1, 20940, -1, 
+  31260, -1, 32190, -1, 33777, -1, 38517, -1, 
+  35712, -1, 25295, -1, 35582, -1, 20025, -1, 
+  23527, -1, 24594, -1, 29575, -1, 30064, -1, 
+  21271, -1, 30971, -1, 20415, -1, 24489, -1, 
+  19981, -1, 27852, -1, 25976, -1, 32034, -1, 
+  21443, -1, 22622, -1, 30465, -1, 33865, -1, 
+  35498, -1, 27578, -1, 27784, -1, 25342, -1, 
+  33509, -1, 25504, -1, 30053, -1, 20142, -1, 
+  20841, -1, 20937, -1, 26753, -1, 31975, -1, 
+  33391, -1, 35538, -1, 37327, -1, 21237, -1, 
+  21570, -1, 24300, -1, 26053, -1, 28670, -1, 
+  31018, -1, 38317, -1, 39530, -1, 40599, -1, 
+  40654, -1, 26310, -1, 27511, -1, 36706, -1, 
+  24180, -1, 24976, -1, 25088, -1, 25754, -1, 
+  28451, -1, 29001, -1, 29833, -1, 31178, -1, 
+  32244, -1, 32879, -1, 36646, -1, 34030, -1, 
+  36899, -1, 37706, -1, 21015, -1, 21155, -1, 
+  21693, -1, 28872, -1, 35010, -1, 24265, -1, 
+  24565, -1, 25467, -1, 27566, -1, 31806, -1, 
+  29557, -1, 20196, -1, 22265, -1, 23994, -1, 
+  24604, -1, 29618, -1, 29801, -1, 32666, -1, 
+  32838, -1, 37428, -1, 38646, -1, 38728, -1, 
+  38936, -1, 20363, -1, 31150, -1, 37300, -1, 
+  38584, -1, 24801, -1, 20102, -1, 20698, -1, 
+  23534, -1, 23615, -1, 26009, -1, 29134, -1, 
+  30274, -1, 34044, -1, 36988, -1, 26248, -1, 
+  38446, -1, 21129, -1, 26491, -1, 26611, -1, 
+  27969, -1, 28316, -1, 29705, -1, 30041, -1, 
+  30827, -1, 32016, -1, 39006, -1, 25134, -1, 
+  38520, -1, 20523, -1, 23833, -1, 28138, -1, 
+  36650, -1, 24459, -1, 24900, -1, 26647, -1, 
+  38534, -1, 21033, -1, 21519, -1, 23653, -1, 
+  26131, -1, 26446, -1, 26792, -1, 27877, -1, 
+  29702, -1, 30178, -1, 32633, -1, 35023, -1, 
+  35041, -1, 38626, -1, 21311, -1, 28346, -1, 
+  21533, -1, 29136, -1, 29848, -1, 34298, -1, 
+  38563, -1, 40023, -1, 40607, -1, 26519, -1, 
+  28107, -1, 33256, -1, 31520, -1, 31890, -1, 
+  29376, -1, 28825, -1, 35672, -1, 20160, -1, 
+  33590, -1, 21050, -1, 20999, -1, 24230, -1, 
+  25299, -1, 31958, -1, 23429, -1, 27934, -1, 
+  26292, -1, 36667, -1, 38477, -1, 24275, -1, 
+  20800, -1, 21952, -1, 22618, -1, 26228, -1, 
+  20958, -1, 29482, -1, 30410, -1, 31036, -1, 
+  31070, -1, 31077, -1, 31119, -1, 38742, -1, 
+  31934, -1, 34322, -1, 35576, -1, 36920, -1, 
+  37117, -1, 39151, -1, 39164, -1, 39208, -1, 
+  40372, -1, 20398, -1, 20711, -1, 20813, -1, 
+  21193, -1, 21220, -1, 21329, -1, 21917, -1, 
+  22022, -1, 22120, -1, 22592, -1, 22696, -1, 
+  23652, -1, 24724, -1, 24936, -1, 24974, -1, 
+  25074, -1, 25935, -1, 26082, -1, 26257, -1, 
+  26757, -1, 28023, -1, 28186, -1, 28450, -1, 
+  29038, -1, 29227, -1, 29730, -1, 30865, -1, 
+  31049, -1, 31048, -1, 31056, -1, 31062, -1, 
+  31117, -1, 31118, -1, 31296, -1, 31361, -1, 
+  31680, -1, 32265, -1, 32321, -1, 32626, -1, 
+  32773, -1, 33261, -1, 33401, -1, 33879, -1, 
+  35088, -1, 35222, -1, 35585, -1, 35641, -1, 
+  36051, -1, 36104, -1, 36790, -1, 38627, -1, 
+  38911, -1, 38971, -1, 20006, -1, 20917, -1, 
+  20840, -1, 20352, -1, 20805, -1, 20864, -1, 
+  21191, -1, 21242, -1, 21845, -1, 21913, -1, 
+  21986, -1, 22707, -1, 22852, -1, 22868, -1, 
+  23138, -1, 23336, -1, 24274, -1, 24281, -1, 
+  24425, -1, 24493, -1, 24792, -1, 24910, -1, 
+  24840, -1, 24928, -1, 25140, -1, 25540, -1, 
+  25628, -1, 25682, -1, 25942, -1, 26395, -1, 
+  26454, -1, 28379, -1, 28363, -1, 28702, -1, 
+  30631, -1, 29237, -1, 29359, -1, 29809, -1, 
+  29958, -1, 30011, -1, 30237, -1, 30239, -1, 
+  30427, -1, 30452, -1, 30538, -1, 30528, -1, 
+  30924, -1, 31409, -1, 31867, -1, 32091, -1, 
+  32574, -1, 33618, -1, 33775, -1, 34681, -1, 
+  35137, -1, 35206, -1, 35519, -1, 35531, -1, 
+  35565, -1, 35722, -1, 36664, -1, 36978, -1, 
+  37273, -1, 37494, -1, 38524, -1, 38875, -1, 
+  38923, -1, 39698, -1, 141386, -1, 141380, -1, 
+  144341, -1, 15261, -1, 16408, -1, 16441, -1, 
+  152137, -1, 154832, -1, 163539, -1, 40771, -1, 
+  40846, -1, 102, 102, -1, 102, 105, -1, 
+  102, 108, -1, 102, 102, 105, -1, 102, 
+  102, 108, -1, 383, 116, -1, 115, 116, 
+  -1, 1396, 1398, -1, 1396, 1381, -1, 1396, 
+  1387, -1, 1406, 1398, -1, 1396, 1389, -1, 
+  1497, 1460, -1, 1522, 1463, -1, 1506, -1, 
+  1492, -1, 1499, -1, 1500, -1, 1501, -1, 
+  1512, -1, 1514, -1, 1513, 1473, -1, 1513, 
+  1474, -1, 64329, 1473, -1, 64329, 1474, -1, 
+  1488, 1463, -1, 1488, 1464, -1, 1488, 1468, 
+  -1, 1489, 1468, -1, 1490, 1468, -1, 1491, 
+  1468, -1, 1492, 1468, -1, 1493, 1468, -1, 
+  1494, 1468, -1, 1496, 1468, -1, 1497, 1468, 
+  -1, 1498, 1468, -1, 1499, 1468, -1, 1500, 
+  1468, -1, 1502, 1468, -1, 1504, 1468, -1, 
+  1505, 1468, -1, 1507, 1468, -1, 1508, 1468, 
+  -1, 1510, 1468, -1, 1511, 1468, -1, 1512, 
+  1468, -1, 1513, 1468, -1, 1514, 1468, -1, 
+  1493, 1465, -1, 1489, 1471, -1, 1499, 1471, 
+  -1, 1508, 1471, -1, 1488, 1500, -1, 1649, 
+  -1, 1659, -1, 1662, -1, 1664, -1, 1658, 
+  -1, 1663, -1, 1657, -1, 1700, -1, 1702, 
+  -1, 1668, -1, 1667, -1, 1670, -1, 1671, 
+  -1, 1677, -1, 1676, -1, 1678, -1, 1672, 
+  -1, 1688, -1, 1681, -1, 1705, -1, 1711, 
+  -1, 1715, -1, 1713, -1, 1722, -1, 1723, 
+  -1, 1728, -1, 1729, -1, 1726, -1, 1746, 
+  -1, 1747, -1, 1709, -1, 1735, -1, 1734, 
+  -1, 1736, -1, 1655, -1, 1739, -1, 1733, 
+  -1, 1737, -1, 1744, -1, 1609, -1, 1574, 
+  1575, -1, 1574, 1749, -1, 1574, 1608, -1, 
+  1574, 1735, -1, 1574, 1734, -1, 1574, 1736, 
+  -1, 1574, 1744, -1, 1574, 1609, -1, 1740, 
+  -1, 1574, 1580, -1, 1574, 1581, -1, 1574, 
+  1605, -1, 1574, 1610, -1, 1576, 1580, -1, 
+  1576, 1581, -1, 1576, 1582, -1, 1576, 1605, 
+  -1, 1576, 1609, -1, 1576, 1610, -1, 1578, 
+  1580, -1, 1578, 1581, -1, 1578, 1582, -1, 
+  1578, 1605, -1, 1578, 1609, -1, 1578, 1610, 
+  -1, 1579, 1580, -1, 1579, 1605, -1, 1579, 
+  1609, -1, 1579, 1610, -1, 1580, 1581, -1, 
+  1580, 1605, -1, 1581, 1580, -1, 1581, 1605, 
+  -1, 1582, 1580, -1, 1582, 1581, -1, 1582, 
+  1605, -1, 1587, 1580, -1, 1587, 1581, -1, 
+  1587, 1582, -1, 1587, 1605, -1, 1589, 1581, 
+  -1, 1589, 1605, -1, 1590, 1580, -1, 1590, 
+  1581, -1, 1590, 1582, -1, 1590, 1605, -1, 
+  1591, 1581, -1, 1591, 1605, -1, 1592, 1605, 
+  -1, 1593, 1580, -1, 1593, 1605, -1, 1594, 
+  1580, -1, 1594, 1605, -1, 1601, 1580, -1, 
+  1601, 1581, -1, 1601, 1582, -1, 1601, 1605, 
+  -1, 1601, 1609, -1, 1601, 1610, -1, 1602, 
+  1581, -1, 1602, 1605, -1, 1602, 1609, -1, 
+  1602, 1610, -1, 1603, 1575, -1, 1603, 1580, 
+  -1, 1603, 1581, -1, 1603, 1582, -1, 1603, 
+  1604, -1, 1603, 1605, -1, 1603, 1609, -1, 
+  1603, 1610, -1, 1604, 1580, -1, 1604, 1581, 
+  -1, 1604, 1582, -1, 1604, 1605, -1, 1604, 
+  1609, -1, 1604, 1610, -1, 1605, 1580, -1, 
+  1605, 1581, -1, 1605, 1582, -1, 1605, 1605, 
+  -1, 1605, 1609, -1, 1605, 1610, -1, 1606, 
+  1580, -1, 1606, 1581, -1, 1606, 1582, -1, 
+  1606, 1605, -1, 1606, 1609, -1, 1606, 1610, 
+  -1, 1607, 1580, -1, 1607, 1605, -1, 1607, 
+  1609, -1, 1607, 1610, -1, 1610, 1580, -1, 
+  1610, 1581, -1, 1610, 1582, -1, 1610, 1605, 
+  -1, 1610, 1609, -1, 1610, 1610, -1, 1584, 
+  1648, -1, 1585, 1648, -1, 1609, 1648, -1, 
+  32, 1612, 1617, -1, 32, 1613, 1617, -1, 
+  32, 1614, 1617, -1, 32, 1615, 1617, -1, 
+  32, 1616, 1617, -1, 32, 1617, 1648, -1, 
+  1574, 1585, -1, 1574, 1586, -1, 1574, 1606, 
+  -1, 1576, 1585, -1, 1576, 1586, -1, 1576, 
+  1606, -1, 1578, 1585, -1, 1578, 1586, -1, 
+  1578, 1606, -1, 1579, 1585, -1, 1579, 1586, 
+  -1, 1579, 1606, -1, 1605, 1575, -1, 1606, 
+  1585, -1, 1606, 1586, -1, 1606, 1606, -1, 
+  1610, 1585, -1, 1610, 1586, -1, 1610, 1606, 
+  -1, 1574, 1582, -1, 1574, 1607, -1, 1576, 
+  1607, -1, 1578, 1607, -1, 1589, 1582, -1, 
+  1604, 1607, -1, 1606, 1607, -1, 1607, 1648, 
+  -1, 1610, 1607, -1, 1579, 1607, -1, 1587, 
+  1607, -1, 1588, 1605, -1, 1588, 1607, -1, 
+  1600, 1614, 1617, -1, 1600, 1615, 1617, -1, 
+  1600, 1616, 1617, -1, 1591, 1609, -1, 1591, 
+  1610, -1, 1593, 1609, -1, 1593, 1610, -1, 
+  1594, 1609, -1, 1594, 1610, -1, 1587, 1609, 
+  -1, 1587, 1610, -1, 1588, 1609, -1, 1588, 
+  1610, -1, 1581, 1609, -1, 1581, 1610, -1, 
+  1580, 1609, -1, 1580, 1610, -1, 1582, 1609, 
+  -1, 1582, 1610, -1, 1589, 1609, -1, 1589, 
+  1610, -1, 1590, 1609, -1, 1590, 1610, -1, 
+  1588, 1580, -1, 1588, 1581, -1, 1588, 1582, 
+  -1, 1588, 1585, -1, 1587, 1585, -1, 1589, 
+  1585, -1, 1590, 1585, -1, 1575, 1611, -1, 
+  1578, 1580, 1605, -1, 1578, 1581, 1580, -1, 
+  1578, 1581, 1605, -1, 1578, 1582, 1605, -1, 
+  1578, 1605, 1580, -1, 1578, 1605, 1581, -1, 
+  1578, 1605, 1582, -1, 1580, 1605, 1581, -1, 
+  1581, 1605, 1610, -1, 1581, 1605, 1609, -1, 
+  1587, 1581, 1580, -1, 1587, 1580, 1581, -1, 
+  1587, 1580, 1609, -1, 1587, 1605, 1581, -1, 
+  1587, 1605, 1580, -1, 1587, 1605, 1605, -1, 
+  1589, 1581, 1581, -1, 1589, 1605, 1605, -1, 
+  1588, 1581, 1605, -1, 1588, 1580, 1610, -1, 
+  1588, 1605, 1582, -1, 1588, 1605, 1605, -1, 
+  1590, 1581, 1609, -1, 1590, 1582, 1605, -1, 
+  1591, 1605, 1581, -1, 1591, 1605, 1605, -1, 
+  1591, 1605, 1610, -1, 1593, 1580, 1605, -1, 
+  1593, 1605, 1605, -1, 1593, 1605, 1609, -1, 
+  1594, 1605, 1605, -1, 1594, 1605, 1610, -1, 
+  1594, 1605, 1609, -1, 1601, 1582, 1605, -1, 
+  1602, 1605, 1581, -1, 1602, 1605, 1605, -1, 
+  1604, 1581, 1605, -1, 1604, 1581, 1610, -1, 
+  1604, 1581, 1609, -1, 1604, 1580, 1580, -1, 
+  1604, 1582, 1605, -1, 1604, 1605, 1581, -1, 
+  1605, 1581, 1580, -1, 1605, 1581, 1605, -1, 
+  1605, 1581, 1610, -1, 1605, 1580, 1581, -1, 
+  1605, 1580, 1605, -1, 1605, 1582, 1580, -1, 
+  1605, 1582, 1605, -1, 1605, 1580, 1582, -1, 
+  1607, 1605, 1580, -1, 1607, 1605, 1605, -1, 
+  1606, 1581, 1605, -1, 1606, 1581, 1609, -1, 
+  1606, 1580, 1605, -1, 1606, 1580, 1609, -1, 
+  1606, 1605, 1610, -1, 1606, 1605, 1609, -1, 
+  1610, 1605, 1605, -1, 1576, 1582, 1610, -1, 
+  1578, 1580, 1610, -1, 1578, 1580, 1609, -1, 
+  1578, 1582, 1610, -1, 1578, 1582, 1609, -1, 
+  1578, 1605, 1610, -1, 1578, 1605, 1609, -1, 
+  1580, 1605, 1610, -1, 1580, 1581, 1609, -1, 
+  1580, 1605, 1609, -1, 1587, 1582, 1609, -1, 
+  1589, 1581, 1610, -1, 1588, 1581, 1610, -1, 
+  1590, 1581, 1610, -1, 1604, 1580, 1610, -1, 
+  1604, 1605, 1610, -1, 1610, 1581, 1610, -1, 
+  1610, 1580, 1610, -1, 1610, 1605, 1610, -1, 
+  1605, 1605, 1610, -1, 1602, 1605, 1610, -1, 
+  1606, 1581, 1610, -1, 1593, 1605, 1610, -1, 
+  1603, 1605, 1610, -1, 1606, 1580, 1581, -1, 
+  1605, 1582, 1610, -1, 1604, 1580, 1605, -1, 
+  1603, 1605, 1605, -1, 1580, 1581, 1610, -1, 
+  1581, 1580, 1610, -1, 1605, 1580, 1610, -1, 
+  1601, 1605, 1610, -1, 1576, 1581, 1610, -1, 
+  1587, 1582, 1610, -1, 1606, 1580, 1610, -1, 
+  1589, 1604, 1746, -1, 1602, 1604, 1746, -1, 
+  1575, 1604, 1604, 1607, -1, 1575, 1603, 1576, 
+  1585, -1, 1605, 1581, 1605, 1583, -1, 1589, 
+  1604, 1593, 1605, -1, 1585, 1587, 1608, 1604, 
+  -1, 1593, 1604, 1610, 1607, -1, 1608, 1587, 
+  1604, 1605, -1, 1589, 1604, 1609, -1, 1589, 
+  1604, 1609, 32, 1575, 1604, 1604, 1607, 32, 
+  1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 
+  1605, -1, 1580, 1604, 32, 1580, 1604, 1575, 
+  1604, 1607, -1, 1585, 1740, 1575, 1604, -1, 
+  44, -1, 12289, -1, 12290, -1, 58, -1, 
+  33, -1, 63, -1, 12310, -1, 12311, -1, 
+  8230, -1, 8229, -1, 8212, -1, 8211, -1, 
+  95, -1, 123, -1, 125, -1, 12308, -1, 
+  12309, -1, 12304, -1, 12305, -1, 12298, -1, 
+  12299, -1, 12300, -1, 12301, -1, 12302, -1, 
+  12303, -1, 91, -1, 93, -1, 8254, -1, 
+  35, -1, 38, -1, 42, -1, 45, -1, 
+  60, -1, 62, -1, 92, -1, 36, -1, 
+  37, -1, 64, -1, 32, 1611, -1, 1600, 
+  1611, -1, 32, 1612, -1, 32, 1613, -1, 
+  32, 1614, -1, 1600, 1614, -1, 32, 1615, 
+  -1, 1600, 1615, -1, 32, 1616, -1, 1600, 
+  1616, -1, 32, 1617, -1, 1600, 1617, -1, 
+  32, 1618, -1, 1600, 1618, -1, 1569, -1, 
+  1570, -1, 1571, -1, 1572, -1, 1573, -1, 
+  1574, -1, 1575, -1, 1576, -1, 1577, -1, 
+  1578, -1, 1579, -1, 1580, -1, 1581, -1, 
+  1582, -1, 1583, -1, 1584, -1, 1585, -1, 
+  1586, -1, 1587, -1, 1588, -1, 1589, -1, 
+  1590, -1, 1591, -1, 1592, -1, 1593, -1, 
+  1594, -1, 1601, -1, 1602, -1, 1603, -1, 
+  1604, -1, 1605, -1, 1606, -1, 1607, -1, 
+  1608, -1, 1610, -1, 1604, 1570, -1, 1604, 
+  1571, -1, 1604, 1573, -1, 1604, 1575, -1, 
+  34, -1, 39, -1, 47, -1, 65345, -1, 
+  65346, -1, 65347, -1, 65348, -1, 65349, -1, 
+  65350, -1, 65351, -1, 65352, -1, 65353, -1, 
+  65354, -1, 65355, -1, 65356, -1, 65357, -1, 
+  65358, -1, 65359, -1, 65360, -1, 65361, -1, 
+  65362, -1, 65363, -1, 65364, -1, 65365, -1, 
+  65366, -1, 65367, -1, 65368, -1, 65369, -1, 
+  65370, -1, 94, -1, 124, -1, 126, -1, 
+  10629, -1, 10630, -1, 12539, -1, 12449, -1, 
+  12451, -1, 12453, -1, 12455, -1, 12457, -1, 
+  12515, -1, 12517, -1, 12519, -1, 12483, -1, 
+  12540, -1, 12531, -1, 12441, -1, 12442, -1, 
+  12644, -1, 12593, -1, 12594, -1, 12595, -1, 
+  12596, -1, 12597, -1, 12598, -1, 12599, -1, 
+  12600, -1, 12601, -1, 12602, -1, 12603, -1, 
+  12604, -1, 12605, -1, 12606, -1, 12607, -1, 
+  12608, -1, 12609, -1, 12610, -1, 12611, -1, 
+  12612, -1, 12613, -1, 12614, -1, 12615, -1, 
+  12616, -1, 12617, -1, 12618, -1, 12619, -1, 
+  12620, -1, 12621, -1, 12622, -1, 12623, -1, 
+  12624, -1, 12625, -1, 12626, -1, 12627, -1, 
+  12628, -1, 12629, -1, 12630, -1, 12631, -1, 
+  12632, -1, 12633, -1, 12634, -1, 12635, -1, 
+  12636, -1, 12637, -1, 12638, -1, 12639, -1, 
+  12640, -1, 12641, -1, 12642, -1, 12643, -1, 
+  162, -1, 163, -1, 172, -1, 175, -1, 
+  166, -1, 165, -1, 8361, -1, 9474, -1, 
+  8592, -1, 8593, -1, 8594, -1, 8595, -1, 
+  9632, -1, 9675, -1, 66600, -1, 66601, -1, 
+  66602, -1, 66603, -1, 66604, -1, 66605, -1, 
+  66606, -1, 66607, -1, 66608, -1, 66609, -1, 
+  66610, -1, 66611, -1, 66612, -1, 66613, -1, 
+  66614, -1, 66615, -1, 66616, -1, 66617, -1, 
+  66618, -1, 66619, -1, 66620, -1, 66621, -1, 
+  66622, -1, 66623, -1, 66624, -1, 66625, -1, 
+  66626, -1, 66627, -1, 66628, -1, 66629, -1, 
+  66630, -1, 66631, -1, 66632, -1, 66633, -1, 
+  66634, -1, 66635, -1, 66636, -1, 66637, -1, 
+  66638, -1, 66639, -1, 119127, 119141, -1, 119128, 
+  119141, -1, 119135, 119150, -1, 119135, 119151, -1, 
+  119135, 119152, -1, 119135, 119153, -1, 119135, 119154, 
+  -1, 119225, 119141, -1, 119226, 119141, -1, 119227, 
+  119150, -1, 119228, 119150, -1, 119227, 119151, -1, 
+  119228, 119151, -1, 305, -1, 567, -1, 913, 
+  -1, 914, -1, 916, -1, 917, -1, 918, 
+  -1, 919, -1, 921, -1, 922, -1, 923, 
+  -1, 924, -1, 925, -1, 926, -1, 927, 
+  -1, 929, -1, 1012, -1, 932, -1, 934, 
+  -1, 935, -1, 936, -1, 8711, -1, 8706, 
+  -1, 1013, -1, 977, -1, 1008, -1, 981, 
+  -1, 1009, -1, 982, -1, 988, -1, 20029, 
+  -1, 20024, -1, 20033, -1, 131362, -1, 20320, 
+  -1, 20411, -1, 20482, -1, 20602, -1, 20633, 
+  -1, 20687, -1, 13470, -1, 132666, -1, 20820, 
+  -1, 20836, -1, 20855, -1, 132380, -1, 13497, 
+  -1, 20839, -1, 20877, -1, 132427, -1, 20887, 
+  -1, 20900, -1, 20172, -1, 20908, -1, 168415, 
+  -1, 20995, -1, 13535, -1, 21051, -1, 21062, 
+  -1, 21106, -1, 21111, -1, 13589, -1, 21253, 
+  -1, 21254, -1, 21321, -1, 21338, -1, 21363, 
+  -1, 21373, -1, 21375, -1, 133676, -1, 28784, 
+  -1, 21450, -1, 21471, -1, 133987, -1, 21483, 
+  -1, 21489, -1, 21510, -1, 21662, -1, 21560, 
+  -1, 21576, -1, 21608, -1, 21666, -1, 21750, 
+  -1, 21776, -1, 21843, -1, 21859, -1, 21892, 
+  -1, 21931, -1, 21939, -1, 21954, -1, 22294, 
+  -1, 22295, -1, 22097, -1, 22132, -1, 22766, 
+  -1, 22478, -1, 22516, -1, 22541, -1, 22411, 
+  -1, 22578, -1, 22577, -1, 22700, -1, 136420, 
+  -1, 22770, -1, 22775, -1, 22790, -1, 22810, 
+  -1, 22818, -1, 22882, -1, 136872, -1, 136938, 
+  -1, 23020, -1, 23067, -1, 23079, -1, 23000, 
+  -1, 23142, -1, 14062, -1, 14076, -1, 23304, 
+  -1, 23358, -1, 137672, -1, 23491, -1, 23512, 
+  -1, 23539, -1, 138008, -1, 23551, -1, 23558, 
+  -1, 24403, -1, 14209, -1, 23648, -1, 23744, 
+  -1, 23693, -1, 138724, -1, 23875, -1, 138726, 
+  -1, 23918, -1, 23915, -1, 23932, -1, 24033, 
+  -1, 24034, -1, 14383, -1, 24061, -1, 24104, 
+  -1, 24125, -1, 24169, -1, 14434, -1, 139651, 
+  -1, 14460, -1, 24240, -1, 24243, -1, 24246, 
+  -1, 172946, -1, 140081, -1, 33281, -1, 24354, 
+  -1, 14535, -1, 144056, -1, 156122, -1, 24418, 
+  -1, 24427, -1, 14563, -1, 24474, -1, 24525, 
+  -1, 24535, -1, 24569, -1, 24705, -1, 14650, 
+  -1, 14620, -1, 141012, -1, 24775, -1, 24904, 
+  -1, 24908, -1, 24954, -1, 25010, -1, 24996, 
+  -1, 25007, -1, 25054, -1, 25104, -1, 25115, 
+  -1, 25181, -1, 25265, -1, 25300, -1, 25424, 
+  -1, 142092, -1, 25405, -1, 25340, -1, 25448, 
+  -1, 25475, -1, 25572, -1, 142321, -1, 25634, 
+  -1, 25541, -1, 25513, -1, 14894, -1, 25705, 
+  -1, 25726, -1, 25757, -1, 25719, -1, 14956, 
+  -1, 25964, -1, 143370, -1, 26083, -1, 26360, 
+  -1, 26185, -1, 15129, -1, 15112, -1, 15076, 
+  -1, 20882, -1, 20885, -1, 26368, -1, 26268, 
+  -1, 32941, -1, 17369, -1, 26401, -1, 26462, 
+  -1, 26451, -1, 144323, -1, 15177, -1, 26618, 
+  -1, 26501, -1, 26706, -1, 144493, -1, 26766, 
+  -1, 26655, -1, 26900, -1, 26946, -1, 27043, 
+  -1, 27114, -1, 27304, -1, 145059, -1, 27355, 
+  -1, 15384, -1, 27425, -1, 145575, -1, 27476, 
+  -1, 15438, -1, 27506, -1, 27551, -1, 27579, 
+  -1, 146061, -1, 138507, -1, 146170, -1, 27726, 
+  -1, 146620, -1, 27839, -1, 27853, -1, 27751, 
+  -1, 27926, -1, 27966, -1, 28009, -1, 28024, 
+  -1, 28037, -1, 146718, -1, 27956, -1, 28207, 
+  -1, 28270, -1, 15667, -1, 28359, -1, 147153, 
+  -1, 28153, -1, 28526, -1, 147294, -1, 147342, 
+  -1, 28614, -1, 28729, -1, 28699, -1, 15766, 
+  -1, 28746, -1, 28797, -1, 28791, -1, 28845, 
+  -1, 132389, -1, 28997, -1, 148067, -1, 29084, 
+  -1, 148395, -1, 29224, -1, 29264, -1, 149000, 
+  -1, 29312, -1, 29333, -1, 149301, -1, 149524, 
+  -1, 29562, -1, 29579, -1, 16044, -1, 29605, 
+  -1, 16056, -1, 29767, -1, 29788, -1, 29829, 
+  -1, 29898, -1, 16155, -1, 29988, -1, 150582, 
+  -1, 30014, -1, 150674, -1, 139679, -1, 30224, 
+  -1, 151457, -1, 151480, -1, 151620, -1, 16380, 
+  -1, 16392, -1, 151795, -1, 151794, -1, 151833, 
+  -1, 151859, -1, 30494, -1, 30495, -1, 30603, 
+  -1, 16454, -1, 16534, -1, 152605, -1, 30798, 
+  -1, 16611, -1, 153126, -1, 153242, -1, 153285, 
+  -1, 31211, -1, 16687, -1, 31306, -1, 31311, 
+  -1, 153980, -1, 154279, -1, 31470, -1, 16898, 
+  -1, 154539, -1, 31686, -1, 31689, -1, 16935, 
+  -1, 154752, -1, 31954, -1, 17056, -1, 31976, 
+  -1, 31971, -1, 32000, -1, 155526, -1, 32099, 
+  -1, 17153, -1, 32199, -1, 32258, -1, 32325, 
+  -1, 17204, -1, 156200, -1, 156231, -1, 17241, 
+  -1, 156377, -1, 32634, -1, 156478, -1, 32661, 
+  -1, 32762, -1, 156890, -1, 156963, -1, 32864, 
+  -1, 157096, -1, 32880, -1, 144223, -1, 17365, 
+  -1, 32946, -1, 33027, -1, 17419, -1, 33086, 
+  -1, 23221, -1, 157607, -1, 157621, -1, 144275, 
+  -1, 144284, -1, 33284, -1, 36766, -1, 17515, 
+  -1, 33425, -1, 33419, -1, 33437, -1, 21171, 
+  -1, 33457, -1, 33459, -1, 33469, -1, 33510, 
+  -1, 158524, -1, 33565, -1, 33635, -1, 33709, 
+  -1, 33571, -1, 33725, -1, 33767, -1, 33619, 
+  -1, 33738, -1, 33740, -1, 33756, -1, 158774, 
+  -1, 159083, -1, 158933, -1, 17707, -1, 34033, 
+  -1, 34035, -1, 34070, -1, 160714, -1, 34148, 
+  -1, 159532, -1, 17757, -1, 17761, -1, 159665, 
+  -1, 159954, -1, 17771, -1, 34384, -1, 34407, 
+  -1, 34409, -1, 34473, -1, 34440, -1, 34574, 
+  -1, 34530, -1, 34600, -1, 34667, -1, 34694, 
+  -1, 17879, -1, 34785, -1, 34817, -1, 17913, 
+  -1, 34912, -1, 161383, -1, 35031, -1, 35038, 
+  -1, 17973, -1, 35066, -1, 13499, -1, 161966, 
+  -1, 162150, -1, 18110, -1, 18119, -1, 35488, 
+  -1, 162984, -1, 36011, -1, 36033, -1, 36123, 
+  -1, 36215, -1, 163631, -1, 133124, -1, 36299, 
+  -1, 36284, -1, 36336, -1, 133342, -1, 36564, 
+  -1, 165330, -1, 165357, -1, 37012, -1, 37105, 
+  -1, 37137, -1, 165678, -1, 37147, -1, 37432, 
+  -1, 37591, -1, 37592, -1, 37500, -1, 37881, 
+  -1, 37909, -1, 166906, -1, 38283, -1, 18837, 
+  -1, 38327, -1, 167287, -1, 18918, -1, 38595, 
+  -1, 23986, -1, 38691, -1, 168261, -1, 168474, 
+  -1, 19054, -1, 19062, -1, 38880, -1, 168970, 
+  -1, 19122, -1, 169110, -1, 38953, -1, 169398, 
+  -1, 39138, -1, 19251, -1, 39209, -1, 39335, 
+  -1, 39362, -1, 39422, -1, 19406, -1, 170800, 
+  -1, 40000, -1, 40189, -1, 19662, -1, 19693, 
+  -1, 40295, -1, 172238, -1, 19704, -1, 172293, 
+  -1, 172558, -1, 172689, -1, 19798, -1, 40702, 
+  -1, 40709, -1, 40719, -1, 40726, -1, 173568, 
+  -1, };
+
+const uint16_t utf8proc_stage1table[] = {
+  0, 256, 512, 768, 1024, 1280, 1536, 
+  1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 
+  3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632, 
+  5888, 6144, 6400, 6656, 6912, 2048, 7168, 7424, 
+  7680, 7936, 8192, 8448, 8704, 8960, 9216, 9472, 
+  9728, 9984, 10240, 10496, 10752, 11008, 11264, 11520, 
+  11776, 12032, 12288, 12544, 12800, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 13056, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  13312, 13568, 5376, 5376, 5376, 13824, 2048, 2048, 
+  14080, 14336, 2048, 2048, 2048, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  14592, 14848, 14848, 14848, 14848, 14848, 14848, 14848, 
+  14848, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15360, 15616, 15872, 16128, 16384, 16640, 
+  16896, 17152, 17408, 2048, 17664, 17920, 2048, 2048, 
+  2048, 18176, 18432, 18688, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 5376, 5376, 5376, 18944, 19200, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 19456, 19712, 19968, 20224, 20480, 20736, 20992, 
+  21248, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 
+  5376, 5376, 5376, 5376, 5376, 5376, 5376, 21504, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 21760, 22016, 22272, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 22528, 22784, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 
+  2048, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  23040, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, 
+  23040, };
+
+const uint16_t utf8proc_stage2table[] = {
+  1, 1, 1, 1, 1, 1, 1, 
+  1, 1, 2, 3, 2, 4, 3, 1, 
+  1, 1, 1, 1, 1, 1, 1, 1, 
+  1, 1, 1, 1, 1, 5, 5, 5, 
+  6, 7, 8, 8, 9, 10, 9, 8, 
+  8, 11, 12, 8, 13, 14, 15, 14, 
+  14, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 14, 8, 17, 18, 19, 
+  8, 8, 20, 21, 22, 23, 24, 25, 
+  26, 27, 28, 29, 30, 31, 32, 33, 
+  34, 35, 36, 37, 38, 39, 40, 41, 
+  42, 43, 44, 45, 11, 8, 12, 46, 
+  47, 46, 48, 49, 50, 51, 52, 53, 
+  54, 55, 56, 57, 58, 59, 60, 61, 
+  62, 63, 64, 65, 66, 67, 68, 69, 
+  70, 71, 72, 73, 11, 74, 12, 74, 
+  1, 1, 1, 1, 1, 1, 3, 1, 
+  1, 1, 1, 1, 1, 1, 1, 1, 
+  1, 1, 1, 1, 1, 1, 1, 1, 
+  1, 1, 1, 1, 1, 1, 1, 1, 
+  1, 75, 8, 10, 10, 10, 10, 76, 
+  76, 77, 76, 78, 79, 74, 80, 76, 
+  81, 82, 83, 84, 85, 86, 87, 76, 
+  8, 88, 89, 90, 91, 92, 93, 94, 
+  8, 95, 96, 97, 98, 99, 100, 101, 
+  102, 103, 104, 105, 106, 107, 108, 109, 
+  110, 111, 112, 113, 114, 115, 116, 117, 
+  74, 118, 119, 120, 121, 122, 123, 124, 
+  125, 126, 127, 128, 129, 130, 131, 132, 
+  133, 134, 135, 136, 137, 138, 139, 140, 
+  141, 142, 143, 144, 145, 146, 147, 148, 
+  74, 149, 150, 151, 152, 153, 154, 155, 
+  156, 157, 158, 159, 160, 161, 162, 163, 
+  164, 165, 166, 167, 168, 169, 170, 171, 
+  172, 173, 174, 175, 176, 177, 178, 179, 
+  180, 181, 182, 183, 184, 185, 186, 187, 
+  188, 189, 190, 191, 192, 193, 194, 195, 
+  196, 197, 198, 199, 200, 201, 202, 203, 
+  204, 205, 206, 207, 208, 209, 210, 211, 
+  212, 213, 214, 215, 216, 217, 218, 219, 
+  220, 221, 222, 223, 224, 225, 226, 227, 
+  228, 229, 230, 231, 232, 233, 234, 235, 
+  236, 237, 238, 239, 240, 241, 242, 243, 
+  244, 245, 246, 247, 248, 249, 250, 251, 
+  252, 253, 254, 255, 256, 257, 258, 259, 
+  260, 261, 262, 263, 264, 265, 266, 267, 
+  268, 269, 270, 271, 272, 273, 274, 275, 
+  276, 277, 278, 279, 280, 281, 282, 283, 
+  284, 285, 286, 287, 288, 289, 290, 291, 
+  292, 293, 294, 295, 296, 297, 213, 298, 
+  299, 300, 301, 302, 303, 304, 305, 306, 
+  307, 308, 309, 310, 213, 311, 312, 313, 
+  314, 315, 316, 317, 318, 319, 320, 321, 
+  322, 323, 324, 213, 213, 325, 326, 327, 
+  328, 329, 330, 331, 332, 333, 334, 335, 
+  336, 337, 338, 213, 339, 340, 341, 213, 
+  342, 339, 339, 339, 339, 343, 344, 345, 
+  346, 347, 348, 349, 350, 351, 352, 353, 
+  354, 355, 356, 357, 358, 359, 360, 361, 
+  362, 363, 364, 365, 366, 367, 368, 369, 
+  370, 371, 372, 373, 374, 375, 376, 377, 
+  378, 379, 380, 381, 382, 383, 384, 385, 
+  386, 387, 388, 389, 390, 391, 392, 393, 
+  394, 395, 396, 397, 398, 399, 400, 401, 
+  402, 403, 404, 405, 406, 407, 408, 409, 
+  410, 411, 412, 413, 414, 415, 416, 417, 
+  418, 419, 420, 421, 422, 423, 424, 425, 
+  426, 427, 428, 429, 430, 431, 432, 433, 
+  434, 435, 213, 436, 437, 438, 439, 440, 
+  441, 442, 443, 444, 445, 446, 447, 448, 
+  449, 450, 451, 452, 453, 213, 213, 213, 
+  213, 213, 213, 454, 455, 456, 457, 458, 
+  213, 213, 459, 460, 461, 462, 463, 464, 
+  465, 466, 467, 468, 469, 470, 471, 472, 
+  473, 213, 213, 213, 474, 475, 213, 476, 
+  477, 213, 478, 213, 479, 213, 213, 213, 
+  213, 480, 213, 213, 481, 213, 213, 213, 
+  213, 482, 483, 213, 484, 213, 213, 213, 
+  485, 213, 213, 486, 213, 213, 487, 213, 
+  213, 213, 213, 213, 213, 213, 488, 213, 
+  213, 489, 213, 213, 490, 213, 213, 213, 
+  213, 491, 492, 493, 494, 495, 213, 213, 
+  213, 213, 213, 496, 213, 339, 213, 213, 
+  213, 213, 213, 213, 213, 213, 213, 213, 
+  213, 213, 213, 213, 213, 213, 213, 213, 
+  213, 213, 213, 213, 213, 213, 213, 213, 
+  213, 497, 498, 499, 500, 501, 502, 503, 
+  504, 505, 506, 506, 507, 507, 507, 507, 
+  507, 507, 507, 46, 46, 46, 46, 506, 
+  506, 506, 506, 506, 506, 506, 506, 506, 
+  506, 507, 507, 46, 46, 46, 46, 46, 
+  46, 508, 509, 510, 511, 512, 513, 46, 
+  46, 514, 515, 516, 517, 518, 46, 46, 
+  46, 46, 46, 46, 46, 46, 46, 507, 
+  46, 46, 46, 46, 46, 46, 46, 46, 
+  46, 46, 46, 46, 46, 46, 46, 46, 
+  46, 519, 520, 521, 522, 523, 524, 525, 
+  526, 527, 528, 529, 530, 531, 524, 524, 
+  532, 524, 533, 524, 534, 535, 536, 537, 
+  537, 537, 537, 536, 538, 537, 537, 537, 
+  537, 537, 539, 539, 540, 541, 542, 543, 
+  544, 545, 537, 537, 537, 537, 546, 547, 
+  537, 548, 549, 537, 537, 550, 550, 550, 
+  550, 551, 537, 537, 537, 537, 524, 524, 
+  524, 552, 553, 554, 555, 556, 557, 524, 
+  537, 537, 537, 524, 524, 524, 537, 537, 
+  558, 524, 524, 524, 537, 537, 537, 537, 
+  524, 536, 537, 537, 524, 559, 560, 560, 
+  559, 560, 560, 559, 524, 524, 524, 524, 
+  524, 524, 524, 524, 524, 524, 524, 524, 
+  524, 0, 0, 0, 0, 561, 46, 0, 
+  0, 0, 0, 562, 563, 564, 565, 566, 
+  0, 0, 0, 0, 0, 86, 567, 568, 
+  569, 570, 571, 572, 0, 573, 0, 574, 
+  575, 576, 577, 578, 579, 580, 581, 582, 
+  583, 584, 585, 586, 587, 588, 589, 590, 
+  591, 592, 593, 0, 594, 595, 596, 597, 
+  598, 599, 600, 601, 602, 603, 604, 605, 
+  606, 607, 608, 609, 610, 611, 612, 613, 
+  614, 615, 616, 617, 618, 619, 620, 621, 
+  622, 623, 624, 625, 626, 627, 628, 629, 
+  630, 631, 632, 633, 634, 635, 636, 637, 
+  0, 638, 639, 640, 641, 642, 643, 644, 
+  213, 645, 646, 647, 648, 649, 650, 651, 
+  652, 653, 654, 655, 656, 657, 658, 659, 
+  660, 661, 662, 663, 664, 665, 666, 667, 
+  668, 669, 670, 671, 213, 672, 673, 74, 
+  674, 675, 676, 677, 678, 213, 679, 680, 
+  681, 682, 683, 684, 685, 686, 687, 688, 
+  689, 690, 691, 692, 693, 694, 695, 696, 
+  697, 698, 699, 700, 701, 702, 703, 704, 
+  705, 706, 707, 708, 709, 710, 711, 712, 
+  713, 714, 715, 716, 717, 718, 719, 720, 
+  721, 722, 723, 724, 725, 726, 727, 728, 
+  729, 730, 731, 732, 733, 734, 735, 736, 
+  737, 738, 739, 740, 741, 742, 743, 744, 
+  745, 746, 747, 748, 749, 750, 751, 752, 
+  753, 754, 755, 756, 757, 758, 759, 760, 
+  761, 762, 763, 764, 765, 766, 767, 768, 
+  769, 770, 771, 772, 773, 774, 775, 776, 
+  777, 778, 779, 780, 781, 782, 783, 784, 
+  785, 786, 787, 788, 789, 790, 791, 792, 
+  793, 794, 795, 796, 797, 798, 799, 800, 
+  801, 802, 803, 804, 805, 806, 807, 808, 
+  809, 810, 811, 812, 524, 524, 524, 524, 
+  0, 813, 813, 814, 815, 816, 817, 818, 
+  819, 820, 821, 822, 823, 824, 825, 826, 
+  827, 828, 829, 830, 831, 832, 833, 834, 
+  835, 836, 837, 838, 839, 840, 841, 842, 
+  843, 844, 845, 846, 847, 848, 849, 850, 
+  851, 852, 853, 854, 855, 856, 857, 858, 
+  859, 860, 861, 862, 863, 864, 865, 866, 
+  867, 868, 869, 870, 871, 872, 873, 874, 
+  875, 876, 877, 878, 879, 880, 881, 882, 
+  883, 884, 885, 886, 887, 888, 889, 890, 
+  891, 892, 893, 894, 895, 896, 897, 898, 
+  899, 900, 901, 902, 903, 904, 905, 906, 
+  907, 908, 909, 910, 911, 912, 913, 914, 
+  915, 916, 917, 918, 919, 920, 921, 922, 
+  923, 924, 925, 926, 927, 928, 929, 930, 
+  931, 932, 933, 934, 935, 936, 937, 938, 
+  939, 940, 941, 942, 943, 944, 945, 946, 
+  947, 948, 949, 950, 951, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 952, 953, 954, 955, 956, 957, 
+  958, 959, 960, 961, 962, 963, 964, 965, 
+  966, 967, 968, 969, 970, 971, 972, 973, 
+  974, 975, 976, 977, 978, 979, 980, 981, 
+  982, 983, 984, 985, 986, 987, 988, 989, 
+  0, 0, 507, 990, 990, 990, 990, 990, 
+  990, 0, 991, 992, 993, 994, 995, 996, 
+  997, 998, 999, 1000, 1001, 1002, 1003, 1004, 
+  1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 
+  1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 
+  1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 
+  1029, 0, 990, 1030, 0, 0, 0, 0, 
+  0, 0, 537, 524, 524, 524, 524, 537, 
+  524, 524, 524, 1031, 537, 524, 524, 524, 
+  524, 524, 524, 537, 537, 537, 537, 537, 
+  537, 524, 524, 537, 524, 524, 1031, 1032, 
+  524, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 
+  1040, 1041, 1042, 1042, 1043, 1044, 1045, 1046, 
+  1047, 1046, 1048, 1049, 1046, 524, 537, 1046, 
+  1041, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 0, 0, 0, 0, 
+  0, 1050, 1050, 1050, 1046, 1046, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1051, 1051, 1051, 1051, 0, 0, 0, 
+  0, 0, 0, 0, 1052, 14, 1053, 76, 
+  76, 524, 524, 524, 524, 524, 524, 0, 
+  0, 0, 0, 0, 1053, 0, 0, 1053, 
+  1053, 0, 1054, 1055, 1056, 1057, 1058, 1059, 
+  1060, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 0, 0, 0, 0, 
+  0, 1061, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1062, 1054, 1063, 1064, 1065, 1066, 1067, 
+  1068, 1069, 1070, 1071, 1072, 1073, 1074, 537, 
+  524, 524, 524, 524, 524, 537, 524, 524, 
+  0, 1075, 1075, 1075, 1075, 1075, 1075, 1075, 
+  1075, 1075, 1075, 9, 1076, 1076, 1053, 1054, 
+  1054, 1077, 1054, 1054, 1054, 1054, 1078, 1079, 
+  1080, 1081, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1082, 1083, 1084, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1085, 1086, 1053, 1087, 524, 
+  524, 524, 524, 524, 524, 524, 1051, 813, 
+  524, 524, 524, 524, 537, 524, 1061, 1061, 
+  524, 524, 76, 537, 524, 524, 537, 1054, 
+  1054, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 1054, 1054, 1054, 1088, 1088, 
+  1054, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 
+  1053, 1053, 1053, 1053, 1053, 1053, 1053, 0, 
+  80, 1054, 1089, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 524, 537, 524, 524, 537, 524, 524, 
+  537, 537, 537, 524, 537, 537, 524, 537, 
+  524, 524, 524, 537, 524, 537, 524, 537, 
+  524, 537, 524, 524, 0, 0, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 
+  1054, 1054, 1054, 1054, 1054, 1054, 1054, 1090, 
+  1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 
+  1090, 1090, 1054, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1091, 1091, 1091, 1091, 1091, 1091, 1091, 
+  1091, 1091, 1091, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 524, 524, 524, 524, 
+  524, 524, 524, 537, 524, 1092, 1092, 76, 
+  8, 8, 8, 1092, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 1090, 1090, 1093, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 1094, 1095, 339, 339, 339, 339, 339, 
+  339, 1096, 1097, 339, 1098, 1099, 339, 339, 
+  339, 339, 339, 0, 0, 1100, 339, 1093, 
+  1093, 1093, 1090, 1090, 1090, 1090, 1090, 1090, 
+  1090, 1090, 1093, 1093, 1093, 1093, 1101, 0, 
+  0, 339, 524, 537, 524, 524, 0, 0, 
+  0, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 
+  1109, 339, 339, 1090, 1090, 990, 990, 1110, 
+  1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 990, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 339, 339, 339, 339, 
+  339, 0, 1090, 1093, 1093, 0, 339, 339, 
+  339, 339, 339, 339, 339, 339, 0, 0, 
+  339, 339, 0, 0, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 0, 0, 0, 339, 
+  339, 339, 339, 0, 0, 1111, 339, 1112, 
+  1093, 1093, 1090, 1090, 1090, 1090, 0, 0, 
+  1113, 1093, 0, 0, 1114, 1115, 1101, 339, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  1116, 0, 0, 0, 0, 1117, 1118, 0, 
+  1119, 339, 339, 1090, 1090, 0, 0, 1110, 
+  1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 339, 339, 10, 10, 1120, 1120, 1120, 
+  1120, 1120, 1120, 812, 0, 0, 0, 0, 
+  0, 0, 1090, 1090, 1093, 0, 339, 339, 
+  339, 339, 339, 339, 0, 0, 0, 0, 
+  339, 339, 0, 0, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 1121, 0, 339, 1122, 
+  0, 339, 339, 0, 0, 1111, 0, 1093, 
+  1093, 1093, 1090, 1090, 0, 0, 0, 0, 
+  1090, 1090, 0, 0, 1090, 1090, 1101, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 1123, 1124, 1125, 339, 0, 1126, 
+  0, 0, 0, 0, 0, 0, 0, 1110, 
+  1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 1090, 1090, 339, 339, 339, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 1090, 1090, 1093, 0, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 0, 
+  339, 339, 339, 0, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 0, 339, 339, 
+  339, 339, 339, 0, 0, 1111, 339, 1093, 
+  1093, 1093, 1090, 1090, 1090, 1090, 1090, 0, 
+  1090, 1090, 1093, 0, 1093, 1093, 1101, 0, 
+  0, 339, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 1090, 1090, 0, 0, 1110, 
+  1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 0, 10, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 1090, 1093, 1093, 0, 339, 339, 
+  339, 339, 339, 339, 339, 339, 0, 0, 
+  339, 339, 0, 0, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 0, 339, 339, 
+  339, 339, 339, 0, 0, 1111, 339, 1127, 
+  1090, 1093, 1090, 1090, 1090, 0, 0, 0, 
+  1128, 1129, 0, 0, 1130, 1131, 1101, 0, 
+  0, 0, 0, 0, 0, 0, 0, 1132, 
+  1133, 0, 0, 0, 0, 1134, 1135, 0, 
+  339, 339, 339, 0, 0, 0, 0, 1110, 
+  1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 812, 339, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 1090, 339, 0, 339, 339, 
+  339, 339, 339, 339, 0, 0, 0, 339, 
+  339, 339, 0, 1136, 339, 1137, 339, 0, 
+  0, 0, 339, 339, 0, 339, 0, 339, 
+  339, 0, 0, 0, 339, 339, 0, 0, 
+  0, 339, 339, 339, 0, 0, 0, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 0, 0, 0, 0, 1138, 
+  1093, 1090, 1093, 1093, 0, 0, 0, 1139, 
+  1140, 1093, 0, 1141, 1142, 1143, 1101, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  1144, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 1110, 
+  1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 1120, 1120, 1120, 76, 76, 76, 76, 
+  76, 76, 10, 76, 0, 0, 0, 0, 
+  0, 0, 1093, 1093, 1093, 0, 339, 339, 
+  339, 339, 339, 339, 339, 339, 0, 339, 
+  339, 339, 0, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 0, 339, 339, 
+  339, 339, 339, 0, 0, 0, 0, 1090, 
+  1090, 1090, 1093, 1093, 1093, 1093, 0, 1145, 
+  1090, 1146, 0, 1090, 1090, 1090, 1101, 0, 
+  0, 0, 0, 0, 0, 0, 1147, 1148, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 0, 0, 0, 0, 1110, 
+  1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 1093, 1093, 0, 339, 339, 
+  339, 339, 339, 339, 339, 339, 0, 339, 
+  339, 339, 0, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 0, 339, 339, 
+  339, 339, 339, 0, 0, 1111, 339, 1093, 
+  1149, 1150, 1093, 1151, 1093, 1093, 0, 1152, 
+  1153, 1154, 0, 1155, 1156, 1090, 1101, 0, 
+  0, 0, 0, 0, 0, 0, 1157, 1158, 
+  0, 0, 0, 0, 0, 0, 0, 339, 
+  0, 339, 339, 1090, 1090, 0, 0, 1110, 
+  1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 0, 76, 76, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 1093, 1093, 0, 339, 339, 
+  339, 339, 339, 339, 339, 339, 0, 339, 
+  339, 339, 0, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 0, 0, 0, 0, 1159, 
+  1093, 1093, 1090, 1090, 1090, 0, 0, 1160, 
+  1161, 1093, 0, 1162, 1163, 1164, 1101, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  1165, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 0, 0, 0, 0, 1110, 
+  1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 1093, 1093, 0, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  0, 0, 0, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 0, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 0, 339, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  0, 0, 0, 1166, 0, 0, 0, 0, 
+  1167, 1093, 1093, 1090, 1090, 1090, 0, 1090, 
+  0, 1093, 1168, 1169, 1093, 1170, 1171, 1172, 
+  1173, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 1093, 1093, 990, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 1090, 339, 1174, 1090, 1090, 1090, 
+  1090, 1175, 1175, 1101, 0, 0, 0, 0, 
+  10, 339, 339, 339, 339, 339, 339, 507, 
+  1090, 1176, 1176, 1176, 1176, 1090, 1090, 1090, 
+  990, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 1110, 1110, 990, 990, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 339, 339, 0, 339, 0, 0, 
+  339, 339, 0, 339, 0, 0, 339, 0, 
+  0, 0, 0, 0, 0, 339, 339, 339, 
+  339, 0, 339, 339, 339, 339, 339, 339, 
+  339, 0, 339, 339, 339, 0, 339, 0, 
+  339, 0, 0, 339, 339, 0, 339, 339, 
+  339, 339, 1090, 339, 1177, 1090, 1090, 1090, 
+  1090, 1178, 1178, 0, 1090, 1090, 339, 0, 
+  0, 339, 339, 339, 339, 339, 0, 507, 
+  0, 1179, 1179, 1179, 1179, 1090, 1090, 0, 
+  0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 1110, 1110, 0, 0, 1180, 1181, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 812, 812, 812, 990, 990, 990, 
+  990, 990, 990, 990, 990, 1182, 990, 990, 
+  990, 990, 990, 990, 812, 812, 812, 812, 
+  812, 537, 537, 812, 812, 812, 812, 812, 
+  812, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 1110, 1110, 1120, 1120, 1120, 1120, 1120, 
+  1120, 1120, 1120, 1120, 1120, 812, 537, 812, 
+  537, 812, 1183, 11, 12, 11, 12, 1093, 
+  1093, 339, 339, 339, 1184, 339, 339, 339, 
+  339, 0, 339, 339, 339, 339, 1185, 339, 
+  339, 339, 339, 1186, 339, 339, 339, 339, 
+  1187, 339, 339, 339, 339, 1188, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 1189, 339, 0, 0, 0, 0, 
+  0, 0, 1190, 1191, 1192, 1193, 1194, 1195, 
+  1196, 1197, 1198, 1191, 1191, 1191, 1191, 1090, 
+  1093, 1191, 1199, 524, 524, 1101, 990, 524, 
+  524, 339, 339, 339, 339, 0, 0, 0, 
+  0, 1090, 1090, 1090, 1200, 1090, 1090, 1090, 
+  1090, 0, 1090, 1090, 1090, 1090, 1201, 1090, 
+  1090, 1090, 1090, 1202, 1090, 1090, 1090, 1090, 
+  1203, 1090, 1090, 1090, 1090, 1204, 1090, 1090, 
+  1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, 
+  1090, 1090, 1205, 1090, 1090, 1090, 0, 812, 
+  812, 812, 812, 812, 812, 812, 812, 537, 
+  812, 812, 812, 812, 812, 812, 0, 0, 
+  812, 990, 990, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 0, 339, 339, 1206, 1207, 
+  339, 0, 339, 339, 0, 1093, 1090, 1208, 
+  1090, 1090, 1093, 1090, 0, 0, 0, 1090, 
+  1111, 1093, 1101, 0, 0, 0, 0, 0, 
+  0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 1110, 1110, 990, 990, 990, 990, 990, 
+  990, 339, 339, 339, 339, 339, 339, 1093, 
+  1093, 1090, 1090, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 
+  1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 
+  1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 
+  1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 
+  1240, 1241, 1242, 1243, 1244, 1245, 1246, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 990, 1247, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 0, 0, 0, 0, 0, 
+  1248, 1248, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 339, 339, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  0, 339, 0, 339, 339, 339, 339, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 339, 339, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 339, 339, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  0, 339, 0, 339, 339, 339, 339, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 0, 339, 339, 339, 339, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 0, 0, 0, 0, 
+  524, 812, 990, 990, 990, 990, 990, 990, 
+  990, 990, 1120, 1120, 1120, 1120, 1120, 1120, 
+  1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 
+  1120, 1120, 1120, 1120, 1120, 1120, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 990, 990, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 7, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 11, 12, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 990, 990, 990, 1249, 
+  1249, 1249, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 0, 339, 
+  339, 339, 339, 1090, 1090, 1101, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 1090, 1090, 1101, 990, 990, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 1090, 1090, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 0, 339, 
+  339, 339, 0, 1090, 1090, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 1250, 1250, 1093, 
+  1090, 1090, 1090, 1090, 1090, 1090, 1090, 1093, 
+  1093, 1093, 1093, 1093, 1093, 1093, 1093, 1090, 
+  1093, 1093, 1090, 1090, 1090, 1090, 1090, 1090, 
+  1090, 1090, 1090, 1101, 1090, 990, 990, 990, 
+  507, 990, 990, 990, 10, 339, 524, 0, 
+  0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 1110, 1110, 0, 0, 0, 0, 0, 
+  0, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 
+  1251, 1251, 1251, 0, 0, 0, 0, 0, 
+  0, 8, 8, 8, 8, 8, 8, 1030, 
+  8, 8, 8, 8, 558, 558, 558, 7, 
+  0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 1110, 1110, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 507, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 1032, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 0, 0, 
+  0, 1090, 1090, 1090, 1093, 1093, 1093, 1093, 
+  1090, 1090, 1252, 1252, 1252, 0, 0, 0, 
+  0, 1093, 1093, 1090, 1093, 1093, 1093, 1093, 
+  1093, 1093, 1031, 524, 537, 0, 0, 0, 
+  0, 76, 0, 0, 0, 8, 8, 1110, 
+  1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 0, 
+  0, 339, 339, 339, 339, 339, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 0, 0, 0, 0, 0, 
+  0, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 
+  1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 
+  1093, 1093, 339, 339, 339, 339, 339, 339, 
+  339, 1093, 1093, 0, 0, 0, 0, 0, 
+  0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 1110, 1110, 0, 0, 0, 0, 8, 
+  8, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  524, 537, 1093, 1093, 1093, 0, 0, 990, 
+  990, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1090, 1090, 1090, 1090, 1093, 1253, 1254, 
+  1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 
+  339, 339, 1263, 1264, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 1111, 1265, 1090, 
+  1090, 1090, 1090, 1266, 1267, 1268, 1269, 1270, 
+  1271, 1272, 1273, 1274, 1275, 1276, 339, 339, 
+  339, 339, 339, 339, 339, 0, 0, 0, 
+  0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 1110, 1110, 990, 990, 990, 990, 990, 
+  990, 990, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 524, 537, 524, 524, 
+  524, 524, 524, 524, 524, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 213, 213, 213, 213, 213, 213, 213, 
+  213, 213, 213, 213, 213, 213, 213, 213, 
+  213, 213, 213, 213, 213, 213, 213, 213, 
+  213, 213, 213, 213, 213, 213, 213, 213, 
+  213, 213, 213, 213, 213, 213, 213, 213, 
+  213, 213, 213, 213, 213, 1277, 1278, 1279, 
+  507, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 
+  1287, 1288, 1289, 1290, 507, 1291, 1292, 1293, 
+  1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 
+  1302, 1303, 1304, 1305, 1306, 1307, 1308, 507, 
+  1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 
+  1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 
+  1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 
+  1333, 1334, 1335, 1336, 213, 213, 213, 213, 
+  213, 213, 213, 213, 213, 213, 213, 213, 
+  213, 1337, 213, 213, 213, 213, 1338, 213, 
+  213, 213, 213, 213, 213, 213, 213, 213, 
+  213, 213, 213, 213, 213, 213, 213, 213, 
+  213, 213, 213, 213, 213, 213, 213, 213, 
+  213, 213, 213, 213, 1339, 1340, 1341, 1342, 
+  1307, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 
+  1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 
+  1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 
+  1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 
+  1374, 524, 524, 537, 524, 524, 524, 524, 
+  524, 524, 524, 537, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 524, 
+  537, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 
+  1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 
+  1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 
+  1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 
+  1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 
+  1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 
+  1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 
+  1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 
+  1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 
+  1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 
+  1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 
+  1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 
+  1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 
+  1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 
+  1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 
+  1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 
+  1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 
+  1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 
+  1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 
+  1526, 1527, 1528, 1529, 1530, 0, 0, 0, 
+  0, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 
+  1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 
+  1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 
+  1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 
+  1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 
+  1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 
+  1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 
+  1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 
+  1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 
+  1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 
+  1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 
+  1618, 1619, 1620, 0, 0, 0, 0, 0, 
+  0, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 
+  1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 
+  1636, 1637, 1638, 1639, 1640, 1641, 1642, 0, 
+  0, 1643, 1644, 1645, 1646, 1647, 1648, 0, 
+  0, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 
+  1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 
+  1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 
+  1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 
+  1680, 1681, 1682, 1683, 1684, 1685, 1686, 0, 
+  0, 1687, 1688, 1689, 1690, 1691, 1692, 0, 
+  0, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 
+  1700, 0, 1701, 0, 1702, 0, 1703, 0, 
+  1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 
+  1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 
+  1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 
+  1728, 1729, 1730, 1731, 1732, 1733, 1734, 0, 
+  0, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 
+  1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 
+  1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 
+  1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 
+  1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 
+  1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 
+  1782, 1783, 1784, 1785, 1786, 1787, 0, 1788, 
+  1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 
+  1797, 1798, 1799, 1800, 1801, 1802, 0, 1803, 
+  1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 
+  1812, 1813, 1814, 1815, 1816, 0, 0, 1817, 
+  1818, 1819, 1820, 1821, 1822, 0, 1823, 1824, 
+  1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 
+  1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 
+  1841, 0, 0, 1842, 1843, 1844, 0, 1845, 
+  1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 
+  0, 1854, 1855, 1856, 1856, 1856, 1856, 1856, 
+  1857, 1856, 1856, 1856, 80, 1858, 1858, 1250, 
+  1859, 1030, 1860, 1030, 1030, 1030, 1030, 8, 
+  1861, 79, 91, 11, 79, 79, 91, 11, 
+  79, 8, 8, 8, 8, 1862, 1863, 1864, 
+  8, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 
+  75, 9, 9, 9, 1872, 1873, 8, 1874, 
+  1875, 8, 79, 91, 8, 1876, 8, 1877, 
+  47, 47, 8, 8, 8, 1878, 11, 12, 
+  1879, 1880, 1881, 8, 8, 8, 8, 8, 
+  8, 8, 8, 74, 8, 47, 8, 8, 
+  1882, 8, 8, 8, 8, 8, 8, 8, 
+  1856, 80, 80, 80, 80, 0, 0, 0, 
+  0, 0, 0, 80, 80, 80, 80, 80, 
+  80, 1883, 1884, 0, 0, 1885, 1886, 1887, 
+  1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 
+  1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 
+  1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 
+  0, 1912, 1913, 1914, 1915, 1916, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 10, 10, 10, 10, 10, 10, 10, 
+  10, 1917, 10, 10, 10, 10, 10, 10, 
+  10, 10, 10, 10, 10, 10, 10, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 524, 524, 550, 550, 524, 524, 524, 
+  524, 550, 550, 550, 524, 524, 813, 813, 
+  813, 813, 524, 813, 813, 813, 550, 550, 
+  524, 537, 524, 550, 550, 537, 537, 537, 
+  537, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1918, 1919, 1920, 1921, 76, 1922, 1923, 
+  1924, 76, 1925, 1926, 1927, 1927, 1927, 1928, 
+  1929, 1930, 1930, 1931, 1932, 76, 1933, 1934, 
+  76, 76, 1935, 1936, 1937, 1937, 1937, 76, 
+  76, 1938, 1939, 1940, 76, 1941, 76, 1942, 
+  76, 1941, 76, 1943, 1944, 1945, 1920, 82, 
+  1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 
+  1954, 1955, 1956, 76, 1957, 1958, 1959, 1960, 
+  1961, 1962, 74, 74, 74, 74, 1963, 1964, 
+  1946, 1956, 1965, 76, 74, 76, 76, 1966, 
+  0, 0, 0, 0, 1967, 1968, 1969, 1970, 
+  1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 
+  1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 
+  1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 
+  1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 
+  2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 
+  2011, 1249, 1249, 1249, 2012, 2013, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 2014, 74, 2015, 74, 2016, 76, 76, 
+  76, 76, 76, 2017, 2018, 76, 76, 76, 
+  76, 74, 76, 76, 74, 76, 76, 74, 
+  76, 76, 76, 76, 76, 76, 76, 2019, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 2020, 2021, 
+  2022, 2023, 76, 2024, 76, 2025, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 2026, 2026, 2027, 2028, 74, 74, 
+  74, 2029, 2030, 2026, 2031, 2032, 2026, 74, 
+  74, 74, 2026, 13, 83, 74, 2026, 2026, 
+  74, 74, 74, 2026, 2026, 2026, 2026, 74, 
+  2026, 2026, 2026, 2026, 2033, 2034, 2035, 2036, 
+  74, 74, 74, 74, 2026, 2037, 2038, 2026, 
+  2039, 2040, 2026, 2026, 2026, 74, 74, 74, 
+  74, 74, 2026, 74, 2026, 2041, 2026, 2026, 
+  2026, 2026, 2042, 2026, 2043, 2044, 2045, 2026, 
+  2046, 2047, 2048, 2026, 2026, 2026, 2049, 74, 
+  74, 74, 74, 2026, 2026, 2026, 2026, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  2026, 2050, 2051, 2052, 74, 2053, 2054, 2026, 
+  2026, 2026, 2026, 2026, 2026, 74, 2055, 2056, 
+  2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 
+  2065, 2066, 2067, 2068, 2069, 2070, 2071, 2026, 
+  2026, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 
+  2079, 2080, 2081, 2026, 2026, 2026, 74, 74, 
+  2026, 2026, 2082, 2083, 74, 74, 74, 74, 
+  74, 2026, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 2084, 2026, 74, 74, 2026, 
+  2026, 2085, 2086, 2026, 2087, 2088, 2089, 2090, 
+  2091, 2026, 2026, 2092, 2093, 2094, 2095, 2026, 
+  2026, 2026, 74, 74, 74, 74, 74, 2026, 
+  2026, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 2026, 2026, 2026, 2026, 2026, 74, 
+  74, 2026, 2026, 74, 74, 74, 74, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2096, 2097, 2098, 2099, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2100, 2101, 2102, 2103, 74, 
+  74, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 76, 76, 76, 76, 76, 76, 76, 
+  76, 2026, 2026, 2026, 2026, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 2026, 2026, 76, 76, 76, 76, 76, 
+  76, 76, 2104, 2105, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 76, 74, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 812, 76, 
+  76, 76, 76, 76, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 74, 74, 74, 
+  74, 74, 74, 76, 76, 76, 76, 76, 
+  76, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 
+  2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 
+  2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 
+  2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 
+  2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 
+  2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 
+  2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 
+  2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 
+  2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 
+  2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 
+  2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 
+  2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, 
+  2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 
+  2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 
+  2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 
+  2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 
+  2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 
+  2241, 2242, 2243, 2244, 1251, 1251, 1251, 1251, 
+  1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 
+  1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 
+  1251, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  74, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 74, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 74, 74, 74, 74, 74, 74, 74, 
+  74, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  74, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 0, 0, 
+  0, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 812, 76, 76, 
+  76, 76, 76, 76, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 76, 76, 76, 76, 0, 76, 
+  76, 76, 76, 0, 0, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 0, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 0, 76, 0, 
+  76, 76, 76, 76, 0, 0, 0, 76, 
+  0, 76, 76, 76, 76, 76, 76, 76, 
+  0, 0, 76, 76, 76, 76, 76, 76, 
+  76, 11, 12, 11, 12, 11, 12, 11, 
+  12, 11, 12, 11, 12, 11, 12, 1251, 
+  1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 
+  1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 
+  1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, 
+  1251, 1251, 1251, 1251, 1251, 76, 0, 0, 
+  0, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 0, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  0, 2026, 74, 74, 2026, 2026, 11, 12, 
+  74, 74, 74, 74, 0, 0, 0, 0, 
+  0, 74, 74, 74, 2026, 2026, 2026, 2026, 
+  74, 74, 74, 74, 74, 2026, 2026, 2026, 
+  74, 74, 74, 2026, 2026, 2026, 2026, 11, 
+  12, 11, 12, 11, 12, 0, 0, 0, 
+  0, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 11, 12, 11, 12, 
+  11, 12, 11, 12, 11, 12, 11, 12, 
+  11, 12, 11, 12, 11, 12, 11, 12, 
+  11, 12, 74, 74, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 74, 74, 74, 74, 74, 74, 74, 
+  74, 2026, 74, 74, 74, 74, 74, 74, 
+  74, 2026, 2026, 2026, 2026, 2026, 2026, 74, 
+  74, 74, 2026, 74, 74, 74, 74, 2026, 
+  2026, 2026, 2026, 2026, 74, 2026, 2026, 74, 
+  74, 11, 12, 11, 12, 2026, 74, 74, 
+  74, 74, 2026, 74, 2026, 2026, 2026, 74, 
+  74, 2026, 2026, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 2026, 2026, 2026, 
+  2026, 2026, 2026, 74, 74, 11, 12, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 2026, 2026, 2245, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 74, 2026, 
+  2026, 2026, 2026, 74, 74, 2026, 74, 2026, 
+  74, 74, 2026, 74, 2026, 2026, 2026, 2026, 
+  74, 74, 74, 74, 74, 2026, 2026, 74, 
+  74, 74, 74, 74, 74, 2026, 2026, 2026, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 74, 74, 74, 
+  2026, 2026, 74, 74, 74, 74, 74, 74, 
+  74, 74, 74, 74, 74, 2026, 2026, 74, 
+  74, 74, 74, 2026, 2026, 2026, 2026, 74, 
+  2026, 2026, 74, 74, 2026, 2246, 2247, 2248, 
+  74, 74, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 74, 74, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 74, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, 
+  74, 74, 74, 74, 74, 2249, 2250, 2026, 
+  74, 74, 74, 2026, 2026, 2026, 2026, 2026, 
+  74, 74, 74, 74, 74, 2026, 2026, 2026, 
+  74, 74, 74, 74, 2026, 74, 74, 74, 
+  2026, 2026, 2026, 2026, 2026, 74, 2026, 74, 
+  74, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 0, 0, 0, 0, 
+  0, 76, 76, 76, 76, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 
+  2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 
+  2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 
+  2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 
+  2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 
+  2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 
+  0, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 
+  2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 
+  2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 
+  2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 
+  2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 
+  2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 
+  0, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 
+  2352, 2353, 2354, 2355, 2356, 2357, 0, 0, 
+  0, 0, 0, 0, 0, 213, 2358, 2359, 
+  213, 0, 0, 0, 0, 0, 0, 0, 
+  0, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 
+  2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 
+  2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 
+  2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 
+  2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 
+  2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 
+  2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 
+  2415, 2416, 2417, 2418, 2419, 2420, 2421, 2422, 
+  2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 
+  2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, 
+  2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 
+  2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, 
+  2455, 2456, 2457, 2458, 2459, 213, 76, 76, 
+  76, 76, 76, 76, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 8, 8, 8, 8, 1251, 8, 
+  8, 2460, 2461, 2462, 2463, 2464, 2465, 2466, 
+  2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 
+  2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 
+  2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 
+  2491, 2492, 2493, 2494, 2495, 2496, 2497, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  2498, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 8, 8, 79, 91, 79, 91, 8, 
+  8, 8, 79, 91, 8, 79, 91, 8, 
+  8, 8, 8, 8, 8, 8, 8, 8, 
+  1030, 0, 0, 0, 0, 79, 91, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 0, 76, 76, 76, 76, 
+  2499, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 2500, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 
+  2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, 
+  2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 
+  2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 
+  2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 
+  2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 
+  2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 
+  2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563, 
+  2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 
+  2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 
+  2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 
+  2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 
+  2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 
+  2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 
+  2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 
+  2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 
+  2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 
+  2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 
+  2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 
+  2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 
+  2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 
+  2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 
+  2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, 
+  2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 
+  2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 
+  2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 
+  2708, 2709, 2710, 2711, 2712, 2713, 2714, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 0, 0, 0, 
+  0, 2715, 8, 8, 8, 76, 507, 339, 
+  1249, 11, 12, 11, 12, 11, 12, 11, 
+  12, 11, 12, 76, 76, 11, 12, 11, 
+  12, 11, 12, 11, 12, 1030, 11, 12, 
+  12, 76, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 2716, 1032, 536, 1031, 2717, 
+  2717, 1030, 507, 507, 507, 507, 507, 2718, 
+  76, 2719, 2720, 2721, 507, 339, 8, 76, 
+  76, 0, 339, 339, 339, 339, 339, 2722, 
+  339, 339, 339, 339, 2723, 2724, 2725, 2726, 
+  2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 
+  2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 
+  2743, 2744, 2745, 2746, 339, 2747, 2748, 2749, 
+  2750, 2751, 2752, 339, 339, 339, 339, 339, 
+  2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 
+  2761, 2762, 2763, 2764, 2765, 2766, 2767, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 2768, 339, 339, 
+  0, 0, 2769, 2770, 2771, 2772, 2773, 2774, 
+  2775, 1030, 339, 339, 339, 339, 339, 2776, 
+  339, 339, 339, 339, 2777, 2778, 2779, 2780, 
+  2781, 2782, 2783, 2784, 2785, 2786, 2787, 2788, 
+  2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 
+  2797, 2798, 2799, 2800, 339, 2801, 2802, 2803, 
+  2804, 2805, 2806, 339, 339, 339, 339, 339, 
+  2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 
+  2815, 2816, 2817, 2818, 2819, 2820, 2821, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  2822, 2823, 2824, 2825, 339, 2826, 339, 339, 
+  2827, 2828, 2829, 2830, 8, 507, 2831, 2832, 
+  2833, 0, 0, 0, 0, 0, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 0, 0, 
+  0, 0, 2834, 2835, 2836, 2837, 2838, 2839, 
+  2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 
+  2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 
+  2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 
+  2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 
+  2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 
+  2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 
+  2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, 
+  2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 
+  2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 
+  2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 
+  2920, 2921, 2922, 2923, 2924, 2925, 2926, 2927, 
+  0, 812, 812, 2928, 2929, 2930, 2931, 2932, 
+  2933, 2934, 2935, 2936, 2937, 2938, 2939, 2940, 
+  2941, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 0, 0, 0, 0, 0, 0, 0, 
+  0, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 
+  2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, 
+  2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 
+  2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, 
+  0, 2973, 2974, 2975, 2976, 2977, 2978, 2979, 
+  2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, 
+  2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 
+  2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, 
+  3004, 3005, 3006, 3007, 3008, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 
+  3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 
+  3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 
+  3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 
+  3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, 
+  3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 
+  812, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 
+  3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 
+  3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 
+  3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, 
+  3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, 
+  3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, 
+  3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 
+  3111, 3112, 3113, 3114, 3115, 3116, 3117, 3118, 
+  3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 
+  3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, 
+  3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, 
+  3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, 
+  3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 
+  3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, 
+  3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 
+  3175, 3176, 3177, 3178, 3179, 3180, 3181, 3182, 
+  0, 3183, 3184, 3185, 3186, 3187, 3188, 3189, 
+  3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, 
+  3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, 
+  3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, 
+  3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, 
+  3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 
+  3230, 3231, 3232, 3233, 3234, 3235, 3236, 3237, 
+  3238, 3239, 3240, 3241, 3242, 3243, 3244, 3245, 
+  3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, 
+  3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, 
+  3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, 
+  3270, 3271, 3272, 3273, 3274, 3275, 3276, 3277, 
+  3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, 
+  3286, 3287, 3288, 3289, 3290, 3291, 3292, 3293, 
+  3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, 
+  3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, 
+  3310, 3311, 3312, 3313, 3314, 3315, 3316, 3317, 
+  3318, 3319, 3320, 3321, 3322, 3323, 3324, 3325, 
+  3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, 
+  3334, 3335, 3336, 3337, 3338, 3339, 3340, 3341, 
+  3342, 3343, 3344, 3345, 3346, 3347, 3348, 3349, 
+  3350, 3351, 3352, 3353, 3354, 3355, 3356, 3357, 
+  3358, 3359, 3360, 3361, 3362, 3363, 3364, 3365, 
+  3366, 3367, 3368, 3369, 3370, 3371, 3372, 3373, 
+  3374, 3375, 3376, 3377, 3378, 3379, 3380, 3381, 
+  3382, 3383, 3384, 3385, 3386, 3387, 3388, 3389, 
+  3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, 
+  3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, 
+  3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, 
+  3414, 3415, 3416, 3417, 3418, 3419, 3420, 3421, 
+  3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, 
+  3430, 3431, 3432, 3433, 3434, 3435, 3436, 3437, 
+  3438, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 507, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 0, 0, 
+  0, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 46, 46, 46, 46, 46, 46, 46, 
+  46, 46, 46, 46, 46, 46, 46, 46, 
+  46, 46, 46, 46, 46, 46, 46, 46, 
+  506, 506, 506, 506, 0, 0, 0, 0, 
+  0, 46, 46, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 1252, 339, 339, 339, 1101, 
+  339, 339, 339, 339, 1090, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 1093, 1093, 1090, 1090, 
+  1093, 76, 76, 76, 76, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 8, 8, 8, 
+  8, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, 
+  3439, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, 
+  3448, 3448, 3449, 3450, 3451, 3452, 3453, 3454, 
+  3455, 3456, 3457, 3458, 3459, 3460, 3461, 3462, 
+  3463, 3464, 3465, 3466, 3467, 3468, 3469, 3470, 
+  3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, 
+  3479, 3480, 3481, 3482, 3483, 3484, 3485, 3486, 
+  3487, 3488, 3489, 3490, 3491, 3492, 3493, 3494, 
+  3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 
+  3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 
+  3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, 
+  3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, 
+  3527, 3528, 3529, 3530, 3531, 3460, 3532, 3533, 
+  3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 
+  3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, 
+  3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, 
+  3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, 
+  3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 
+  3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, 
+  3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 
+  3590, 3591, 3592, 3593, 3594, 3595, 3596, 3597, 
+  3598, 3599, 3550, 3600, 3601, 3602, 3603, 3604, 
+  3605, 3606, 3607, 3534, 3608, 3609, 3610, 3611, 
+  3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 
+  3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 
+  3460, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 
+  3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 
+  3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, 
+  3651, 3652, 3653, 3654, 3536, 3655, 3656, 3657, 
+  3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 
+  3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 
+  3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, 
+  3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 
+  3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, 
+  3698, 3699, 3700, 3701, 3702, 3703, 3704, 339, 
+  339, 3705, 339, 3706, 339, 339, 3707, 3708, 
+  3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, 
+  339, 3717, 339, 3718, 339, 339, 3719, 3720, 
+  339, 339, 339, 3721, 3722, 3723, 3724, 0, 
+  0, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 
+  3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 
+  3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 
+  3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 
+  3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 
+  3589, 3764, 3765, 3766, 3767, 3768, 3769, 3769, 
+  3770, 3771, 3772, 3773, 3774, 3775, 3776, 3777, 
+  3719, 3778, 3779, 3780, 0, 0, 0, 0, 
+  0, 3781, 3782, 3783, 3784, 3785, 3786, 3787, 
+  3788, 3731, 3789, 3790, 3791, 3705, 3792, 3793, 
+  3794, 3795, 3796, 3797, 3798, 3799, 3800, 3801, 
+  3802, 3803, 3740, 3804, 3741, 3805, 3806, 3807, 
+  3808, 3809, 3706, 3481, 3810, 3811, 3812, 3551, 
+  3638, 3813, 3814, 3748, 3815, 3749, 3816, 3817, 
+  3818, 3708, 3819, 3820, 3821, 3822, 3823, 3709, 
+  3824, 3825, 3826, 3827, 3828, 3829, 3763, 3830, 
+  3831, 3589, 3832, 3767, 3833, 3834, 3835, 3836, 
+  3837, 3772, 3838, 3718, 3839, 3773, 3532, 3840, 
+  3774, 3841, 3776, 3842, 3843, 3844, 3845, 3846, 
+  3778, 3714, 3847, 3779, 3848, 3780, 3849, 3448, 
+  3850, 3851, 3852, 3853, 3854, 3855, 3856, 3857, 
+  3858, 3859, 3860, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 3861, 3862, 3863, 3864, 3865, 3866, 3867, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 3868, 3869, 3870, 3871, 
+  3872, 0, 0, 0, 0, 0, 3873, 3874, 
+  3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, 
+  3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, 
+  3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, 
+  0, 3899, 3900, 3901, 3902, 3903, 0, 3904, 
+  0, 3905, 3906, 0, 3907, 3908, 0, 3909, 
+  3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, 
+  3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, 
+  3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, 
+  3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, 
+  3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949, 
+  3950, 3951, 3952, 3953, 3954, 3955, 3956, 3957, 
+  3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, 
+  3966, 3967, 3968, 3969, 3970, 3971, 3972, 3973, 
+  3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 
+  3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, 
+  3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, 
+  3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 
+  4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 
+  4014, 4015, 4016, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 4017, 4018, 4019, 4020, 
+  4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 
+  4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 
+  4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 
+  4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, 
+  4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, 
+  4061, 4062, 4063, 4064, 4055, 4065, 4066, 4067, 
+  4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 
+  4076, 4077, 4078, 4079, 4080, 4081, 4082, 4083, 
+  4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 
+  4092, 4093, 4094, 4095, 4096, 4097, 4098, 4099, 
+  4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 
+  4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, 
+  4116, 4117, 4118, 4119, 4120, 4121, 4122, 4123, 
+  4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 
+  4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 
+  4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 
+  4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 
+  4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, 
+  4164, 4056, 4165, 4166, 4167, 4168, 4169, 4170, 
+  4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, 
+  4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, 
+  4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 
+  4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 
+  4203, 4204, 4205, 4206, 4207, 4208, 4209, 4210, 
+  4211, 4212, 4213, 4214, 4215, 4216, 4217, 4218, 
+  4219, 4220, 4221, 4222, 4223, 4224, 4225, 4226, 
+  4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 
+  4235, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 
+  4243, 4244, 4245, 4246, 4247, 4248, 4249, 4250, 
+  4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 
+  4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 
+  4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 
+  4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 
+  4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, 
+  4291, 4292, 4293, 4294, 4295, 4296, 4297, 4298, 
+  4299, 4300, 4301, 4302, 4303, 4304, 4305, 4306, 
+  4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, 
+  4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 
+  4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 
+  4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 
+  4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 
+  4347, 4348, 4349, 4350, 4351, 4352, 4353, 4354, 
+  4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 
+  4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 
+  4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, 
+  4379, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 4380, 4381, 4382, 4383, 4384, 4385, 4386, 
+  4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, 
+  4395, 4396, 4397, 4398, 4399, 4400, 4401, 4402, 
+  4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, 
+  4411, 4412, 4413, 4414, 4415, 4416, 4417, 4418, 
+  4419, 4420, 4421, 4422, 4423, 4424, 4425, 4426, 
+  4427, 4428, 4429, 4430, 4431, 4432, 4433, 4434, 
+  4435, 4436, 4437, 4438, 4439, 4440, 4441, 4442, 
+  4443, 0, 0, 4444, 4445, 4446, 4447, 4448, 
+  4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 
+  4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, 
+  4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, 
+  4473, 4474, 4475, 4476, 4477, 4478, 4479, 4480, 
+  4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 
+  4489, 4490, 4491, 4492, 4493, 4494, 4495, 4496, 
+  4497, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 4498, 4499, 4500, 4501, 4502, 4503, 4504, 
+  4505, 4506, 4507, 4508, 4509, 4510, 76, 0, 
+  0, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 4511, 4512, 4513, 4514, 4515, 4516, 4517, 
+  4518, 4519, 4520, 0, 0, 0, 0, 0, 
+  0, 524, 524, 524, 524, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 4521, 4522, 4523, 4524, 4524, 4525, 4526, 
+  4527, 4528, 4529, 4530, 4531, 4532, 4533, 4534, 
+  4535, 4536, 4537, 4538, 4539, 4540, 8, 8, 
+  4541, 4542, 4543, 4543, 4543, 4543, 4544, 4544, 
+  4544, 4545, 4546, 4547, 0, 4548, 4549, 4550, 
+  4551, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 
+  4559, 4560, 4561, 4562, 4563, 4564, 4565, 4566, 
+  0, 4567, 4568, 4569, 4570, 0, 0, 0, 
+  0, 4571, 4572, 4573, 1054, 4574, 0, 4575, 
+  4576, 4577, 4578, 4579, 4580, 4581, 4582, 4583, 
+  4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, 
+  4592, 4593, 4594, 4595, 4596, 4597, 4598, 4599, 
+  4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 
+  4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 
+  4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 
+  4624, 4625, 4626, 4627, 4628, 4629, 4630, 4631, 
+  4632, 4633, 4634, 4635, 4636, 4637, 4638, 4639, 
+  4640, 4641, 4642, 4643, 4644, 4645, 4646, 4647, 
+  4648, 4649, 4650, 4651, 4652, 4653, 4654, 4655, 
+  4656, 4657, 4658, 4659, 4660, 4661, 4662, 4663, 
+  4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 
+  4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, 
+  4680, 4681, 4682, 4683, 4684, 4685, 4686, 4687, 
+  4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 
+  4696, 4697, 4698, 4699, 4700, 4701, 4702, 4703, 
+  4704, 4705, 4706, 4707, 4708, 4709, 0, 0, 
+  80, 0, 4710, 4711, 4712, 4713, 4714, 4715, 
+  4716, 4717, 4718, 4719, 4720, 4721, 4722, 4723, 
+  4724, 4725, 4726, 4727, 4728, 4729, 4730, 4731, 
+  4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, 
+  4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 
+  4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 
+  4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, 
+  4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, 
+  4772, 4773, 4774, 4775, 4776, 4777, 4778, 4779, 
+  4780, 4781, 4782, 4783, 4784, 4785, 4786, 4787, 
+  4788, 4789, 4790, 4791, 4792, 4793, 4794, 4795, 
+  4796, 4797, 4798, 4799, 4800, 4801, 4802, 4803, 
+  4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 
+  4812, 4813, 4814, 4815, 4816, 4817, 4818, 4819, 
+  4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, 
+  4828, 4829, 4830, 4831, 4832, 4833, 4834, 4835, 
+  4836, 4837, 4838, 4839, 4840, 4841, 4842, 4843, 
+  4844, 4845, 4846, 4847, 4848, 4849, 4850, 4851, 
+  4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, 
+  4860, 4861, 4862, 4863, 4864, 4865, 4866, 4867, 
+  4868, 4869, 4870, 4871, 4872, 4873, 4874, 4875, 
+  4876, 4877, 4878, 4879, 4880, 4881, 4882, 4883, 
+  4884, 4885, 4886, 4887, 4888, 4889, 4890, 4891, 
+  4892, 4893, 4894, 4895, 4896, 4897, 4898, 4899, 
+  0, 0, 0, 4900, 4901, 4902, 4903, 4904, 
+  4905, 0, 0, 4906, 4907, 4908, 4909, 4910, 
+  4911, 0, 0, 4912, 4913, 4914, 4915, 4916, 
+  4917, 0, 0, 4918, 4919, 4920, 0, 0, 
+  0, 4921, 4922, 4923, 4924, 4925, 4926, 4927, 
+  0, 4928, 4929, 4930, 4931, 4932, 4933, 4934, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 4935, 4935, 4935, 76, 76, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 0, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 0, 339, 339, 0, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 0, 0, 0, 0, 
+  0, 990, 8, 812, 0, 0, 0, 0, 
+  1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 
+  1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 
+  1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 
+  1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 
+  1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 
+  1120, 1120, 1120, 1120, 1120, 0, 0, 0, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 4936, 4936, 4936, 4936, 4936, 4936, 4936, 
+  4936, 4936, 4936, 4936, 4936, 4936, 4936, 4936, 
+  4936, 4936, 4936, 4936, 4936, 4936, 4936, 4936, 
+  4936, 4936, 4936, 4936, 4936, 4936, 4936, 4936, 
+  4936, 4936, 4936, 4936, 4936, 4936, 4936, 4936, 
+  4936, 4936, 4936, 4936, 4936, 4936, 4936, 4936, 
+  4936, 4936, 4936, 4936, 4936, 4936, 1251, 1251, 
+  1251, 1251, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 1251, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  0, 1120, 1120, 1120, 1120, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 1249, 339, 339, 339, 339, 339, 
+  339, 339, 339, 1249, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 0, 
+  990, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 990, 1249, 1249, 1249, 1249, 1249, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 4937, 4938, 4939, 4940, 4941, 4942, 4943, 
+  4944, 4945, 4946, 4947, 4948, 4949, 4950, 4951, 
+  4952, 4953, 4954, 4955, 4956, 4957, 4958, 4959, 
+  4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, 
+  4968, 4969, 4970, 4971, 4972, 4973, 4974, 4975, 
+  4976, 4977, 4978, 4979, 4980, 4981, 4982, 4983, 
+  4984, 4985, 4986, 4987, 4988, 4989, 4990, 4991, 
+  4992, 4993, 4994, 4995, 4996, 4997, 4998, 4999, 
+  5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 
+  5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 
+  5016, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 0, 
+  0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, 
+  1110, 1110, 1110, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1050, 1050, 1050, 1050, 1050, 1050, 0, 
+  0, 1050, 0, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 0, 
+  1050, 1050, 0, 0, 0, 1050, 0, 0, 
+  1050, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 5017, 
+  5017, 5017, 5017, 0, 0, 0, 0, 0, 
+  8, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1050, 1090, 1090, 1090, 0, 1090, 1090, 
+  0, 0, 0, 0, 0, 1090, 537, 1090, 
+  524, 1050, 1050, 1050, 1050, 0, 1050, 1050, 
+  1050, 0, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 
+  1050, 1050, 1050, 1050, 1050, 0, 0, 0, 
+  0, 524, 550, 537, 0, 0, 0, 0, 
+  1101, 5017, 5017, 5017, 5017, 5017, 5017, 5017, 
+  5017, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 
+  1046, 1046, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 
+  1249, 1249, 1249, 1249, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 990, 990, 990, 990, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  0, 0, 0, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  5018, 5019, 812, 812, 812, 812, 812, 5020, 
+  5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 
+  550, 550, 550, 812, 812, 812, 5029, 5030, 
+  5031, 5032, 5033, 5034, 80, 80, 80, 80, 
+  80, 80, 80, 80, 537, 537, 537, 537, 
+  537, 537, 537, 537, 812, 812, 524, 524, 
+  524, 524, 524, 537, 537, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 524, 524, 524, 524, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 5035, 5036, 5037, 5038, 5039, 5040, 
+  5041, 5042, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 812, 
+  812, 812, 812, 812, 812, 812, 812, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 524, 524, 524, 76, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  76, 76, 76, 76, 76, 76, 76, 76, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 
+  1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 
+  1120, 1120, 1120, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 5043, 1945, 1920, 1963, 1947, 1948, 5044, 
+  1927, 1930, 5045, 5046, 1931, 1950, 1933, 5047, 
+  1935, 1936, 1937, 5048, 5049, 5050, 5051, 5052, 
+  5053, 5054, 1941, 5055, 5056, 5057, 1964, 1946, 
+  5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, 
+  5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, 
+  5068, 5069, 5070, 5071, 5072, 5043, 1945, 1920, 
+  1963, 1947, 1948, 5044, 1927, 1930, 5045, 5046, 
+  1931, 1950, 1933, 5047, 1935, 1936, 1937, 5048, 
+  5049, 5050, 5051, 5052, 5053, 5054, 1941, 5055, 
+  5056, 5057, 1964, 1946, 5058, 1926, 0, 1956, 
+  1965, 5059, 1932, 5060, 5061, 1951, 5062, 5063, 
+  5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 
+  5072, 5043, 1945, 1920, 1963, 1947, 1948, 5044, 
+  1927, 1930, 5045, 5046, 1931, 1950, 1933, 5047, 
+  1935, 1936, 1937, 5048, 5049, 5050, 5051, 5052, 
+  5053, 5054, 1941, 5055, 5056, 5057, 1964, 1946, 
+  5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, 
+  5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, 
+  5068, 5069, 5070, 5071, 5072, 5043, 0, 1920, 
+  1963, 0, 0, 5044, 0, 0, 5045, 5046, 
+  0, 0, 1933, 5047, 1935, 1936, 0, 5048, 
+  5049, 5050, 5051, 5052, 5053, 5054, 1941, 5055, 
+  5056, 5057, 1964, 0, 5058, 0, 1928, 1956, 
+  1965, 5059, 1932, 5060, 5061, 0, 5062, 5063, 
+  5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 
+  5072, 5043, 1945, 1920, 1963, 1947, 1948, 5044, 
+  1927, 1930, 5045, 5046, 1931, 1950, 1933, 5047, 
+  1935, 1936, 1937, 5048, 5049, 5050, 5051, 5052, 
+  5053, 5054, 1941, 5055, 5056, 5057, 1964, 1946, 
+  5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, 
+  5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, 
+  5068, 5069, 5070, 5071, 5072, 5043, 1945, 0, 
+  1963, 1947, 1948, 5044, 0, 0, 5045, 5046, 
+  1931, 1950, 1933, 5047, 1935, 1936, 0, 5048, 
+  5049, 5050, 5051, 5052, 5053, 5054, 0, 5055, 
+  5056, 5057, 1964, 1946, 5058, 1926, 1928, 1956, 
+  1965, 5059, 1932, 5060, 5061, 1951, 5062, 5063, 
+  5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 
+  5072, 5043, 1945, 0, 1963, 1947, 1948, 5044, 
+  0, 1930, 5045, 5046, 1931, 1950, 0, 5047, 
+  0, 0, 0, 5048, 5049, 5050, 5051, 5052, 
+  5053, 5054, 0, 5055, 5056, 5057, 1964, 1946, 
+  5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, 
+  5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, 
+  5068, 5069, 5070, 5071, 5072, 5043, 1945, 1920, 
+  1963, 1947, 1948, 5044, 1927, 1930, 5045, 5046, 
+  1931, 1950, 1933, 5047, 1935, 1936, 1937, 5048, 
+  5049, 5050, 5051, 5052, 5053, 5054, 1941, 5055, 
+  5056, 5057, 1964, 1946, 5058, 1926, 1928, 1956, 
+  1965, 5059, 1932, 5060, 5061, 1951, 5062, 5063, 
+  5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 
+  5072, 5043, 1945, 1920, 1963, 1947, 1948, 5044, 
+  1927, 1930, 5045, 5046, 1931, 1950, 1933, 5047, 
+  1935, 1936, 1937, 5048, 5049, 5050, 5051, 5052, 
+  5053, 5054, 1941, 5055, 5056, 5057, 1964, 1946, 
+  5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, 
+  5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, 
+  5068, 5069, 5070, 5071, 5072, 5043, 1945, 1920, 
+  1963, 1947, 1948, 5044, 1927, 1930, 5045, 5046, 
+  1931, 1950, 1933, 5047, 1935, 1936, 1937, 5048, 
+  5049, 5050, 5051, 5052, 5053, 5054, 1941, 5055, 
+  5056, 5057, 1964, 1946, 5058, 1926, 1928, 1956, 
+  1965, 5059, 1932, 5060, 5061, 1951, 5062, 5063, 
+  5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 
+  5072, 5043, 1945, 1920, 1963, 1947, 1948, 5044, 
+  1927, 1930, 5045, 5046, 1931, 1950, 1933, 5047, 
+  1935, 1936, 1937, 5048, 5049, 5050, 5051, 5052, 
+  5053, 5054, 1941, 5055, 5056, 5057, 1964, 1946, 
+  5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, 
+  5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, 
+  5068, 5069, 5070, 5071, 5072, 5043, 1945, 1920, 
+  1963, 1947, 1948, 5044, 1927, 1930, 5045, 5046, 
+  1931, 1950, 1933, 5047, 1935, 1936, 1937, 5048, 
+  5049, 5050, 5051, 5052, 5053, 5054, 1941, 5055, 
+  5056, 5057, 1964, 1946, 5058, 1926, 1928, 1956, 
+  1965, 5059, 1932, 5060, 5061, 1951, 5062, 5063, 
+  5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 
+  5072, 5043, 1945, 1920, 1963, 1947, 1948, 5044, 
+  1927, 1930, 5045, 5046, 1931, 1950, 1933, 5047, 
+  1935, 1936, 1937, 5048, 5049, 5050, 5051, 5052, 
+  5053, 5054, 1941, 5055, 5056, 5057, 1964, 1946, 
+  5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, 
+  5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, 
+  5068, 5069, 5070, 5071, 5072, 5073, 5074, 0, 
+  0, 5075, 5076, 1960, 5077, 5078, 5079, 5080, 
+  5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 
+  1961, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 
+  5096, 5097, 5098, 5099, 5100, 1959, 5101, 5102, 
+  5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, 
+  5111, 5112, 1958, 5113, 5114, 5115, 5116, 5117, 
+  5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, 
+  5126, 5127, 5128, 5075, 5076, 1960, 5077, 5078, 
+  5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 
+  5087, 5088, 1961, 5089, 5090, 5091, 5092, 5093, 
+  5094, 5095, 5096, 5097, 5098, 5099, 5100, 1959, 
+  5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108, 
+  5109, 5110, 5111, 5112, 1958, 5113, 5114, 5115, 
+  5116, 5117, 5118, 5119, 5120, 5121, 5122, 5123, 
+  5124, 5125, 5126, 5127, 5128, 5075, 5076, 1960, 
+  5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 
+  5085, 5086, 5087, 5088, 1961, 5089, 5090, 5091, 
+  5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 
+  5100, 1959, 5101, 5102, 5103, 5104, 5105, 5106, 
+  5107, 5108, 5109, 5110, 5111, 5112, 1958, 5113, 
+  5114, 5115, 5116, 5117, 5118, 5119, 5120, 5121, 
+  5122, 5123, 5124, 5125, 5126, 5127, 5128, 5075, 
+  5076, 1960, 5077, 5078, 5079, 5080, 5081, 5082, 
+  5083, 5084, 5085, 5086, 5087, 5088, 1961, 5089, 
+  5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 
+  5098, 5099, 5100, 1959, 5101, 5102, 5103, 5104, 
+  5105, 5106, 5107, 5108, 5109, 5110, 5111, 5112, 
+  1958, 5113, 5114, 5115, 5116, 5117, 5118, 5119, 
+  5120, 5121, 5122, 5123, 5124, 5125, 5126, 5127, 
+  5128, 5075, 5076, 1960, 5077, 5078, 5079, 5080, 
+  5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 
+  1961, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 
+  5096, 5097, 5098, 5099, 5100, 1959, 5101, 5102, 
+  5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, 
+  5111, 5112, 1958, 5113, 5114, 5115, 5116, 5117, 
+  5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, 
+  5126, 5127, 5128, 5129, 5130, 0, 0, 5131, 
+  5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, 
+  5140, 5131, 5132, 5133, 5134, 5135, 5136, 5137, 
+  5138, 5139, 5140, 5131, 5132, 5133, 5134, 5135, 
+  5136, 5137, 5138, 5139, 5140, 5131, 5132, 5133, 
+  5134, 5135, 5136, 5137, 5138, 5139, 5140, 5131, 
+  5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, 
+  5140, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  339, 339, 339, 339, 339, 339, 339, 339, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 5141, 5142, 5143, 5144, 5145, 3725, 5146, 
+  5147, 5148, 5149, 3726, 5150, 5151, 5152, 3727, 
+  5153, 5154, 5155, 5156, 5157, 5158, 5159, 5160, 
+  5161, 5162, 5163, 5164, 3782, 5165, 5166, 5167, 
+  5168, 5169, 5170, 5171, 5172, 5173, 3787, 3728, 
+  3729, 3788, 5174, 5175, 3538, 5176, 3730, 5177, 
+  5178, 5179, 5180, 5180, 5180, 5181, 5182, 5183, 
+  5184, 5185, 5186, 5187, 5188, 5189, 5190, 5191, 
+  5192, 5193, 5194, 5195, 5196, 5197, 5198, 5198, 
+  3790, 5199, 5200, 5201, 5202, 3732, 5203, 5204, 
+  5205, 3691, 5206, 5207, 5208, 5209, 5210, 5211, 
+  5212, 5213, 5214, 5215, 5216, 5217, 5218, 5219, 
+  5220, 5221, 5222, 5223, 5224, 5225, 5226, 5227, 
+  5228, 5229, 5230, 5231, 5231, 5232, 5233, 5234, 
+  3534, 5235, 5236, 5237, 5238, 5239, 5240, 5241, 
+  5242, 3737, 5243, 5244, 5245, 5246, 5247, 5248, 
+  5249, 5250, 5251, 5252, 5253, 5254, 5255, 5256, 
+  5257, 5258, 5259, 5260, 5261, 5262, 5263, 3480, 
+  5264, 5265, 5266, 5266, 5267, 5268, 5268, 5269, 
+  5270, 5271, 5272, 5273, 5274, 5275, 5276, 5277, 
+  5278, 5279, 5280, 5281, 3738, 5282, 5283, 5284, 
+  5285, 3802, 5285, 5286, 3740, 5287, 5288, 5289, 
+  5290, 3741, 3453, 5291, 5292, 5293, 5294, 5295, 
+  5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 
+  5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 
+  5312, 3742, 5313, 5314, 5315, 5316, 5317, 5318, 
+  3744, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 
+  5326, 3481, 3810, 5327, 5328, 5329, 5330, 5331, 
+  5332, 5333, 5334, 3745, 5335, 5336, 5337, 5338, 
+  3853, 5339, 5340, 5341, 5342, 5343, 5344, 5345, 
+  5346, 5347, 5348, 5349, 5350, 5351, 3551, 5352, 
+  5353, 5354, 5355, 5356, 5357, 5358, 5359, 5360, 
+  5361, 5362, 3746, 3638, 5363, 5364, 5365, 5366, 
+  5367, 5368, 5369, 5370, 3814, 5371, 5372, 5373, 
+  5374, 5375, 5376, 5377, 5378, 3815, 5379, 5380, 
+  5381, 5382, 5383, 5384, 5385, 5386, 5387, 5388, 
+  5389, 5390, 3817, 5391, 5392, 5393, 5394, 5395, 
+  5396, 5397, 5398, 5399, 5400, 5401, 5401, 5402, 
+  5403, 3819, 5404, 5405, 5406, 5407, 5408, 5409, 
+  5410, 3537, 5411, 5412, 5413, 5414, 5415, 5416, 
+  5417, 3825, 5418, 5419, 5420, 5421, 5422, 5423, 
+  5423, 3826, 3855, 5424, 5425, 5426, 5427, 5428, 
+  3499, 3828, 5429, 5430, 3757, 5431, 5432, 3713, 
+  5433, 5434, 3761, 5435, 5436, 5437, 5438, 5438, 
+  5439, 5440, 5441, 5442, 5443, 5444, 5445, 5446, 
+  5447, 5448, 5449, 5450, 5451, 5452, 5453, 5454, 
+  5455, 5456, 5457, 5458, 5459, 5460, 5461, 5462, 
+  5463, 5464, 5465, 3767, 5466, 5467, 5468, 5469, 
+  5470, 5471, 5472, 5473, 5474, 5475, 5476, 5477, 
+  5478, 5479, 5480, 5481, 5267, 5482, 5483, 5484, 
+  5485, 5486, 5487, 5488, 5489, 5490, 5491, 5492, 
+  5493, 3555, 5494, 5495, 5496, 5497, 5498, 5499, 
+  3770, 5500, 5501, 5502, 5503, 5504, 5505, 5506, 
+  5507, 5508, 5509, 5510, 5511, 5512, 5513, 5514, 
+  5515, 5516, 5517, 5518, 5519, 3494, 5520, 5521, 
+  5522, 5523, 5524, 5525, 3835, 5526, 5527, 5528, 
+  5529, 5530, 5531, 5532, 5533, 5534, 5535, 5536, 
+  5537, 5538, 5539, 5540, 5541, 5542, 5543, 5544, 
+  5545, 3840, 3841, 5546, 5547, 5548, 5549, 5550, 
+  5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, 
+  3842, 5559, 5560, 5561, 5562, 5563, 5564, 5565, 
+  5566, 5567, 5568, 5569, 5570, 5571, 5572, 5573, 
+  5574, 5575, 5576, 5577, 5578, 5579, 5580, 5581, 
+  5582, 5583, 5584, 5585, 5586, 5587, 5588, 3848, 
+  3848, 5589, 5590, 5591, 5592, 5593, 5594, 5595, 
+  5596, 5597, 5598, 3849, 5599, 5600, 5601, 5602, 
+  5603, 5604, 5605, 5606, 5607, 5608, 5609, 5610, 
+  5611, 5612, 5613, 5614, 5615, 5616, 5617, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 80, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 80, 80, 80, 80, 80, 80, 80, 
+  80, 80, 80, 80, 80, 80, 80, 80, 
+  80, 80, 80, 80, 80, 80, 80, 80, 
+  80, 80, 80, 80, 80, 80, 80, 80, 
+  80, 80, 80, 80, 80, 80, 80, 80, 
+  80, 80, 80, 80, 80, 80, 80, 80, 
+  80, 80, 80, 80, 80, 80, 80, 80, 
+  80, 80, 80, 80, 80, 80, 80, 80, 
+  80, 80, 80, 80, 80, 80, 80, 80, 
+  80, 80, 80, 80, 80, 80, 80, 80, 
+  80, 80, 80, 80, 80, 80, 80, 80, 
+  80, 80, 80, 80, 80, 80, 80, 80, 
+  80, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 558, 558, 558, 558, 558, 558, 558, 
+  558, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 
+  3440, 3440, 3440, 3440, 3440, 3440, 3440, 0, 
+  0, };
+
+const utf8proc_property_t utf8proc_properties[] = {
+  {0, 0, 0, 0, NULL, false, -1, -1, -1, -1, -1, false},
+  {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
+  {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_S, 0, NULL, false, -1, -1, -1, -1, -1, false, false, true, false, NULL},
+  {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, NULL, false, -1, -1, -1, -1, -1, false, false, true, false, NULL},
+  {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_WS, 0, NULL, false, -1, -1, -1, -1, -1, false, false, true, false, NULL},
+  {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
+  {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_S, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
+  {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17580, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 17400, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17640, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 97, -1, 0, -1, false, false, false, false, utf8proc_sequences + 0},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 98, -1, 8640, -1, false, false, false, false, utf8proc_sequences + 2},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 99, -1, 60, -1, false, false, false, false, utf8proc_sequences + 4},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 100, -1, 960, -1, false, false, false, false, utf8proc_sequences + 6},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 101, -1, 120, -1, false, false, false, false, utf8proc_sequences + 8},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 102, -1, 9120, -1, false, false, false, false, utf8proc_sequences + 10},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 103, -1, 1080, -1, false, false, false, false, utf8proc_sequences + 12},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 104, -1, 1200, -1, false, false, false, false, utf8proc_sequences + 14},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 105, -1, 180, -1, false, false, false, false, utf8proc_sequences + 16},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 106, -1, 1320, -1, false, false, false, false, utf8proc_sequences + 18},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 107, -1, 1440, -1, false, false, false, false, utf8proc_sequences + 20},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 108, -1, 1560, -1, false, false, false, false, utf8proc_sequences + 22},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 109, -1, 9480, -1, false, false, false, false, utf8proc_sequences + 24},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 110, -1, 240, -1, false, false, false, false, utf8proc_sequences + 26},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 111, -1, 300, -1, false, false, false, false, utf8proc_sequences + 28},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 112, -1, 9720, -1, false, false, false, false, utf8proc_sequences + 30},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 113, -1, -1, -1, false, false, false, false, utf8proc_sequences + 32},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 114, -1, 1680, -1, false, false, false, false, utf8proc_sequences + 34},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 115, -1, 1800, -1, false, false, false, false, utf8proc_sequences + 36},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 116, -1, 1920, -1, false, false, false, false, utf8proc_sequences + 38},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 117, -1, 360, -1, false, false, false, false, utf8proc_sequences + 40},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 118, -1, 10560, -1, false, false, false, false, utf8proc_sequences + 42},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 119, -1, 2040, -1, false, false, false, false, utf8proc_sequences + 44},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 120, -1, 10680, -1, false, false, false, false, utf8proc_sequences + 46},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 121, -1, 420, -1, false, false, false, false, utf8proc_sequences + 48},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 122, -1, 2160, -1, false, false, false, false, utf8proc_sequences + 50},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 65, -1, 65, 480, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66, -1, 66, 8700, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 67, -1, 67, 540, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 68, -1, 68, 1020, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 69, -1, 69, 600, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 70, -1, 70, 9180, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 71, -1, 71, 1140, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 72, -1, 72, 1260, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 73, -1, 73, 660, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 74, -1, 74, 1380, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 75, -1, 75, 1500, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 76, -1, 76, 1620, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 77, -1, 77, 9540, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 78, -1, 78, 720, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 79, -1, 79, 780, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 80, -1, 80, 9780, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 81, -1, 81, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 82, -1, 82, 1740, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 83, -1, 83, 1860, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 84, -1, 84, 1980, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 85, -1, 85, 840, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 86, -1, 86, 10620, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 87, -1, 87, 2100, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 88, -1, 88, 10740, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 89, -1, 89, 900, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 90, -1, 90, 2220, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_NOBREAK, utf8proc_sequences + 52, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 54, false, -1, -1, -1, 3600, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 0, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PI, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 57, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ET, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ET, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 60, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 62, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 64, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 67, false, 924, -1, 924, -1, -1, false, false, false, false, utf8proc_sequences + 67},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 69, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 72, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 28, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PF, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 74, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 78, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 82, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 86, false, -1, 224, -1, -1, -1, false, false, false, false, utf8proc_sequences + 89},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 91, false, -1, 225, -1, -1, -1, false, false, false, false, utf8proc_sequences + 94},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 96, false, -1, 226, -1, 10860, -1, false, false, false, false, utf8proc_sequences + 99},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 101, false, -1, 227, -1, -1, -1, false, false, false, false, utf8proc_sequences + 104},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 106, false, -1, 228, -1, 2400, -1, false, false, false, false, utf8proc_sequences + 109},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 111, false, -1, 229, -1, 3000, -1, false, false, false, false, utf8proc_sequences + 114},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 230, -1, 2640, -1, false, false, false, false, utf8proc_sequences + 116},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 118, false, -1, 231, -1, 8760, -1, false, false, false, false, utf8proc_sequences + 121},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 123, false, -1, 232, -1, -1, -1, false, false, false, false, utf8proc_sequences + 126},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 128, false, -1, 233, -1, -1, -1, false, false, false, false, utf8proc_sequences + 131},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 133, false, -1, 234, -1, 11220, -1, false, false, false, false, utf8proc_sequences + 136},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 138, false, -1, 235, -1, -1, -1, false, false, false, false, utf8proc_sequences + 141},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 143, false, -1, 236, -1, -1, -1, false, false, false, false, utf8proc_sequences + 146},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 148, false, -1, 237, -1, -1, -1, false, false, false, false, utf8proc_sequences + 151},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 153, false, -1, 238, -1, -1, -1, false, false, false, false, utf8proc_sequences + 156},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 158, false, -1, 239, -1, 9240, -1, false, false, false, false, utf8proc_sequences + 161},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 240, -1, -1, -1, false, false, false, false, utf8proc_sequences + 163},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 165, false, -1, 241, -1, -1, -1, false, false, false, false, utf8proc_sequences + 168},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 170, false, -1, 242, -1, -1, -1, false, false, false, false, utf8proc_sequences + 173},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 175, false, -1, 243, -1, -1, -1, false, false, false, false, utf8proc_sequences + 178},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 180, false, -1, 244, -1, 11460, -1, false, false, false, false, utf8proc_sequences + 183},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 185, false, -1, 245, -1, 3360, -1, false, false, false, false, utf8proc_sequences + 188},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 190, false, -1, 246, -1, 3240, -1, false, false, false, false, utf8proc_sequences + 193},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 248, -1, 3120, -1, false, false, false, false, utf8proc_sequences + 195},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 197, false, -1, 249, -1, -1, -1, false, false, false, false, utf8proc_sequences + 200},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 202, false, -1, 250, -1, -1, -1, false, false, false, false, utf8proc_sequences + 205},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 207, false, -1, 251, -1, -1, -1, false, false, false, false, utf8proc_sequences + 210},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 212, false, -1, 252, -1, 2280, -1, false, false, false, false, utf8proc_sequences + 215},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 217, false, -1, 253, -1, -1, -1, false, false, false, false, utf8proc_sequences + 220},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 254, -1, -1, -1, false, false, false, false, utf8proc_sequences + 222},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 224},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 227, false, 192, -1, 192, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 230, false, 193, -1, 193, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 233, false, 194, -1, 194, 10920, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 236, false, 195, -1, 195, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 239, false, 196, -1, 196, 2460, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 242, false, 197, -1, 197, 3060, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 198, -1, 198, 2700, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 245, false, 199, -1, 199, 8820, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 248, false, 200, -1, 200, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 251, false, 201, -1, 201, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 254, false, 202, -1, 202, 11280, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 257, false, 203, -1, 203, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 260, false, 204, -1, 204, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 263, false, 205, -1, 205, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 266, false, 206, -1, 206, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 269, false, 207, -1, 207, 9300, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 208, -1, 208, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 272, false, 209, -1, 209, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 275, false, 210, -1, 210, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 278, false, 211, -1, 211, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 281, false, 212, -1, 212, 11520, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 284, false, 213, -1, 213, 3420, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 287, false, 214, -1, 214, 3300, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 216, -1, 216, 3180, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 290, false, 217, -1, 217, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 293, false, 218, -1, 218, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 296, false, 219, -1, 219, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 299, false, 220, -1, 220, 2340, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 302, false, 221, -1, 221, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 222, -1, 222, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 305, false, 376, -1, 376, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 308, false, -1, 257, -1, -1, -1, false, false, false, false, utf8proc_sequences + 311},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 313, false, 256, -1, 256, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 316, false, -1, 259, -1, 11100, -1, false, false, false, false, utf8proc_sequences + 319},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 321, false, 258, -1, 258, 11160, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 324, false, -1, 261, -1, -1, -1, false, false, false, false, utf8proc_sequences + 327},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 329, false, 260, -1, 260, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 332, false, -1, 263, -1, -1, -1, false, false, false, false, utf8proc_sequences + 335},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 337, false, 262, -1, 262, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 340, false, -1, 265, -1, -1, -1, false, false, false, false, utf8proc_sequences + 343},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 345, false, 264, -1, 264, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 348, false, -1, 267, -1, -1, -1, false, false, false, false, utf8proc_sequences + 351},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 353, false, 266, -1, 266, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 356, false, -1, 269, -1, -1, -1, false, false, false, false, utf8proc_sequences + 359},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 361, false, 268, -1, 268, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 364, false, -1, 271, -1, -1, -1, false, false, false, false, utf8proc_sequences + 367},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 369, false, 270, -1, 270, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 273, -1, -1, -1, false, false, false, false, utf8proc_sequences + 372},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 272, -1, 272, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 374, false, -1, 275, -1, 8880, -1, false, false, false, false, utf8proc_sequences + 377},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 379, false, 274, -1, 274, 8940, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 382, false, -1, 277, -1, -1, -1, false, false, false, false, utf8proc_sequences + 385},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 387, false, 276, -1, 276, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 390, false, -1, 279, -1, -1, -1, false, false, false, false, utf8proc_sequences + 393},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 395, false, 278, -1, 278, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 398, false, -1, 281, -1, -1, -1, false, false, false, false, utf8proc_sequences + 401},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 403, false, 280, -1, 280, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 406, false, -1, 283, -1, -1, -1, false, false, false, false, utf8proc_sequences + 409},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 411, false, 282, -1, 282, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 414, false, -1, 285, -1, -1, -1, false, false, false, false, utf8proc_sequences + 417},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 419, false, 284, -1, 284, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 422, false, -1, 287, -1, -1, -1, false, false, false, false, utf8proc_sequences + 425},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 427, false, 286, -1, 286, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 430, false, -1, 289, -1, -1, -1, false, false, false, false, utf8proc_sequences + 433},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 435, false, 288, -1, 288, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 438, false, -1, 291, -1, -1, -1, false, false, false, false, utf8proc_sequences + 441},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 443, false, 290, -1, 290, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 446, false, -1, 293, -1, -1, -1, false, false, false, false, utf8proc_sequences + 449},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 451, false, 292, -1, 292, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 295, -1, -1, -1, false, false, false, false, utf8proc_sequences + 454},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 294, -1, 294, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 456, false, -1, 297, -1, -1, -1, false, false, false, false, utf8proc_sequences + 459},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 461, false, 296, -1, 296, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 464, false, -1, 299, -1, -1, -1, false, false, false, false, utf8proc_sequences + 467},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 469, false, 298, -1, 298, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 472, false, -1, 301, -1, -1, -1, false, false, false, false, utf8proc_sequences + 475},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 477, false, 300, -1, 300, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 480, false, -1, 303, -1, -1, -1, false, false, false, false, utf8proc_sequences + 483},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 485, false, 302, -1, 302, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 488, false, -1, 105, -1, -1, -1, false, false, false, false, utf8proc_sequences + 491},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 73, -1, 73, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 494, false, -1, 307, -1, -1, -1, false, false, false, false, utf8proc_sequences + 497},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 499, false, 306, -1, 306, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 502, false, -1, 309, -1, -1, -1, false, false, false, false, utf8proc_sequences + 505},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 507, false, 308, -1, 308, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 510, false, -1, 311, -1, -1, -1, false, false, false, false, utf8proc_sequences + 513},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 515, false, 310, -1, 310, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 518, false, -1, 314, -1, -1, -1, false, false, false, false, utf8proc_sequences + 521},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 523, false, 313, -1, 313, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 526, false, -1, 316, -1, -1, -1, false, false, false, false, utf8proc_sequences + 529},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 531, false, 315, -1, 315, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 534, false, -1, 318, -1, -1, -1, false, false, false, false, utf8proc_sequences + 537},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 539, false, 317, -1, 317, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 542, false, -1, 320, -1, -1, -1, false, false, false, false, utf8proc_sequences + 545},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 547, false, 319, -1, 319, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 322, -1, -1, -1, false, false, false, false, utf8proc_sequences + 550},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 321, -1, 321, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 552, false, -1, 324, -1, -1, -1, false, false, false, false, utf8proc_sequences + 555},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 557, false, 323, -1, 323, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 560, false, -1, 326, -1, -1, -1, false, false, false, false, utf8proc_sequences + 563},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 565, false, 325, -1, 325, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 568, false, -1, 328, -1, -1, -1, false, false, false, false, utf8proc_sequences + 571},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 573, false, 327, -1, 327, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 576, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 576},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 331, -1, -1, -1, false, false, false, false, utf8proc_sequences + 579},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 330, -1, 330, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 581, false, -1, 333, -1, 9600, -1, false, false, false, false, utf8proc_sequences + 584},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 586, false, 332, -1, 332, 9660, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 589, false, -1, 335, -1, -1, -1, false, false, false, false, utf8proc_sequences + 592},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 594, false, 334, -1, 334, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 597, false, -1, 337, -1, -1, -1, false, false, false, false, utf8proc_sequences + 600},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 602, false, 336, -1, 336, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 339, -1, -1, -1, false, false, false, false, utf8proc_sequences + 605},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 338, -1, 338, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 607, false, -1, 341, -1, -1, -1, false, false, false, false, utf8proc_sequences + 610},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 612, false, 340, -1, 340, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 615, false, -1, 343, -1, -1, -1, false, false, false, false, utf8proc_sequences + 618},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 620, false, 342, -1, 342, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 623, false, -1, 345, -1, -1, -1, false, false, false, false, utf8proc_sequences + 626},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 628, false, 344, -1, 344, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 631, false, -1, 347, -1, 9960, -1, false, false, false, false, utf8proc_sequences + 634},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 636, false, 346, -1, 346, 10020, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 639, false, -1, 349, -1, -1, -1, false, false, false, false, utf8proc_sequences + 642},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 644, false, 348, -1, 348, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 647, false, -1, 351, -1, -1, -1, false, false, false, false, utf8proc_sequences + 650},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 652, false, 350, -1, 350, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 655, false, -1, 353, -1, 10080, -1, false, false, false, false, utf8proc_sequences + 658},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 660, false, 352, -1, 352, 10140, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 663, false, -1, 355, -1, -1, -1, false, false, false, false, utf8proc_sequences + 666},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 668, false, 354, -1, 354, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 671, false, -1, 357, -1, -1, -1, false, false, false, false, utf8proc_sequences + 674},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 676, false, 356, -1, 356, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 359, -1, -1, -1, false, false, false, false, utf8proc_sequences + 679},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 358, -1, 358, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 681, false, -1, 361, -1, 10320, -1, false, false, false, false, utf8proc_sequences + 684},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 686, false, 360, -1, 360, 10380, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 689, false, -1, 363, -1, 10440, -1, false, false, false, false, utf8proc_sequences + 692},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 694, false, 362, -1, 362, 10500, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 697, false, -1, 365, -1, -1, -1, false, false, false, false, utf8proc_sequences + 700},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 702, false, 364, -1, 364, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 705, false, -1, 367, -1, -1, -1, false, false, false, false, utf8proc_sequences + 708},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 710, false, 366, -1, 366, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 713, false, -1, 369, -1, -1, -1, false, false, false, false, utf8proc_sequences + 716},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 718, false, 368, -1, 368, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 721, false, -1, 371, -1, -1, -1, false, false, false, false, utf8proc_sequences + 724},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 726, false, 370, -1, 370, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 729, false, -1, 373, -1, -1, -1, false, false, false, false, utf8proc_sequences + 732},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 734, false, 372, -1, 372, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 737, false, -1, 375, -1, -1, -1, false, false, false, false, utf8proc_sequences + 740},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 742, false, 374, -1, 374, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 745, false, -1, 255, -1, -1, -1, false, false, false, false, utf8proc_sequences + 748},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 750, false, -1, 378, -1, -1, -1, false, false, false, false, utf8proc_sequences + 753},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 755, false, 377, -1, 377, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 758, false, -1, 380, -1, -1, -1, false, false, false, false, utf8proc_sequences + 761},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 763, false, 379, -1, 379, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 766, false, -1, 382, -1, -1, -1, false, false, false, false, utf8proc_sequences + 769},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 771, false, 381, -1, 381, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 36, false, 83, -1, 83, 10800, -1, false, false, false, false, utf8proc_sequences + 36},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 579, -1, 579, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 595, -1, -1, -1, false, false, false, false, utf8proc_sequences + 774},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 387, -1, -1, -1, false, false, false, false, utf8proc_sequences + 776},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 386, -1, 386, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 389, -1, -1, -1, false, false, false, false, utf8proc_sequences + 778},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 388, -1, 388, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 596, -1, -1, -1, false, false, false, false, utf8proc_sequences + 780},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 392, -1, -1, -1, false, false, false, false, utf8proc_sequences + 782},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 391, -1, 391, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 598, -1, -1, -1, false, false, false, false, utf8proc_sequences + 784},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 599, -1, -1, -1, false, false, false, false, utf8proc_sequences + 786},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 396, -1, -1, -1, false, false, false, false, utf8proc_sequences + 788},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 395, -1, 395, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 477, -1, -1, -1, false, false, false, false, utf8proc_sequences + 790},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 601, -1, -1, -1, false, false, false, false, utf8proc_sequences + 792},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 603, -1, -1, -1, false, false, false, false, utf8proc_sequences + 794},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 402, -1, -1, -1, false, false, false, false, utf8proc_sequences + 796},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 401, -1, 401, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 608, -1, -1, -1, false, false, false, false, utf8proc_sequences + 798},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 611, -1, -1, -1, false, false, false, false, utf8proc_sequences + 800},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 502, -1, 502, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 617, -1, -1, -1, false, false, false, false, utf8proc_sequences + 802},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 616, -1, -1, -1, false, false, false, false, utf8proc_sequences + 804},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 409, -1, -1, -1, false, false, false, false, utf8proc_sequences + 806},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 408, -1, 408, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 573, -1, 573, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 623, -1, -1, -1, false, false, false, false, utf8proc_sequences + 808},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 626, -1, -1, -1, false, false, false, false, utf8proc_sequences + 810},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 544, -1, 544, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 629, -1, -1, -1, false, false, false, false, utf8proc_sequences + 812},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 814, false, -1, 417, -1, 11700, -1, false, false, false, false, utf8proc_sequences + 817},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 819, false, 416, -1, 416, 11760, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 419, -1, -1, -1, false, false, false, false, utf8proc_sequences + 822},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 418, -1, 418, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 421, -1, -1, -1, false, false, false, false, utf8proc_sequences + 824},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 420, -1, 420, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 640, -1, -1, -1, false, false, false, false, utf8proc_sequences + 826},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 424, -1, -1, -1, false, false, false, false, utf8proc_sequences + 828},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 423, -1, 423, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 643, -1, -1, -1, false, false, false, false, utf8proc_sequences + 830},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 429, -1, -1, -1, false, false, false, false, utf8proc_sequences + 832},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 428, -1, 428, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 648, -1, -1, -1, false, false, false, false, utf8proc_sequences + 834},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 836, false, -1, 432, -1, 11820, -1, false, false, false, false, utf8proc_sequences + 839},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 841, false, 431, -1, 431, 11880, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 650, -1, -1, -1, false, false, false, false, utf8proc_sequences + 844},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 651, -1, -1, -1, false, false, false, false, utf8proc_sequences + 846},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 436, -1, -1, -1, false, false, false, false, utf8proc_sequences + 848},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 435, -1, 435, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 438, -1, -1, -1, false, false, false, false, utf8proc_sequences + 850},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 437, -1, 437, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 658, -1, 2880, -1, false, false, false, false, utf8proc_sequences + 852},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 441, -1, -1, -1, false, false, false, false, utf8proc_sequences + 854},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 440, -1, 440, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 445, -1, -1, -1, false, false, false, false, utf8proc_sequences + 856},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 444, -1, 444, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 503, -1, 503, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 858, false, -1, 454, 453, -1, -1, false, false, false, false, utf8proc_sequences + 861},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 863, false, 452, 454, 453, -1, -1, false, false, false, false, utf8proc_sequences + 861},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 866, false, 452, -1, 453, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 869, false, -1, 457, 456, -1, -1, false, false, false, false, utf8proc_sequences + 872},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 874, false, 455, 457, 456, -1, -1, false, false, false, false, utf8proc_sequences + 872},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 877, false, 455, -1, 456, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 880, false, -1, 460, 459, -1, -1, false, false, false, false, utf8proc_sequences + 883},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 885, false, 458, 460, 459, -1, -1, false, false, false, false, utf8proc_sequences + 883},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 888, false, 458, -1, 459, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 891, false, -1, 462, -1, -1, -1, false, false, false, false, utf8proc_sequences + 894},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 896, false, 461, -1, 461, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 899, false, -1, 464, -1, -1, -1, false, false, false, false, utf8proc_sequences + 902},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 904, false, 463, -1, 463, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 907, false, -1, 466, -1, -1, -1, false, false, false, false, utf8proc_sequences + 910},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 912, false, 465, -1, 465, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 915, false, -1, 468, -1, -1, -1, false, false, false, false, utf8proc_sequences + 918},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 920, false, 467, -1, 467, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 923, false, -1, 470, -1, -1, -1, false, false, false, false, utf8proc_sequences + 926},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 928, false, 469, -1, 469, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 931, false, -1, 472, -1, -1, -1, false, false, false, false, utf8proc_sequences + 934},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 936, false, 471, -1, 471, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 939, false, -1, 474, -1, -1, -1, false, false, false, false, utf8proc_sequences + 942},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 944, false, 473, -1, 473, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 947, false, -1, 476, -1, -1, -1, false, false, false, false, utf8proc_sequences + 950},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 952, false, 475, -1, 475, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 398, -1, 398, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 955, false, -1, 479, -1, -1, -1, false, false, false, false, utf8proc_sequences + 958},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 960, false, 478, -1, 478, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 963, false, -1, 481, -1, -1, -1, false, false, false, false, utf8proc_sequences + 966},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 968, false, 480, -1, 480, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 971, false, -1, 483, -1, -1, -1, false, false, false, false, utf8proc_sequences + 974},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 976, false, 482, -1, 482, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 485, -1, -1, -1, false, false, false, false, utf8proc_sequences + 979},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 484, -1, 484, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 981, false, -1, 487, -1, -1, -1, false, false, false, false, utf8proc_sequences + 984},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 986, false, 486, -1, 486, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 989, false, -1, 489, -1, -1, -1, false, false, false, false, utf8proc_sequences + 992},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 994, false, 488, -1, 488, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 997, false, -1, 491, -1, 2760, -1, false, false, false, false, utf8proc_sequences + 1000},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1002, false, 490, -1, 490, 2820, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1005, false, -1, 493, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1008},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1010, false, 492, -1, 492, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1013, false, -1, 495, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1016},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1018, false, 494, -1, 494, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1021, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1021},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1024, false, -1, 499, 498, -1, -1, false, false, false, false, utf8proc_sequences + 1027},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1029, false, 497, 499, 498, -1, -1, false, false, false, false, utf8proc_sequences + 1027},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1032, false, 497, -1, 498, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1035, false, -1, 501, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1038},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1040, false, 500, -1, 500, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 405, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1043},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 447, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1045},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1047, false, -1, 505, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1050},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1052, false, 504, -1, 504, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1055, false, -1, 507, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1058},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1060, false, 506, -1, 506, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1063, false, -1, 509, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1066},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1068, false, 508, -1, 508, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1071, false, -1, 511, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1074},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1076, false, 510, -1, 510, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1079, false, -1, 513, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1082},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1084, false, 512, -1, 512, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1087, false, -1, 515, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1090},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1092, false, 514, -1, 514, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1095, false, -1, 517, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1098},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1100, false, 516, -1, 516, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1103, false, -1, 519, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1106},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1108, false, 518, -1, 518, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1111, false, -1, 521, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1114},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1116, false, 520, -1, 520, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1119, false, -1, 523, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1122},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1124, false, 522, -1, 522, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1127, false, -1, 525, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1130},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1132, false, 524, -1, 524, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1135, false, -1, 527, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1138},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1140, false, 526, -1, 526, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1143, false, -1, 529, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1146},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1148, false, 528, -1, 528, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1151, false, -1, 531, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1154},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1156, false, 530, -1, 530, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1159, false, -1, 533, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1162},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1164, false, 532, -1, 532, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1167, false, -1, 535, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1170},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1172, false, 534, -1, 534, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1175, false, -1, 537, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1178},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1180, false, 536, -1, 536, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1183, false, -1, 539, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1186},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1188, false, 538, -1, 538, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 541, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1191},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 540, -1, 540, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1193, false, -1, 543, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1196},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1198, false, 542, -1, 542, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 414, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1201},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 547, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1203},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 546, -1, 546, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 549, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1205},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 548, -1, 548, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1207, false, -1, 551, -1, 2520, -1, false, false, false, false, utf8proc_sequences + 1210},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1212, false, 550, -1, 550, 2580, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1215, false, -1, 553, -1, 9000, -1, false, false, false, false, utf8proc_sequences + 1218},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1220, false, 552, -1, 552, 9060, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1223, false, -1, 555, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1226},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1228, false, 554, -1, 554, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1231, false, -1, 557, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1234},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1236, false, 556, -1, 556, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1239, false, -1, 559, -1, 3480, -1, false, false, false, false, utf8proc_sequences + 1242},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1244, false, 558, -1, 558, 3540, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1247, false, -1, 561, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1250},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1252, false, 560, -1, 560, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1255, false, -1, 563, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1258},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1260, false, 562, -1, 562, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11365, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1263},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 572, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1265},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 571, -1, 571, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 410, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1267},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11366, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1269},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 578, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1271},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 577, -1, 577, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 384, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1273},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 649, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1275},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 652, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1277},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 583, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1279},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 582, -1, 582, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 585, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1281},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 584, -1, 584, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 587, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1283},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 586, -1, 586, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 589, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1285},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 588, -1, 588, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 591, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1287},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 590, -1, 590, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 385, -1, 385, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 390, -1, 390, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 393, -1, 393, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 394, -1, 394, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 399, -1, 399, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 400, -1, 400, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 403, -1, 403, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 404, -1, 404, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 407, -1, 407, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 406, -1, 406, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11362, -1, 11362, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 412, -1, 412, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 413, -1, 413, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 415, -1, 415, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11364, -1, 11364, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 422, -1, 422, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 425, -1, 425, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 430, -1, 430, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 580, -1, 580, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 433, -1, 433, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 434, -1, 434, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 581, -1, 581, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 439, -1, 439, 2940, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 14, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1289, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 18, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 34, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1291, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1293, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1295, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 44, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 48, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1297, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1300, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1303, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1306, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1309, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1312, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 800, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 22, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 36, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 46, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1315, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 0, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 2, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 3, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 7, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 8, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 10, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 4, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 46, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 5, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 12, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 11, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 14, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 15, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 47, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 48, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 232, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 13, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 40, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 45, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 39, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 16, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 6, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 9, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 42, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 44, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 43, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 41, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 1, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 1, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 51, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 1317, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 1319, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 49, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 1321, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 1323, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 240, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, 921, -1, 921, -1, 50, false, false, false, true, utf8proc_sequences + 1326},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, true, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 233, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 234, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 1328, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1330, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1021, -1, 1021, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1022, -1, 1022, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1023, -1, 1023, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 1333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 1335, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1338, false, -1, 940, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1341},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 1343, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1345, false, -1, 941, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1348},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1350, false, -1, 942, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1353},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1355, false, -1, 943, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1358},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1360, false, -1, 972, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1363},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1365, false, -1, 973, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1368},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1370, false, -1, 974, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1373},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1375, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1378},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 945, -1, 3660, -1, false, false, false, false, utf8proc_sequences + 1382},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 946, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1384},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 947, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1386},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 948, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1388},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 949, -1, 3720, -1, false, false, false, false, utf8proc_sequences + 1390},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 950, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1392},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 951, -1, 3780, -1, false, false, false, false, utf8proc_sequences + 1394},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 952, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1396},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 953, -1, 3840, -1, false, false, false, false, utf8proc_sequences + 1326},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 954, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1398},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 955, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1400},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 956, -1, -1, -1, false, false, false, false, utf8proc_sequences + 67},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 957, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1402},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 958, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1404},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 959, -1, 3900, -1, false, false, false, false, utf8proc_sequences + 1406},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 960, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1408},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 961, -1, 16260, -1, false, false, false, false, utf8proc_sequences + 1410},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 963, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1412},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 964, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1414},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 965, -1, 3960, -1, false, false, false, false, utf8proc_sequences + 1416},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 966, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1418},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 967, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1420},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 968, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1422},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 969, -1, 4020, -1, false, false, false, false, utf8proc_sequences + 1424},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1426, false, -1, 970, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1429},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1431, false, -1, 971, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1434},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1436, false, 902, -1, 902, 15780, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1439, false, 904, -1, 904, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1442, false, 905, -1, 905, 15960, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1445, false, 906, -1, 906, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1448, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1451},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 913, -1, 913, 4140, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 914, -1, 914, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 915, -1, 915, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 916, -1, 916, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 917, -1, 917, 4200, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 918, -1, 918, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 919, -1, 919, 4260, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 920, -1, 920, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 921, -1, 921, 4320, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 922, -1, 922, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 923, -1, 923, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 924, -1, 924, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 925, -1, 925, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 926, -1, 926, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 927, -1, 927, 4500, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 928, -1, 928, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 929, -1, 929, 16200, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 931, -1, 931, -1, -1, false, false, false, false, utf8proc_sequences + 1412},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 931, -1, 931, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 932, -1, 932, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 933, -1, 933, 4440, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 934, -1, 934, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 935, -1, 935, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 936, -1, 936, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 937, -1, 937, 4560, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1455, false, 938, -1, 938, 4080, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1458, false, 939, -1, 939, 4380, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1461, false, 908, -1, 908, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1464, false, 910, -1, 910, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1467, false, 911, -1, 911, 16380, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1384, false, 914, -1, 914, -1, -1, false, false, false, false, utf8proc_sequences + 1384},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1396, false, 920, -1, 920, -1, -1, false, false, false, false, utf8proc_sequences + 1396},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1470, false, -1, -1, -1, 4620, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1472, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1475, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1418, false, 934, -1, 934, -1, -1, false, false, false, false, utf8proc_sequences + 1418},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1408, false, 928, -1, 928, -1, -1, false, false, false, false, utf8proc_sequences + 1408},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 985, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1478},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 984, -1, 984, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 987, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1480},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 986, -1, 986, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 989, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1482},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 988, -1, 988, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 991, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1484},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 990, -1, 990, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 993, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1486},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 992, -1, 992, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 995, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1488},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 994, -1, 994, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 997, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1490},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 996, -1, 996, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 999, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1492},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 998, -1, 998, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1001, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1494},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1000, -1, 1000, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1003, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1496},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1002, -1, 1002, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1005, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1498},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1004, -1, 1004, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1007, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1500},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1006, -1, 1006, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1398, false, 922, -1, 922, -1, -1, false, false, false, false, utf8proc_sequences + 1398},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1410, false, 929, -1, 929, -1, -1, false, false, false, false, utf8proc_sequences + 1410},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1502, false, 1017, -1, 1017, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1504, false, -1, 952, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1396},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1390, false, 917, -1, 917, -1, -1, false, false, false, false, utf8proc_sequences + 1390},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1016, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1506},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1015, -1, 1015, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1508, false, -1, 1010, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1510},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1019, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1512},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1018, -1, 1018, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 891, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1514},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 892, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1516},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 893, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1518},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1520, false, -1, 1104, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1523},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1525, false, -1, 1105, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1528},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1106, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1530},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1532, false, -1, 1107, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1535},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1108, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1537},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1109, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1539},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1110, -1, 4800, -1, false, false, false, false, utf8proc_sequences + 1541},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1543, false, -1, 1111, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1546},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1112, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1548},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1113, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1550},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1114, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1552},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1115, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1554},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1556, false, -1, 1116, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1559},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1561, false, -1, 1117, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1564},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1566, false, -1, 1118, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1569},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1119, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1571},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1072, -1, 5640, -1, false, false, false, false, utf8proc_sequences + 1573},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1073, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1575},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1074, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1577},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1075, -1, 4740, -1, false, false, false, false, utf8proc_sequences + 1579},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1076, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1581},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1077, -1, 4680, -1, false, false, false, false, utf8proc_sequences + 1583},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1078, -1, 5520, -1, false, false, false, false, utf8proc_sequences + 1585},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1079, -1, 5880, -1, false, false, false, false, utf8proc_sequences + 1587},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1080, -1, 4920, -1, false, false, false, false, utf8proc_sequences + 1589},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1591, false, -1, 1081, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1594},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1082, -1, 4860, -1, false, false, false, false, utf8proc_sequences + 1596},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1083, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1598},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1084, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1600},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1085, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1602},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1086, -1, 6000, -1, false, false, false, false, utf8proc_sequences + 1604},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1087, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1606},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1088, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1608},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1089, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1610},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1090, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1612},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1091, -1, 4980, -1, false, false, false, false, utf8proc_sequences + 1614},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1092, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1616},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1093, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1618},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1094, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1620},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1095, -1, 6360, -1, false, false, false, false, utf8proc_sequences + 1622},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1096, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1624},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1097, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1626},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1098, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1628},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1099, -1, 6480, -1, false, false, false, false, utf8proc_sequences + 1630},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1100, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1632},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1101, -1, 6240, -1, false, false, false, false, utf8proc_sequences + 1634},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1102, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1636},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1103, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1638},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1040, -1, 1040, 5700, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1041, -1, 1041, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1042, -1, 1042, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1043, -1, 1043, 5160, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1044, -1, 1044, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1045, -1, 1045, 5100, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1046, -1, 1046, 5580, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1047, -1, 1047, 5940, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1048, -1, 1048, 5040, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1640, false, 1049, -1, 1049, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1050, -1, 1050, 5280, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1051, -1, 1051, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1052, -1, 1052, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1053, -1, 1053, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1054, -1, 1054, 6060, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1055, -1, 1055, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1056, -1, 1056, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1057, -1, 1057, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1058, -1, 1058, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1059, -1, 1059, 5340, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1060, -1, 1060, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1061, -1, 1061, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1062, -1, 1062, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1063, -1, 1063, 6420, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1064, -1, 1064, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1065, -1, 1065, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1066, -1, 1066, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1067, -1, 1067, 6540, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1068, -1, 1068, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1069, -1, 1069, 6300, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1070, -1, 1070, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1071, -1, 1071, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1643, false, 1024, -1, 1024, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1646, false, 1025, -1, 1025, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1026, -1, 1026, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1649, false, 1027, -1, 1027, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1028, -1, 1028, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1029, -1, 1029, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1030, -1, 1030, 5220, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1652, false, 1031, -1, 1031, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1032, -1, 1032, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1033, -1, 1033, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1034, -1, 1034, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1035, -1, 1035, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1655, false, 1036, -1, 1036, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1658, false, 1037, -1, 1037, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1661, false, 1038, -1, 1038, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1039, -1, 1039, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1121, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1664},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1120, -1, 1120, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1123, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1666},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1122, -1, 1122, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1125, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1668},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1124, -1, 1124, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1127, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1670},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1126, -1, 1126, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1129, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1672},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1128, -1, 1128, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1131, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1674},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1130, -1, 1130, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1133, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1676},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1132, -1, 1132, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1135, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1678},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1134, -1, 1134, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1137, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1680},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1136, -1, 1136, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1139, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1682},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1138, -1, 1138, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1141, -1, 5400, -1, false, false, false, false, utf8proc_sequences + 1684},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1140, -1, 1140, 5460, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1686, false, -1, 1143, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1689},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1691, false, 1142, -1, 1142, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1145, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1694},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1144, -1, 1144, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1147, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1696},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1146, -1, 1146, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1149, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1698},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1148, -1, 1148, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1151, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1700},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1150, -1, 1150, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1153, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1702},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1152, -1, 1152, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ME, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1163, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1704},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1162, -1, 1162, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1165, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1706},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1164, -1, 1164, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1167, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1708},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1166, -1, 1166, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1169, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1710},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1168, -1, 1168, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1171, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1712},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1170, -1, 1170, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1173, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1714},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1172, -1, 1172, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1175, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1716},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1174, -1, 1174, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1177, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1718},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1176, -1, 1176, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1179, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1720},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1178, -1, 1178, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1181, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1722},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1180, -1, 1180, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1183, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1724},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1182, -1, 1182, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1185, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1726},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1184, -1, 1184, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1187, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1728},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1186, -1, 1186, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1189, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1730},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1188, -1, 1188, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1191, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1732},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1190, -1, 1190, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1193, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1734},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1192, -1, 1192, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1195, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1736},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1194, -1, 1194, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1197, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1738},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1196, -1, 1196, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1199, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1740},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1198, -1, 1198, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1201, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1742},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1200, -1, 1200, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1203, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1744},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1202, -1, 1202, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1205, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1746},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1204, -1, 1204, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1207, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1748},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1206, -1, 1206, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1209, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1750},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1208, -1, 1208, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1211, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1752},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1210, -1, 1210, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1213, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1754},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1212, -1, 1212, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1215, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1756},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1214, -1, 1214, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1231, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1758},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1760, false, -1, 1218, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1763},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1765, false, 1217, -1, 1217, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1220, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1768},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1219, -1, 1219, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1222, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1770},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1221, -1, 1221, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1224, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1772},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1223, -1, 1223, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1226, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1774},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1225, -1, 1225, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1228, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1776},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1227, -1, 1227, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1230, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1778},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1229, -1, 1229, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1216, -1, 1216, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1780, false, -1, 1233, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1783},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1785, false, 1232, -1, 1232, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1788, false, -1, 1235, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1791},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1793, false, 1234, -1, 1234, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1237, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1796},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1236, -1, 1236, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1798, false, -1, 1239, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1801},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1803, false, 1238, -1, 1238, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1241, -1, 5760, -1, false, false, false, false, utf8proc_sequences + 1806},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1240, -1, 1240, 5820, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1808, false, -1, 1243, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1811},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1813, false, 1242, -1, 1242, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1816, false, -1, 1245, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1819},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1821, false, 1244, -1, 1244, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1824, false, -1, 1247, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1827},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1829, false, 1246, -1, 1246, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1249, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1832},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1248, -1, 1248, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1834, false, -1, 1251, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1837},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1839, false, 1250, -1, 1250, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1842, false, -1, 1253, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1845},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1847, false, 1252, -1, 1252, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1850, false, -1, 1255, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1853},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1855, false, 1254, -1, 1254, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1257, -1, 6120, -1, false, false, false, false, utf8proc_sequences + 1858},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1256, -1, 1256, 6180, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1860, false, -1, 1259, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1863},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1865, false, 1258, -1, 1258, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1868, false, -1, 1261, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1871},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1873, false, 1260, -1, 1260, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1876, false, -1, 1263, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1879},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1881, false, 1262, -1, 1262, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1884, false, -1, 1265, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1887},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1889, false, 1264, -1, 1264, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1892, false, -1, 1267, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1895},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1897, false, 1266, -1, 1266, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1900, false, -1, 1269, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1903},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1905, false, 1268, -1, 1268, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1271, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1908},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1270, -1, 1270, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1910, false, -1, 1273, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1913},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1915, false, 1272, -1, 1272, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1275, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1918},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1274, -1, 1274, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1277, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1920},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1276, -1, 1276, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1279, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1922},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1278, -1, 1278, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1281, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1924},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1280, -1, 1280, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1283, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1926},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1282, -1, 1282, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1285, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1928},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1284, -1, 1284, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1287, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1930},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1286, -1, 1286, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1289, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1932},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1288, -1, 1288, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1291, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1934},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1290, -1, 1290, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1293, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1936},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1292, -1, 1292, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1295, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1938},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1294, -1, 1294, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1297, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1940},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1296, -1, 1296, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1299, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1942},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1298, -1, 1298, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1377, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1944},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1378, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1946},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1379, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1948},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1380, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1950},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1381, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1952},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1382, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1954},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1383, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1956},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1384, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1958},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1385, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1960},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1386, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1962},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1387, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1964},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1388, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1966},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1389, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1968},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1390, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1970},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1391, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1972},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1392, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1974},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1393, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1976},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1394, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1978},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1395, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1980},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1396, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1982},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1397, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1984},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1398, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1986},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1399, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1988},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1400, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1990},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1401, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1992},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1402, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1994},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1403, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1996},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1404, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1998},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1405, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2000},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1406, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2002},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1407, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2004},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1408, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2006},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1409, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2008},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1410, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2010},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1411, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2012},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1412, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2014},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1413, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2016},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1414, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2018},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1329, -1, 1329, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1330, -1, 1330, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1331, -1, 1331, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1332, -1, 1332, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1333, -1, 1333, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1334, -1, 1334, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1335, -1, 1335, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1336, -1, 1336, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1337, -1, 1337, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1338, -1, 1338, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1339, -1, 1339, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1340, -1, 1340, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1341, -1, 1341, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1342, -1, 1342, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1343, -1, 1343, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1344, -1, 1344, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1345, -1, 1345, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1346, -1, 1346, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1347, -1, 1347, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1348, -1, 1348, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1349, -1, 1349, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1350, -1, 1350, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1351, -1, 1351, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1352, -1, 1352, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1353, -1, 1353, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1354, -1, 1354, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1355, -1, 1355, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1356, -1, 1356, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1357, -1, 1357, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1358, -1, 1358, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1359, -1, 1359, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1360, -1, 1360, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1361, -1, 1361, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1362, -1, 1362, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1363, -1, 1363, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1364, -1, 1364, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1365, -1, 1365, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1366, -1, 1366, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2020, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2020},
+  {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 222, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 228, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 10, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 11, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 12, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 13, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 14, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 15, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 16, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 17, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 18, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 19, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 20, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 21, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 22, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_R, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 23, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 24, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 25, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
+  {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2023, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2026, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2032, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2035, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, 6600, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, 6660, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, 6720, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 27, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 28, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 29, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 30, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 31, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 32, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 33, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 34, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 17, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 18, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 19, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_AN, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AN, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 35, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2044, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2050, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, 6840, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2053, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, 6900, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2056, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, 6780, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 36, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_R, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_R, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 6960, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7020, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2062, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7080, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2065, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 20, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2068, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2071, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2074, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2077, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2080, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2083, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2086, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2089, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 21, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7140, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2092, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 22, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2098, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2101, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2104, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2107, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2110, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2113, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2116, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2119, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2122, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 24, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7200, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2128, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 23, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 25, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2134, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2137, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7260, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2140, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 27, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7320, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7380, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2146, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2149, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 26, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, 7440, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2152, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 84, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 91, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 28, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7500, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2155, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 31, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7560, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2161, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2164, false, -1, -1, -1, 7620, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2167, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 29, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 30, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 32, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7680, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7740, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2170, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2173, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2176, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 33, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 34, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 35, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7800, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2179, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2182, false, -1, -1, -1, 7860, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2185, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2188, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 36, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2191, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 103, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 107, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2194, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 118, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 122, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2197, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2200, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NOBREAK, utf8proc_sequences + 2203, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2205, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2208, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2211, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2214, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2217, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2220, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 129, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 130, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2223, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 132, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2226, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2229, false, -1, -1, -1, -1, -1, true, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2232, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2235, false, -1, -1, -1, -1, -1, true, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2238, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2241, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2244, false, -1, -1, -1, -1, -1, true, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2247, false, -1, -1, -1, -1, -1, true, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2250, false, -1, -1, -1, -1, -1, true, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2253, false, -1, -1, -1, -1, -1, true, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2256, false, -1, -1, -1, -1, -1, true, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2259, false, -1, -1, -1, -1, -1, true, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7920, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2262, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 37, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11520, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2265},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11521, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2267},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11522, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2269},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11523, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2271},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11524, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2273},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11525, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2275},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11526, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2277},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11527, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2279},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11528, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2281},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11529, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2283},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11530, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2285},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11531, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2287},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11532, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2289},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11533, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2291},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11534, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2293},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11535, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2295},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11536, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2297},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11537, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2299},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11538, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2301},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11539, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2303},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11540, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2305},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11541, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2307},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11542, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2309},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11543, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2311},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11544, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2313},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11545, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2315},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11546, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2317},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11547, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2319},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11548, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2321},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11549, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2323},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11550, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2325},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11551, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2327},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11552, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2329},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11553, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2331},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11554, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2333},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11555, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2335},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11556, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2337},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11557, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2339},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2341, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, true, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7980, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2343, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8040, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2346, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8100, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2349, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8160, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2352, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8220, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2355, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8280, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2358, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 38, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, 8340, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2361, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, 8400, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2364, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8460, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8520, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2367, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2370, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, 8580, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2373, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 9, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2376, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2378, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2380, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2382, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2384, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2388, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2390, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2392, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2394, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2396, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2398, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2400, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2402, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2404, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2406, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2408, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2410, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2412, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2414, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2416, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 0, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2418, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2420, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2422, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 8, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 792, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 794, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2424, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 12, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 20, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 24, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 579, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 28, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 780, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2426, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2428, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 30, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 38, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 40, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2430, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 808, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 42, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2432, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1384, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1388, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1418, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1420, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 16, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 34, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 40, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 42, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 1384, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 1386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 1410, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 1418, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 1420, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1602, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11363, -1, 11363, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2434, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2436, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 163, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 10, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2438, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2440, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2442, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 804, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 802, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2444, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2446, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2448, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2450, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2452, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2454, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2456, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2458, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 810, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2460, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2462, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 812, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2464, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2466, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 830, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2468, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1275, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 844, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2470, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 846, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1277, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 50, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2472, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2474, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 852, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1396, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2476, false, -1, 7681, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2479},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2481, false, 7680, -1, 7680, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2484, false, -1, 7683, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2487},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2489, false, 7682, -1, 7682, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2492, false, -1, 7685, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2495},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2497, false, 7684, -1, 7684, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2500, false, -1, 7687, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2503},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2505, false, 7686, -1, 7686, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2508, false, -1, 7689, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2511},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2513, false, 7688, -1, 7688, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2516, false, -1, 7691, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2519},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2521, false, 7690, -1, 7690, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2524, false, -1, 7693, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2527},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2529, false, 7692, -1, 7692, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2532, false, -1, 7695, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2535},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2537, false, 7694, -1, 7694, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2540, false, -1, 7697, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2543},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2545, false, 7696, -1, 7696, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2548, false, -1, 7699, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2551},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2553, false, 7698, -1, 7698, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2556, false, -1, 7701, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2559},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2561, false, 7700, -1, 7700, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2564, false, -1, 7703, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2567},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2569, false, 7702, -1, 7702, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2572, false, -1, 7705, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2575},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2577, false, 7704, -1, 7704, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2580, false, -1, 7707, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2583},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2585, false, 7706, -1, 7706, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2588, false, -1, 7709, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2591},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2593, false, 7708, -1, 7708, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2596, false, -1, 7711, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2599},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2601, false, 7710, -1, 7710, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2604, false, -1, 7713, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2607},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2609, false, 7712, -1, 7712, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2612, false, -1, 7715, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2615},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2617, false, 7714, -1, 7714, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2620, false, -1, 7717, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2623},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2625, false, 7716, -1, 7716, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2628, false, -1, 7719, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2631},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2633, false, 7718, -1, 7718, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2636, false, -1, 7721, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2639},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2641, false, 7720, -1, 7720, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2644, false, -1, 7723, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2647},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2649, false, 7722, -1, 7722, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2652, false, -1, 7725, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2655},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2657, false, 7724, -1, 7724, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2660, false, -1, 7727, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2663},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2665, false, 7726, -1, 7726, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2668, false, -1, 7729, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2671},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2673, false, 7728, -1, 7728, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2676, false, -1, 7731, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2679},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2681, false, 7730, -1, 7730, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2684, false, -1, 7733, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2687},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2689, false, 7732, -1, 7732, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2692, false, -1, 7735, -1, 9360, -1, false, false, false, false, utf8proc_sequences + 2695},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2697, false, 7734, -1, 7734, 9420, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2700, false, -1, 7737, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2703},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2705, false, 7736, -1, 7736, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2708, false, -1, 7739, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2711},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2713, false, 7738, -1, 7738, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2716, false, -1, 7741, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2719},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2721, false, 7740, -1, 7740, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2724, false, -1, 7743, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2727},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2729, false, 7742, -1, 7742, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2732, false, -1, 7745, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2735},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2737, false, 7744, -1, 7744, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2740, false, -1, 7747, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2743},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2745, false, 7746, -1, 7746, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2748, false, -1, 7749, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2751},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2753, false, 7748, -1, 7748, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2756, false, -1, 7751, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2759},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2761, false, 7750, -1, 7750, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2764, false, -1, 7753, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2767},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2769, false, 7752, -1, 7752, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2772, false, -1, 7755, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2775},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2777, false, 7754, -1, 7754, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2780, false, -1, 7757, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2783},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2785, false, 7756, -1, 7756, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2788, false, -1, 7759, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2791},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2793, false, 7758, -1, 7758, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2796, false, -1, 7761, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2799},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2801, false, 7760, -1, 7760, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2804, false, -1, 7763, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2807},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2809, false, 7762, -1, 7762, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2812, false, -1, 7765, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2815},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2817, false, 7764, -1, 7764, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2820, false, -1, 7767, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2823},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2825, false, 7766, -1, 7766, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2828, false, -1, 7769, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2831},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2833, false, 7768, -1, 7768, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2836, false, -1, 7771, -1, 9840, -1, false, false, false, false, utf8proc_sequences + 2839},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2841, false, 7770, -1, 7770, 9900, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2844, false, -1, 7773, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2847},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2849, false, 7772, -1, 7772, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2852, false, -1, 7775, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2855},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2857, false, 7774, -1, 7774, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2860, false, -1, 7777, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2863},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2865, false, 7776, -1, 7776, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2868, false, -1, 7779, -1, 10200, -1, false, false, false, false, utf8proc_sequences + 2871},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2873, false, 7778, -1, 7778, 10260, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2876, false, -1, 7781, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2879},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2881, false, 7780, -1, 7780, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2884, false, -1, 7783, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2887},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2889, false, 7782, -1, 7782, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2892, false, -1, 7785, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2895},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2897, false, 7784, -1, 7784, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2900, false, -1, 7787, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2903},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2905, false, 7786, -1, 7786, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2908, false, -1, 7789, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2911},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2913, false, 7788, -1, 7788, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2916, false, -1, 7791, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2919},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2921, false, 7790, -1, 7790, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2924, false, -1, 7793, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2927},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2929, false, 7792, -1, 7792, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2932, false, -1, 7795, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2935},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2937, false, 7794, -1, 7794, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2940, false, -1, 7797, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2943},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2945, false, 7796, -1, 7796, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2948, false, -1, 7799, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2951},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2953, false, 7798, -1, 7798, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2956, false, -1, 7801, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2959},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2961, false, 7800, -1, 7800, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2964, false, -1, 7803, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2967},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2969, false, 7802, -1, 7802, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2972, false, -1, 7805, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2975},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2977, false, 7804, -1, 7804, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2980, false, -1, 7807, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2983},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2985, false, 7806, -1, 7806, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2988, false, -1, 7809, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2991},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2993, false, 7808, -1, 7808, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2996, false, -1, 7811, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2999},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3001, false, 7810, -1, 7810, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3004, false, -1, 7813, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3007},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3009, false, 7812, -1, 7812, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3012, false, -1, 7815, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3015},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3017, false, 7814, -1, 7814, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3020, false, -1, 7817, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3023},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3025, false, 7816, -1, 7816, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3028, false, -1, 7819, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3031},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3033, false, 7818, -1, 7818, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3036, false, -1, 7821, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3039},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3041, false, 7820, -1, 7820, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3044, false, -1, 7823, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3047},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3049, false, 7822, -1, 7822, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3052, false, -1, 7825, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3055},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3057, false, 7824, -1, 7824, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3060, false, -1, 7827, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3063},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3065, false, 7826, -1, 7826, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3068, false, -1, 7829, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3071},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3073, false, 7828, -1, 7828, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3076, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3076},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3079, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3079},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3082, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3082},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3085, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3085},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 3088, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3088},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3091, false, 7776, -1, 7776, -1, -1, false, false, false, false, utf8proc_sequences + 2863},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3094, false, -1, 7841, -1, 10980, -1, false, false, false, false, utf8proc_sequences + 3097},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3099, false, 7840, -1, 7840, 11040, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3102, false, -1, 7843, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3105},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3107, false, 7842, -1, 7842, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3110, false, -1, 7845, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3113},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3115, false, 7844, -1, 7844, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3118, false, -1, 7847, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3121},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3123, false, 7846, -1, 7846, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3126, false, -1, 7849, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3129},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3131, false, 7848, -1, 7848, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3134, false, -1, 7851, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3137},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3139, false, 7850, -1, 7850, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3142, false, -1, 7853, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3145},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3147, false, 7852, -1, 7852, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3150, false, -1, 7855, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3153},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3155, false, 7854, -1, 7854, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3158, false, -1, 7857, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3161},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3163, false, 7856, -1, 7856, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3166, false, -1, 7859, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3169},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3171, false, 7858, -1, 7858, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3174, false, -1, 7861, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3177},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3179, false, 7860, -1, 7860, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3182, false, -1, 7863, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3185},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3187, false, 7862, -1, 7862, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3190, false, -1, 7865, -1, 11340, -1, false, false, false, false, utf8proc_sequences + 3193},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3195, false, 7864, -1, 7864, 11400, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3198, false, -1, 7867, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3201},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3203, false, 7866, -1, 7866, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3206, false, -1, 7869, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3209},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3211, false, 7868, -1, 7868, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3214, false, -1, 7871, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3217},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3219, false, 7870, -1, 7870, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3222, false, -1, 7873, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3225},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3227, false, 7872, -1, 7872, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3230, false, -1, 7875, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3233},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3235, false, 7874, -1, 7874, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3238, false, -1, 7877, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3241},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3243, false, 7876, -1, 7876, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3246, false, -1, 7879, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3249},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3251, false, 7878, -1, 7878, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3254, false, -1, 7881, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3257},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3259, false, 7880, -1, 7880, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3262, false, -1, 7883, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3265},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3267, false, 7882, -1, 7882, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3270, false, -1, 7885, -1, 11580, -1, false, false, false, false, utf8proc_sequences + 3273},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3275, false, 7884, -1, 7884, 11640, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3278, false, -1, 7887, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3281},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3283, false, 7886, -1, 7886, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3286, false, -1, 7889, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3289},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3291, false, 7888, -1, 7888, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3294, false, -1, 7891, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3297},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3299, false, 7890, -1, 7890, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3302, false, -1, 7893, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3305},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3307, false, 7892, -1, 7892, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3310, false, -1, 7895, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3313},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3315, false, 7894, -1, 7894, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3318, false, -1, 7897, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3321},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3323, false, 7896, -1, 7896, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3326, false, -1, 7899, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3329},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3331, false, 7898, -1, 7898, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3334, false, -1, 7901, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3337},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3339, false, 7900, -1, 7900, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3342, false, -1, 7903, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3345},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3347, false, 7902, -1, 7902, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3350, false, -1, 7905, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3353},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3355, false, 7904, -1, 7904, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3358, false, -1, 7907, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3361},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3363, false, 7906, -1, 7906, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3366, false, -1, 7909, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3369},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3371, false, 7908, -1, 7908, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3374, false, -1, 7911, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3377},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3379, false, 7910, -1, 7910, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3382, false, -1, 7913, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3385},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3387, false, 7912, -1, 7912, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3390, false, -1, 7915, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3393},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3395, false, 7914, -1, 7914, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3398, false, -1, 7917, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3401},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3403, false, 7916, -1, 7916, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3406, false, -1, 7919, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3409},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3411, false, 7918, -1, 7918, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3414, false, -1, 7921, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3417},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3419, false, 7920, -1, 7920, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3422, false, -1, 7923, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3425},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3427, false, 7922, -1, 7922, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3430, false, -1, 7925, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3433},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3435, false, 7924, -1, 7924, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3438, false, -1, 7927, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3441},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3443, false, 7926, -1, 7926, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3446, false, -1, 7929, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3449},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3451, false, 7928, -1, 7928, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3454, false, 7944, -1, 7944, 11940, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3457, false, 7945, -1, 7945, 12000, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3460, false, 7946, -1, 7946, 13560, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3463, false, 7947, -1, 7947, 13620, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3466, false, 7948, -1, 7948, 13680, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3469, false, 7949, -1, 7949, 13740, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3472, false, 7950, -1, 7950, 13800, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3475, false, 7951, -1, 7951, 13860, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3478, false, -1, 7936, -1, 12060, -1, false, false, false, false, utf8proc_sequences + 3481},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3483, false, -1, 7937, -1, 12120, -1, false, false, false, false, utf8proc_sequences + 3486},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3488, false, -1, 7938, -1, 13920, -1, false, false, false, false, utf8proc_sequences + 3491},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3493, false, -1, 7939, -1, 13980, -1, false, false, false, false, utf8proc_sequences + 3496},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3498, false, -1, 7940, -1, 14040, -1, false, false, false, false, utf8proc_sequences + 3501},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3503, false, -1, 7941, -1, 14100, -1, false, false, false, false, utf8proc_sequences + 3506},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3508, false, -1, 7942, -1, 14160, -1, false, false, false, false, utf8proc_sequences + 3511},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3513, false, -1, 7943, -1, 14220, -1, false, false, false, false, utf8proc_sequences + 3516},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3518, false, 7960, -1, 7960, 12180, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3521, false, 7961, -1, 7961, 12240, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3524, false, 7962, -1, 7962, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3527, false, 7963, -1, 7963, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3530, false, 7964, -1, 7964, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3533, false, 7965, -1, 7965, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3536, false, -1, 7952, -1, 12300, -1, false, false, false, false, utf8proc_sequences + 3539},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3541, false, -1, 7953, -1, 12360, -1, false, false, false, false, utf8proc_sequences + 3544},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3546, false, -1, 7954, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3549},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3551, false, -1, 7955, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3554},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3556, false, -1, 7956, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3559},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3561, false, -1, 7957, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3564},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3566, false, 7976, -1, 7976, 12420, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3569, false, 7977, -1, 7977, 12480, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3572, false, 7978, -1, 7978, 14280, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3575, false, 7979, -1, 7979, 14340, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3578, false, 7980, -1, 7980, 14400, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3581, false, 7981, -1, 7981, 14460, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3584, false, 7982, -1, 7982, 14520, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3587, false, 7983, -1, 7983, 14580, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3590, false, -1, 7968, -1, 12540, -1, false, false, false, false, utf8proc_sequences + 3593},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3595, false, -1, 7969, -1, 12600, -1, false, false, false, false, utf8proc_sequences + 3598},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3600, false, -1, 7970, -1, 14640, -1, false, false, false, false, utf8proc_sequences + 3603},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3605, false, -1, 7971, -1, 14700, -1, false, false, false, false, utf8proc_sequences + 3608},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3610, false, -1, 7972, -1, 14760, -1, false, false, false, false, utf8proc_sequences + 3613},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3615, false, -1, 7973, -1, 14820, -1, false, false, false, false, utf8proc_sequences + 3618},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3620, false, -1, 7974, -1, 14880, -1, false, false, false, false, utf8proc_sequences + 3623},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3625, false, -1, 7975, -1, 14940, -1, false, false, false, false, utf8proc_sequences + 3628},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3630, false, 7992, -1, 7992, 12660, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3633, false, 7993, -1, 7993, 12720, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3636, false, 7994, -1, 7994, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3639, false, 7995, -1, 7995, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3642, false, 7996, -1, 7996, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3645, false, 7997, -1, 7997, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3648, false, 7998, -1, 7998, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3651, false, 7999, -1, 7999, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3654, false, -1, 7984, -1, 12780, -1, false, false, false, false, utf8proc_sequences + 3657},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3659, false, -1, 7985, -1, 12840, -1, false, false, false, false, utf8proc_sequences + 3662},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3664, false, -1, 7986, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3667},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3669, false, -1, 7987, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3672},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3674, false, -1, 7988, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3677},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3679, false, -1, 7989, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3682},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3684, false, -1, 7990, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3687},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3689, false, -1, 7991, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3692},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3694, false, 8008, -1, 8008, 12900, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3697, false, 8009, -1, 8009, 12960, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3700, false, 8010, -1, 8010, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3703, false, 8011, -1, 8011, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3706, false, 8012, -1, 8012, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3709, false, 8013, -1, 8013, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3712, false, -1, 8000, -1, 13020, -1, false, false, false, false, utf8proc_sequences + 3715},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3717, false, -1, 8001, -1, 13080, -1, false, false, false, false, utf8proc_sequences + 3720},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3722, false, -1, 8002, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3725},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3727, false, -1, 8003, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3730},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3732, false, -1, 8004, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3735},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3737, false, -1, 8005, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3740},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3742, false, -1, -1, -1, 13140, -1, false, false, false, false, utf8proc_sequences + 3742},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3745, false, 8025, -1, 8025, 13200, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3748, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3751},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3755, false, 8027, -1, 8027, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3758, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3761},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3765, false, 8029, -1, 8029, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3768, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3771},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3775, false, 8031, -1, 8031, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3778, false, -1, 8017, -1, 13260, -1, false, false, false, false, utf8proc_sequences + 3781},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3783, false, -1, 8019, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3786},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3788, false, -1, 8021, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3791},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3793, false, -1, 8023, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3796},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3798, false, 8040, -1, 8040, 13320, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3801, false, 8041, -1, 8041, 13380, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3804, false, 8042, -1, 8042, 15000, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3807, false, 8043, -1, 8043, 15060, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3810, false, 8044, -1, 8044, 15120, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3813, false, 8045, -1, 8045, 15180, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3816, false, 8046, -1, 8046, 15240, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3819, false, 8047, -1, 8047, 15300, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3822, false, -1, 8032, -1, 13440, -1, false, false, false, false, utf8proc_sequences + 3825},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3827, false, -1, 8033, -1, 13500, -1, false, false, false, false, utf8proc_sequences + 3830},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3832, false, -1, 8034, -1, 15360, -1, false, false, false, false, utf8proc_sequences + 3835},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3837, false, -1, 8035, -1, 15420, -1, false, false, false, false, utf8proc_sequences + 3840},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3842, false, -1, 8036, -1, 15480, -1, false, false, false, false, utf8proc_sequences + 3845},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3847, false, -1, 8037, -1, 15540, -1, false, false, false, false, utf8proc_sequences + 3850},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3852, false, -1, 8038, -1, 15600, -1, false, false, false, false, utf8proc_sequences + 3855},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3857, false, -1, 8039, -1, 15660, -1, false, false, false, false, utf8proc_sequences + 3860},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3862, false, 8122, -1, 8122, 15720, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1341, false, 8123, -1, 8123, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3865, false, 8136, -1, 8136, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1348, false, 8137, -1, 8137, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3868, false, 8138, -1, 8138, 15900, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1353, false, 8139, -1, 8139, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3871, false, 8154, -1, 8154, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1358, false, 8155, -1, 8155, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3874, false, 8184, -1, 8184, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1363, false, 8185, -1, 8185, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3877, false, 8170, -1, 8170, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1368, false, 8171, -1, 8171, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3880, false, 8186, -1, 8186, 16320, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1373, false, 8187, -1, 8187, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3883, false, 8072, -1, 8072, -1, -1, false, false, false, false, utf8proc_sequences + 3886},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3889, false, 8073, -1, 8073, -1, -1, false, false, false, false, utf8proc_sequences + 3892},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3895, false, 8074, -1, 8074, -1, -1, false, false, false, false, utf8proc_sequences + 3898},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3901, false, 8075, -1, 8075, -1, -1, false, false, false, false, utf8proc_sequences + 3904},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3907, false, 8076, -1, 8076, -1, -1, false, false, false, false, utf8proc_sequences + 3910},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3913, false, 8077, -1, 8077, -1, -1, false, false, false, false, utf8proc_sequences + 3916},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3919, false, 8078, -1, 8078, -1, -1, false, false, false, false, utf8proc_sequences + 3922},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3925, false, 8079, -1, 8079, -1, -1, false, false, false, false, utf8proc_sequences + 3928},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3931, false, -1, 8064, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3934},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3936, false, -1, 8065, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3939},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3941, false, -1, 8066, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3944},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3946, false, -1, 8067, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3949},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3951, false, -1, 8068, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3954},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3956, false, -1, 8069, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3959},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3961, false, -1, 8070, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3964},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3966, false, -1, 8071, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3969},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3971, false, 8088, -1, 8088, -1, -1, false, false, false, false, utf8proc_sequences + 3974},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3977, false, 8089, -1, 8089, -1, -1, false, false, false, false, utf8proc_sequences + 3980},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3983, false, 8090, -1, 8090, -1, -1, false, false, false, false, utf8proc_sequences + 3986},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3989, false, 8091, -1, 8091, -1, -1, false, false, false, false, utf8proc_sequences + 3992},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3995, false, 8092, -1, 8092, -1, -1, false, false, false, false, utf8proc_sequences + 3998},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4001, false, 8093, -1, 8093, -1, -1, false, false, false, false, utf8proc_sequences + 4004},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4007, false, 8094, -1, 8094, -1, -1, false, false, false, false, utf8proc_sequences + 4010},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4013, false, 8095, -1, 8095, -1, -1, false, false, false, false, utf8proc_sequences + 4016},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4019, false, -1, 8080, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4022},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4024, false, -1, 8081, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4027},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4029, false, -1, 8082, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4032},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4034, false, -1, 8083, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4037},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4039, false, -1, 8084, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4042},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4044, false, -1, 8085, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4047},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4049, false, -1, 8086, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4052},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4054, false, -1, 8087, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4057},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4059, false, 8104, -1, 8104, -1, -1, false, false, false, false, utf8proc_sequences + 4062},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4065, false, 8105, -1, 8105, -1, -1, false, false, false, false, utf8proc_sequences + 4068},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4071, false, 8106, -1, 8106, -1, -1, false, false, false, false, utf8proc_sequences + 4074},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4077, false, 8107, -1, 8107, -1, -1, false, false, false, false, utf8proc_sequences + 4080},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4083, false, 8108, -1, 8108, -1, -1, false, false, false, false, utf8proc_sequences + 4086},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4089, false, 8109, -1, 8109, -1, -1, false, false, false, false, utf8proc_sequences + 4092},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4095, false, 8110, -1, 8110, -1, -1, false, false, false, false, utf8proc_sequences + 4098},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4101, false, 8111, -1, 8111, -1, -1, false, false, false, false, utf8proc_sequences + 4104},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4107, false, -1, 8096, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4110},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4112, false, -1, 8097, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4115},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4117, false, -1, 8098, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4120},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4122, false, -1, 8099, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4125},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4127, false, -1, 8100, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4130},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4132, false, -1, 8101, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4135},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4137, false, -1, 8102, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4140},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4142, false, -1, 8103, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4145},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4147, false, 8120, -1, 8120, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4150, false, 8121, -1, 8121, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4153, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4156},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4159, false, 8124, -1, 8124, -1, -1, false, false, false, false, utf8proc_sequences + 4162},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4165, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4168},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4171, false, -1, -1, -1, 15840, -1, false, false, false, false, utf8proc_sequences + 4171},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4174, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4177},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4181, false, -1, 8112, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4184},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4186, false, -1, 8113, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4189},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4191, false, -1, 8048, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4194},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4196, false, -1, 8049, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4198},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4200, false, -1, 8115, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4203},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4205, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1326, false, 921, -1, 921, -1, -1, false, false, false, false, utf8proc_sequences + 1326},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4205, false, -1, -1, -1, 16080, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4208, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4211, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4214, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4217},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4220, false, 8140, -1, 8140, -1, -1, false, false, false, false, utf8proc_sequences + 4223},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4226, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4229},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4232, false, -1, -1, -1, 16020, -1, false, false, false, false, utf8proc_sequences + 4232},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4235, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4238},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4242, false, -1, 8050, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4245},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4247, false, -1, 8051, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4249},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4251, false, -1, 8052, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4254},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4256, false, -1, 8053, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4258},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4260, false, -1, 8131, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4263},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4265, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4268, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4271, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4274, false, 8152, -1, 8152, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4277, false, 8153, -1, 8153, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4280, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4283},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4287, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1378},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4289, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4289},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4292, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4295},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4299, false, -1, 8144, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4302},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4304, false, -1, 8145, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4307},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4309, false, -1, 8054, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4312},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4314, false, -1, 8055, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4316},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4318, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4321, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4324, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4327, false, 8168, -1, 8168, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4330, false, 8169, -1, 8169, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4333, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4336},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4340, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1451},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4342, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4342},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4345, false, 8172, -1, 8172, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4348, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4348},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4351, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4354},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4358, false, -1, 8160, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4361},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4363, false, -1, 8161, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4366},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4368, false, -1, 8058, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4371},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4373, false, -1, 8059, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4375},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4377, false, -1, 8165, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4380},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4382, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4385, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4387, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4389, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4392},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4395, false, 8188, -1, 8188, -1, -1, false, false, false, false, utf8proc_sequences + 4398},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4401, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4404},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4407, false, -1, -1, -1, 16440, -1, false, false, false, false, utf8proc_sequences + 4407},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4410, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4413},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4417, false, -1, 8056, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4420},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4422, false, -1, 8057, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4424},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4426, false, -1, 8060, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4429},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4431, false, -1, 8061, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4433},
+  {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4435, false, -1, 8179, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4438},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4440, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4442, false, -1, -1, -1, 16140, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, utf8proc_sequences + 4445, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, utf8proc_sequences + 4447, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 52, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_NOBREAK, utf8proc_sequences + 52, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, true, NULL},
+  {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_R, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
+  {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NOBREAK, utf8proc_sequences + 4449, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4451, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4454, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4456, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4459, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ZL, 0, UTF8PROC_BIDI_CLASS_WS, 0, NULL, false, -1, -1, -1, -1, -1, false, false, true, false, NULL},
+  {UTF8PROC_CATEGORY_ZP, 0, UTF8PROC_BIDI_CLASS_B, 0, NULL, false, -1, -1, -1, -1, -1, false, false, true, false, NULL},
+  {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRE, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
+  {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLE, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
+  {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_PDF, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
+  {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRO, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
+  {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLO, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4463, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4466, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4470, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4473, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4477, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4480, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_CS, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4483, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4486, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4489, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4492, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 16, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4501, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4509, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4513, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4515, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4517, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4519, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 26, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 72, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 60, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 62, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4501, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4509, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4513, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4515, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4517, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4519, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 0, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 8, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 28, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 46, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 792, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4521, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4524, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4528, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4534, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4537, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4541, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4545, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4547, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 12, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2390, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 14, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 454, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2392, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2398, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 22, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2402, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4550, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2408, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4553, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2410, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4555, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4558, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4562, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4565, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4567, false, -1, 969, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1424},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2396, false, -1, 107, -1, -1, -1, false, false, false, false, utf8proc_sequences + 20},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4569, false, -1, 229, -1, -1, -1, false, false, false, false, utf8proc_sequences + 114},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2380, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2384, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4571, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 8526, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4573},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2400, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 28, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4575, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4577, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4579, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4581, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 16, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4583, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1408, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4587, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4589, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4591, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2382, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 6, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 18, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 8498, -1, 8498, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4593, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4597, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4601, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4605, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4609, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4613, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4617, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4621, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4625, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4629, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4633, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4637, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4641, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2392, false, -1, 8560, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4644},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4646, false, -1, 8561, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4649},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4651, false, -1, 8562, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4655},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4657, false, -1, 8563, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4660},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4662, false, -1, 8564, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4664},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4666, false, -1, 8565, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4669},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4671, false, -1, 8566, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4675},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4677, false, -1, 8567, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4682},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4684, false, -1, 8568, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4687},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4689, false, -1, 8569, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4691},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4693, false, -1, 8570, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4696},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4698, false, -1, 8571, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4702},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2398, false, -1, 8572, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4704},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4532, false, -1, 8573, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4706},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2382, false, -1, 8574, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4708},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2400, false, -1, 8575, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4710},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 16, false, 8544, -1, 8544, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4712, false, 8545, -1, 8545, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4715, false, 8546, -1, 8546, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4719, false, 8547, -1, 8547, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 42, false, 8548, -1, 8548, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4722, false, 8549, -1, 8549, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4725, false, 8550, -1, 8550, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4729, false, 8551, -1, 8551, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4734, false, 8552, -1, 8552, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 46, false, 8553, -1, 8553, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4737, false, 8554, -1, 8554, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4740, false, 8555, -1, 8555, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 22, false, 8556, -1, 8556, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4, false, 8557, -1, 8557, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6, false, 8558, -1, 8558, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 24, false, 8559, -1, 8559, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 8580, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4744},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 8579, -1, 8579, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 16500, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 16560, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 16620, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4746, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4749, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4752, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4755, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4758, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4761, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 16680, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 16800, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 16740, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 16860, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4764, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 16920, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4767, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 16980, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4770, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 17040, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4773, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 17100, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4776, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4779, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4782, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4786, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4789, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17160, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4793, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17220, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4796, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17280, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4799, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17340, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4802, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 17520, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4805, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 17460, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4808, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17700, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17760, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4811, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4814, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4817, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4820, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4823, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17820, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17880, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4826, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4829, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17940, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18000, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4832, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4835, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18060, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18120, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18660, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18720, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4838, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4841, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18180, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18240, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4844, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4847, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18300, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18360, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4850, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4853, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18780, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18840, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18420, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18480, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18540, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18600, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4856, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4859, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4862, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4865, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18900, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18960, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 19020, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 19080, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4868, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4871, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4874, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4877, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4880, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4883, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4886, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4889, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4892, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4894, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 72, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 60, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 62, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4501, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4509, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4896, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4899, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4905, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4911, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4917, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4923, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4929, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4933, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4937, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4941, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4945, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4949, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4953, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4957, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4961, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4970, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4975, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4985, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4990, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4995, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5000, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5005, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5010, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5015, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5020, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5023, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5026, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5032, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5035, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5044, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5051, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5055, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5063, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5067, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5071, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5075, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5079, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5083, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5099, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5107, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5111, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5123, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5127, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5135, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5139, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5147, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5151, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5155, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5159, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5163, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5167, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5171, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5175, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5179, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5183, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5187, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5191, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2376, false, -1, 9424, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5195},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2380, false, -1, 9425, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5197},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4532, false, -1, 9426, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5199},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2382, false, -1, 9427, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5201},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2384, false, -1, 9428, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5203},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4571, false, -1, 9429, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5205},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2388, false, -1, 9430, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5207},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2390, false, -1, 9431, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5209},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2392, false, -1, 9432, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5211},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2394, false, -1, 9433, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5213},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2396, false, -1, 9434, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5215},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2398, false, -1, 9435, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5217},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2400, false, -1, 9436, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5219},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2402, false, -1, 9437, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5221},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2404, false, -1, 9438, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5223},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2408, false, -1, 9439, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5225},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4553, false, -1, 9440, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5227},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2410, false, -1, 9441, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5229},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5231, false, -1, 9442, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5233},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2412, false, -1, 9443, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5235},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2414, false, -1, 9444, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5237},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4662, false, -1, 9445, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5239},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2416, false, -1, 9446, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5241},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4689, false, -1, 9447, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5243},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5245, false, -1, 9448, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5247},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4565, false, -1, 9449, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5249},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 0, false, 9398, -1, 9398, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2, false, 9399, -1, 9399, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4, false, 9400, -1, 9400, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6, false, 9401, -1, 9401, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 8, false, 9402, -1, 9402, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 10, false, 9403, -1, 9403, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 12, false, 9404, -1, 9404, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 14, false, 9405, -1, 9405, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 16, false, 9406, -1, 9406, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 18, false, 9407, -1, 9407, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 20, false, 9408, -1, 9408, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 22, false, 9409, -1, 9409, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 24, false, 9410, -1, 9410, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 26, false, 9411, -1, 9411, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 28, false, 9412, -1, 9412, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 30, false, 9413, -1, 9413, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 32, false, 9414, -1, 9414, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 34, false, 9415, -1, 9415, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 36, false, 9416, -1, 9416, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 38, false, 9417, -1, 9417, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 40, false, 9418, -1, 9418, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 42, false, 9419, -1, 9419, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 44, false, 9420, -1, 9420, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 46, false, 9421, -1, 9421, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 48, false, 9422, -1, 9422, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 50, false, 9423, -1, 9423, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5251, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5256, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5260, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5263, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 5267, true, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 19140, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11312, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5270},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11313, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5272},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11314, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5274},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11315, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5276},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11316, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5278},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11317, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5280},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11318, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5282},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11319, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5284},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11320, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5286},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11321, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5288},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11322, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5290},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11323, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5292},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11324, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5294},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11325, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5296},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11326, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5298},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11327, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5300},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11328, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5302},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11329, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5304},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11330, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5306},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11331, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5308},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11332, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5310},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11333, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5312},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11334, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5314},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11335, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5316},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11336, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5318},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11337, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5320},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11338, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5322},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11339, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5324},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11340, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5326},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11341, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5328},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11342, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5330},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11343, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5332},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11344, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5334},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11345, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5336},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11346, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5338},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11347, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5340},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11348, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5342},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11349, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5344},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11350, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5346},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11351, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5348},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11352, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5350},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11353, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5352},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11354, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5354},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11355, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5356},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11356, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5358},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11357, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5360},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11358, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5362},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11264, -1, 11264, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11265, -1, 11265, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11266, -1, 11266, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11267, -1, 11267, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11268, -1, 11268, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11269, -1, 11269, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11270, -1, 11270, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11271, -1, 11271, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11272, -1, 11272, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11273, -1, 11273, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11274, -1, 11274, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11275, -1, 11275, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11276, -1, 11276, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11277, -1, 11277, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11278, -1, 11278, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11279, -1, 11279, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11280, -1, 11280, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11281, -1, 11281, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11282, -1, 11282, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11283, -1, 11283, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11284, -1, 11284, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11285, -1, 11285, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11286, -1, 11286, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11287, -1, 11287, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11288, -1, 11288, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11289, -1, 11289, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11290, -1, 11290, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11291, -1, 11291, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11292, -1, 11292, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11293, -1, 11293, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11294, -1, 11294, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11295, -1, 11295, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11296, -1, 11296, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11297, -1, 11297, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11298, -1, 11298, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11299, -1, 11299, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11300, -1, 11300, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11301, -1, 11301, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11302, -1, 11302, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11303, -1, 11303, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11304, -1, 11304, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11305, -1, 11305, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11306, -1, 11306, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11307, -1, 11307, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11308, -1, 11308, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11309, -1, 11309, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11310, -1, 11310, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11361, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5364},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11360, -1, 11360, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 619, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5366},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 7549, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5368},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 637, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5370},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 570, -1, 570, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 574, -1, 574, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11368, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5372},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11367, -1, 11367, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11370, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5374},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11369, -1, 11369, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11372, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5376},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11371, -1, 11371, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11382, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5378},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11381, -1, 11381, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11393, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5380},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11392, -1, 11392, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11395, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5382},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11394, -1, 11394, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11397, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5384},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11396, -1, 11396, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11399, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5386},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11398, -1, 11398, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11401, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5388},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11400, -1, 11400, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11403, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5390},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11402, -1, 11402, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11405, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5392},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11404, -1, 11404, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11407, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5394},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11406, -1, 11406, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11409, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5396},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11408, -1, 11408, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11411, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5398},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11410, -1, 11410, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11413, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5400},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11412, -1, 11412, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11415, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5402},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11414, -1, 11414, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11417, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5404},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11416, -1, 11416, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11419, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5406},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11418, -1, 11418, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11421, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5408},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11420, -1, 11420, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11423, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5410},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11422, -1, 11422, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11425, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5412},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11424, -1, 11424, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11427, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5414},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11426, -1, 11426, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11429, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5416},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11428, -1, 11428, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11431, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5418},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11430, -1, 11430, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11433, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5420},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11432, -1, 11432, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11435, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5422},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11434, -1, 11434, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11437, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5424},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11436, -1, 11436, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11439, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5426},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11438, -1, 11438, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11441, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5428},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11440, -1, 11440, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11443, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5430},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11442, -1, 11442, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11445, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5432},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11444, -1, 11444, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11447, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5434},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11446, -1, 11446, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11449, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5436},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11448, -1, 11448, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11451, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5438},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11450, -1, 11450, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11453, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5440},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11452, -1, 11452, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11455, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5442},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11454, -1, 11454, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11457, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5444},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11456, -1, 11456, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11459, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5446},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11458, -1, 11458, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11461, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5448},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11460, -1, 11460, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11463, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5450},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11462, -1, 11462, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11465, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5452},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11464, -1, 11464, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11467, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5454},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11466, -1, 11466, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11469, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5456},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11468, -1, 11468, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11471, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5458},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11470, -1, 11470, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11473, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5460},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11472, -1, 11472, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11475, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5462},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11474, -1, 11474, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11477, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5464},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11476, -1, 11476, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11479, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5466},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11478, -1, 11478, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11481, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5468},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11480, -1, 11480, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11483, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5470},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11482, -1, 11482, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11485, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5472},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11484, -1, 11484, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11487, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5474},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11486, -1, 11486, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11489, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5476},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11488, -1, 11488, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11491, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5478},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11490, -1, 11490, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4256, -1, 4256, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4257, -1, 4257, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4258, -1, 4258, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4259, -1, 4259, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4260, -1, 4260, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4261, -1, 4261, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4262, -1, 4262, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4263, -1, 4263, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4264, -1, 4264, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4265, -1, 4265, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4266, -1, 4266, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4267, -1, 4267, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4268, -1, 4268, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4269, -1, 4269, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4270, -1, 4270, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4271, -1, 4271, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4272, -1, 4272, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4273, -1, 4273, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4274, -1, 4274, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4275, -1, 4275, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4276, -1, 4276, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4277, -1, 4277, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4278, -1, 4278, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4279, -1, 4279, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4280, -1, 4280, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4281, -1, 4281, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4282, -1, 4282, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4283, -1, 4283, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4284, -1, 4284, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4285, -1, 4285, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4286, -1, 4286, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4287, -1, 4287, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4288, -1, 4288, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4289, -1, 4289, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4290, -1, 4290, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4291, -1, 4291, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4292, -1, 4292, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4293, -1, 4293, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 5480, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5484, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5486, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5488, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5490, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5492, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5494, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5496, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5498, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5500, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5502, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5504, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5506, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5508, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5510, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5512, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5514, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5516, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5518, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5520, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5522, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5524, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5526, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5528, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5530, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5534, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5536, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5538, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5540, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5542, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5544, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5546, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5548, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5550, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5552, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5554, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5556, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5558, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5560, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5562, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5564, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5566, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5568, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5570, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5572, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5574, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5576, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5578, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5580, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5582, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5584, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5586, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5588, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5590, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5592, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5594, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5596, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5598, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5600, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5602, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5604, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5606, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5608, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5610, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5612, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5614, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5616, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5618, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5620, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5622, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5624, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5626, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5628, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5630, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5632, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5634, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5636, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5638, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5640, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5642, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5644, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5646, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5648, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5650, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5652, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5654, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5656, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5658, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5660, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5662, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5664, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5666, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5668, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5670, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5672, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5674, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5676, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5678, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5680, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5682, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5684, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5686, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5688, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5690, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5692, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5694, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5696, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5698, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5700, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5702, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5704, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5706, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5708, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5710, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5712, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5714, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5716, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5718, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5720, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5722, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5724, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5726, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5728, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5730, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5732, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5734, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5736, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5738, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5740, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5742, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5744, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5746, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5748, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5750, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5752, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5754, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5756, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5758, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5760, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5762, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5764, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5766, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5768, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5770, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5772, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5774, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5776, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5778, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5780, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5782, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5784, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5786, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5788, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5790, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5792, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5794, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5796, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5798, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5800, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5802, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5804, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5806, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5808, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5810, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5812, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5814, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5816, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5818, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5820, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5822, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5824, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5826, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5828, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5830, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5832, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5834, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5836, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5838, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5840, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5842, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5844, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5846, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5848, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5850, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5852, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5854, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5856, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5858, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5860, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5862, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5864, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5866, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5868, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5870, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5872, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5874, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5876, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5878, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5880, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5882, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5884, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5886, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5888, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5890, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5892, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5894, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5896, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5898, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5900, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5904, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5906, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 52, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 218, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 224, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5916, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5918, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20400, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19200, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19260, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5923, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19320, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19380, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5929, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19440, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5932, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19500, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5935, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19560, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5938, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19620, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5941, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19680, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5944, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19740, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5947, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19800, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5950, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19860, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5953, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19920, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5956, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19980, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5959, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20040, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5962, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20100, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5968, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20160, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5971, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5974, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20220, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5977, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20280, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5983, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5986, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20340, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5989, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5992, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5995, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 8, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 52, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MN, 8, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 53, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5998, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6001, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20460, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6004, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 6007, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21720, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20520, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6010, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20580, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6013, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20640, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6016, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20700, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6019, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20760, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6022, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20820, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6025, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20880, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6028, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20940, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6031, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21000, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6034, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21060, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6037, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21120, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6040, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21180, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6043, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21240, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6046, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21300, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6049, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21360, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6052, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21420, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6055, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6058, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21480, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6061, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6064, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21540, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6067, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6070, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21600, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6073, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6076, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21660, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6079, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6082, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21780, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21840, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21900, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21960, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6085, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6088, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6094, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6097, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 22020, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6100, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 6103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6106, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6108, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6110, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6112, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6114, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6116, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6118, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6120, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6122, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6124, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6126, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6128, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6130, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6132, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6134, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6136, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6138, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6140, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6142, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6144, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6146, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6148, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6150, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6152, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6154, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6156, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6160, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6162, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6164, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6166, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6168, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6170, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6172, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6174, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6176, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6178, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6180, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6182, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6184, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6186, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6188, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6190, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6192, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6194, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6196, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6198, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6200, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6202, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6204, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6206, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6208, false, -1, -1, -1, -1, -1, false, true, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6210, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6212, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6214, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6216, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6218, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6220, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6222, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6224, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6226, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6228, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6230, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6232, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6234, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6236, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6238, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6240, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6242, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6244, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6246, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6248, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6250, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6252, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6254, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6256, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6258, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6260, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6262, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6264, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6266, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6268, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6270, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6272, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6274, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6276, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6278, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6280, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6282, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6284, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6286, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6288, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6290, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6292, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 5486, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 5498, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6294, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6296, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6298, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6300, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6302, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6304, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 5494, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6306, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6308, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6310, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6312, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 5502, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6314, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6318, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6322, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6326, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6330, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6334, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6338, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6342, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6346, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6350, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6354, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6358, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6362, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6366, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6370, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6375, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6380, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6385, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6390, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6395, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6400, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6405, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6410, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6415, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6420, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6425, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6430, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6435, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6440, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6445, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6453, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6460, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6464, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6468, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6472, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6476, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6480, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6484, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6488, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6492, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6496, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6500, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6504, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6508, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6512, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6516, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6520, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6524, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6528, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6536, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6540, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6544, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6548, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6552, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6556, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6560, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6564, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6568, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6572, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6576, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6580, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6584, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6588, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6592, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6596, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6600, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6604, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6608, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6611, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6614, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6617, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6620, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6623, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6626, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6629, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6632, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6635, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6638, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6641, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6644, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6647, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6650, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6106, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6112, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6118, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6122, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6138, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6140, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6146, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6150, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6152, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6156, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6160, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6162, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6164, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6653, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6656, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6659, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6662, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6665, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6668, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6671, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6674, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6677, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6680, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6683, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6686, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6689, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6692, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6695, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6701, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6706, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5486, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5498, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6294, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6296, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6709, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6711, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6713, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5508, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6715, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5632, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5656, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5654, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5634, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5818, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5548, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5628, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6717, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6719, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6721, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6723, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6725, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6727, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6729, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6731, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6733, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6735, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5560, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6737, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6739, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6741, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6743, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6745, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6747, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6749, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6751, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6298, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6300, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6302, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6753, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6755, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6757, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6759, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6761, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6763, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6765, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6767, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6769, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6771, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6773, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6776, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6779, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6782, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6785, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6788, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6791, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6794, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6797, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6800, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6803, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6806, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6809, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6812, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6815, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6818, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6821, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6824, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6827, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6830, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6833, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6836, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6839, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6842, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6845, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6849, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6853, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6857, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6860, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6864, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6867, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6871, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6873, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6875, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6877, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6879, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6881, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6883, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6885, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6887, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6889, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6891, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6893, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6895, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6897, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6899, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6901, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6903, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6905, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6907, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6909, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6911, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6913, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6915, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6917, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6919, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6921, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6923, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6925, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6927, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6929, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6931, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6933, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6935, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6937, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6939, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6941, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6943, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6945, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6947, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6949, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6951, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6953, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6955, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6957, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6959, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6961, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6963, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6970, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6975, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6984, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6989, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6993, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6997, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7003, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7008, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7012, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7016, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7020, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7025, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7030, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7034, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7045, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7050, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7055, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7058, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7064, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7071, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7077, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7081, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7093, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7098, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7102, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7106, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7110, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7121, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7126, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7130, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7134, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7138, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7141, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7144, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7147, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7150, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7154, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7164, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7168, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7173, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7179, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7183, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7186, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7189, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7195, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7200, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7206, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7210, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7216, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7219, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7223, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7227, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7231, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7235, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7244, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7248, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7251, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7255, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7259, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7263, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7268, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7272, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7276, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7280, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7286, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7291, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7294, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7300, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7303, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7308, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7313, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7317, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7321, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7325, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7330, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7337, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7342, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7345, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7351, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7355, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7358, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7361, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7364, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7367, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7370, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7373, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7376, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7379, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7382, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7385, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7389, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7393, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7397, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7401, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7405, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7409, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7413, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7417, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7421, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7425, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7429, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7433, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7437, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7441, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7445, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7449, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7452, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7455, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7459, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7462, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7465, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7468, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7472, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7476, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7479, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7485, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7488, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7491, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7496, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7502, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7508, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7514, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7517, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7520, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7524, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7529, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7535, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7538, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7541, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7544, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7547, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7550, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7554, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7558, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7562, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7566, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7569, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7572, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7575, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7578, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7581, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7584, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7587, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7590, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7593, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7596, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7600, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7604, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7607, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7611, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7615, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7619, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7622, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7626, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7630, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7635, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7638, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7642, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7646, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7650, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7654, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7660, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7667, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7670, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7673, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7676, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7679, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7682, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7685, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7688, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7691, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7694, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7697, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7700, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7703, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7706, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7709, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7712, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7715, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7718, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7721, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7726, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7729, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7732, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7735, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7740, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7744, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7747, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7750, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7753, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7756, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7759, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7762, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7765, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7768, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7771, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7774, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7778, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7781, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7784, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7788, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7792, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7795, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7800, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7804, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7807, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7810, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7813, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7816, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7820, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7824, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7827, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7830, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7833, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7836, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7839, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7842, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7845, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7848, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7851, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7855, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7859, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7863, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7867, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7871, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7875, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7879, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7883, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7887, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7891, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7895, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7899, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7903, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7907, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7911, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7915, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7919, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7923, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7927, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7931, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7935, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7939, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_CS, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, true, false, false, NULL},
+  {UTF8PROC_CATEGORY_CO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7943, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7945, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5802, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7947, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7949, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7951, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7953, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7955, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5818, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7957, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7959, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7961, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7963, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7967, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7969, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7971, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7973, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7975, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7977, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7979, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7981, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7983, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7985, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7987, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7989, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7991, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7993, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7995, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7997, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7999, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8001, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8003, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8005, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8007, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8009, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8011, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8013, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8015, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8017, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8019, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8021, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8023, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8025, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8027, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8031, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8033, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8035, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8037, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5734, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8039, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8043, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8045, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8049, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8051, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8053, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8055, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8057, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5880, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8061, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8063, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8065, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8067, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8069, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8071, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8073, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8075, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8077, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8079, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8081, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8083, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8085, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8089, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8093, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8097, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8099, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8105, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8107, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8109, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8111, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8117, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8121, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8123, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8127, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8129, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8133, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8135, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8139, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8141, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8145, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8147, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8149, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8151, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8153, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5806, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8155, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8157, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8159, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8161, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8163, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8165, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8167, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8169, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8171, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8173, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8175, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8177, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8179, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8181, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8183, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5560, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8185, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8187, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8189, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8191, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8193, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8195, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8197, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8199, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5522, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8201, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8203, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8205, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8207, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8209, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8211, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8213, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8215, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8217, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8219, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8221, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8223, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8225, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8227, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8229, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8231, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8233, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8235, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8237, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8241, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8243, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8245, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8247, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8249, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8251, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8253, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8255, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8257, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8259, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8261, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8263, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8265, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8267, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8269, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8271, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8273, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8275, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8277, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8279, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8281, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8283, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8285, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8287, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8289, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8291, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8293, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8295, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8297, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8299, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8301, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8303, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8305, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8307, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8309, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8311, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8313, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8315, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8317, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8319, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8321, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8323, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8325, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8327, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8329, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8331, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6711, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8335, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8337, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8339, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8341, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8343, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8345, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8347, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8349, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8351, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8353, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8355, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8357, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8359, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8361, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8363, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8365, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8367, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8369, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8371, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8373, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8375, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5816, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8377, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8379, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8381, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8383, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8385, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8387, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8389, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8391, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8393, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8395, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8397, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8399, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8401, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5718, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8403, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8405, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8407, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8409, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8411, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8413, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8415, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8417, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8419, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8421, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8423, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8425, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8427, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8429, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8431, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8433, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5772, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8435, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5778, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8437, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8439, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8441, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8443, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8445, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8447, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8449, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8451, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8453, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8455, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8457, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8459, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8461, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8463, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5732, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8465, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8467, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8469, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8471, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8473, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8475, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8477, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8479, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8481, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8483, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8485, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8487, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8489, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8491, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8493, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8495, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8501, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5574, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8509, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8513, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8515, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8517, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8519, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8521, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8523, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8525, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8527, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8529, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8531, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8533, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6721, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8535, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8537, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8539, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8541, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6729, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8543, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8545, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8547, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8549, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8551, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8553, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8555, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8557, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8559, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8561, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8563, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8565, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8567, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8569, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8571, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8573, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8575, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8577, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8579, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8581, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8583, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8585, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8587, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8589, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8591, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8593, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8595, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8597, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8599, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8601, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8603, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8605, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8607, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8609, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8611, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8613, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8615, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8617, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8619, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8621, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8623, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8625, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8627, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8629, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8631, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8633, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8635, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8637, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8639, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8641, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8643, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8645, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8647, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5640, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8649, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8651, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8653, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8655, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8657, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8659, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8661, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8663, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8665, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8667, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8669, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8671, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8673, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8675, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8677, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8679, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8681, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8683, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8685, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8687, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8689, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8691, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8693, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8695, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8697, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8699, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8701, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8703, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8705, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8707, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8709, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8711, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8713, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8715, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8717, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8719, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8721, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8723, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8725, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8727, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8729, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8731, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8733, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8735, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8737, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8739, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8741, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8743, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8745, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8745},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8748, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8748},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8751, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8751},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8754, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8754},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8758, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8758},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8762, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8765},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8765, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8765},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8768, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8768},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8771, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8771},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8774, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8774},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8777, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8777},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8780, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8780},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8783, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MN, 26, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8786, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8789, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4575, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4581, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8791, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8793, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8795, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8797, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8799, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8801, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8803, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8806, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8809, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8812, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8815, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8818, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8821, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8824, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8827, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8830, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8833, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8836, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8839, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8842, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8845, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8848, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8851, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8854, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8857, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8860, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8863, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8866, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8869, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8872, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8875, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8878, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8881, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8884, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8887, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8890, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8893, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8896, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8899, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8904, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8904, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8904, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8904, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8906, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8906, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8906, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8906, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8916, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8916, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8916, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8916, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8918, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8918, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8918, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8918, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8922, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8922, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8922, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8922, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8924, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8924, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8924, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8924, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8928, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8928, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8930, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8930, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8932, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8932, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8934, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8934, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8936, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8936, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8938, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8938, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8940, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8940, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8940, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8940, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8942, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8942, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8942, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8942, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8944, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8944, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8944, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8944, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8946, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8946, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8946, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8946, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8948, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8948, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8950, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8950, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8950, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8950, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8952, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8952, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8954, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8954, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8954, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8954, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8956, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8956, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8956, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8956, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8958, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8958, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8960, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8960, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8962, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8962, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8962, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8962, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8964, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8964, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8966, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8966, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8968, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8968, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8970, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8972, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8972, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8974, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8974, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8976, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8976, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8978, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8978, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8978, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8978, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8982, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8982, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8985, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8985, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8988, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8988, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8991, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8991, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8994, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8994, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8997, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8997, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9000, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9000, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9000, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9003, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9003, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9003, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9006, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9006, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9006, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9006, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9008, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9011, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9014, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9017, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9020, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9023, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9026, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9032, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9035, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9044, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9050, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9053, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9056, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9062, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9065, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9068, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9071, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9074, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9077, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9080, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9083, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9086, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9089, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9092, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9098, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9104, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9107, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9110, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9116, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9122, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9128, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9134, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9140, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9146, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9149, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9152, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9155, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9161, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9164, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9167, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9170, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9173, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9176, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9179, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9182, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9185, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9188, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9191, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9194, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9197, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9200, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9203, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9206, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9209, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9212, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9215, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9218, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9221, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9224, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9227, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9230, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9233, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9236, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9242, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9245, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9248, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9251, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9254, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9257, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9260, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9263, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9266, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9269, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9272, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9275, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9278, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9281, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9284, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9287, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9291, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9295, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9299, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9303, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9307, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9311, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9314, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9014, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9317, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9017, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9320, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9323, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9326, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9032, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9035, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9329, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9332, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9335, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9050, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9053, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9338, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9341, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9344, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9062, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9065, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9152, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9155, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9164, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9167, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9170, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9182, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9185, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9188, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9191, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9203, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9206, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9209, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9347, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9221, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9350, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9353, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9356, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9242, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9245, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9284, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9359, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9362, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9269, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9365, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9272, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9275, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9008, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9011, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9368, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9014, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9371, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9020, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9023, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9026, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9374, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9044, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9377, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9068, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9071, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9074, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9077, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9080, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9086, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9089, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9092, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9098, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9380, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9104, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9107, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9110, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9116, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9128, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9134, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9140, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9146, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9149, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9161, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9173, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9176, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9179, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9182, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9185, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9194, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9197, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9200, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9203, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9383, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9212, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9215, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9218, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9221, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9230, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9233, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9236, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9248, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9251, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9389, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9260, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9263, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9266, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9269, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9392, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9014, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9371, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9374, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9377, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9395, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9098, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9398, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9401, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9404, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9182, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9185, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9203, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9269, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9392, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9407, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9411, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9415, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9419, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9422, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9425, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9428, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9431, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9434, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9437, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9440, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9443, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9446, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9449, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9452, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9455, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9458, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9461, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9464, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9467, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9470, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9473, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9476, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9479, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9485, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9401, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9488, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9491, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9494, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9419, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9422, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9425, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9428, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9431, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9434, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9437, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9440, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9443, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9446, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9449, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9452, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9455, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9458, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9461, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9464, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9467, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9470, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9473, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9476, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9479, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9485, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9401, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9488, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9491, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9494, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9479, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9485, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9401, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9398, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9404, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9122, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9089, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9092, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9479, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9485, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9122, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9500, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9500, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9515, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9519, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9523, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9527, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9531, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9531, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9535, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9539, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9543, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9547, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9551, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9555, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9555, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9559, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9563, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9563, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9567, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9567, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9571, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9575, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9575, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9579, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9583, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9583, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9587, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9587, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9591, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9595, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9595, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9599, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9599, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9603, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9607, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9611, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9615, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9615, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9619, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9623, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9627, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9631, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9635, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9635, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9639, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9643, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9647, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9651, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9655, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9659, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9659, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9663, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9663, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9667, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9667, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9671, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9675, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9679, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9683, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9687, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9691, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9695, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9699, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9703, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9707, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9711, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9715, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9719, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9719, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9723, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9727, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9731, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9735, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9735, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9739, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9743, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9747, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9751, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9755, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9759, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9763, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9767, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9771, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9775, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9779, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9783, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9787, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9791, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9795, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9799, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9803, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9807, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9811, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9815, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9819, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9823, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9639, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9647, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9827, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9831, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9835, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9839, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9843, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9847, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9843, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9835, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9851, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9855, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9859, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9863, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9867, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9847, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9611, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9571, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9871, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9875, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9879, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9883, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9887, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9892, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9897, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9907, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9917, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9922, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9945, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9954, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9959, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9961, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9963, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 1333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9967, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9969, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9971, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9973, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9975, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9977, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9979, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9981, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9983, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 4517, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 4519, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9985, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9987, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9989, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9991, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9993, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9995, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9997, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9999, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 4892, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 4894, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 10001, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 10003, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 10005, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 10007, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 10009, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 10011, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 10013, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 9983, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9959, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9961, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 4454, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 1333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9969, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9967, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9979, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 4517, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 4519, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9985, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9987, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9989, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9991, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10015, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10017, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10019, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 4511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10021, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10023, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10025, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 4515, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10027, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10031, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10033, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10035, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10044, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10050, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10053, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10056, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10062, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10065, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10068, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10071, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10074, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10077, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10079, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10079, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10081, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10081, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10083, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10083, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10085, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10085, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10089, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10089, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10093, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10093, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10097, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10097, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10097, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10097, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10099, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10099, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10099, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10099, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10105, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10105, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10107, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10107, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10109, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10109, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10111, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10111, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10117, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10117, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10117, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10117, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10121, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10121, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10121, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10121, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10123, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10123, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10123, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10123, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10127, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10127, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10127, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10127, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10129, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10129, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10129, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10129, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10133, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10133, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10133, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10133, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10135, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10135, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10135, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10135, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10139, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10139, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10139, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10139, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10141, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10141, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10141, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10141, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10145, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10145, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10145, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10145, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10147, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10147, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10150, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10150, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10153, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10153, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10156, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10156, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9967, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10159, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10015, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10031, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10017, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10161, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4517, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4519, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10019, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9959, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10021, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4454, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10163, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 72, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 60, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 62, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4501, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4509, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 1333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10023, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4515, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10025, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9969, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10033, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2376, false, -1, 65345, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10165},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2380, false, -1, 65346, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10167},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4532, false, -1, 65347, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10169},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2382, false, -1, 65348, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10171},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2384, false, -1, 65349, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10173},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4571, false, -1, 65350, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10175},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2388, false, -1, 65351, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10177},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2390, false, -1, 65352, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10179},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2392, false, -1, 65353, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10181},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2394, false, -1, 65354, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10183},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2396, false, -1, 65355, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10185},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2398, false, -1, 65356, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10187},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2400, false, -1, 65357, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10189},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2402, false, -1, 65358, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10191},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2404, false, -1, 65359, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10193},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2408, false, -1, 65360, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10195},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4553, false, -1, 65361, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10197},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2410, false, -1, 65362, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10199},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 5231, false, -1, 65363, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10201},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2412, false, -1, 65364, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10203},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2414, false, -1, 65365, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10205},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4662, false, -1, 65366, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10207},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2416, false, -1, 65367, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10209},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4689, false, -1, 65368, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10211},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 5245, false, -1, 65369, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10213},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4565, false, -1, 65370, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10215},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10009, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10027, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10011, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10217, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9983, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4387, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 0, false, 65313, -1, 65313, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2, false, 65314, -1, 65314, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4, false, 65315, -1, 65315, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 6, false, 65316, -1, 65316, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 8, false, 65317, -1, 65317, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10, false, 65318, -1, 65318, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 12, false, 65319, -1, 65319, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 14, false, 65320, -1, 65320, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 16, false, 65321, -1, 65321, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 18, false, 65322, -1, 65322, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 20, false, 65323, -1, 65323, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 22, false, 65324, -1, 65324, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 24, false, 65325, -1, 65325, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 26, false, 65326, -1, 65326, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 28, false, 65327, -1, 65327, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 30, false, 65328, -1, 65328, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 32, false, 65329, -1, 65329, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 34, false, 65330, -1, 65330, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 36, false, 65331, -1, 65331, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 38, false, 65332, -1, 65332, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 40, false, 65333, -1, 65333, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 42, false, 65334, -1, 65334, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 44, false, 65335, -1, 65335, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 46, false, 65336, -1, 65336, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 48, false, 65337, -1, 65337, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 50, false, 65338, -1, 65338, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9985, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10219, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9987, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10221, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10223, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10225, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 9963, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10001, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10003, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 9961, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10227, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6963, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10229, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10231, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10233, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10235, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10237, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10241, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10243, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10245, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10247, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6871, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6873, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6875, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6877, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6879, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6881, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6883, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6885, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6887, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6889, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6891, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6893, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6895, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6897, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6899, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6901, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6903, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6905, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6907, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6909, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6911, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6913, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6915, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6917, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6919, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6921, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6923, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6925, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6927, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6929, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6931, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6933, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6935, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6937, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6939, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6941, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6943, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6945, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6947, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6949, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6951, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6953, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6955, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6957, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10249, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10251, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10253, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10255, false, -1, -1, -1, -1, -1, false, true, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10257, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10259, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10261, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10263, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10265, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10267, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10269, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10271, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10273, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10275, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10277, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10279, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10281, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10283, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10285, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10287, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10289, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10291, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10293, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10295, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10297, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10299, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10301, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10303, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10305, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10307, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10309, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10311, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10313, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10315, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10317, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10319, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10321, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10323, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10325, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10327, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10329, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10331, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10335, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10337, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10339, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10341, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10343, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10345, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10347, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10349, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10351, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10353, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10355, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10357, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10359, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10361, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10363, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10365, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10367, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10369, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10371, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10373, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10375, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10377, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10379, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10381, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10383, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10385, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, true, false, NULL},
+  {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66600, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10387},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66601, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10389},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66602, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10391},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66603, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10393},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66604, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10395},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66605, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10397},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66606, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10399},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66607, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10401},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66608, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10403},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66609, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10405},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66610, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10407},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66611, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10409},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66612, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10411},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66613, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10413},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66614, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10415},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66615, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10417},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66616, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10419},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66617, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10421},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66618, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10423},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66619, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10425},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66620, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10427},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66621, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10429},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66622, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10431},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66623, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10433},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66624, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10435},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66625, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10437},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66626, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10439},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66627, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10441},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66628, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10443},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66629, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10445},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66630, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10447},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66631, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10449},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66632, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10451},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66633, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10453},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66634, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10455},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66635, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10457},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66636, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10459},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66637, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10461},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66638, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10463},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66639, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10465},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66560, -1, 66560, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66561, -1, 66561, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66562, -1, 66562, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66563, -1, 66563, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66564, -1, 66564, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66565, -1, 66565, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66566, -1, 66566, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66567, -1, 66567, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66568, -1, 66568, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66569, -1, 66569, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66570, -1, 66570, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66571, -1, 66571, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66572, -1, 66572, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66573, -1, 66573, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66574, -1, 66574, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66575, -1, 66575, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66576, -1, 66576, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66577, -1, 66577, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66578, -1, 66578, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66579, -1, 66579, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66580, -1, 66580, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66581, -1, 66581, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66582, -1, 66582, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66583, -1, 66583, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66584, -1, 66584, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66585, -1, 66585, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66586, -1, 66586, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66587, -1, 66587, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66588, -1, 66588, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66589, -1, 66589, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66590, -1, 66590, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66591, -1, 66591, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66592, -1, 66592, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66593, -1, 66593, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66594, -1, 66594, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66595, -1, 66595, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66596, -1, 66596, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66597, -1, 66597, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66598, -1, 66598, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66599, -1, 66599, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_R, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 22080, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 22140, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10467, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10470, false, -1, -1, -1, 22200, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10473, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10476, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10479, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10482, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10485, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 54, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 226, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 55, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 56, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 57, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 58, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 59, false, false, false, true, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 22260, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 22320, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10488, false, -1, -1, -1, 22380, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10491, false, -1, -1, -1, 22440, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10494, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10497, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10500, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10503, false, -1, -1, -1, -1, -1, true, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2376, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2388, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2394, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2396, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2404, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 5231, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2412, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2414, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4662, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2416, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4689, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 5245, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 0, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 20, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 24, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 26, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 30, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 32, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 34, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 36, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 38, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 40, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 42, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 44, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 46, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 48, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 50, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10506, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10508, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10510, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10512, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10514, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10516, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10518, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10520, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1504, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10522, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10524, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10526, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10528, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10530, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10534, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10536, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10538, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1508, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10540, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1470, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10542, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10544, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10546, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4567, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10548, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1382, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1384, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1388, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1390, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1392, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1394, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1396, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1326, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1398, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1400, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 67, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1402, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1404, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1406, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1410, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1502, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1412, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1414, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1416, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1418, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1420, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1422, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1424, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10550, true, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10552, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10554, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10556, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10558, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10560, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10562, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10564, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 72, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 60, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 62, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4501, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4509, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10566, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10568, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10570, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10572, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10574, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10576, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10578, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10580, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10582, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10584, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10586, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10588, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10590, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10592, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10594, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10596, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10598, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10600, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10602, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10604, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10606, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10608, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10610, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10612, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10614, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5518, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10616, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10618, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10620, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10622, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10624, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10626, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10628, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10630, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10632, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10634, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10636, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10638, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10640, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10642, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10644, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10646, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10648, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10650, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10652, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10654, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10656, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10658, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10660, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10662, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10664, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10666, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10668, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10670, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10672, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10674, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10676, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10678, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10680, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10682, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10684, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10686, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10688, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10690, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10692, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10694, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10696, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10698, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10700, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10702, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10704, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10706, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10708, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10710, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10712, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10714, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10716, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10718, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10720, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10722, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10724, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10726, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10728, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10730, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10732, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10734, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10736, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10738, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10740, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10742, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10744, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10746, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10748, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10750, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10752, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10754, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10756, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10758, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10760, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5570, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10762, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10764, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10766, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10768, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10770, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10772, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10774, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10776, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10778, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10780, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10782, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10784, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10786, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10788, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10790, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10792, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10794, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10796, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10798, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10800, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10802, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10804, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10806, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10808, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5594, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10810, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10812, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10814, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10816, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10818, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10820, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10822, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10824, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10826, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10828, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10830, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10832, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10834, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10836, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10838, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10840, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10842, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10844, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10846, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10848, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10850, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10852, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10854, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10856, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10858, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10860, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10862, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10864, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10866, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10868, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10870, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10872, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10874, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10876, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10878, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10880, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10882, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10884, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10886, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10888, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10890, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10892, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10894, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10896, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10898, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10900, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10904, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10906, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10916, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10918, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10922, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10924, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10928, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10930, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10932, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10934, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10936, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10938, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10940, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10942, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10944, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10946, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10948, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10950, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10952, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10954, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10956, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10958, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10960, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10962, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10964, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10966, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10968, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10970, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10972, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10974, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10976, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10978, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10982, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10984, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10986, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10988, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10990, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10992, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10994, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10996, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10998, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11000, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11002, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11004, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11006, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11008, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11010, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11012, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11014, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11016, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11018, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11020, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11022, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11024, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11026, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11028, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11030, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11032, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11034, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11036, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11040, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11042, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11044, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11046, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11048, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11050, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11052, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11054, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11056, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11058, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11060, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11062, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11064, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11066, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11068, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11070, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11072, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11074, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11076, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11078, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11080, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11082, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11084, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11086, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11088, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11090, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11092, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11094, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11096, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11098, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11100, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11102, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11104, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11106, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11108, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11110, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11112, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11114, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11116, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11118, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11120, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11122, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11124, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11126, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11128, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11130, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11132, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11134, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11136, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11138, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11140, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11142, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11144, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11146, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11148, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11150, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11152, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11154, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11156, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11160, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11162, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11164, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11166, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11168, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11170, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11172, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11174, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11176, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11178, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11180, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11182, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11184, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11186, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11188, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11190, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11192, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11194, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11196, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11198, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11200, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11202, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11204, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11206, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11208, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11210, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11212, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11214, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11216, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11218, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11220, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11222, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11224, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11226, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11228, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11230, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11232, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11234, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11236, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11238, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11240, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11242, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11244, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11246, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11248, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11250, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11252, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11254, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11256, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11258, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11260, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11262, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11264, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11266, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11268, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11270, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11272, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11274, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11276, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11278, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11280, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11282, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11284, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11286, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11288, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11290, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11292, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11294, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11296, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11298, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11300, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11302, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11304, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11306, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11308, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11310, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11312, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11314, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11316, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11318, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11320, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11322, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11324, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11326, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11328, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11330, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11332, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11334, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11336, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11338, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11340, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11342, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11344, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5774, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11346, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11348, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11350, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11352, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11354, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11356, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11358, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11360, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11362, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11364, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11366, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5788, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11368, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11370, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11372, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11374, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11376, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11378, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11380, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11382, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11384, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11388, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11390, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11392, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11394, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11396, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11398, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11400, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11402, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11404, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11406, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11408, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11410, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11412, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11414, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11416, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11418, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11420, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11422, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11424, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11426, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11428, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11430, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11432, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11434, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11436, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11438, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11440, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11442, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11444, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11446, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11448, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11450, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11452, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11454, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11456, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11458, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11460, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11462, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11464, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11466, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11468, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11470, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11472, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11474, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11476, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11478, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11480, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11484, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11486, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11488, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11490, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5884, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11492, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5892, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11494, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11496, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11498, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11500, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+  {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11502, false, -1, -1, -1, -1, -1, false, false, false, false, NULL},
+};
+
+const int32_t utf8proc_combinations[] = {
+  192, 193, 194, 195, 196, 197, -1, 
+  256, 258, 260, 550, 461, -1, -1, 512, 
+  514, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  7680, 7840, -1, -1, -1, -1, -1, 7842, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 262, 264, 
+  -1, -1, -1, 199, -1, -1, -1, 266, 
+  268, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 200, 201, 202, 7868, 203, -1, 552, 
+  274, 276, 280, 278, 282, -1, -1, 516, 
+  518, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7864, -1, 7704, 7706, -1, -1, 7866, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 204, 205, 206, 
+  296, 207, -1, -1, 298, 300, 302, 304, 
+  463, -1, -1, 520, 522, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7882, -1, -1, 
+  7724, -1, -1, 7880, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 504, 323, -1, 209, -1, -1, 325, 
+  -1, -1, -1, 7748, 327, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7750, 7752, 7754, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 210, 211, 212, 
+  213, 214, -1, -1, 332, 334, 490, 558, 
+  465, 336, 416, 524, 526, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7884, -1, -1, 
+  -1, -1, -1, 7886, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 217, 218, 219, 360, 220, 366, -1, 
+  362, 364, 370, -1, 467, 368, 431, 532, 
+  534, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7908, -1, 7798, 7796, -1, 7794, 7910, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7922, 221, 374, 
+  7928, 376, -1, -1, 562, -1, -1, 7822, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7924, -1, -1, 
+  -1, -1, -1, 7926, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 224, 225, 226, 227, 228, 229, -1, 
+  257, 259, 261, 551, 462, -1, -1, 513, 
+  515, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  7681, 7841, -1, -1, -1, -1, -1, 7843, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 263, 265, 
+  -1, -1, -1, 231, -1, -1, -1, 267, 
+  269, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 232, 233, 234, 7869, 235, -1, 553, 
+  275, 277, 281, 279, 283, -1, -1, 517, 
+  519, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7865, -1, 7705, 7707, -1, -1, 7867, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 236, 237, 238, 
+  297, 239, -1, -1, 299, 301, 303, -1, 
+  464, -1, -1, 521, 523, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7883, -1, -1, 
+  7725, -1, -1, 7881, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 505, 324, -1, 241, -1, -1, 326, 
+  -1, -1, -1, 7749, 328, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7751, 7753, 7755, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 242, 243, 244, 
+  245, 246, -1, -1, 333, 335, 491, 559, 
+  466, 337, 417, 525, 527, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7885, -1, -1, 
+  -1, -1, -1, 7887, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 249, 250, 251, 361, 252, 367, -1, 
+  363, 365, 371, -1, 468, 369, 432, 533, 
+  535, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7909, -1, 7799, 7797, -1, 7795, 7911, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7923, 253, 375, 
+  7929, 255, 7833, -1, 563, -1, -1, 7823, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7925, -1, -1, 
+  -1, -1, -1, 7927, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7696, 
+  -1, -1, -1, 7690, 270, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7692, 7694, 7698, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7697, -1, -1, -1, 7691, 
+  271, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7693, 7695, 7699, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 500, 284, -1, -1, -1, 290, 
+  7712, 286, -1, 288, 486, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 501, 285, 
+  -1, -1, -1, 291, 7713, 287, -1, 289, 
+  487, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 292, -1, 7718, -1, 7720, 
+  -1, -1, -1, 7714, 542, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7716, -1, -1, -1, 7722, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 293, 
+  -1, 7719, -1, 7721, -1, -1, -1, 7715, 
+  543, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7717, 7830, -1, 
+  -1, 7723, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 308, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 309, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  496, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7728, -1, -1, -1, -1, 310, 
+  -1, -1, -1, -1, 488, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7730, 7732, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7729, -1, 
+  -1, -1, -1, 311, -1, -1, -1, -1, 
+  489, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7731, 7733, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 313, -1, -1, -1, -1, 315, 
+  -1, -1, -1, -1, 317, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7734, 7738, 7740, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 314, -1, 
+  -1, -1, -1, 316, -1, -1, -1, -1, 
+  318, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7735, 7739, 7741, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 340, -1, -1, -1, -1, 342, 
+  -1, -1, -1, 7768, 344, -1, -1, 528, 
+  530, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7770, 7774, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 341, -1, 
+  -1, -1, -1, 343, -1, -1, -1, 7769, 
+  345, -1, -1, 529, 531, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7771, 7775, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 346, 348, -1, -1, -1, 350, 
+  -1, -1, -1, 7776, 352, -1, -1, -1, 
+  -1, 536, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7778, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 347, 349, 
+  -1, -1, -1, 351, -1, -1, -1, 7777, 
+  353, -1, -1, -1, -1, 537, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7779, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 354, 
+  -1, -1, -1, 7786, 356, -1, -1, -1, 
+  -1, 538, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7788, 7790, 7792, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7831, -1, 355, -1, -1, -1, 7787, 
+  357, -1, -1, -1, -1, 539, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7789, 7791, 7793, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7808, 7810, 372, -1, 7812, -1, -1, 
+  -1, -1, -1, 7814, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7816, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7809, 7811, 373, 
+  -1, 7813, 7832, -1, -1, -1, -1, 7815, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7817, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 377, 7824, -1, -1, -1, -1, 
+  -1, -1, -1, 379, 381, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7826, 7828, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 378, 7825, 
+  -1, -1, -1, -1, -1, -1, -1, 380, 
+  382, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7827, 7829, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 475, 471, -1, -1, -1, -1, -1, 
+  469, -1, -1, -1, 473, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 476, 472, -1, 
+  -1, -1, -1, -1, 470, -1, -1, -1, 
+  474, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  478, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 479, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  480, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 481, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 508, -1, -1, -1, -1, -1, 
+  482, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 509, -1, 
+  -1, -1, -1, -1, 483, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  492, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 493, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 494, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  495, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 506, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 507, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 510, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 511, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  554, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 555, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7756, -1, -1, 7758, -1, -1, 
+  556, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7757, -1, 
+  -1, 7759, -1, -1, 557, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  560, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 561, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8173, 901, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 8129, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8122, 902, -1, 
+  -1, -1, -1, -1, 8121, 8120, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 7944, 7945, -1, 8124, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8136, 904, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  7960, 7961, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8138, 905, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 7976, 7977, -1, 8140, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8154, 906, -1, -1, 938, -1, -1, 
+  8153, 8152, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  7992, 7993, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8184, 908, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8008, 8009, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8170, 910, -1, -1, 939, -1, -1, 
+  8169, 8168, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8025, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8186, 911, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8040, 8041, -1, 8188, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8146, 912, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 8151, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8048, 940, -1, 
+  -1, -1, -1, -1, 8113, 8112, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 7936, 7937, 8118, 8115, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8050, 941, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  7952, 7953, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8052, 942, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 7968, 7969, 8134, 8131, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8054, 943, -1, -1, 970, -1, -1, 
+  8145, 8144, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  7984, 7985, 8150, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8162, 944, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 8167, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8058, 973, -1, -1, 971, -1, -1, 
+  8161, 8160, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8016, 8017, 8166, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8056, 972, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8000, 8001, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8060, 974, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8032, 8033, 8182, 8179, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 979, -1, 
+  -1, 980, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1024, -1, -1, -1, 1025, -1, -1, 
+  -1, 1238, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 1027, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 1031, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 1036, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1037, -1, -1, -1, 1252, -1, -1, 
+  1250, 1049, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1264, -1, -1, 1262, 1038, -1, -1, 
+  -1, 1266, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1117, -1, -1, -1, 1253, -1, -1, 
+  1251, 1081, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 1104, -1, -1, 
+  -1, 1105, -1, -1, -1, 1239, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 1107, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1111, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 1116, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1265, -1, -1, 1263, 1118, -1, -1, 
+  -1, 1267, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 1142, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 1143, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 1244, -1, -1, 
+  -1, 1217, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1245, -1, -1, -1, 1218, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 1234, -1, -1, 
+  -1, 1232, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1235, -1, -1, -1, 1233, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 1242, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1243, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 1246, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1247, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 1254, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1255, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 1258, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1259, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 1260, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1261, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 1268, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1269, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 1272, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 1273, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 1570, 1571, 1573, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 1572, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 1574, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 1728, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 1730, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 1747, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 2345, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 2353, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 2356, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 2507, 2508, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  2888, 2891, 2892, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 2964, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 3020, 3018, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  3019, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 3144, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 3264, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 3271, 3272, 
+  3274, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 3275, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 3402, 3404, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 3403, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 3546, 3548, 3550, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 3549, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 4134, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 6918, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 6920, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 6922, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 6924, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 6926, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 6930, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 6971, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 6973, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 6976, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 6977, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 6979, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7682, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7684, 7686, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7683, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7685, 7687, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7688, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7689, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7700, 7702, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7701, 7703, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7708, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7709, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7710, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7711, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7726, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7727, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  7736, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 7737, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7742, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7744, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7746, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7743, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7745, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7747, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7760, 7762, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7761, 7763, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7764, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7766, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7765, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7767, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  7772, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 7773, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7780, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7781, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7782, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7783, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7784, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7785, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7800, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7801, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7802, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7803, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 7804, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7806, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  7805, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7807, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7820, -1, -1, 
+  -1, -1, -1, 7818, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7821, -1, -1, -1, -1, -1, 7819, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7835, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7846, 7844, -1, 
+  7850, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7848, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7847, 7845, -1, 7851, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7849, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7852, 
+  -1, -1, -1, -1, -1, 7862, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7853, -1, -1, -1, -1, 
+  -1, 7863, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7856, 7854, -1, 
+  7860, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7858, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7857, 7855, -1, 7861, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7859, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7872, 7870, -1, 
+  7876, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7874, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7873, 7871, -1, 7877, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7875, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7878, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7879, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7890, 7888, -1, 
+  7894, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7892, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7891, 7889, -1, 7895, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7893, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 7896, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 7897, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7900, 7898, -1, 
+  7904, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7906, -1, -1, 
+  -1, -1, -1, 7902, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7901, 7899, -1, 7905, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7907, -1, -1, -1, -1, -1, 7903, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7914, 7912, -1, 
+  7918, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7920, -1, -1, 
+  -1, -1, -1, 7916, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7915, 7913, -1, 7919, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7921, -1, -1, -1, -1, -1, 7917, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7938, 7940, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7942, 8064, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7939, 7941, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7943, 8065, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7946, 7948, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7950, 8072, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7947, 7949, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7951, 8073, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7954, 7956, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7955, 7957, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7962, 7964, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7963, 7965, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7970, 7972, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7974, 8080, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7971, 7973, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7975, 8081, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7978, 7980, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7982, 8088, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7979, 7981, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7983, 8089, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7986, 7988, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7990, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7987, 7989, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7991, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 7994, 7996, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 7998, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 7995, 7997, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 7999, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8002, 8004, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8003, 8005, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8010, 8012, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8011, 8013, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8018, 8020, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 8022, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8019, 8021, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 8023, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8027, 8029, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 8031, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8034, 8036, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 8038, 8096, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8035, 8037, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 8039, 8097, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8042, 8044, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 8046, 8104, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8043, 8045, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 8047, 8105, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8066, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8067, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8068, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8069, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8070, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8071, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8074, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8075, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8076, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8077, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8078, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8079, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8082, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8083, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8084, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8085, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8086, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8087, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8090, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8091, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8092, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8093, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8094, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8095, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8098, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8099, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8100, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8101, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8102, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8103, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8106, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8107, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8108, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8109, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8110, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8111, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8114, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8116, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8119, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8130, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8132, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8135, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 8141, 8142, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, 8143, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8157, 8158, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, 8159, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8164, 8165, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 8172, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8178, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 8180, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 8183, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8602, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8603, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8622, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8653, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8654, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8655, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8708, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8713, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8716, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8740, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8742, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8769, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8772, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8775, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8777, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8800, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8802, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8813, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8814, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8815, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8816, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8817, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8820, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8821, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8824, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8825, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8832, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8833, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8836, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8837, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8840, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8841, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8876, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8877, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8878, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8879, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8928, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8929, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8930, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8931, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8938, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8939, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  8940, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 8941, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  10972, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12364, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12366, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12368, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12370, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12372, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12374, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12376, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12378, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12380, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12382, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12384, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12386, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12389, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12391, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12393, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12400, 12401, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12403, 12404, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12406, 12407, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12409, 12410, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12412, 12413, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12436, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12446, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12460, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12462, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12464, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12466, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12468, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12470, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12472, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12474, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12476, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12478, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12480, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12482, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12485, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12487, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12489, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12496, 12497, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12499, 12500, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12502, 12503, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12505, 12506, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12508, 12509, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12532, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12535, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12536, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12537, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, 12538, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, 12542, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 119134, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 119135, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  119136, 119137, 119138, 119139, 119140, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, 119227, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, 119228, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, 119229, 119231, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  119230, 119232, -1, -1, -1, };
+
diff --git a/src/lib/util.c b/src/lib/util.c
new file mode 100644
index 0000000..50c14fa
--- /dev/null
+++ b/src/lib/util.c
@@ -0,0 +1,92 @@
+/*
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: util.c 2214 2015-12-08 00:33:40Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mpi.h>
+#include "nc.h"
+#include "macro.h"
+
+/*----< ncmpii_sanity_check() >----------------------------------------------*/
+int ncmpii_sanity_check(int               ncid,
+                        int               varid,
+                        const MPI_Offset *start,
+                        const MPI_Offset *count,
+                        MPI_Offset        bufcount,
+                        enum API_KIND     api,
+                        int               mustInDataMode,
+                        int               isFlexAPI,
+                        int               rw_flag,
+                        int               io_method,
+                        NC              **ncp,
+                        NC_var          **varp)
+{
+    /* all errors detected here are fatal, must return immediately */
+    int status;
+
+    /* check if ncid is valid */
+    status = ncmpii_NC_check_id(ncid, ncp);
+    if (status != NC_NOERR) return status;
+    /* For invalid ncid, we must return error now, as there is no way to
+     * continue with invalid ncp. However, collective APIs might hang if this
+     * error occurs only on a subset of processes
+     */
+
+    /* if this call must be made in data mode, check if currently is in define
+     * mode */
+    if (mustInDataMode && NC_indef(*ncp)) {
+        DEBUG_ASSIGN_ERROR(status, NC_EINDEFINE)
+        goto fn_exit;
+    }
+
+    /* check file write permission if this is write request */
+    if (rw_flag == WRITE_REQ && NC_readonly(*ncp)) {
+        DEBUG_ASSIGN_ERROR(status, NC_EPERM)
+        goto fn_exit;
+    }
+
+    if (io_method != NONBLOCKING_IO) { /* for blocking APIs */
+        /* check if in the right collective or independent mode and initialize
+         * MPI file handlers */
+        status = ncmpii_check_mpifh(*ncp, io_method);
+        if (status != NC_NOERR) goto fn_exit;
+    }
+
+    /* check if varid is valid */
+    status = ncmpii_NC_lookupvar(*ncp, varid, varp);
+    if (status != NC_NOERR) goto fn_exit;
+
+    /* for API var1, vara, vars, varm, and varn, start cannot be NULL */
+    if (start == NULL && api >= API_VAR1 && (*varp)->ndims > 0) {
+        DEBUG_ASSIGN_ERROR(status, NC_ENULLSTART)
+        goto fn_exit;
+    }
+
+    /* for API vara, vars, and varm, count cannot be NULL */
+    if (count == NULL && api >= API_VARA && (*varp)->ndims > 0) {
+        DEBUG_ASSIGN_ERROR(status, NC_ENULLCOUNT)
+        goto fn_exit;
+    }
+
+    /* for flexible APIs, bufcount cannot be negative */
+    if (isFlexAPI && bufcount < 0) {
+        DEBUG_ASSIGN_ERROR(status, NC_EINVAL)
+        goto fn_exit;
+    }
+
+fn_exit:
+    if ((*ncp)->safe_mode == 1 && io_method == COLL_IO) {
+        int min_st;
+        MPI_Allreduce(&status, &min_st, 1, MPI_INT, MPI_MIN, (*ncp)->nciop->comm);
+        if (status == NC_NOERR) status = min_st;
+    }
+    return status;
+}
+
diff --git a/src/lib/var.c b/src/lib/var.c
new file mode 100644
index 0000000..dfd0915
--- /dev/null
+++ b/src/lib/var.c
@@ -0,0 +1,939 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: var.c 2196 2015-11-27 22:31:05Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <string.h> /* memset() */
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "rnd.h"
+#include "macro.h"
+#include "utf8proc.h"
+
+/*----< ncmpii_free_NC_var() >------------------------------------------------*/
+/*
+ * Free var
+ * Formerly
+NC_free_var(var)
+ */
+inline void
+ncmpii_free_NC_var(NC_var *varp)
+{
+    if (varp == NULL) return;
+    ncmpii_free_NC_attrarray(&varp->attrs);
+    ncmpii_free_NC_string(varp->name);
+#ifdef ENABLE_SUBFILING
+    if (varp->num_subfiles > 1) /* deallocate it */
+        NCI_Free(varp->dimids_org);
+#endif
+    NCI_Free(varp);
+}
+
+
+/*----< ncmpii_new_x_NC_var() >-----------------------------------------------*/
+/*
+ * Common code for ncmpii_new_NC_var()
+ * and ncx_get_NC_var()
+ */
+NC_var *
+ncmpii_new_x_NC_var(NC_string *strp,
+                    int        ndims)
+{
+    NC_var *varp;
+    int shape_space   = M_RNDUP(ndims * SIZEOF_MPI_OFFSET);
+    int dsizes_space  = M_RNDUP(ndims * SIZEOF_MPI_OFFSET);
+    int dimids_space  = M_RNDUP(ndims * SIZEOF_INT);
+    size_t sizeof_NC_var = M_RNDUP(sizeof(NC_var));
+    size_t sz = sizeof_NC_var + (size_t)(shape_space + dsizes_space + dimids_space);
+
+    /* this function allocates a contiguous memory space to put all
+     * members of NC_var structure together:
+     * dimid_space is for dimids[],
+     * shape_space is for shape[],
+     * dsizes_space is for dsizes[]
+     * (I don't know why M_RNDUP is needed here and why they should be kept
+     * in a contiguous memory space.)
+     */
+    varp = (NC_var *) NCI_Malloc(sz);
+    if (varp == NULL ) return NULL;
+
+    memset(varp, 0, sz);
+
+    varp->name = strp;
+    varp->ndims = ndims;
+
+    if (ndims != 0) {
+        /*
+         * NOTE: lint may complain about the next 3 lines:
+         * "pointer cast may result in improper alignment".
+         * We use the M_RNDUP() macro to get the proper alignment.
+         * roundup to a double
+         */
+        varp->shape  = (MPI_Offset *)((char *)varp + sizeof_NC_var);
+        varp->dsizes = (MPI_Offset *)((char *)varp->shape  + shape_space);
+        varp->dimids = (int *)       ((char *)varp->dsizes + dsizes_space);
+    }
+
+    varp->xsz = 0;
+    varp->len = 0;
+    varp->begin = 0;
+
+    return varp;
+}
+
+
+/*----< ncmpii_new_NC_var() >------------------------------------------------*/
+/*
+ * Formerly, NC_new_var()
+ */
+static NC_var *
+ncmpii_new_NC_var(const char *uname,  /* variable name (NULL terminated) */
+                  nc_type     type,
+                  int         ndims,
+                  const int  *dimids)
+{
+    NC_string *strp;
+    NC_var *varp;
+
+    char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
+    if (name == NULL) return NULL;
+
+    strp = ncmpii_new_NC_string(strlen(name), name);
+    free(name);
+    if (strp == NULL) return NULL;
+
+    varp = ncmpii_new_x_NC_var(strp, ndims);
+    if (varp == NULL ) {
+        ncmpii_free_NC_string(strp);
+        return NULL;
+    }
+
+    varp->type = type;
+
+    if (ndims != 0 && dimids != NULL)
+        memcpy(varp->dimids, dimids, (size_t)ndims * SIZEOF_INT);
+
+    return(varp);
+}
+
+/*----< dup_NC_var() >--------------------------------------------------------*/
+NC_var *
+dup_NC_var(const NC_var *rvarp)
+{
+    NC_var *varp;
+
+    varp = ncmpii_new_NC_var(rvarp->name->cp, rvarp->type, rvarp->ndims,
+                             rvarp->dimids);
+    if (varp == NULL) return NULL;
+
+    if (ncmpii_dup_NC_attrarray(&varp->attrs, &rvarp->attrs) != NC_NOERR) {
+        ncmpii_free_NC_var(varp);
+        return NULL;
+    }
+
+    /* copy the contents of shape may not be necessary, as one must call
+     * ncmpii_NC_computeshapes() to recompute it after a new variable is
+     * created */
+    memcpy(varp->shape,  rvarp->shape,  (size_t)rvarp->ndims * SIZEOF_MPI_OFFSET);
+    memcpy(varp->dsizes, rvarp->dsizes, (size_t)rvarp->ndims * SIZEOF_MPI_OFFSET);
+    varp->xsz = rvarp->xsz;
+    varp->len = rvarp->len;
+    varp->begin = rvarp->begin;
+
+    return varp;
+}
+
+/* vararray */
+
+/*----< ncmpii_free_NC_vararray() >-------------------------------------------*/
+/*
+ * Free NC_vararray values.
+ * formerly
+NC_free_array()
+ */
+inline void
+ncmpii_free_NC_vararray(NC_vararray *ncap)
+{
+    int i;
+
+    assert(ncap != NULL);
+    if (ncap->nalloc == 0) return;
+
+    assert(ncap->value != NULL);
+    for (i=0; i<ncap->ndefined; i++) {
+        if (ncap->value[i] != NULL)
+            ncmpii_free_NC_var(ncap->value[i]);
+    }
+
+    NCI_Free(ncap->value);
+    ncap->value    = NULL;
+    ncap->nalloc   = 0;
+    ncap->ndefined = 0;
+}
+
+
+/*----< ncmpii_dup_NC_vararray() >--------------------------------------------*/
+int
+ncmpii_dup_NC_vararray(NC_vararray       *ncap,
+                       const NC_vararray *ref)
+{
+    int i, status=NC_NOERR;
+
+    assert(ref != NULL);
+    assert(ncap != NULL);
+
+    if (ref->nalloc == 0) {
+        ncap->nalloc = 0;
+        ncap->ndefined = 0;
+        ncap->value = NULL;
+        return NC_NOERR;
+    }
+
+    if (ref->nalloc > 0) {
+        ncap->value = (NC_var **) NCI_Calloc((size_t)ref->nalloc, sizeof(NC_var*));
+        if (ncap->value == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+        ncap->nalloc = ref->nalloc;
+    }
+
+    ncap->ndefined = 0;
+    for (i=0; i<ref->ndefined; i++) {
+        ncap->value[i] = dup_NC_var(ref->value[i]);
+        if (ncap->value[i] == NULL) {
+            DEBUG_ASSIGN_ERROR(status, NC_ENOMEM)
+            break;
+        }
+    }
+
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_vararray(ncap);
+        return status;
+    }
+
+    ncap->ndefined = ref->ndefined;
+
+    return NC_NOERR;
+}
+
+
+/*
+ * Add a new handle on the end of an array of handles
+ * Formerly
+NC_incr_array(array, tail)
+ */
+int
+incr_NC_vararray(NC_vararray *ncap,
+                 NC_var      *newvarp)
+{
+    NC_var **vp;
+
+    assert(ncap != NULL);
+    assert(newvarp != NULL);
+
+    if (ncap->nalloc == 0) { /* no variable has been allocated yet */
+        assert(ncap->ndefined == 0);
+        vp = (NC_var **) NCI_Malloc(NC_ARRAY_GROWBY * sizeof(NC_var *));
+        if (vp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+        ncap->value = vp;
+        ncap->nalloc = NC_ARRAY_GROWBY;
+    }
+    else if (ncap->ndefined + 1 > ncap->nalloc) {
+        vp = (NC_var **) NCI_Realloc(ncap->value,
+                         (size_t)(ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_var *));
+        if (vp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+        ncap->value = vp;
+        ncap->nalloc += NC_ARRAY_GROWBY;
+    }
+
+    if (newvarp != NULL) {
+        ncap->value[ncap->ndefined] = newvarp;
+        ncap->ndefined++;
+    }
+
+    return NC_NOERR;
+}
+
+
+inline static NC_var *
+elem_NC_vararray(const NC_vararray *ncap,
+                 int                varid)
+{
+    assert(ncap != NULL);
+    /* cast needed for braindead systems with signed MPI_Offset */
+    if ((varid < 0) ||  ncap->ndefined == 0 || varid >= ncap->ndefined)
+        return NULL;
+
+    assert(ncap->value != NULL);
+
+    return ncap->value[varid];
+}
+
+
+/* End vararray per se */
+
+
+/*
+ * Step thru NC_VARIABLE array, seeking match on name.
+ * Return varid or -1 on not found.
+ * *varpp is set to the appropriate NC_var.
+ * Formerly (sort of)
+NC_hvarid
+ */
+static int
+ncmpii_NC_findvar(const NC_vararray  *ncap,
+                  const char         *uname,
+                  NC_var            **varpp)
+{
+    int varid;
+    size_t nchars;
+    char *name;
+    NC_var **loc;
+
+    assert (ncap != NULL);
+
+    if (ncap->ndefined == 0) return -1;
+
+    loc = (NC_var **) ncap->value;
+
+    /* normalized version of uname */
+    name = (char *)utf8proc_NFC((const unsigned char *)uname);
+    if (name == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+    nchars = strlen(name);
+
+    for (varid=0; varid<ncap->ndefined; varid++, loc++) {
+        if ((*loc)->name->nchars == nchars &&
+            strncmp((*loc)->name->cp, name, nchars) == 0) {
+            if (varpp != NULL)
+                *varpp = *loc;
+            free(name);
+            return (varid); /* Normal return */
+        }
+    }
+    free(name);
+    return (-1); /* not found */
+}
+
+/*
+ * For a netcdf type
+ *  return the size of one element in the external representation.
+ * Note that arrays get rounded up to X_ALIGN boundaries.
+ * Formerly
+NC_xtypelen
+ * See also ncx_len()
+ */
+static int
+ncx_szof(nc_type type)
+{
+    switch(type){
+        case NC_BYTE:
+        case NC_CHAR:   return (1);
+        case NC_SHORT:  return (2);
+        case NC_INT:    return X_SIZEOF_INT;
+        case NC_FLOAT:  return X_SIZEOF_FLOAT;
+        case NC_DOUBLE: return X_SIZEOF_DOUBLE;
+        case NC_UBYTE:  return (1);
+        case NC_USHORT: return (2);
+        case NC_UINT:   return X_SIZEOF_UINT;
+        case NC_INT64:  return X_SIZEOF_INT64;
+        case NC_UINT64: return X_SIZEOF_UINT64;
+        default:
+             assert("ncx_szof invalid type" == 0);
+    }
+    /* default */
+    return 0;
+}
+
+/*----< ncmpii_NC_var_shape64() >--------------------------------------------*/
+/*
+ * set varp->xsz, varp->shape and varp->len of a variable
+ */
+int
+ncmpii_NC_var_shape64(NC                *ncp,
+                      NC_var            *varp,
+                      const NC_dimarray *dims)
+{
+    int i;
+    MPI_Offset product = 1;
+
+    /* set the size of 1 element */
+    varp->xsz = ncx_szof(varp->type);
+
+    if (varp->ndims == 0) goto out;
+
+    /*
+     * use the user supplied dimension indices to determine the shape
+     */
+    for (i=0; i<varp->ndims; i++) {
+        const NC_dim *dimp;
+
+        if (varp->dimids[i] < 0)
+            DEBUG_RETURN_ERROR(NC_EBADDIM)
+
+        if (varp->dimids[i] >= ((dims != NULL) ? dims->ndefined : 1))
+            DEBUG_RETURN_ERROR(NC_EBADDIM)
+
+        /* get the pointer to the dim object */
+        dimp = ncmpii_elem_NC_dimarray(dims, varp->dimids[i]);
+        varp->shape[i] = dimp->size;
+
+        /* check for record variable, only the highest dimension can
+         * be unlimited */
+        if (varp->shape[i] == NC_UNLIMITED && i != 0)
+            DEBUG_RETURN_ERROR(NC_EUNLIMPOS)
+    }
+
+    /*
+     * compute the dsizes, the right to left product of shape
+     */
+    product = 1;
+    if (varp->ndims == 1) {
+        if (varp->shape[0] == NC_UNLIMITED)
+            varp->dsizes[0] = 1;
+        else {
+            varp->dsizes[0] = varp->shape[0];
+            product = varp->shape[0];
+        }
+    }
+    else { /* varp->ndims > 1 */
+        varp->dsizes[varp->ndims-1] = varp->shape[varp->ndims-1];
+        product = varp->shape[varp->ndims-1];
+        for (i=varp->ndims-2; i>=0; i--) {
+            if (varp->shape[i] != NC_UNLIMITED)
+                product *= varp->shape[i];
+            varp->dsizes[i] = product;
+        }
+    }
+
+out :
+    /*
+     * For CDF-1 and CDF-2 formats, the total number of array elements
+     * cannot exceed 2^32, unless this variable is the last fixed-size
+     * variable, there is no record variable, and the file starting
+     * offset of this variable is less than 2GiB.
+     * We will check this in ncmpi_enddef() which calls ncmpii_NC_enddef()
+     * which calls ncmpii_NC_check_vlens()
+     *
+    if (! fIsSet(ncp->flags, NC_64BIT_DATA) && product >= X_UINT_MAX)
+        DEBUG_RETURN_ERROR(NC_EVARSIZE)
+     */
+
+    /*
+     * align variable size to 4 byte boundary, required by all netcdf
+     * file formats
+     */
+    varp->len = product * varp->xsz;
+    if (varp->len % 4 > 0)
+        varp->len += 4 - varp->len % 4; /* round up */
+
+    return NC_NOERR;
+}
+
+/*
+ * Check whether variable size is less than or equal to vlen_max,
+ * without overflowing in arithmetic calculations.  If OK, return 1,
+ * else, return 0.  For CDF1 format or for CDF2 format on non-LFS
+ * platforms, vlen_max should be 2^31 - 4, but for CDF2 format on
+ * systems with LFS it should be 2^32 - 4.
+ */
+inline int
+ncmpii_NC_check_vlen(NC_var     *varp,
+                     MPI_Offset  vlen_max)
+{
+    int ii;
+    MPI_Offset prod=varp->xsz;     /* product of xsz and dimensions so far */
+
+    for (ii = IS_RECVAR(varp) ? 1 : 0; ii < varp->ndims; ii++) {
+        if (varp->shape[ii] > vlen_max / prod) {
+            return 0;           /* size in bytes won't fit in a 32-bit int */
+        }
+        prod *= varp->shape[ii];
+    }
+    return 1;                  /* OK */
+}
+
+/*----< ncmpii_NC_lookupvar() >----------------------------------------------*/
+/*
+ * Given valid ncp and varid, return var
+ *  else NULL on error
+ * Formerly
+NC_hlookupvar()
+ */
+int
+ncmpii_NC_lookupvar(NC      *ncp,
+                    int      varid,
+                    NC_var **varp)
+{
+    if (varid == NC_GLOBAL) /* Global is error in this context */
+        DEBUG_RETURN_ERROR(NC_EGLOBAL)
+
+    *varp = elem_NC_vararray(&ncp->vars, varid);
+    if (*varp == NULL) /* could not find variable with varid */
+        DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    return NC_NOERR;
+}
+
+
+/* Public */
+
+/*----< ncmpi_def_var() >----------------------------------------------------*/
+int
+ncmpi_def_var(int         ncid,
+              const char *name,
+              nc_type     type,
+              int         ndims,
+              const int  *dimids,
+              int        *varidp)
+{
+    int varid, file_ver, status;
+    NC *ncp;
+    NC_var *varp;
+
+    /* check if ncid is valid */
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* check if called in define mode */
+    if (!NC_indef(ncp)) DEBUG_RETURN_ERROR(NC_ENOTINDEFINE)
+
+    /* check if the name string is legal for netcdf format */
+    file_ver = 1;
+    if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
+        file_ver = 2;
+    else if (fIsSet(ncp->flags, NC_64BIT_DATA))
+        file_ver = 5;
+    status = ncmpii_NC_check_name(name, file_ver);
+    if (status != NC_NOERR) return status;
+
+    /* check if type is a valid netcdf type */
+    status = ncmpii_cktype(file_ver, type);
+    if (status != NC_NOERR) return status;
+
+    /* TODO: can ndims > 2^31-1 in CDF-5 ? */
+    if ((ndims < 0) || ndims > X_INT_MAX) DEBUG_RETURN_ERROR(NC_EINVAL)
+
+    /* there is an upperbound for the number of variables defined in a file */
+    if (ncp->vars.ndefined >= NC_MAX_VARS) DEBUG_RETURN_ERROR(NC_EMAXVARS)
+
+    /* check whether the variable name has been used */
+    varid = ncmpii_NC_findvar(&ncp->vars, name, &varp);
+    if (varid != -1) DEBUG_RETURN_ERROR(NC_ENAMEINUSE)
+
+    /* create a new variable */
+    varp = ncmpii_new_NC_var(name, type, ndims, dimids);
+    if (varp == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+    /* set up array dimensional structures */
+    status = ncmpii_NC_var_shape64(ncp, varp, &ncp->dims);
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_var(varp);
+        return status;
+    }
+
+    /* Add a new handle to the end of an array of handles */
+    status = incr_NC_vararray(&ncp->vars, varp);
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_var(varp);
+        return status;
+    }
+
+    if (varidp != NULL)
+        *varidp = (int)ncp->vars.ndefined - 1; /* varid */
+        /* ncp->vars.ndefined has been increased in incr_NC_vararray() */
+
+    /* default is NOFILL */
+    varp->no_fill = 1;
+
+    /* change to FILL only if the entire dataset fill mode is FILL */
+    if (NC_dofill(ncp)) varp->no_fill = 0;
+
+    return NC_NOERR;
+}
+
+
+/*----< ncmpi_inq_varid() >--------------------------------------------------*/
+int
+ncmpi_inq_varid(int         ncid,
+                const char *name,
+                int        *varid_ptr)
+{
+    int status;
+    NC *ncp;
+    NC_var *varp;
+    int varid;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    varid = ncmpii_NC_findvar(&ncp->vars, name, &varp);
+    if (varid == -1) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    *varid_ptr = varid;
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_var() >----------------------------------------------------*/
+int
+ncmpi_inq_var(int      ncid,
+              int      varid,
+              char    *name,
+              nc_type *typep,
+              int     *ndimsp,
+              int     *dimids,
+              int     *nattsp)
+{
+    int status;
+    NC *ncp;
+    NC_var *varp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* using NC_GLOBAL in varid is illegal for this API. See
+     * http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2015/msg00196.html
+     */
+    if (varid == NC_GLOBAL) DEBUG_RETURN_ERROR(NC_EGLOBAL)
+
+    varp = elem_NC_vararray(&ncp->vars, varid);
+    if (varp == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    if (name != NULL)
+        /* in PnetCDF, name->cp is always NULL character terminated */
+        strcpy(name, varp->name->cp);
+
+    if (typep != 0)
+        *typep = varp->type;
+
+    if (ndimsp != 0) {
+#ifdef ENABLE_SUBFILING
+        /* varp->num_subfiles is already set during open or enddef */
+        if (varp->num_subfiles > 1)
+            *ndimsp = varp->ndims_org;
+        else
+#endif
+            *ndimsp = varp->ndims;
+    }
+    if (dimids != 0) {
+#ifdef ENABLE_SUBFILING
+        /* varp->dimids_org is already set during open or enddef */
+        if (varp->num_subfiles > 1)
+            memcpy(dimids, varp->dimids_org, (size_t)varp->ndims_org * SIZEOF_INT);
+        else
+#endif
+            memcpy(dimids, varp->dimids, (size_t)varp->ndims * SIZEOF_INT);
+    }
+    if (nattsp != 0)
+        *nattsp = (int) varp->attrs.ndefined;
+
+    return NC_NOERR;
+}
+
+
+/*----< ncmpi_inq_varname() >------------------------------------------------*/
+int
+ncmpi_inq_varname(int   ncid,
+                  int   varid,
+                  char *name)
+{
+    int status;
+    NC *ncp;
+    NC_var *varp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* using NC_GLOBAL in varid is illegal for this API. See
+     * http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2015/msg00196.html
+     */
+    if (varid == NC_GLOBAL) DEBUG_RETURN_ERROR(NC_EGLOBAL)
+
+    varp = elem_NC_vararray(&ncp->vars, varid);
+    if (varp == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    if (name != NULL)
+        /* in PnetCDF, name->cp is always NULL character terminated */
+        strcpy(name, varp->name->cp);
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_vartype() >------------------------------------------------*/
+int
+ncmpi_inq_vartype(int      ncid,
+                  int      varid,
+                  nc_type *typep)
+{
+    int status;
+    NC *ncp;
+    NC_var *varp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* using NC_GLOBAL in varid is illegal for this API. See
+     * http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2015/msg00196.html
+     */
+    if (varid == NC_GLOBAL) DEBUG_RETURN_ERROR(NC_EGLOBAL)
+
+    varp = elem_NC_vararray(&ncp->vars, varid);
+    if (varp == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    if (typep != NULL) *typep = varp->type;
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_varndims() >-----------------------------------------------*/
+int
+ncmpi_inq_varndims(int ncid, int varid, int *ndimsp)
+{
+    int status;
+    NC *ncp;
+    NC_var *varp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* using NC_GLOBAL in varid is illegal for this API. See
+     * http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2015/msg00196.html
+     */
+    if (varid == NC_GLOBAL) DEBUG_RETURN_ERROR(NC_EGLOBAL)
+
+    varp = elem_NC_vararray(&ncp->vars, varid);
+    if (varp == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    if (ndimsp != 0) {
+#ifdef ENABLE_SUBFILNIG
+        if (varp->num_subfiles > 1)
+            *ndimsp = varp->ndims_org;
+        else
+#endif
+            *ndimsp = varp->ndims;
+    }
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_inq_vardimid() >-----------------------------------------------*/
+int
+ncmpi_inq_vardimid(int ncid, int varid, int *dimids)
+{
+    int status;
+    NC *ncp;
+    NC_var *varp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* using NC_GLOBAL in varid is illegal for this API. See
+     * http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2015/msg00196.html
+     */
+    if (varid == NC_GLOBAL) DEBUG_RETURN_ERROR(NC_EGLOBAL)
+
+    varp = elem_NC_vararray(&ncp->vars, varid);
+    if (varp == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    if (dimids != 0) {
+#ifdef ENABLE_SUBFILING
+        if (varp->num_subfiles > 1)
+            memcpy(dimids, varp->dimids_org, (size_t)varp->ndims_org * SIZEOF_INT);
+        else
+#endif
+            memcpy(dimids, varp->dimids, (size_t)varp->ndims * SIZEOF_INT);
+    }
+
+    return NC_NOERR;
+}
+
+
+/*----< ncmpi_inq_varnatts() >------------------------------------------------*/
+int
+ncmpi_inq_varnatts(int  ncid,
+                   int  varid,
+                   int *nattsp)
+{
+    int status;
+    NC *ncp;
+    NC_var *varp;
+
+    if (varid == NC_GLOBAL)
+        return ncmpi_inq_natts(ncid, nattsp);
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    varp = elem_NC_vararray(&ncp->vars, varid);
+    if (varp == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    if (nattsp != NULL)
+        *nattsp = (int) varp->attrs.ndefined;
+
+    return NC_NOERR;
+}
+
+/*----< ncmpi_rename_var() >--------------------------------------------------*/
+/* This API is collective if called in data mode */
+int
+ncmpi_rename_var(int         ncid,
+                 int         varid,
+                 const char *newname)
+{
+    int file_ver, status=NC_NOERR, other, err, mpireturn;
+    NC *ncp;
+    NC_var *varp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    if (NC_readonly(ncp)) DEBUG_RETURN_ERROR(NC_EPERM)
+
+    /* check if variable ID is valid*/
+    status = ncmpii_NC_lookupvar(ncp, varid, &varp);
+    if (status != NC_NOERR) return status;
+
+    file_ver = 1;
+    if (fIsSet(ncp->flags, NC_64BIT_OFFSET))
+        file_ver = 2;
+    else if (fIsSet(ncp->flags, NC_64BIT_DATA))
+        file_ver = 5;
+
+    status = ncmpii_NC_check_name(newname, file_ver);
+    if (status != NC_NOERR) return status;
+
+    /* check for name in use */
+    other = ncmpii_NC_findvar(&ncp->vars, newname, &varp);
+    if (other != -1)
+        DEBUG_RETURN_ERROR(NC_ENAMEINUSE)
+
+    /* if called in define mode, just update to the NC object */
+    if (NC_indef(ncp)) {
+        NC_string *newStr = ncmpii_new_NC_string(strlen(newname), newname);
+        if (newStr == NULL) DEBUG_RETURN_ERROR(NC_ENOMEM)
+
+        ncmpii_free_NC_string(varp->name);
+        varp->name = newStr;
+        return NC_NOERR;
+    }
+    /* else, not in define mode.
+     * if called in data mode (collective or independent), this function must
+     * be called collectively, i.e. all processes must participate.
+     */
+
+    if (ncp->safe_mode) {
+        int nchars = (int)strlen(newname);
+        TRACE_COMM(MPI_Bcast)(&nchars, 1, MPI_INT, 0, ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Bcast"); 
+
+        if (nchars != (int) strlen(newname)) {
+            /* newname's length is inconsistent with root's */
+            printf("Warning: variable name(%s) used in %s() is inconsistent\n",
+                   newname, __func__);
+            if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EMULTIDEFINE_VAR_NAME)
+        }
+    }
+
+    /* ncmpii_set_NC_string() will check for strlen(newname) > nchars error */
+    err = ncmpii_set_NC_string(varp->name, newname);
+    if (status == NC_NOERR) status = err;
+
+    /* PnetCDF expects all processes use the same name, However, when names
+     * are not the same, only root's value is significant. Broadcast the
+     * new name at root to overwrite new names at other processes.
+     * (This API is collective if called in data mode)
+     */
+    TRACE_COMM(MPI_Bcast)(varp->name->cp, (int)varp->name->nchars, MPI_CHAR, 0,
+                          ncp->nciop->comm);
+
+    /* Let root write the entire header to the file. Note that we cannot just
+     * update the variable name in its space occupied in the file header,
+     * because if the file space occupied by the name shrinks, all the metadata
+     * following it must be moved ahead.
+     */
+    err = ncmpii_write_header(ncp);
+    if (status == NC_NOERR) status = err;
+
+    return status;
+}
+
+/* some utility functions for debugging purpose */
+
+/*----< ncmpi_inq_varoffset() >-----------------------------------------------*/
+int
+ncmpi_inq_varoffset(int         ncid,
+                    int         varid,
+                    MPI_Offset *offset)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp;
+
+    status = ncmpii_NC_check_id(ncid, &ncp);
+    if (status != NC_NOERR) return status;
+
+    /* using NC_GLOBAL in varid is illegal for this API. See
+     * http://www.unidata.ucar.edu/mailing_lists/archives/netcdfgroup/2015/msg00196.html
+     */
+    if (varid == NC_GLOBAL) DEBUG_RETURN_ERROR(NC_EGLOBAL)
+
+    varp = elem_NC_vararray(&ncp->vars, varid);
+    if (varp == NULL) DEBUG_RETURN_ERROR(NC_ENOTVAR)
+
+    if (offset != NULL)
+        *offset = varp->begin;
+
+    return NC_NOERR;
+}
+
+#ifdef __DEBUG
+
+/*----< ncmpi_print_all_var_offsets() >---------------------------------------*/
+int
+ncmpi_print_all_var_offsets(int ncid) {
+    int i;
+    NC_var **vpp;
+    NC *ncp;
+
+    ncmpii_NC_check_id(ncid, &ncp);
+
+    if (ncp->begin_var%1048576)
+        printf("%s header size (ncp->begin_var)=%lld MB + %lld\n",
+        ncp->nciop->path, ncp->begin_var/1048575, ncp->begin_var%1048576);
+    else
+        printf("%s header size (ncp->begin_var)=%lld MB\n",
+        ncp->nciop->path, ncp->begin_var/1048575);
+
+    vpp = ncp->vars.value;
+    for (i=0; i<ncp->vars.ndefined; i++, vpp++) {
+        char str[1024];
+        MPI_Offset off = (*vpp)->begin;
+        MPI_Offset rem = off % 1048576;;
+
+        if (IS_RECVAR(*vpp))
+            sprintf(str,"    Record variable \"%20s\": ",(*vpp)->name->cp);
+        else
+            sprintf(str,"non-record variable \"%20s\": ",(*vpp)->name->cp);
+
+        if (rem)
+            printf("%s offset=%12lld MB + %7lld len=%lld\n", str, off/1048576, rem,(*vpp)->len);
+        else
+            printf("%s offset=%12lld MB len=%lld\n", str, off/1048576,(*vpp)->len);
+    }
+    return NC_NOERR;
+}
+
+#endif
diff --git a/src/lib/vard.c b/src/lib/vard.c
new file mode 100644
index 0000000..16b4076
--- /dev/null
+++ b/src/lib/vard.c
@@ -0,0 +1,407 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: vard.c 2216 2015-12-08 05:47:19Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h> /* memcpy() */
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "ncmpidtype.h"
+#include "macro.h"
+#ifdef ENABLE_SUBFILING
+#include "subfile.h"
+#endif
+
+/* for write case, buf needs to swapped back if swapped previously */
+#define FINAL_CLEAN_UP {                                                       \
+    if (is_buf_swapped) /* byte-swap back to buf's original contents */        \
+        ncmpii_in_swapn(buf, bnelems, ncmpix_len_nctype(varp->type));          \
+                                                                               \
+    if (cbuf != NULL && cbuf != buf) NCI_Free(cbuf);                           \
+}
+
+/*----< ncmpii_getput_vard() >------------------------------------------------*/
+static int
+ncmpii_getput_vard(NC               *ncp,
+                   NC_var           *varp,
+                   MPI_Datatype      filetype,  /* data type of the variable */
+                   void             *buf,
+                   MPI_Offset        bufcount,
+                   MPI_Datatype      buftype,  /* data type of the bufer */
+                   int               rw_flag,
+                   int               io_method)
+{
+    void *cbuf=NULL;
+    int i, isderived, el_size, mpireturn, status=NC_NOERR, err=NC_NOERR;
+    int buftype_is_contig, filetype_is_contig=1, need_swap=0, is_buf_swapped=0;
+    int filetype_size=0, buftype_size;
+    MPI_Offset btnelems, bnelems=0, offset=0, orig_bufcount=bufcount;
+    MPI_Status mpistatus;
+    MPI_Datatype ptype, orig_buftype=buftype;
+    MPI_File fh=MPI_FILE_NULL;
+
+    if (filetype == MPI_DATATYPE_NULL) { /* this process does zero-length I/O */
+        if (io_method == INDEP_IO) return NC_NOERR;
+        bufcount = 0;
+        goto err_check;
+    }
+
+    if (bufcount == 0 && buftype != MPI_DATATYPE_NULL) {
+        /* if this process has nothing to read/write */
+        if (io_method == INDEP_IO) return NC_NOERR;
+        goto err_check;
+    }
+
+#ifdef ENABLE_SUBFILING
+    /* call a separate routine if variable is stored in subfiles */
+    if (varp->num_subfiles > 1) {
+        printf("This feature for subfiling is yet to implement\n");
+        DEBUG_RETURN_ERROR(NC_ENOTSUPPORT)
+    }
+#endif
+
+    /* PROBLEM: argument filetype_size is a 4-byte integer, cannot be used
+     * for largefiletypes */
+    mpireturn = MPI_Type_size(filetype, &filetype_size);
+    if (mpireturn != MPI_SUCCESS) {
+        err = ncmpii_handle_error(mpireturn, "MPI_Type_size");
+        goto err_check;
+    }
+
+    if (filetype_size == 0) { /* zero-length request */
+        if (io_method == INDEP_IO) return NC_NOERR;
+        bufcount = 0;
+        goto err_check;
+    }
+
+    MPI_Aint true_lb, true_extent;
+    MPI_Type_get_true_extent(filetype, &true_lb, &true_extent);
+    MPI_Aint lb, extent;
+    MPI_Type_get_extent(filetype, &lb, &extent);
+
+    if (!IS_RECVAR(varp)) {
+        /* for fixed-size variable, extent should not be larger than the
+         * variabe size */
+        MPI_Offset var_size = varp->xsz;
+        for (i=0; i<varp->ndims; i++)
+            var_size *= varp->shape[i];
+
+        if (extent > var_size) {
+            DEBUG_ASSIGN_ERROR(err, NC_ETYPESIZE)
+            goto err_check;
+        }
+    }
+
+    cbuf = (void*) buf;
+
+    /* find the element type of filetype */
+    err = ncmpii_dtype_decode(filetype, &ptype, &el_size, &btnelems,
+                              &isderived, &filetype_is_contig);
+    if (err != NC_NOERR) goto err_check;
+
+    /* element type of filetype must be the same as variable's type */
+    if (ptype != ncmpii_nc2mpitype(varp->type)) {
+        DEBUG_ASSIGN_ERROR(err, NC_ETYPE_MISMATCH)
+        goto err_check;
+    }
+
+    if (bufcount != (int)bufcount) {
+        DEBUG_ASSIGN_ERROR(err, NC_EINTOVERFLOW)
+        goto err_check;
+    }
+
+    if (buftype == MPI_DATATYPE_NULL) {
+        /* In this case, bufcount is ignored and will be set to the size of
+         * filetype. Note buf's data type must match the data type of variable
+         * defined in the file - no data conversion will be done.
+         */
+        /* set buftype to the variable's data type */
+        buftype = ncmpii_nc2mpitype(varp->type);
+        MPI_Type_size(buftype, &buftype_size);
+        bufcount = filetype_size / buftype_size;
+        buftype_is_contig = 1;
+        bnelems = bufcount;
+    }
+    else {
+        MPI_Offset outsize;
+
+        /* find whether buftype is contiguous */
+        err = ncmpii_dtype_decode(buftype, &ptype, &el_size, &btnelems,
+                                  &isderived, &buftype_is_contig);
+        if (err != NC_NOERR) goto err_check;
+
+        err = NCMPII_ECHAR(varp->type, ptype);
+        if (err != NC_NOERR) goto err_check;
+
+        if (btnelems != (int)btnelems) {
+            DEBUG_ASSIGN_ERROR(err, NC_EINTOVERFLOW)
+            goto err_check;
+        }
+
+        bnelems      = bufcount * btnelems;
+        buftype_size = el_size  * (int)btnelems;
+        outsize      = bufcount * buftype_size;
+
+        if (outsize != filetype_size) {
+            DEBUG_ASSIGN_ERROR(err, NC_ETYPESIZE_MISMATCH)
+            goto err_check;
+        }
+
+        /* if buf is not contiguous, we need to pack it to one, cbuf */
+        if (!buftype_is_contig && bnelems > 0) {
+            cbuf = NCI_Malloc((size_t)outsize);
+
+            if (rw_flag == WRITE_REQ) {
+                /* pack buf into cbuf, a contiguous buffer */
+                int position = 0;
+                MPI_Pack(buf, (int)bufcount, buftype, cbuf, (int)outsize, &position,
+                         MPI_COMM_SELF);
+            }
+            buftype = ptype;
+            bufcount *= bnelems;
+        }
+    }
+
+    /* Check if we need byte swap cbuf in-place or (into cbuf) */
+    need_swap = ncmpii_need_swap(varp->type, ptype);
+    if (need_swap) {
+        if (rw_flag == WRITE_REQ) {
+#ifdef DISABLE_IN_PLACE_SWAP
+            if (cbuf == buf) {
+#else
+            if (cbuf == buf && filetype_size <= NC_BYTE_SWAP_BUFFER_SIZE) {
+#endif
+                /* allocate cbuf and copy buf to cbuf, cbuf is to be freed */
+                cbuf = NCI_Malloc((size_t)filetype_size);
+                memcpy(cbuf, buf, filetype_size);
+            }
+            /* perform array in-place byte swap on cbuf */
+            ncmpii_in_swapn(cbuf, bnelems, ncmpix_len_nctype(varp->type));
+            is_buf_swapped = (cbuf == buf) ? 1 : 0;
+            /* is_buf_swapped indicates if the contents of the original user
+             * buffer, buf, have been changed, i.e. byte swapped. */
+        }
+    }
+    /* no type conversion */
+
+    /* set fileview's displacement to the variable's starting file offset */
+    offset = varp->begin;
+
+err_check:
+    /* check API error from any proc before going into a collective call.
+     * optimization: to avoid MPI_Allreduce to check parameters at
+     * every call, we assume caller does the right thing most of the
+     * time.  If caller passed in bad parameters, we'll still conduct a
+     * zero-byte operation (everyone has to participate in the
+     * collective I/O call) but return error */
+    if (err != NC_NOERR || bufcount == 0 || filetype_size == 0) {
+        if (io_method == INDEP_IO) {
+            FINAL_CLEAN_UP  /* swap back put buffer and free temp buffers */
+            return err;
+        }
+        /* else for COLL_IO, must participate successive collective calls */
+    }
+    status = err;
+
+    if (io_method == COLL_IO)
+        fh = ncp->nciop->collective_fh;
+    else
+        fh = ncp->nciop->independent_fh;
+
+    /* set the file view */
+    err = ncmpii_file_set_view(ncp, fh, &offset, filetype);
+    if (err != NC_NOERR) {
+        bufcount = 0; /* skip this request */
+        if (status == NC_NOERR) status = err;
+    }
+
+    if (rw_flag == WRITE_REQ) {
+        if (io_method == COLL_IO) {
+            TRACE_IO(MPI_File_write_at_all)(fh, offset, cbuf, (int)bufcount, buftype, &mpistatus);
+            if (mpireturn != MPI_SUCCESS)
+                return ncmpii_handle_error(mpireturn, "MPI_File_write_at_all");
+        }
+        else { /* io_method == INDEP_IO */
+            TRACE_IO(MPI_File_write_at)(fh, offset, cbuf, (int)bufcount, buftype, &mpistatus);
+            if (mpireturn != MPI_SUCCESS)
+                return ncmpii_handle_error(mpireturn, "MPI_File_write_at");
+        }
+        int put_size;
+        MPI_Get_count(&mpistatus, MPI_BYTE, &put_size);
+        ncp->nciop->put_size += put_size;
+    }
+    else {  /* rw_flag == READ_REQ */
+        if (io_method == COLL_IO) {
+            TRACE_IO(MPI_File_read_at_all)(fh, offset, cbuf, (int)bufcount, buftype, &mpistatus);
+            if (mpireturn != MPI_SUCCESS)
+                return ncmpii_handle_error(mpireturn, "MPI_File_read_at_all");
+        }
+        else { /* io_method == INDEP_IO */
+            TRACE_IO(MPI_File_read_at)(fh, offset, cbuf, (int)bufcount, buftype, &mpistatus);
+            if (mpireturn != MPI_SUCCESS)
+                return ncmpii_handle_error(mpireturn, "MPI_File_read_at");
+        }
+        int get_size;
+        MPI_Get_count(&mpistatus, MPI_BYTE, &get_size);
+        ncp->nciop->get_size += get_size;
+    }
+
+    /* No longer need to reset the file view, as the root's fileview includes
+     * the whole file header.
+     TRACE_IO(MPI_File_set_view)(fh, 0, MPI_BYTE, MPI_BYTE, "native", MPI_INFO_NULL);
+     */
+
+    if (rw_flag == READ_REQ) {
+        if (need_swap)
+            /* perform array in-place byte swap on cbuf */
+            ncmpii_in_swapn(cbuf, bnelems, ncmpix_len_nctype(varp->type));
+
+        if (!buftype_is_contig && bnelems > 0) {
+            /* unpack cbuf, a contiguous buffer, to buf using buftype */
+            int position = 0;
+            MPI_Offset insize = bnelems * el_size;
+            if (insize != (int)insize) {
+                if (status == NC_NOERR) DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+            }
+            else
+                MPI_Unpack(cbuf, (int)insize, &position, buf, (int)orig_bufcount,
+                           orig_buftype, MPI_COMM_SELF);
+        }
+    }
+    else { /* WRITE_REQ */
+        if (IS_RECVAR(varp)) {
+            /* update header's number of records in memory */
+            MPI_Offset new_numrecs;
+
+            /* since filetype's LB is required to be == varp->begin for vard
+             * API, we can simply use extent to calculate new_numrecs */
+            new_numrecs = extent / ncp->recsize;
+            if (extent % ncp->recsize) new_numrecs++;
+
+            if (io_method == INDEP_IO) {
+                /* For independent put, we delay the sync for numrecs until
+                 * the next collective call, such as end_indep(), sync(),
+                 * enddef(), or close(). This is because if we update numrecs
+                 * to file now, race condition can happen. Note numrecs in
+                 * memory may be inconsistent and obsolete till then.
+                 */
+                if (ncp->numrecs < new_numrecs) {
+                    ncp->numrecs = new_numrecs;
+                    set_NC_ndirty(ncp);
+                }
+            }
+            else { /* COLL_IO: sync numrecs in memory and file */
+                err = ncmpii_sync_numrecs(ncp, new_numrecs);
+                if (err != NC_NOERR && status == NC_NOERR) status = err;
+            }
+        }
+
+        if (NC_doFsync(ncp)) { /* NC_SHARE is set */
+            TRACE_IO(MPI_File_sync)(fh);
+            if (io_method == COLL_IO)
+                TRACE_COMM(MPI_Barrier)(ncp->nciop->comm);
+        }
+    }
+
+    FINAL_CLEAN_UP  /* swap back the put buffer and free temp buffers */
+
+    return status;
+}
+
+/*----< ncmpi_get_vard() >---------------------------------------------------*/
+int
+ncmpi_get_vard(int           ncid,
+               int           varid,
+               MPI_Datatype  filetype,  /* access layout to the variable in file */
+               void         *buf,
+               MPI_Offset    bufcount,
+               MPI_Datatype  buftype)   /* data type of the buffer */
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VARD,
+                                 1, 1, READ_REQ, INDEP_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_getput_vard(ncp, varp, filetype, buf, bufcount, buftype,
+                              READ_REQ, INDEP_IO);
+}
+
+/*----< ncmpi_get_vard_all() >-----------------------------------------------*/
+int
+ncmpi_get_vard_all(int           ncid,
+                   int           varid,
+                   MPI_Datatype  filetype,  /* access layout to the variable in file */
+                   void         *buf,
+                   MPI_Offset    bufcount,
+                   MPI_Datatype  buftype)   /* data type of the buffer */
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VARD,
+                                 1, 1, READ_REQ, COLL_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_getput_vard(ncp, varp, filetype, buf, bufcount, buftype,
+                              READ_REQ, COLL_IO);
+}
+
+/*----< ncmpi_put_vard() >---------------------------------------------------*/
+int
+ncmpi_put_vard(int           ncid,
+               int           varid,
+               MPI_Datatype  filetype,  /* access layout to the variable in file */
+               const void   *buf,
+               MPI_Offset    bufcount,
+               MPI_Datatype  buftype)   /* data type of the buffer */
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VARD,
+                                 1, 1, WRITE_REQ, INDEP_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_getput_vard(ncp, varp, filetype, (void*)buf, bufcount,
+                              buftype, WRITE_REQ, INDEP_IO);
+}
+
+/*----< ncmpi_put_vard_all() >-----------------------------------------------*/
+int
+ncmpi_put_vard_all(int           ncid,
+                   int           varid,
+                   MPI_Datatype  filetype,  /* access layout to the variable in file */
+                   const void   *buf,
+                   MPI_Offset    bufcount,
+                   MPI_Datatype  buftype)   /* data type of the buffer */
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VARD,
+                                 1, 1, WRITE_REQ, COLL_IO, &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_getput_vard(ncp, varp, filetype, (void*)buf, bufcount,
+                              buftype, WRITE_REQ, COLL_IO);
+}
diff --git a/src/lib/varn.m4 b/src/lib/varn.m4
new file mode 100644
index 0000000..1fd0993
--- /dev/null
+++ b/src/lib/varn.m4
@@ -0,0 +1,368 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: varn.m4 2290 2016-01-02 18:37:46Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include "ncconfig.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <assert.h>
+
+#include <mpi.h>
+
+#include "nc.h"
+#include "ncx.h"
+#include "ncmpidtype.h"
+#include "macro.h"
+
+/* ncmpi_get/put_varn_<type>_<mode> API:
+ *    type:   data type of I/O buffer, buf
+ *    mode:   independent (<nond>) or collective (_all)
+ *
+ * arguments:
+ *    num:    number of start and count pairs
+ *    starts: an 2D array of size [num][ndims]. Each starts[i][*] indicates
+ *            the starting array indices for a subarray request. ndims is
+ *            the number of dimensions of the defined netCDF variable.
+ *    counts: an 2D array of size [num][ndims]. Each counts[i][*] indicates
+ *            the number of array elements to be accessed. This argument
+ *            can be NULL, equivalent to counts with all 1s.
+ *    bufcount and buftype: these 2 arguments are only available for flexible
+ *            APIs, indicating the I/O buffer memory layout. When buftype is
+ *            MPI_DATATYPE_NULL, bufcount is ignored and the data type of buf
+ *            is considered matched the variable data type defined in the file.
+ */
+
+static int
+ncmpii_getput_varn(NC               *ncp,
+                   NC_var           *varp,
+                   int               num,
+                   MPI_Offset* const starts[],  /* [num][varp->ndims] */
+                   MPI_Offset* const counts[],  /* [num][varp->ndims] */
+                   void             *buf,
+                   MPI_Offset        bufcount,
+                   MPI_Datatype      buftype,   /* data type of the buffer */
+                   int               rw_flag,
+                   int               io_method);
+
+define(`CollIndep', `ifelse(`$1',`_all', `COLL_IO', `INDEP_IO')')dnl
+define(`BufConst',  `ifelse(`$1', `put', `const')')dnl
+define(`ReadWrite', `ifelse(`$1', `get', `READ_REQ', `WRITE_REQ')')dnl
+
+dnl
+dnl VARN_FLEXIBLE(ncid, varid, num starts, counts, buf, bufcount, buftype)
+dnl
+define(`VARN_FLEXIBLE',dnl
+`dnl
+/*----< ncmpi_$1_varn$2() >---------------------------------------------------*/
+int
+ncmpi_$1_varn$2(int                ncid,
+                int                varid,
+                int                num,
+                MPI_Offset* const  starts[],
+                MPI_Offset* const  counts[],
+                BufConst($1) void *buf,
+                MPI_Offset         bufcount,
+                MPI_Datatype       buftype)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, bufcount, API_VARN,
+                                 1, 1, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    return ncmpii_getput_varn(ncp, varp, num, starts, counts, (void*)buf,
+                              bufcount, buftype, ReadWrite($1), CollIndep($2));
+}
+')dnl
+
+dnl PnetCDF flexible APIs
+VARN_FLEXIBLE(put)
+VARN_FLEXIBLE(put, _all)
+VARN_FLEXIBLE(get)
+VARN_FLEXIBLE(get, _all)
+
+dnl
+dnl VARN(ncid, varid, starts, counts, buf)
+dnl
+define(`VARN',dnl
+`dnl
+/*----< ncmpi_$1_varn_$3$2() >------------------------------------------------*/
+int
+ncmpi_$1_varn_$3$2(int                ncid,
+                   int                varid,
+                   int                num,
+                   MPI_Offset* const  starts[],
+                   MPI_Offset* const  counts[],
+                   BufConst($1) $4   *buf)
+{
+    int     status;
+    NC     *ncp;
+    NC_var *varp=NULL;
+
+    status = ncmpii_sanity_check(ncid, varid, NULL, NULL, 0, API_VARN,
+                                 1, 0, ReadWrite($1), CollIndep($2), &ncp, &varp);
+    if (status != NC_NOERR) return status;
+
+    /* set bufcount to -1 indicating non-flexible API */
+    return ncmpii_getput_varn(ncp, varp, num, starts, counts, (void*)buf,
+                              -1, $5, ReadWrite($1), CollIndep($2));
+}
+')dnl
+
+VARN(put,     , text,      char,               MPI_CHAR)
+VARN(put,     , schar,     schar,              MPI_SIGNED_CHAR)
+VARN(put,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARN(put,     , short,     short,              MPI_SHORT)
+VARN(put,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARN(put,     , int,       int,                MPI_INT)
+VARN(put,     , uint,      uint,               MPI_UNSIGNED)
+VARN(put,     , long,      long,               MPI_LONG)
+VARN(put,     , float,     float,              MPI_FLOAT)
+VARN(put,     , double,    double,             MPI_DOUBLE)
+VARN(put,     , longlong,  long long,          MPI_LONG_LONG_INT)
+VARN(put,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARN(put, _all, text,      char,               MPI_CHAR)
+VARN(put, _all, schar,     schar,              MPI_SIGNED_CHAR)
+VARN(put, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARN(put, _all, short,     short,              MPI_SHORT)
+VARN(put, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARN(put, _all, int,       int,                MPI_INT)
+VARN(put, _all, uint,      uint,               MPI_UNSIGNED)
+VARN(put, _all, long,      long,               MPI_LONG)
+VARN(put, _all, float,     float,              MPI_FLOAT)
+VARN(put, _all, double,    double,             MPI_DOUBLE)
+VARN(put, _all, longlong,  long long,          MPI_LONG_LONG_INT)
+VARN(put, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARN(get,     , text,      char,               MPI_CHAR)
+VARN(get,     , schar,     schar,              MPI_SIGNED_CHAR)
+VARN(get,     , uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARN(get,     , short,     short,              MPI_SHORT)
+VARN(get,     , ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARN(get,     , int,       int,                MPI_INT)
+VARN(get,     , uint,      uint,               MPI_UNSIGNED)
+VARN(get,     , long,      long,               MPI_LONG)
+VARN(get,     , float,     float,              MPI_FLOAT)
+VARN(get,     , double,    double,             MPI_DOUBLE)
+VARN(get,     , longlong,  long long,          MPI_LONG_LONG_INT)
+VARN(get,     , ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+VARN(get, _all, text,      char,               MPI_CHAR)
+VARN(get, _all, schar,     schar,              MPI_SIGNED_CHAR)
+VARN(get, _all, uchar,     uchar,              MPI_UNSIGNED_CHAR)
+VARN(get, _all, short,     short,              MPI_SHORT)
+VARN(get, _all, ushort,    ushort,             MPI_UNSIGNED_SHORT)
+VARN(get, _all, int,       int,                MPI_INT)
+VARN(get, _all, uint,      uint,               MPI_UNSIGNED)
+VARN(get, _all, long,      long,               MPI_LONG)
+VARN(get, _all, float,     float,              MPI_FLOAT)
+VARN(get, _all, double,    double,             MPI_DOUBLE)
+VARN(get, _all, longlong,  long long,          MPI_LONG_LONG_INT)
+VARN(get, _all, ulonglong, unsigned long long, MPI_UNSIGNED_LONG_LONG)
+
+
+/*----< ncmpii_getput_varn() >------------------------------------------------*/
+static int
+ncmpii_getput_varn(NC               *ncp,
+                   NC_var           *varp,
+                   int               num,
+                   MPI_Offset* const starts[],  /* [num][varp->ndims] */
+                   MPI_Offset* const counts[],  /* [num][varp->ndims] */
+                   void             *buf,
+                   MPI_Offset        bufcount,
+                   MPI_Datatype      buftype,   /* data type of the buffer */
+                   int               rw_flag,   /* WRITE_REQ or READ_REQ */
+                   int               io_method) /* COLL_IO or INDEP_IO */
+{
+    int i, j, el_size, status=NC_NOERR, min_st, err, free_cbuf=0;
+    int req_id=NC_REQ_NULL, st, isSameGroup, position;
+    void *cbuf=NULL;
+    char *bufp;
+    MPI_Offset packsize=0, **_counts=NULL;
+    MPI_Datatype ptype;
+
+    /* check for zero-size request */
+    if (num == 0 || bufcount == 0) goto err_check;
+
+    /* it is illegal for starts to be NULL */
+    if (starts == NULL) {
+        DEBUG_ASSIGN_ERROR(status, NC_ENULLSTART)
+        goto err_check;
+    }
+
+    if (buftype == MPI_DATATYPE_NULL) {
+        /* In this case, bufcount is ignored and will be recalculated to match
+         * counts[]. Note buf's data type must match the data type of
+         * variable defined in the file - no data conversion will be done.
+         */
+        if (counts == NULL)
+            bufcount = 1;
+        else {
+            bufcount = 0;
+            for (j=0; j<num; j++) {
+                MPI_Offset bufcount_j = 1;
+                for (i=0; i<varp->ndims; i++) {
+                    if (counts[j][i] < 0) { /* no negative counts[][] */
+                        DEBUG_ASSIGN_ERROR(err, NC_ENEGATIVECNT)
+                        goto err_check;
+                    }
+                    bufcount_j *= counts[j][i];
+                }
+                bufcount += bufcount_j;
+            }
+        }
+        /* assign buftype match with the variable's data type */
+        buftype = ncmpii_nc2mpitype(varp->type);
+    }
+
+    cbuf = buf;
+    if (bufcount > 0) { /* flexible API is used */
+        /* pack buf into cbuf, a contiguous buffer */
+        int isderived, iscontig_of_ptypes;
+        MPI_Offset bnelems;
+
+        /* ptype (primitive MPI data type) from buftype
+         * el_size is the element size of ptype
+         * bnelems is the total number of ptype elements in buftype
+         */
+        status = ncmpii_dtype_decode(buftype, &ptype, &el_size, &bnelems,
+                                     &isderived, &iscontig_of_ptypes);
+
+        if (status != NC_NOERR) goto err_check;
+
+        if (bufcount != (int)bufcount) {
+            DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+            goto err_check;
+        }
+
+        /* check if buftype is contiguous, if not, pack to one, cbuf */
+        if (! iscontig_of_ptypes && bnelems > 0) {
+            position = 0;
+            packsize  = bnelems*el_size;
+            if (packsize != (int)packsize) {
+                DEBUG_ASSIGN_ERROR(status, NC_EINTOVERFLOW)
+                goto err_check;
+            }
+            cbuf = NCI_Malloc((size_t)packsize);
+            free_cbuf = 1;
+            if (rw_flag == WRITE_REQ)
+                MPI_Pack(buf, (int)bufcount, buftype, cbuf, (int)packsize,
+                         &position, MPI_COMM_SELF);
+        }
+    }
+    else {
+        /* this subroutine is called from a high-level API */
+        status = NCMPII_ECHAR(varp->type, buftype);
+        if (status != NC_NOERR) goto err_check;
+
+        ptype = buftype;
+        el_size = ncmpix_len_nctype(varp->type);
+    }
+
+    /* We allow counts == NULL and treat this the same as all 1s */
+    if (counts == NULL) {
+        _counts    = (MPI_Offset**) NCI_Malloc((size_t)num * sizeof(MPI_Offset*));
+        _counts[0] = (MPI_Offset*)  NCI_Malloc((size_t)(num * varp->ndims *
+                                                        SIZEOF_MPI_OFFSET));
+        for (i=1; i<num; i++)
+            _counts[i] = _counts[i-1] + varp->ndims;
+        for (i=0; i<num; i++)
+            for (j=0; j<varp->ndims; j++)
+                _counts[i][j] = 1;
+    }
+    else
+        _counts = (MPI_Offset**) counts;
+
+    /* break buf into num pieces */
+    isSameGroup=0;
+    bufp = (char*)cbuf;
+    for (i=0; i<num; i++) {
+        MPI_Offset buflen;
+        for (buflen=1, j=0; j<varp->ndims; j++) {
+            if (_counts[i][j] < 0) { /* any negative counts[][] is illegal */
+                DEBUG_ASSIGN_ERROR(status, NC_ENEGATIVECNT)
+                goto err_check;
+            }
+            buflen *= _counts[i][j];
+        }
+        if (buflen == 0) continue;
+        status = ncmpii_igetput_varm(ncp, varp, starts[i], _counts[i], NULL,
+                                     NULL, bufp, buflen, ptype, &req_id,
+                                     rw_flag, 0, isSameGroup);
+        if (status != NC_NOERR) goto err_check;
+
+        /* use isSamegroup so we end up with one nonblocking request (only the
+         * first request gets a request ID back, the rest reuse the same ID.
+         * This single ID represents num nonblocking requests */
+        isSameGroup=1;
+        bufp += buflen * el_size;
+    }
+
+err_check:
+    if (_counts != NULL && _counts != counts) {
+        NCI_Free(_counts[0]);
+        NCI_Free(_counts);
+    }
+
+    if (ncp->safe_mode == 1 && io_method == COLL_IO) {
+        int mpireturn;
+        TRACE_COMM(MPI_Allreduce)(&status, &min_st, 1, MPI_INT, MPI_MIN,
+                                  ncp->nciop->comm);
+        if (mpireturn != MPI_SUCCESS)
+            return ncmpii_handle_error(mpireturn, "MPI_Allreduce"); 
+
+        if (min_st != NC_NOERR) {
+            if (req_id != NC_REQ_NULL) /* cancel pending nonblocking request */
+                ncmpii_cancel(ncp, 1, &req_id, &st);
+            if (free_cbuf) NCI_Free(cbuf);
+            return status;
+        }
+    }
+
+    if (io_method == INDEP_IO && status != NC_NOERR) {
+        if (req_id != NC_REQ_NULL) /* cancel pending nonblocking request */
+            ncmpii_cancel(ncp, 1, &req_id, &st);
+        if (free_cbuf) NCI_Free(cbuf);
+        return status;
+    }
+
+    num = 1;
+    if (status != NC_NOERR)
+        /* This can only be reached for COLL_IO and safe_mode == 0.
+           Set num=0 just so this process can participate the collective
+           calls in wait_all */
+        num = 0;
+
+    err = ncmpii_wait(ncp, io_method, num, &req_id, &st);
+
+    /* unpack to user buf, if buftype is noncontiguous */
+    if (status == NC_NOERR && rw_flag == READ_REQ && free_cbuf) {
+        position = 0;
+        MPI_Unpack(cbuf, (int)packsize, &position, buf, (int)bufcount, buftype,
+                   MPI_COMM_SELF);
+    }
+
+    /* return the first error, if there is one */
+    if (status == NC_NOERR) status = err;
+    if (status == NC_NOERR) status = st;
+
+    if (free_cbuf) NCI_Free(cbuf);
+
+    return status;
+}
diff --git a/src/libcxx/Makefile.in b/src/libcxx/Makefile.in
new file mode 100755
index 0000000..3744491
--- /dev/null
+++ b/src/libcxx/Makefile.in
@@ -0,0 +1,83 @@
+#
+# Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2285 2015-12-30 20:48:25Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+# generated by configure, so it's in the build dir, not srcdirr
+include ../../macros.make
+
+# For VPATH build:
+# Add ../lib into search path because ../lib/pnetcdf.h is created at the
+# configure time and included by all C++ source files.
+INCLUDES = -I../lib
+
+CXX_HEADER = pnetcdf
+
+LIBRARY = ../lib/libpnetcdf.a
+
+# Note the file order is important
+LIBS_HEADERS = ncmpi_notyet.h \
+               ncmpiCheck.h \
+               ncmpiType.h \
+               ncmpiAtt.h \
+               ncmpiEnumType.h \
+               ncmpiGroupAtt.h \
+               ncmpiGroup.h \
+               ncmpiByte.h \
+               ncmpiChar.h \
+               ncmpiCompoundType.h \
+               ncmpiDouble.h \
+               ncmpiFloat.h \
+               ncmpiInt.h \
+               ncmpiInt64.h \
+               ncmpiOpaqueType.h \
+               ncmpiShort.h \
+               ncmpiUbyte.h \
+               ncmpiUint.h \
+               ncmpiUint64.h \
+               ncmpiUshort.h \
+               ncmpiException.h \
+               ncmpiDim.h \
+               ncmpiFile.h \
+               ncmpiVarAtt.h \
+               ncmpiVar.h \
+               ncmpiVlenType.h
+
+LIB_SRCS   = $(LIBS_HEADERS:.h=.cpp)
+
+LIB_OBJS   = $(LIBS_HEADERS:.h=.o)
+
+PACKING_LIST = $(LIBS_HEADERS) $(LIB_SRCS) pnetcdf.in \
+               Makefile.in depend
+
+GARBAGE      = $(LIB_OBJS) $(CXX_HEADER)
+DIST_GARBAGE =
+
+all: $(CXX_HEADER) $(LIBRARY)
+
+library $(LIBRARY): $(LIB_OBJS)
+	$(AR) $(ARFLAGS) $(LIBRARY) $(LIB_OBJS)
+	$(RANLIB) $(LIBRARY)
+
+$(CXX_HEADER): $(LIBS_HEADERS)
+	cp -f $(srcdir)/pnetcdf.in $(CXX_HEADER)
+	set -e; for i in $(LIBS_HEADERS); do ( \
+	sed -e '/#ifndef/d' -e '/#define/d' -e '/#endif/d' -e '/#include/d' $(srcdir)/$$i >> $(CXX_HEADER); \
+	) ; done
+
+install:
+	$(INSTALL) -d -m 755 $(INCDIR)
+	$(INSTALL_DATA) $(CXX_HEADER) $(INCDIR)
+
+uninstall:
+	$(RM) -f $(INCDIR)/$(CXX_HEADER)
+
+include $(srcdir)/depend
+include $(srcdir)/../../rules.make
+
diff --git a/src/libcxx/depend b/src/libcxx/depend
new file mode 100644
index 0000000..d2e244f
--- /dev/null
+++ b/src/libcxx/depend
@@ -0,0 +1,67 @@
+ncmpi_notyet.o: ncmpi_notyet.cpp ../lib/pnetcdf.h ncmpi_notyet.h
+ncmpiCheck.o: ncmpiCheck.cpp ../lib/pnetcdf.h ncmpiException.h
+ncmpiType.o: ncmpiType.cpp ncmpiType.h ../lib/pnetcdf.h \
+  ncmpiGroup.h ncmpiEnumType.h ncmpiCheck.h ncmpi_notyet.h \
+  ncmpiGroupAtt.h ncmpiAtt.h ncmpiException.h
+ncmpiAtt.o: ncmpiAtt.cpp ncmpiAtt.h ncmpiType.h ../lib/pnetcdf.h \
+  ncmpiException.h ncmpiGroup.h ncmpiEnumType.h ncmpiCheck.h \
+  ncmpi_notyet.h ncmpiGroupAtt.h
+ncmpiEnumType.o: ncmpiEnumType.cpp ncmpiEnumType.h ncmpiType.h \
+  ../lib/pnetcdf.h ncmpiCheck.h ncmpi_notyet.h \
+  ncmpiGroup.h ncmpiGroupAtt.h ncmpiAtt.h ncmpiException.h ncmpiByte.h \
+  ncmpiUbyte.h ncmpiChar.h ncmpiShort.h ncmpiUshort.h ncmpiInt.h \
+  ncmpiUint.h ncmpiInt64.h ncmpiUint64.h ncmpiFloat.h ncmpiDouble.h
+ncmpiGroupAtt.o: ncmpiGroupAtt.cpp ncmpiGroupAtt.h ncmpiAtt.h ncmpiType.h \
+  ../lib/pnetcdf.h ncmpiException.h ncmpiGroup.h \
+  ncmpiEnumType.h ncmpiCheck.h ncmpi_notyet.h
+ncmpiGroup.o: ncmpiGroup.cpp ncmpiGroup.h ncmpiType.h ../lib/pnetcdf.h \
+  ncmpiEnumType.h ncmpiCheck.h ncmpi_notyet.h ncmpiGroupAtt.h ncmpiAtt.h \
+  ncmpiException.h ncmpiVar.h ncmpiVarAtt.h ncmpiByte.h ncmpiUbyte.h \
+  ncmpiChar.h ncmpiShort.h ncmpiUshort.h ncmpiInt.h ncmpiUint.h \
+  ncmpiInt64.h ncmpiUint64.h ncmpiFloat.h ncmpiDouble.h \
+  ncmpiDim.h ncmpiVlenType.h ncmpiCompoundType.h ncmpiOpaqueType.h \
+  ncmpiException.h
+ncmpiByte.o: ncmpiByte.cpp ncmpiByte.h ncmpiType.h ../lib/pnetcdf.h
+ncmpiChar.o: ncmpiChar.cpp ncmpiChar.h ncmpiType.h ../lib/pnetcdf.h
+ncmpiCompoundType.o: ncmpiCompoundType.cpp ncmpiGroup.h ncmpiType.h \
+  ../lib/pnetcdf.h ncmpiEnumType.h ncmpiCheck.h \
+  ncmpi_notyet.h ncmpiGroupAtt.h ncmpiAtt.h ncmpiException.h \
+  ncmpiCompoundType.h ncmpiByte.h ncmpiUbyte.h ncmpiChar.h ncmpiShort.h \
+  ncmpiUshort.h ncmpiInt.h ncmpiUint.h ncmpiInt64.h ncmpiUint64.h \
+  ncmpiFloat.h ncmpiDouble.h
+ncmpiDouble.o: ncmpiDouble.cpp ncmpiDouble.h ncmpiType.h ../lib/pnetcdf.h
+ncmpiFloat.o: ncmpiFloat.cpp ncmpiFloat.h ncmpiType.h ../lib/pnetcdf.h
+ncmpiInt.o: ncmpiInt.cpp ncmpiInt.h ncmpiType.h ../lib/pnetcdf.h
+ncmpiInt64.o: ncmpiInt64.cpp ncmpiInt64.h ncmpiType.h ../lib/pnetcdf.h
+ncmpiOpaqueType.o: ncmpiOpaqueType.cpp ncmpiOpaqueType.h ncmpiType.h \
+  ../lib/pnetcdf.h ncmpiGroup.h ncmpiEnumType.h \
+  ncmpiCheck.h ncmpi_notyet.h ncmpiGroupAtt.h ncmpiAtt.h ncmpiException.h
+ncmpiShort.o: ncmpiShort.cpp ncmpiShort.h ncmpiType.h ../lib/pnetcdf.h
+ncmpiUbyte.o: ncmpiUbyte.cpp ncmpiUbyte.h ncmpiType.h ../lib/pnetcdf.h
+ncmpiUint.o: ncmpiUint.cpp ncmpiUint.h ncmpiType.h ../lib/pnetcdf.h
+ncmpiUint64.o: ncmpiUint64.cpp ncmpiUint64.h ncmpiType.h ../lib/pnetcdf.h
+ncmpiUshort.o: ncmpiUshort.cpp ncmpiUshort.h ncmpiType.h ../lib/pnetcdf.h
+ncmpiException.o: ncmpiException.cpp ncmpiException.h ../lib/pnetcdf.h
+ncmpiDim.o: ncmpiDim.cpp ncmpiDim.h ncmpiGroup.h ncmpiType.h \
+  ../lib/pnetcdf.h ncmpiEnumType.h ncmpiCheck.h ncmpi_notyet.h \
+  ncmpiGroupAtt.h ncmpiAtt.h ncmpiException.h
+ncmpiFile.o: ncmpiFile.cpp ncmpiFile.h ncmpiGroup.h ncmpiType.h \
+  ../lib/pnetcdf.h ncmpiEnumType.h ncmpiCheck.h \
+  ncmpi_notyet.h ncmpiGroupAtt.h ncmpiAtt.h ncmpiException.h ncmpiByte.h
+ncmpiVarAtt.o: ncmpiVarAtt.cpp ncmpiVar.h ../lib/pnetcdf.h \
+  ncmpiVarAtt.h ncmpiAtt.h ncmpiType.h ncmpiException.h ncmpiGroup.h \
+  ncmpiEnumType.h ncmpiCheck.h ncmpi_notyet.h ncmpiGroupAtt.h ncmpiByte.h \
+  ncmpiUbyte.h ncmpiChar.h ncmpiShort.h ncmpiUshort.h ncmpiInt.h \
+  ncmpiUint.h ncmpiInt64.h ncmpiUint64.h ncmpiFloat.h ncmpiDouble.h
+ncmpiVar.o: ncmpiVar.cpp ncmpiVarAtt.h ncmpiAtt.h ncmpiType.h \
+  ../lib/pnetcdf.h ncmpiException.h ncmpiDim.h \
+  ncmpiVar.h ncmpiGroup.h ncmpiEnumType.h ncmpiCheck.h ncmpi_notyet.h \
+  ncmpiGroupAtt.h ncmpiByte.h ncmpiUbyte.h ncmpiChar.h ncmpiShort.h \
+  ncmpiUshort.h ncmpiInt.h ncmpiUint.h ncmpiInt64.h ncmpiUint64.h \
+  ncmpiFloat.h ncmpiDouble.h
+ncmpiVlenType.o: ncmpiVlenType.cpp ncmpiVlenType.h ncmpiType.h \
+  ../lib/pnetcdf.h ncmpiGroup.h ncmpiEnumType.h \
+  ncmpiCheck.h ncmpi_notyet.h ncmpiGroupAtt.h ncmpiAtt.h ncmpiException.h \
+  ncmpiByte.h ncmpiUbyte.h ncmpiChar.h ncmpiShort.h ncmpiUshort.h \
+  ncmpiInt.h ncmpiUint.h ncmpiInt64.h ncmpiUint64.h ncmpiFloat.h \
+  ncmpiDouble.h
diff --git a/src/libcxx/ncmpiAtt.cpp b/src/libcxx/ncmpiAtt.cpp
new file mode 100644
index 0000000..ec207f3
--- /dev/null
+++ b/src/libcxx/ncmpiAtt.cpp
@@ -0,0 +1,224 @@
+#include "ncmpiAtt.h"
+#include "ncmpiGroup.h"
+#include "ncmpiCheck.h"
+#include <vector>
+#include <assert.h>
+
+using namespace std;
+using namespace PnetCDF;
+  
+
+// destructor  (defined even though it is virtual)
+NcmpiAtt::~NcmpiAtt() {}
+
+// assignment operator
+NcmpiAtt& NcmpiAtt::operator=(const NcmpiAtt& rhs)
+{
+  nullObject = rhs.nullObject;
+  myName = rhs.myName;
+  groupId = rhs.groupId;
+  varId =rhs.varId;
+  return *this;
+}
+
+// Constructor generates a null object.
+NcmpiAtt::NcmpiAtt() : 
+  nullObject(true) 
+{}
+
+// Constructor for non-null instances.
+NcmpiAtt::NcmpiAtt(bool nullObject): 
+  nullObject(nullObject)
+{}
+
+// The copy constructor.
+NcmpiAtt::NcmpiAtt(const NcmpiAtt& rhs) :
+  nullObject(rhs.nullObject),
+  myName(rhs.myName),
+  groupId(rhs.groupId),
+   varId(rhs.varId)
+{}
+
+
+// equivalence operator
+bool NcmpiAtt::operator==(const NcmpiAtt & rhs) const
+{
+  if(nullObject) 
+    return nullObject == rhs.nullObject;
+  else
+    return myName == rhs.myName && groupId == rhs.groupId && varId == rhs.varId;
+}  
+
+//  !=  operator
+bool NcmpiAtt::operator!=(const NcmpiAtt & rhs) const
+{
+  return !(*this == rhs);
+}  
+
+// Gets parent group.
+PnetCDF::NcmpiGroup  NcmpiAtt::getParentGroup() const {
+  return PnetCDF::NcmpiGroup(groupId);
+}
+      
+
+// Returns the attribute type.
+NcmpiType  NcmpiAtt::getType() const{
+  // get the identifier for the netCDF type of this attribute.
+  nc_type xtypep;
+  ncmpiCheck(ncmpi_inq_atttype(groupId,varId,myName.c_str(),&xtypep),__FILE__,__LINE__);
+  if(xtypep <= 12)
+    // This is an atomic type
+    return NcmpiType(xtypep);
+  else
+    // this is a user-defined type
+    {
+      // now get the set of NcmpiType objects in this file.
+      multimap<string,NcmpiType> typeMap(getParentGroup().getTypes(NcmpiGroup::ParentsAndCurrent));
+      multimap<string,NcmpiType>::iterator iter;
+      // identify the Nctype object with the same id as this attribute.
+      for (iter=typeMap.begin(); iter!= typeMap.end();iter++) {
+	if(iter->second.getId() == xtypep) return iter->second;
+      }
+      // return a null object, as no type was identified.
+      return NcmpiType();
+    }
+}
+
+// Gets attribute length.
+MPI_Offset  NcmpiAtt::getAttLength() const{
+  MPI_Offset lenp;
+  ncmpiCheck(ncmpi_inq_attlen(groupId, varId, myName.c_str(), &lenp),__FILE__,__LINE__);
+  return lenp;
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(string& dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+
+  MPI_Offset att_len=getAttLength();
+  char* tmpValues;
+  assert(att_len == (MPI_Offset)(size_t)att_len);
+  tmpValues = (char *) malloc((size_t)att_len + 1);  /* + 1 for trailing null */
+
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),tmpValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_text(groupId,varId,myName.c_str(),tmpValues),__FILE__,__LINE__);
+  dataValues=string(tmpValues, (size_t)att_len);
+  free(tmpValues);
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(char* dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_text(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(unsigned char* dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_uchar(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(signed char* dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_schar(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(short* dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_short(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(int* dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_int(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(long* dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_long(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(float* dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_float(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(double* dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_double(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(unsigned short* dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_ushort(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(unsigned int* dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_uint(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(long long* dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_longlong(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(unsigned long long* dataValues) const {
+  NcmpiType::ncmpiType typeClass(getType().getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_get_att_ulonglong(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
+// Gets a netCDF variable attribute.
+void NcmpiAtt::getValues(void* dataValues) const {
+  ncmpiCheck(ncmpi_get_att(groupId,varId,myName.c_str(),dataValues),__FILE__,__LINE__);
+}
+
diff --git a/src/libcxx/ncmpiAtt.h b/src/libcxx/ncmpiAtt.h
new file mode 100644
index 0000000..423e1dd
--- /dev/null
+++ b/src/libcxx/ncmpiAtt.h
@@ -0,0 +1,121 @@
+#include "ncmpiType.h"
+#include "ncmpiException.h"
+#include <string>
+#include <typeinfo>
+
+#ifndef NcmpiAttClass
+#define NcmpiAttClass
+
+namespace PnetCDF
+{
+
+  /*! Abstract base class represents inherited by ncmpiVarAtt and ncmpiGroupAtt. */
+  class NcmpiAtt
+  {
+  public:
+    
+    /*! destructor */
+    virtual ~NcmpiAtt()=0;
+
+    /*! Constructor generates a \ref isNull "null object". */
+    NcmpiAtt ();
+    
+    /*! Constructor for non-null instances. */
+    NcmpiAtt(bool nullObject); 
+
+    /*! The copy constructor. */
+    NcmpiAtt(const NcmpiAtt& rhs);
+
+    /*! Get the attribute name. */
+    std::string getName() const {return myName;}
+
+    /*! Gets attribute length. */
+    MPI_Offset  getAttLength() const;
+
+    /*! Returns the attribute type. */
+    NcmpiType  getType() const;
+
+    /*! Gets parent group. */
+    NcmpiGroup  getParentGroup() const;
+      
+    /*! equivalence operator */
+    bool operator== (const NcmpiAtt& rhs) const;
+      
+    /*!  != operator */
+    bool operator!=(const NcmpiAtt& rhs) const;     
+
+    /*! \overload
+     */ 
+    void getValues(char* dataValues) const;
+    /*! \overload
+     */ 
+    void getValues(unsigned char* dataValues) const;
+    /*! \overload
+     */ 
+    void getValues(signed char* dataValues) const;
+    /*! \overload
+     */ 
+    void getValues(short* dataValues) const;
+    /*! \overload
+     */ 
+    void getValues(int* dataValues) const;
+    /*! \overload
+     */ 
+    void getValues(long* dataValues) const;
+    /*! \overload
+     */ 
+    void getValues(float* dataValues) const;
+    /*! \overload
+     */ 
+    void getValues(double* dataValues) const;
+    /*! \overload
+     */ 
+    void getValues(unsigned short* dataValues) const;
+    /*! \overload
+     */ 
+    void getValues(unsigned int* dataValues) const;
+    /*! \overload
+     */ 
+    void getValues(long long* dataValues) const;
+    /*! \overload
+     */ 
+    void getValues(unsigned long long* dataValues) const;
+    /*! \overload
+     */ 
+    void getValues(char** dataValues) const;
+
+    /*! \overload
+      (The string variable does not need preallocating.)
+     */ 
+    void getValues(std::string& dataValues) const;
+
+    /*! 
+      Gets a netCDF attribute.
+      The user must ensure that the variable "dataValues" has sufficient space to hold the attribute.
+      \param  dataValues On return contains the value of the attribute. 
+      If the type of data values differs from the netCDF variable type, type conversion will occur. 
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getValues(void* dataValues) const;
+
+    /*! Returns true if this object is null (i.e. it has no contents); otherwise returns false. */
+    bool isNull() const {return nullObject;}
+
+  protected:
+    /*! assignment operator */
+    NcmpiAtt& operator= (const NcmpiAtt& rhs);
+      
+    bool nullObject;
+
+    std::string myName;
+    
+    int groupId;
+      
+    int varId;
+    
+  };
+  
+}
+
+#endif
diff --git a/src/libcxx/ncmpiByte.cpp b/src/libcxx/ncmpiByte.cpp
new file mode 100644
index 0000000..8d057f8
--- /dev/null
+++ b/src/libcxx/ncmpiByte.cpp
@@ -0,0 +1,24 @@
+#include "ncmpiByte.h"
+#include <pnetcdf.h>
+using namespace PnetCDF;
+
+// create an instance of NcmpiByte  called PnetCDF::ncmpiByte
+namespace PnetCDF {
+  NcmpiByte ncmpiByte;
+}
+
+// constructor
+NcmpiByte::NcmpiByte() : NcmpiType(NC_BYTE){
+}
+
+NcmpiByte::~NcmpiByte() {
+}
+
+int NcmpiByte::sizeoff(){char a;return sizeof(a);};
+
+
+// equivalence operator
+bool NcmpiByte::operator==(const NcmpiByte & rhs)    {
+  // simply check the netCDF id.
+  return myId == rhs.myId;
+}  
diff --git a/src/libcxx/ncmpiByte.h b/src/libcxx/ncmpiByte.h
new file mode 100644
index 0000000..8c973ac
--- /dev/null
+++ b/src/libcxx/ncmpiByte.h
@@ -0,0 +1,30 @@
+#include "ncmpiType.h"
+
+#ifndef NcmpiByteClass
+#define NcmpiByteClass
+
+namespace PnetCDF
+{
+  
+  /*! Class represents a netCDF atomic Byte type. */
+  class NcmpiByte : public NcmpiType
+  {
+  public: 
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiByte & rhs);
+
+    /*! storage size */
+    int sizeoff();
+
+    ~NcmpiByte();
+    
+    /*! Constructor */
+    NcmpiByte();
+  };
+
+  /*! A global instance  of the NcmpiByte class within the netCDF namespace. */
+  extern NcmpiByte ncmpiByte;
+
+}
+#endif
diff --git a/src/libcxx/ncmpiChar.cpp b/src/libcxx/ncmpiChar.cpp
new file mode 100644
index 0000000..a4f7cc0
--- /dev/null
+++ b/src/libcxx/ncmpiChar.cpp
@@ -0,0 +1,22 @@
+#include "ncmpiChar.h"
+#include <pnetcdf.h>
+using namespace PnetCDF;
+
+// create an instance of NcmpiChar  called PnetCDF::ncmpiChar
+namespace PnetCDF {
+  NcmpiChar ncmpiChar;
+}
+
+// constructor
+NcmpiChar::NcmpiChar() : NcmpiType(NC_CHAR){
+}
+
+NcmpiChar::~NcmpiChar() {
+}
+
+
+// equivalence operator
+bool NcmpiChar::operator==(const NcmpiChar & rhs)    {
+  // simply check the netCDF id.
+  return myId == rhs.myId;
+}  
diff --git a/src/libcxx/ncmpiChar.h b/src/libcxx/ncmpiChar.h
new file mode 100644
index 0000000..9b8ed0f
--- /dev/null
+++ b/src/libcxx/ncmpiChar.h
@@ -0,0 +1,27 @@
+#include "ncmpiType.h"
+
+#ifndef NcmpiCharClass
+#define NcmpiCharClass
+
+namespace PnetCDF
+{
+  
+  /*! Class represents a netCDF atomic Char type. */
+  class NcmpiChar : public NcmpiType
+  {
+  public: 
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiChar & rhs);
+    
+    ~NcmpiChar();
+    
+    /*! Constructor */
+    NcmpiChar();
+  };
+
+  /*! A global instance  of the NcmpiChar class within the netCDF namespace. */
+  extern NcmpiChar ncmpiChar;
+
+}
+#endif
diff --git a/src/libcxx/ncmpiCheck.cpp b/src/libcxx/ncmpiCheck.cpp
new file mode 100644
index 0000000..c9d3793
--- /dev/null
+++ b/src/libcxx/ncmpiCheck.cpp
@@ -0,0 +1,94 @@
+#include <cstring>
+#include <pnetcdf.h>
+#include "ncmpiException.h"
+using namespace std;
+using namespace PnetCDF::exceptions;
+
+//  C++ API for netCDF4.
+namespace PnetCDF
+{
+  // function checks error code and if necessary throws appropriate exception.
+  void ncmpiCheck(int retCode, const char* file, int line){
+    if (retCode==NC_NOERR)
+      return;
+
+    const char* msg = 0;
+    if (NC_ISSYSERR(retCode)){
+      msg = std::strerror(retCode);
+      msg = msg ? msg : "Unknown system error";
+    }else{
+      msg = ncmpi_strerror(retCode);
+    }
+
+    switch(retCode) {
+    case NC_EBADID          : throw NcBadId(msg,file,line);
+    case NC_ENFILE          : throw NcNFile(msg,file,line);
+    case NC_EEXIST          : throw NcExist(msg,file,line);
+    case NC_EINVAL          : throw NcInvalidArg(msg,file,line);
+    case NC_EPERM           : throw NcInvalidWrite(msg,file,line);
+    case NC_ENOTINDEFINE    : throw NcNotInDefineMode(msg,file,line);
+    case NC_EINDEFINE       : throw NcInDefineMode(msg,file,line);
+    case NC_EINVALCOORDS    : throw NcInvalidCoords(msg,file,line);
+    case NC_EMAXDIMS        : throw NcMaxDims(msg,file,line);
+    case NC_ENAMEINUSE      : throw NcNameInUse(msg,file,line);
+    case NC_ENOTATT         : throw NcNotAtt(msg,file,line);
+    case NC_EMAXATTS        : throw NcMaxAtts(msg,file,line);
+    case NC_EBADTYPE        : throw NcBadType(msg,file,line);
+    case NC_EBADDIM         : throw NcBadDim(msg,file,line);
+    case NC_EUNLIMPOS       : throw NcUnlimPos(msg,file,line);
+    case NC_EMAXVARS        : throw NcMaxVars(msg,file,line);
+    case NC_ENOTVAR         : throw NcNotVar(msg,file,line);
+    case NC_EGLOBAL         : throw NcGlobal(msg,file,line);
+    case NC_ENOTNC          : throw NcNotNCF(msg,file,line);
+    case NC_ESTS            : throw NcSts(msg,file,line);
+    case NC_EMAXNAME        : throw NcMaxName(msg,file,line);
+    case NC_EUNLIMIT        : throw NcUnlimit(msg,file,line);
+    case NC_ENORECVARS      : throw NcNoRecVars(msg,file,line);
+    case NC_ECHAR           : throw NcmpiChar(msg,file,line);
+    case NC_EEDGE           : throw NcEdge(msg,file,line);
+    case NC_ESTRIDE         : throw NcStride(msg,file,line);
+    case NC_EBADNAME        : throw NcBadName(msg,file,line);
+    case NC_ERANGE          : throw NcRange(msg,file,line);
+    case NC_ENOMEM          : throw NcNoMem(msg,file,line);
+    case NC_EVARSIZE        : throw NcmpiVarSize(msg,file,line);
+    case NC_EDIMSIZE        : throw NcmpiDimSize(msg,file,line);
+    case NC_ETRUNC          : throw NcTrunc(msg,file,line);
+
+      // The following are specific netCDF4 errors.
+    case NC_EHDFERR         : throw NcHdfErr(msg,file,line);
+    case NC_ECANTREAD       : throw NcCantRead(msg,file,line);
+    case NC_ECANTWRITE      : throw NcCantWrite(msg,file,line);
+    case NC_ECANTCREATE     : throw NcCantCreate(msg,file,line);
+    case NC_EFILEMETA       : throw NcmpiFileMeta(msg,file,line);
+    case NC_EDIMMETA        : throw NcmpiDimMeta(msg,file,line);
+    case NC_EATTMETA        : throw NcmpiAttMeta(msg,file,line);
+    case NC_EVARMETA        : throw NcmpiVarMeta(msg,file,line);
+    case NC_ENOCOMPOUND     : throw NcNoCompound(msg,file,line);
+    case NC_EATTEXISTS      : throw NcmpiAttExists(msg,file,line);
+    case NC_ENOTNC4         : throw NcNotNc4(msg,file,line);
+    case NC_ESTRICTNC3      : throw NcStrictNc3(msg,file,line);
+    case NC_EBADGRPID       : throw NcBadGroupId(msg,file,line);
+    case NC_EBADTYPID       : throw NcBadTypeId(msg,file,line);                       // netcdf.h file inconsistent with documentation!!
+    case NC_EBADFIELD       : throw NcBadFieldId(msg,file,line);                     // netcdf.h file inconsistent with documentation!!
+      //  case NC_EUNKNAME        : throw NcUnkownName("Cannot find the field id.",file,line);   // netcdf.h file inconsistent with documentation!!
+
+    case NC_ENOGRP          : throw NcEnoGrp(msg,file,line);
+    case NC_ELATEDEF        : throw NcElateDef(msg,file,line);
+
+    default:
+      throw NcmpiException(retCode, msg, file, line);
+    }
+  }
+
+  void ncmpiCheckDefineMode(int ncid)
+  {
+    int status = ncmpi_redef(ncid);
+    if (status != NC_EINDEFINE) ncmpiCheck(status, __FILE__, __LINE__);
+  }
+
+  void ncmpiCheckDataMode(int ncid)
+  {
+    int status = ncmpi_enddef(ncid);
+    if (status != NC_ENOTINDEFINE) ncmpiCheck(status, __FILE__, __LINE__);
+  }
+}
diff --git a/src/libcxx/ncmpiCheck.h b/src/libcxx/ncmpiCheck.h
new file mode 100644
index 0000000..3cd09c9
--- /dev/null
+++ b/src/libcxx/ncmpiCheck.h
@@ -0,0 +1,35 @@
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef NcmpiCheckFunction
+#define NcmpiCheckFunction
+
+namespace PnetCDF
+{
+  /*! 
+    Function checks error code and if necessary throws an exception.
+    \param retCode Integer value returned by %netCDF C-routines.
+    \param file    The name of the file from which this call originates.
+    \param line    The line number in the file from which this call originates.
+  */
+  void ncmpiCheck(int retCode, const char* file, int line);
+
+  /*! 
+    Function checks if the file (group) is in define mode.
+    If not, it places it in the define mode.
+    While this is automatically done by the underlying C API
+    for netCDF-4 files, the netCDF-3 files still need this call.
+  */
+  void ncmpiCheckDefineMode(int ncid);
+
+  /*! 
+    Function checks if the file (group) is in data mode.
+    If not, it places it in the data mode.
+    While this is automatically done by the underlying C API
+    for netCDF-4 files, the netCDF-3 files still need this call.
+  */
+  void ncmpiCheckDataMode(int ncid);
+
+};
+
+#endif
diff --git a/src/libcxx/ncmpiCompoundType.cpp b/src/libcxx/ncmpiCompoundType.cpp
new file mode 100644
index 0000000..99cd96b
--- /dev/null
+++ b/src/libcxx/ncmpiCompoundType.cpp
@@ -0,0 +1,156 @@
+#include "ncmpiGroup.h"
+#include "ncmpiCheck.h"
+#include "ncmpiCompoundType.h"
+#include "ncmpiByte.h"
+#include "ncmpiUbyte.h"
+#include "ncmpiChar.h"
+#include "ncmpiShort.h"
+#include "ncmpiUshort.h"
+#include "ncmpiInt.h"
+#include "ncmpiUint.h"
+#include "ncmpiInt64.h"
+#include "ncmpiUint64.h"
+#include "ncmpiFloat.h"
+#include "ncmpiDouble.h"
+#include "ncmpiException.h"
+
+using namespace std;
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+// Class represents a netCDF variable.
+
+// assignment operator
+NcmpiCompoundType& NcmpiCompoundType::operator=(const NcmpiCompoundType& rhs)
+{
+  NcmpiType::operator=(rhs);    // assign base class parts
+  return *this;
+}
+
+// assignment operator
+NcmpiCompoundType& NcmpiCompoundType::operator=(const NcmpiType& rhs)
+{
+  if (&rhs != this) {
+    // check the rhs is the base of a Compound type
+    if(getTypeClass() != ncmpi_COMPOUND) 	throw NcmpiException("The NcmpiType object must be the base of a Compound type.",__FILE__,__LINE__);
+    // assign base class parts
+    NcmpiType::operator=(rhs);
+  }
+  return *this;
+}
+
+// The copy constructor.
+NcmpiCompoundType::NcmpiCompoundType(const NcmpiCompoundType& rhs): 
+  NcmpiType(rhs)
+{
+}
+
+
+// equivalence operator
+bool NcmpiCompoundType::operator==(const NcmpiCompoundType& rhs)
+{
+  if(nullObject) 
+    return nullObject == rhs.nullObject;
+  else
+    return myId ==rhs.myId && groupId == rhs.groupId;
+}  
+  
+// Constructor generates a null object.
+NcmpiCompoundType::NcmpiCompoundType() : 
+  NcmpiType()   // invoke base class constructor
+{}
+  
+// constructor
+NcmpiCompoundType::NcmpiCompoundType(const NcmpiGroup& grp, const string& name): 
+  NcmpiType(grp,name)
+{
+}
+
+// constructor
+// The copy constructor.
+NcmpiCompoundType::NcmpiCompoundType(const NcmpiType& rhs): 
+  NcmpiType()
+{
+  // assign base class parts
+  NcmpiType::operator=(rhs);
+}
+  
+//  Inserts a named field.
+void NcmpiCompoundType::addMember(const string& memberName, const NcmpiType& newMemberType,MPI_Offset offset)
+{
+  ncmpiCheck(ncmpi_insert_compound(groupId,myId,const_cast<char*>(memberName.c_str()),offset,newMemberType.getId()),__FILE__,__LINE__);
+}
+
+
+
+//  Inserts a named array field.
+void NcmpiCompoundType::addMember(const string& memberName, const NcmpiType& newMemberType, MPI_Offset offset, const vector<int>& shape)
+{
+  if (!shape.empty())
+    ncmpiCheck(ncmpi_insert_array_compound(groupId, myId,const_cast<char*>(memberName.c_str()), offset, newMemberType.getId(), shape.size(), const_cast<int*>(&shape[0])),__FILE__,__LINE__);
+  else
+    addMember(memberName, newMemberType, offset);
+}
+
+
+
+// Returns number of members in this NcmpiCompoundType object.
+MPI_Offset  NcmpiCompoundType::getMemberCount() const
+{
+  MPI_Offset nfieldsp;
+  ncmpiCheck(ncmpi_inq_compound_nfields(groupId,myId,&nfieldsp),__FILE__,__LINE__);
+  return nfieldsp;
+}
+  
+
+// Returns a NcmpiType object for a single member. */
+NcmpiType NcmpiCompoundType::getMember(int memberIndex) const 
+{
+  nc_type fieldtypeidp;
+  ncmpiCheck(ncmpi_inq_compound_fieldtype(groupId,myId,memberIndex,&fieldtypeidp),__FILE__,__LINE__);
+  switch (fieldtypeidp) {
+  case NC_BYTE    : return ncmpiByte;
+  case NC_UBYTE   : return ncmpiUbyte;
+  case NC_CHAR    : return ncmpiChar;
+  case NC_SHORT   : return ncmpiShort;
+  case NC_USHORT  : return ncmpiUshort;
+  case NC_INT     : return ncmpiInt;
+  case NC_UINT    : return ncmpiUint;  
+  case NC_INT64   : return ncmpiInt64; 
+  case NC_UINT64  : return ncmpiUint64;
+  case NC_FLOAT   : return ncmpiFloat;
+  case NC_DOUBLE  : return ncmpiDouble;
+  default:  
+    // this is a user defined type
+    return NcmpiType(getParentGroup(),fieldtypeidp);
+  }
+}
+
+  
+// Returns the number of dimensions of a member with the given index.
+int NcmpiCompoundType::getMemberDimCount(int memberIndex) const 
+{
+  int ndimsp;
+  ncmpiCheck(ncmpi_inq_compound_fieldndims(groupId,myId,memberIndex, &ndimsp),__FILE__,__LINE__);
+  return ndimsp;
+}
+  
+  
+// Returns the shape of the given member.
+vector<int> NcmpiCompoundType::getMemberShape(int memberIndex) const 
+{
+  vector<int> dim_size;
+  dim_size.resize(getMemberDimCount(memberIndex));
+  if(!dim_size.empty())
+    ncmpiCheck(ncmpi_inq_compound_fielddim_sizes(groupId,myId,memberIndex,&dim_size[0]),__FILE__,__LINE__);
+  return dim_size;
+}
+ 
+
+// Returns the offset of the member with given index.
+MPI_Offset NcmpiCompoundType::getMemberOffset(const int index) const
+{
+  MPI_Offset offsetp;
+  ncmpiCheck(ncmpi_inq_compound_fieldoffset(groupId,myId, index,&offsetp),__FILE__,__LINE__);
+  return offsetp;
+}
diff --git a/src/libcxx/ncmpiCompoundType.h b/src/libcxx/ncmpiCompoundType.h
new file mode 100644
index 0000000..9ff9cd4
--- /dev/null
+++ b/src/libcxx/ncmpiCompoundType.h
@@ -0,0 +1,107 @@
+#include <string>
+#include <vector>
+#include "ncmpiType.h"
+
+#ifndef NcmpiCompoundTypeClass
+#define NcmpiCompoundTypeClass
+
+
+namespace PnetCDF
+{
+  class NcmpiGroup;  // forward declaration.
+
+  /*!
+    Class represents a netCDF compound type
+  */
+  class NcmpiCompoundType : public NcmpiType
+  {
+  public:
+
+    /*! Constructor generates a \ref isNull "null object". */
+    NcmpiCompoundType();
+
+    /*!
+      Constructor.
+      The compound Type must already exist in the netCDF file. New netCDF compound types can be
+      added using NcmpiGroup::addNcmpiCompoundType();
+      \param grp        The parent group where this type is defined.
+      \param name       Name of new type.
+    */
+    NcmpiCompoundType(const NcmpiGroup& grp, const std::string& name);
+
+    /*!
+      Constructor.
+      Constructs from the base type NcmpiType object. Will throw an exception if the NcmpiType is not the base of a Compound type.
+      \param ncmpiType     A Nctype object.
+    */
+    NcmpiCompoundType(const NcmpiType& ncmpiType);
+
+    /*! assignment operator */
+    NcmpiCompoundType& operator=(const NcmpiCompoundType& rhs);
+
+    /*!
+      Assignment operator.
+      This assigns from the base type NcmpiType object. Will throw an exception if the NcmpiType is not the base of a Compound type.
+    */
+    NcmpiCompoundType& operator=(const NcmpiType& rhs);
+
+    /*! The copy constructor. */
+    NcmpiCompoundType(const NcmpiCompoundType& rhs);
+
+    /*! equivalence operator */
+    bool operator==(const NcmpiCompoundType & rhs);
+
+    /*! destructor */
+    ~NcmpiCompoundType(){;}
+
+
+    /*!
+      Adds a named field.
+      \param memName       Name of new field.
+      \param newMemberType The type of the new member.
+      \param offset        Offset of this member in bytes, obtained by a call to offsetof. For example
+the offset of a member "mem4" in structure struct1 is: offsetof(struct1,mem4).
+    */
+    void addMember(const std::string& memName, const NcmpiType& newMemberType,MPI_Offset offset);
+
+    /*!
+      Adds a named array field.
+      \param memName       Name of new field.
+      \param newMemberType The type of the new member.
+      \param offset        Offset of this member in bytes, obtained by a call to offsetof. For example
+                           the offset of a member "mem4" in structure struct1 is: offsetof(struct1,mem4).
+      \param shape         The shape of the array field.
+    */
+    void addMember(const std::string& memName, const NcmpiType& newMemberType, MPI_Offset offset, const std::vector<int>& shape);
+
+
+    /*! Returns number of members in this NcmpiCompoundType object. */
+    MPI_Offset  getMemberCount() const;
+
+    /*! Returns a NcmpiType object for a single member. */
+    NcmpiType getMember(int memberIndex) const;
+
+    /*! Returns the offset of the member with given index. */
+    MPI_Offset getMemberOffset(const int index) const;
+
+    /*!
+      Returns the number of dimensions of a member with the given index.
+      \param Index of member (numbering starts at zero).
+      \return The number of dimensions of the field. Non-array fields have 0 dimensions.
+    */
+    int getMemberDimCount(int memberIndex) const;
+
+
+    /*!
+      Returns the shape of a given member.
+      \param Index of member (numbering starts at zero).
+      \return The size of the dimensions of the field. Non-array fields have 0 dimensions.
+    */
+    std::vector<int> getMemberShape(int memberIndex) const;
+
+  };
+
+}
+
+
+#endif
diff --git a/src/libcxx/ncmpiDim.cpp b/src/libcxx/ncmpiDim.cpp
new file mode 100644
index 0000000..cd29382
--- /dev/null
+++ b/src/libcxx/ncmpiDim.cpp
@@ -0,0 +1,125 @@
+#include "ncmpiDim.h"
+#include "ncmpiGroup.h"
+#include "ncmpiCheck.h"
+#include <algorithm>
+using namespace std;
+
+
+namespace PnetCDF {
+  //  Global comparator operator ==============
+  // comparator operator 
+  bool operator<(const NcmpiDim& lhs,const NcmpiDim& rhs)
+  {
+    return false;
+  }
+  
+  // comparator operator 
+  bool operator>(const NcmpiDim& lhs,const NcmpiDim& rhs)
+  {
+    return true;
+  }
+}
+
+using namespace PnetCDF;
+
+// assignment operator
+NcmpiDim& NcmpiDim::operator=(const NcmpiDim & rhs)
+{
+  nullObject = rhs.nullObject;
+  myId = rhs.myId;
+  groupId = rhs.groupId;
+  return *this;
+}
+
+// The copy constructor.
+NcmpiDim::NcmpiDim(const NcmpiDim& rhs): 
+  nullObject(rhs.nullObject),
+  myId(rhs.myId),
+  groupId(rhs.groupId)
+{}
+
+
+// equivalence operator
+bool NcmpiDim::operator==(const NcmpiDim& rhs) const
+{
+  if(nullObject) 
+    return nullObject == rhs.nullObject;
+  else
+    return myId == rhs.myId && groupId == rhs.groupId;
+}  
+
+//  !=  operator
+bool NcmpiDim::operator!=(const NcmpiDim & rhs) const
+{
+  return !(*this == rhs);
+}  
+
+
+// Gets parent group.
+NcmpiGroup  NcmpiDim::getParentGroup() const {
+  return NcmpiGroup(groupId);
+}
+
+// Constructor generates a null object.
+NcmpiDim::NcmpiDim() : 
+  nullObject(true) 
+{}
+
+// Constructor for a dimension (must already exist in the netCDF file.)
+NcmpiDim::NcmpiDim(const NcmpiGroup& grp, int dimId) :
+  nullObject(false)
+{
+  groupId = grp.getId();
+  myId = dimId;
+}
+
+// gets the size of the dimension, for unlimited, this is the current number of records.
+MPI_Offset NcmpiDim::getSize() const
+{
+  MPI_Offset dimSize;
+  ncmpiCheck(ncmpi_inq_dimlen(groupId, myId, &dimSize),__FILE__,__LINE__);
+  return dimSize;
+}
+
+
+// returns true if this dimension is unlimited.
+bool NcmpiDim::isUnlimited() const
+{
+  int dimid;
+  ncmpiCheck(ncmpi_inq_unlimdim(groupId,&dimid),__FILE__,__LINE__);
+  return (myId == dimid);
+
+#if 0
+  int numlimdims;
+  int* unlimdimidsp=NULL;
+  // get the number of unlimited dimensions
+  ncmpiCheck(ncmpi_inq_unlimdims(groupId,&numlimdims,unlimdimidsp),__FILE__,__LINE__);
+  if (numlimdims){
+	  // get all the unlimited dimension ids in this group
+	  vector<int> unlimdimid(numlimdims);
+	  ncmpiCheck(ncmpi_inq_unlimdims(groupId,&numlimdims,&unlimdimid[0]),__FILE__,__LINE__);
+	  vector<int>::iterator it;
+	  // now look to see if this dimension is unlimited
+	  it = find(unlimdimid.begin(),unlimdimid.end(),myId);
+	  return it != unlimdimid.end();
+  }
+  return false;
+#endif
+}
+
+
+// gets the name of the dimension.
+const string NcmpiDim::getName() const
+{
+  char dimName[NC_MAX_NAME+1];
+  ncmpiCheck(ncmpi_inq_dimname(groupId, myId, dimName),__FILE__,__LINE__);
+  return string(dimName);
+}
+  
+// renames this dimension.
+void NcmpiDim::rename(const string& name)
+{
+  ncmpiCheck(ncmpi_rename_dim(groupId, myId, name.c_str()),__FILE__,__LINE__);
+}
+
+
diff --git a/src/libcxx/ncmpiDim.h b/src/libcxx/ncmpiDim.h
new file mode 100644
index 0000000..a381849
--- /dev/null
+++ b/src/libcxx/ncmpiDim.h
@@ -0,0 +1,84 @@
+#include <string>
+#include <mpi.h>
+
+#ifndef NcmpiDimClass
+#define NcmpiDimClass
+
+
+namespace PnetCDF
+{
+  class NcmpiGroup;  // forward declaration.
+     
+  /*! Class represents a netCDF dimension */
+  class NcmpiDim   {
+    
+  public:
+     
+    /*! destructor*/
+    ~NcmpiDim(){};
+
+    /*! Constructor generates a \ref isNull "null object". */
+    NcmpiDim ();
+
+    /*! 
+      Constructor for a dimension .
+      The dimension must already exist in the netCDF file. New netCDF variables can be added using NcmpiGroup::addNcmpiDim();
+      \param grp    Parent NcmpiGroup object.
+      \param dimId  Id of the NcmpiDim object.
+    */
+    NcmpiDim(const NcmpiGroup& grp, int dimId);
+
+    /*! assignment operator  */
+    NcmpiDim& operator =(const NcmpiDim &);
+
+    /*! equivalence operator */
+    bool operator==(const NcmpiDim& rhs) const;     
+
+    /*!  != operator */
+    bool operator!=(const NcmpiDim& rhs) const;     
+
+    /*! The copy constructor. */
+    NcmpiDim(const NcmpiDim& ncmpiDim);
+
+    /*! The name of this dimension.*/
+    const std::string getName() const;
+
+    /*! The netCDF Id of this dimension. */
+    int getId() const {return myId;};
+    
+    /*! Gets a  NcmpiGroup object of the parent group. */
+    NcmpiGroup getParentGroup() const;
+      
+    /*! Returns true if this is an unlimited dimension */
+    bool isUnlimited() const;
+
+    /*! The size of the dimension; for unlimited, this is the number of records written so far. */
+    MPI_Offset  getSize() const;
+
+    /*!renames the dimension */
+    void rename( const std::string& newName);
+
+    /*! Returns true if this object is null (i.e. it has no contents); otherwise returns false. */
+    bool isNull() const  {return nullObject;}
+
+    /*! comparator operator  */
+    friend bool operator<(const NcmpiDim& lhs,const NcmpiDim& rhs);
+    
+    /*! comparator operator  */
+    friend bool operator>(const NcmpiDim& lhs,const NcmpiDim& rhs);
+    
+  private:
+
+    bool nullObject;
+
+    int myId;	
+
+    int groupId;
+
+  };
+  
+}
+
+ 
+#endif
+
diff --git a/src/libcxx/ncmpiDouble.cpp b/src/libcxx/ncmpiDouble.cpp
new file mode 100644
index 0000000..94cd401
--- /dev/null
+++ b/src/libcxx/ncmpiDouble.cpp
@@ -0,0 +1,22 @@
+#include "ncmpiDouble.h"
+#include <pnetcdf.h>
+using namespace PnetCDF;
+
+// create an instance of NcmpiDouble  called PnetCDF::ncmpiDouble
+namespace PnetCDF {
+  NcmpiDouble ncmpiDouble;
+}
+
+// constructor
+NcmpiDouble::NcmpiDouble() : NcmpiType(NC_DOUBLE){
+}
+
+NcmpiDouble::~NcmpiDouble() {
+}
+
+
+// equivalence operator
+bool NcmpiDouble::operator==(const NcmpiDouble & rhs)    {
+  // simply check the netCDF id.
+  return myId == rhs.myId;
+}  
diff --git a/src/libcxx/ncmpiDouble.h b/src/libcxx/ncmpiDouble.h
new file mode 100644
index 0000000..73dcc32
--- /dev/null
+++ b/src/libcxx/ncmpiDouble.h
@@ -0,0 +1,28 @@
+#include "ncmpiType.h"
+
+#ifndef NcmpiDoubleClass
+#define NcmpiDoubleClass
+
+namespace PnetCDF
+{
+  
+  /*! Class represents a netCDF atomic Double type. */
+  class NcmpiDouble : public NcmpiType
+  {
+  public: 
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiDouble & rhs);
+    
+    /*!  destructor */
+    ~NcmpiDouble();
+    
+    /*! Constructor */
+    NcmpiDouble();
+  };
+
+  /*! A global instance  of the NcmpiDouble class within the netCDF namespace. */
+  extern NcmpiDouble ncmpiDouble;
+
+}
+#endif
diff --git a/src/libcxx/ncmpiEnumType.cpp b/src/libcxx/ncmpiEnumType.cpp
new file mode 100644
index 0000000..e0223ba
--- /dev/null
+++ b/src/libcxx/ncmpiEnumType.cpp
@@ -0,0 +1,111 @@
+#include "ncmpiEnumType.h"
+#include "ncmpiGroup.h"
+#include "ncmpiCheck.h"
+#include "ncmpiByte.h"
+#include "ncmpiUbyte.h"
+#include "ncmpiChar.h"
+#include "ncmpiShort.h"
+#include "ncmpiUshort.h"
+#include "ncmpiInt.h"
+#include "ncmpiUint.h"
+#include "ncmpiInt64.h"
+#include "ncmpiUint64.h"
+#include "ncmpiFloat.h"
+#include "ncmpiDouble.h"
+#include "ncmpiException.h"
+
+using namespace std;
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+// Class represents a netCDF variable.
+
+// assignment operator
+NcmpiEnumType& NcmpiEnumType::operator=(const NcmpiEnumType& rhs)
+{
+  NcmpiType::operator=(rhs);    // assign base class parts
+  return *this;
+}
+
+// assignment operator
+NcmpiEnumType& NcmpiEnumType::operator=(const NcmpiType& rhs)
+{
+  if (&rhs != this) {
+    // check the rhs is the base of an Enum type
+    if(getTypeClass() != NC_ENUM) throw NcmpiException("The NcmpiType object must be the base of an Enum type.",__FILE__,__LINE__);
+    // assign base class parts
+    NcmpiType::operator=(rhs);
+  }
+  return *this;
+}
+
+// The copy constructor.
+NcmpiEnumType::NcmpiEnumType(const NcmpiEnumType& rhs): 
+  NcmpiType(rhs)
+{
+}
+
+
+// Constructor generates a null object.
+NcmpiEnumType::NcmpiEnumType() :
+  NcmpiType()   // invoke base class constructor
+{}
+  
+// constructor
+NcmpiEnumType::NcmpiEnumType(const NcmpiGroup& grp, const string& name):
+  NcmpiType(grp,name)
+{}
+  
+
+// constructor
+NcmpiEnumType::NcmpiEnumType(const NcmpiType& ncmpiType): 
+  NcmpiType(ncmpiType)
+{
+  // check the nctype object is the base of an Enum type
+  if(getTypeClass() != NC_ENUM) throw NcmpiException("The NcmpiType object must be the base of an Enum type.",__FILE__,__LINE__);
+}
+
+// Returns the base type.
+NcmpiType NcmpiEnumType::getBaseType() const
+{
+  char charName[NC_MAX_NAME+1];
+  nc_type base_nc_typep;
+  MPI_Offset *base_sizep=NULL;
+  MPI_Offset *num_membersp=NULL;
+  ncmpiCheck(ncmpi_inq_enum(groupId,myId,charName,&base_nc_typep,base_sizep,num_membersp),__FILE__,__LINE__);
+  switch (base_nc_typep) {
+  case NC_BYTE    : return ncmpiByte;
+  case NC_UBYTE   : return ncmpiUbyte;
+  case NC_CHAR    : return ncmpiChar;
+  case NC_SHORT   : return ncmpiShort;
+  case NC_USHORT  : return ncmpiUshort;
+  case NC_INT     : return ncmpiInt;
+  case NC_UINT    : return ncmpiUint;  
+  case NC_INT64   : return ncmpiInt64; 
+  case NC_UINT64  : return ncmpiUint64;
+  case NC_FLOAT   : return ncmpiFloat;
+  case NC_DOUBLE  : return ncmpiDouble;
+  default:  
+    // this is a user defined type
+    return NcmpiType(getParentGroup(),base_nc_typep);
+  }
+}
+
+  
+// Returns number of members in this NcmpiEnumType object.
+MPI_Offset   NcmpiEnumType::getMemberCount() const{
+  char charName[NC_MAX_NAME+1];
+  nc_type* base_nc_typep=NULL;
+  MPI_Offset* base_sizep=NULL;
+  MPI_Offset num_membersp;
+  ncmpiCheck(ncmpi_inq_enum(groupId,myId,charName,base_nc_typep,base_sizep,&num_membersp),__FILE__,__LINE__);
+  return num_membersp;
+};
+  
+// Returns the member name for the given zero-based index.
+string NcmpiEnumType::getMemberNameFromIndex(int index) const{
+  void* value=NULL;
+  char charName[NC_MAX_NAME+1];
+  ncmpiCheck(ncmpi_inq_enum_member(groupId,myId,index,charName,value),__FILE__,__LINE__);
+  return static_cast<string> (charName);
+};
diff --git a/src/libcxx/ncmpiEnumType.h b/src/libcxx/ncmpiEnumType.h
new file mode 100644
index 0000000..d2d6bd6
--- /dev/null
+++ b/src/libcxx/ncmpiEnumType.h
@@ -0,0 +1,109 @@
+#include <string>
+#include "ncmpiType.h"
+#include "ncmpiCheck.h"
+
+#include <pnetcdf.h>
+#include "ncmpi_notyet.h"
+
+#ifndef NcmpiEnumTypeClass
+#define NcmpiEnumTypeClass
+
+
+namespace PnetCDF
+{
+  class NcmpiGroup;  // forward declaration.
+
+  /*! Class represents a netCDF enum type */
+  class NcmpiEnumType : public NcmpiType
+    {
+    public:
+      
+      /*! List of NetCDF-4 Enumeration types.*/
+      enum ncmpiEnumType	{
+	ncmpi_BYTE     = NC_BYTE, 	//!< signed 1 byte integer
+	ncmpi_SHORT    = NC_SHORT, 	//!< signed 2 byte integer
+	ncmpi_INT      = NC_INT,	//!< signed 4 byte integer
+	ncmpi_UBYTE    = NC_UBYTE,	//!< unsigned 1 byte int
+	ncmpi_USHORT   = NC_USHORT,	//!< unsigned 2-byte int
+	ncmpi_UINT     = NC_UINT,	//!< unsigned 4-byte int
+	ncmpi_INT64    = NC_INT64,	//!< signed 8-byte int
+	ncmpi_UINT64   = NC_UINT64	//!< unsigned 8-byte int
+      };
+      
+      /*! Constructor generates a \ref isNull "null object". */
+      NcmpiEnumType();
+
+      /*! 
+	Constructor.
+	The enum Type must already exist in the netCDF file. New netCDF enum types can 
+	be added using NcmpiGroup::addNcmpiEnumType();
+	\param grp        The parent group where this type is defined.
+	\param name       Name of new type.
+      */
+      NcmpiEnumType(const NcmpiGroup& grp, const std::string& name);
+
+      /*! 
+	Constructor.
+	Constructs from the base type NcmpiType object. Will throw an exception if the NcmpiType is not the base of an Enum type.
+	\param ncmpiType     A Nctype object.
+      */
+      NcmpiEnumType(const NcmpiType& ncmpiType);
+
+      /*! assignment operator */
+      NcmpiEnumType& operator=(const NcmpiEnumType& rhs);
+      
+      /*! 
+	Assignment operator.
+       This assigns from the base type NcmpiType object. Will throw an exception if the NcmpiType is not the base of an Enum type.
+      */
+      NcmpiEnumType& operator=(const NcmpiType& rhs);
+      
+      /*! The copy constructor. */
+      NcmpiEnumType(const NcmpiEnumType& rhs);
+      
+      /*! Destructor */
+      ~NcmpiEnumType(){}
+      
+      
+      /*! 
+	Adds a new member to this NcmpiEnumType type.
+	\param name         Name for this new Enum memebr.
+	\param memberValue  Member value, must be of the correct NcmpiType.
+      */
+      template <class T> void addMember(const std::string& name, T memberValue)
+      {
+	ncmpiCheck(ncmpi_insert_enum(groupId, myId, name.c_str(), (void*) &memberValue),__FILE__,__LINE__);
+      }
+
+      /*! Returns number of members in this NcmpiEnumType object. */
+      MPI_Offset  getMemberCount() const;
+      
+      /*! Returns the member name for the given zero-based index. */
+      std::string  getMemberNameFromIndex(int index) const;
+
+      /*! Returns the member name for the given NcmpiEnumType value. */
+      template <class T>  std::string  getMemberNameFromValue(const T memberValue) const {
+	char charName[NC_MAX_NAME+1];
+	ncmpiCheck(ncmpi_inq_enum_ident(groupId,myId,static_cast<long long>(memberValue),charName),__FILE__,__LINE__);
+	return std::string(charName);
+      }
+	
+      /*! 
+	Returns the value of a member with the given zero-based index.
+	\param name         Name for this new Enum member.
+	\param memberValue  Member value, returned by this routine.
+      */
+      template <class T> void getMemberValue(int index, T& memberValue) const
+	{
+	  char* charName=NULL;
+	  ncmpiCheck(ncmpi_inq_enum_member(groupId,myId,index,charName,&memberValue),__FILE__,__LINE__);
+	}
+
+      /*! Returns the base type. */
+      NcmpiType  getBaseType() const;
+      
+  };
+  
+}
+
+#endif
diff --git a/src/libcxx/ncmpiException.cpp b/src/libcxx/ncmpiException.cpp
new file mode 100644
index 0000000..ac8785a
--- /dev/null
+++ b/src/libcxx/ncmpiException.cpp
@@ -0,0 +1,308 @@
+#include "ncmpiException.h"
+#include <sstream>
+#include <pnetcdf.h>
+using namespace std;
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+
+// Default object thrown if a netCDF exception is encountered.
+/*NcmpiException::NcmpiException(const string& complaint,const char* fileName,int lineNumber)
+  : what_msg(NULL)
+  , ec(0)
+{
+	try{
+		std::ostringstream oss;
+		oss << lineNumber;
+		what_msg = new std::string(complaint+"\nfile: "+fileName+"  line:"+oss.str());
+	}catch(...){
+		what_msg = NULL;
+	}
+}*/
+
+NcmpiException::NcmpiException(const char* complaint,const char* fileName,int lineNumber)
+  : what_msg(NULL)
+  , ec(0)
+{
+  try{
+    std::ostringstream oss;
+    oss << lineNumber;
+    what_msg = new std::string(complaint?complaint:"");
+    what_msg->append("\nfile: ");
+    what_msg->append(fileName);
+    what_msg->append("  line:");
+    what_msg->append(oss.str());
+  }catch(...){
+    what_msg = NULL;
+  }
+}
+
+NcmpiException::NcmpiException(int errorCode, const char* complaint,const char* fileName,int lineNumber)
+  : what_msg(NULL)
+  , ec(errorCode)
+{
+  try{
+    std::ostringstream oss;
+    oss << lineNumber;
+    what_msg = new std::string(complaint?complaint:"");
+    what_msg->append("\nfile: ");
+    what_msg->append(fileName);
+    what_msg->append("  line:");
+    what_msg->append(oss.str());
+  }catch(...){
+    what_msg = NULL;
+  }
+}
+
+NcmpiException::NcmpiException(const NcmpiException& e) throw()
+	: what_msg(NULL)
+  , ec(e.ec)
+{
+	try{
+		what_msg = new std::string(*(e.what_msg));
+	}catch(...){
+		what_msg = NULL;
+	}
+}
+
+NcmpiException& NcmpiException::operator=(const NcmpiException& e) throw(){
+	if (this != &e){
+    ec = e.ec;
+		delete what_msg;
+		try{
+			what_msg = new std::string(*(e.what_msg));
+		}catch(...){
+			what_msg = NULL;
+		}
+	}
+	return *this;
+}
+
+NcmpiException::~NcmpiException()throw() {
+	delete what_msg;
+}
+
+
+const char* NcmpiException::what() const throw()
+{
+  return what_msg==NULL ? "" : what_msg->c_str();
+}
+
+int NcmpiException::errorCode() const throw() {
+  return ec;
+}
+
+
+// Thrown if the specified netCDF ID does not refer to an open netCDF dataset. 
+NcBadId::NcBadId(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EBADID,complaint,file,line) { }
+
+
+// Thrown if too many netcdf files are open.
+NcNFile::NcNFile(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ENFILE,complaint,file,line) { }
+
+// Thrown if, having set NC_NOCLOBBER, the specified dataset already exists. 
+NcExist::NcExist(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EEXIST,complaint,file,line) { }
+
+// Thrown if not a netCDF id.
+NcInvalidArg::NcInvalidArg(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EINVAL,complaint,file,line) { }
+
+// Thrown if invalid argument.
+NcInvalidWrite::NcInvalidWrite(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EPERM,complaint,file,line) { }
+
+// Thrown if operation not allowed in data mode.
+NcNotInDefineMode::NcNotInDefineMode(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ENOTINDEFINE,complaint,file,line) { }
+
+// Thrown if operation not allowed in defined mode.
+NcInDefineMode::NcInDefineMode(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EINDEFINE,complaint,file,line) { }
+
+// Index exceeds dimension bound
+NcInvalidCoords::NcInvalidCoords(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EINVALCOORDS,complaint,file,line) { }
+
+// Thrown if NC_MAX_DIMS is exceeded.
+NcMaxDims::NcMaxDims(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EMAXDIMS,complaint,file,line) { }
+
+// Thrown if string match to name is in use.
+NcNameInUse::NcNameInUse(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ENAMEINUSE,complaint,file,line) { }
+
+// Thrown if attribute is not found.
+NcNotAtt::NcNotAtt(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ENOTATT,complaint,file,line) { }
+
+// Thrown if Nc_MAX_ATTRS is exceeded.
+NcMaxAtts::NcMaxAtts(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EMAXATTS,complaint,file,line) { }
+
+// Thrown if not a valid netCDF data type.
+NcBadType::NcBadType(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EBADTYPE,complaint,file,line) { }
+
+// Thrown if an invalid dimension id or name.
+NcBadDim::NcBadDim(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EBADDIM,complaint,file,line) { }
+
+// Thrown if Nc_UNLIMITED is in the wrong index.
+NcUnlimPos::NcUnlimPos(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EUNLIMPOS,complaint,file,line) { }
+
+// Thrown if NC_MAX_VARS is exceeded.
+NcMaxVars::NcMaxVars(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EMAXVARS,complaint,file,line) { }
+
+// Thrown if variable is not found.
+NcNotVar::NcNotVar(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ENOTVAR,complaint,file,line) { }
+
+// Thrown if the action is prohibited on the NC_GLOBAL varid.
+NcGlobal::NcGlobal(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EGLOBAL,complaint,file,line) { }
+
+// Thrown if not a netCDF file.
+NcNotNCF::NcNotNCF(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ENOTNC,complaint,file,line) { }
+
+// Thrown if in FORTRAN, string is too short.
+NcSts::NcSts(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ESTS,complaint,file,line) { }
+
+// Thrown if NC_MAX_NAME is exceeded.
+NcMaxName::NcMaxName(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EMAXNAME,complaint,file,line) { }
+
+// Thrown if NC_UNLIMITED size is already in use.
+NcUnlimit::NcUnlimit(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EUNLIMIT,complaint,file,line) { }
+
+// Thrown if ncmpi_rec op when there are no record vars.
+NcNoRecVars::NcNoRecVars(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ENORECVARS,complaint,file,line) { }
+
+// Thrown if attempt to convert between text and numbers.
+NcmpiChar::NcmpiChar(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ECHAR,complaint,file,line) { }
+
+// Thrown if edge+start exceeds dimension bound.
+NcEdge::NcEdge(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EEDGE,complaint,file,line) { }
+
+// Thrown if illegal stride.
+NcStride::NcStride(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ESTRIDE,complaint,file,line) { }
+
+// Thrown if attribute or variable name contains illegal characters.
+NcBadName::NcBadName(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EBADNAME,complaint,file,line) { }
+
+// Thrown if math result not representable.
+NcRange::NcRange(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ERANGE,complaint,file,line) { }
+
+// Thrown if memory allocation (malloc) failure.
+NcNoMem::NcNoMem(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ENOMEM,complaint,file,line) { }
+
+// Thrown if one or more variable sizes violate format constraints
+NcmpiVarSize::NcmpiVarSize(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EVARSIZE,complaint,file,line) { }
+
+// Thrown if invalid dimension size.
+NcmpiDimSize::NcmpiDimSize(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EDIMSIZE,complaint,file,line) { }
+
+// Thrown if file likely truncated or possibly corrupted.
+NcTrunc::NcTrunc(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ETRUNC,complaint,file,line) { }
+
+// Thrown if an error was reported by the HDF5 layer.
+NcHdfErr::NcHdfErr(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EHDFERR,complaint,file,line) { }
+
+// Thrown if cannot read.
+NcCantRead::NcCantRead(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ECANTREAD,complaint,file,line) { }
+
+// Thrown if cannot write.
+NcCantWrite::NcCantWrite(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ECANTWRITE,complaint,file,line) { }
+
+// Thrown if cannot create.
+NcCantCreate::NcCantCreate(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ECANTCREATE,complaint,file,line) { }
+
+// Thrown if file meta.
+NcmpiFileMeta::NcmpiFileMeta(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EFILEMETA,complaint,file,line) { }
+
+// Thrown if dim meta.
+NcmpiDimMeta::NcmpiDimMeta(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EDIMMETA,complaint,file,line) { }
+
+// Thrown if attribute meta.
+NcmpiAttMeta::NcmpiAttMeta(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EATTMETA,complaint,file,line) { }
+
+// Thrown if variable meta.
+NcmpiVarMeta::NcmpiVarMeta(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EVARMETA,complaint,file,line) { }
+
+// Thrown if no compound.
+NcNoCompound::NcNoCompound(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ENOCOMPOUND,complaint,file,line) { }
+
+// Thrown if attribute exists.
+NcmpiAttExists::NcmpiAttExists(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EATTEXISTS,complaint,file,line) { }
+
+// Thrown if attempting netcdf-4 operation on netcdf-3 file.
+NcNotNc4::NcNotNc4(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ENOTNC4,complaint,file,line) { }
+
+// Thrown if attempting netcdf-4 operation on strict nc3 netcdf-4 file.
+NcStrictNc3::NcStrictNc3(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ESTRICTNC3,complaint,file,line) { }
+
+// Thrown if bad group id.
+NcBadGroupId::NcBadGroupId(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EBADGRPID,complaint,file,line) { }
+
+// Thrown if bad type id.
+NcBadTypeId::NcBadTypeId(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EBADTYPID,complaint,file,line) { }
+
+// Thrown if bad field id.
+NcBadFieldId::NcBadFieldId(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_EBADFIELD,complaint,file,line) { }
+
+// Thrown if cannot find the field id.
+NcUnknownName::NcUnknownName(const char* complaint,const char* file,int line) :
+  NcmpiException(complaint,file,line) { }
+
+// Thrown if cannot find the field id.
+NcEnoGrp::NcEnoGrp(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ENOGRP,complaint,file,line) { }
+
+// Thrown if cannot find the field id.
+NcNullGrp::NcNullGrp(const char* complaint,const char* file,int line) :
+  NcmpiException(complaint,file,line) { }
+
+// Thrown if cannot find the field id.
+NcNullDim::NcNullDim(const char* complaint,const char* file,int line) :
+  NcmpiException(complaint,file,line) { }
+
+// Thrown if cannot find the field id.
+NcNullType::NcNullType(const char* complaint,const char* file,int line) :
+  NcmpiException(complaint,file,line) { }
+
+// Thrown if an operation to set the deflation, chunking, endianness, fill, compression, or checksum of a NcmpiVar object is issued after a call to NcmpiVar::getVar or NcmpiVar::putVar.
+NcElateDef::NcElateDef(const char* complaint,const char* file,int line) :
+  NcmpiException(NC_ELATEDEF,complaint,file,line) { }
+
diff --git a/src/libcxx/ncmpiException.h b/src/libcxx/ncmpiException.h
new file mode 100644
index 0000000..4bad82d
--- /dev/null
+++ b/src/libcxx/ncmpiException.h
@@ -0,0 +1,437 @@
+#include <exception>
+#include <string>
+#include <iostream>
+
+#ifndef NcmpiExceptionClasses
+#define NcmpiExceptionClasses
+
+namespace PnetCDF
+{
+
+  //!  Exception classes.
+  /*!
+    These exceptions are thrown if the netCDF-4 API encounters an error.
+  */
+  namespace exceptions
+  {
+
+    /*! 
+      Base object is thrown if a netCDF exception is encountered.
+      An unsatisfactory return from a call to one of the netCDF C-routines 
+      generates an exception using an object inheriting this class.  All other netCDF-related
+      errors  including those originating in the C++ binding, generates an NcmpiException.
+    */
+    class NcmpiException : public std::exception {
+    public:
+      //NcmpiException(const string& complaint,const char* fileName,int lineNumber);
+      NcmpiException(const char* complaint,const char* fileName,int lineNumber);
+      NcmpiException(int errorCode, const char* complaint,const char* fileName,int lineNumber);
+      NcmpiException(const NcmpiException& e) throw();
+      NcmpiException& operator=(const NcmpiException& e) throw();
+      virtual ~NcmpiException() throw();
+      const char* what() const throw();
+      int errorCode() const throw();
+    private:
+      std::string* what_msg;
+      int ec;
+    };
+
+
+    /*! Thrown if the specified netCDF ID does not refer to an open netCDF dataset. */
+    class NcBadId : public NcmpiException
+    {
+    public:
+      NcBadId(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if too many netcdf files are open. */
+    class NcNFile : public NcmpiException
+    {
+    public:
+      NcNFile(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if, having set NC_NOCLOBBER, the specified dataset already exists. */
+    class NcExist : public NcmpiException
+    {
+    public:
+      NcExist(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if not a netCDF id.  */
+    class NcInvalidArg : public NcmpiException
+    {
+    public:
+      NcInvalidArg(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if invalid argument. */
+    class NcInvalidWrite : public NcmpiException
+    {
+    public:
+      NcInvalidWrite(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if operation not allowed in data mode. */
+    class NcNotInDefineMode : public NcmpiException
+    {
+    public:
+      NcNotInDefineMode(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if operation not allowed in defined mode. */
+    class NcInDefineMode : public NcmpiException
+    {
+    public:
+      NcInDefineMode(const char* complaint,const char* file,int line);
+    };
+
+    /*! 
+      Index exceeds dimension bound.
+      Exception may  be generated during operations to get or put  netCDF variable data.
+      The exception is thrown if the specified indices were out of range for the rank of the 
+      specified variable. For example, a negative index or an index that is larger than 
+      the corresponding dimension length will cause an error.
+    */
+    class NcInvalidCoords : public NcmpiException
+    {
+    public:
+      NcInvalidCoords(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if NC_MAX_DIMS is exceeded. */
+    class NcMaxDims : public NcmpiException
+    {
+    public:
+      NcMaxDims(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if string match to name is in use. */
+    class NcNameInUse : public NcmpiException
+    {
+    public:
+      NcNameInUse(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if attribute is not found. */
+    class NcNotAtt : public NcmpiException
+    {
+    public:
+      NcNotAtt(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if Nc_MAX_ATTRS is exceeded. */
+    class NcMaxAtts : public NcmpiException
+    {
+    public:
+      NcMaxAtts(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if not a valid netCDF data type. */
+    class NcBadType : public NcmpiException
+    {
+    public:
+      NcBadType(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if an invalid dimension id or name. */
+    class NcBadDim : public NcmpiException
+    {
+    public:
+      NcBadDim(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if Nc_UNLIMITED is in the wrong index. */
+    class NcUnlimPos : public NcmpiException
+    {
+    public:
+      NcUnlimPos(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if NC_MAX_VARS is exceeded. */
+    class NcMaxVars : public NcmpiException
+    {
+    public:
+      NcMaxVars(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if variable is not found. */
+    class NcNotVar : public NcmpiException
+    {
+    public:
+      NcNotVar(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if the action is prohibited on the NC_GLOBAL varid. */
+    class NcGlobal : public NcmpiException
+    {
+    public:
+      NcGlobal(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if not a netCDF file. */
+    class NcNotNCF : public NcmpiException
+    {
+    public:
+      NcNotNCF(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if in FORTRAN, string is too short. */
+    class NcSts : public NcmpiException
+    {
+    public:
+      NcSts(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if NC_MAX_NAME is exceeded. */
+    class NcMaxName : public NcmpiException
+    {
+    public:
+      NcMaxName(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if NC_UNLIMITED size is already in use. */
+    class NcUnlimit : public NcmpiException
+    {
+    public:
+      NcUnlimit(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if ncmpi_rec op when there are no record vars. */
+    class NcNoRecVars : public NcmpiException
+    {
+    public:
+      NcNoRecVars(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if attempt to convert between text and numbers. */
+    class NcmpiChar : public NcmpiException
+    {
+    public:
+      NcmpiChar(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if edge+start exceeds dimension bound. */
+    class NcEdge : public NcmpiException
+    {
+    public:
+      NcEdge(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if illegal stride. */
+    class NcStride : public NcmpiException
+    {
+    public:
+      NcStride(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if attribute or variable name contains illegal characters. */
+    class NcBadName : public NcmpiException
+    {
+    public:
+      NcBadName(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if math result not representable. */
+    class NcRange : public NcmpiException
+    {
+    public:
+      NcRange(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if memory allocation (malloc) failure. */
+    class NcNoMem : public NcmpiException
+    {
+    public:
+      NcNoMem(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if one or more variable sizes violate format constraints */
+    class NcmpiVarSize : public NcmpiException
+    {
+    public:
+      NcmpiVarSize(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if invalid dimension size. */
+    class NcmpiDimSize : public NcmpiException
+    {
+    public:
+      NcmpiDimSize(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if file likely truncated or possibly corrupted. */
+    class NcTrunc : public NcmpiException
+    {
+    public:
+      NcTrunc(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if an error was reported by the HDF5 layer. */
+    class NcHdfErr : public NcmpiException
+    {
+    public:
+      NcHdfErr(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if cannot read. */
+    class NcCantRead : public NcmpiException
+    {
+    public:
+      NcCantRead(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if cannot write. */
+    class NcCantWrite : public NcmpiException
+    {
+    public:
+      NcCantWrite(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if cannot create. */
+    class NcCantCreate : public NcmpiException
+    {
+    public:
+      NcCantCreate(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if file meta. */
+    class NcmpiFileMeta : public NcmpiException
+    {
+    public:
+      NcmpiFileMeta(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if dim meta. */
+    class NcmpiDimMeta : public NcmpiException
+    {
+    public:
+      NcmpiDimMeta(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if attribute meta. */
+    class NcmpiAttMeta : public NcmpiException
+    {
+    public:
+      NcmpiAttMeta(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if variable meta. */
+    class NcmpiVarMeta : public NcmpiException
+    {
+    public:
+      NcmpiVarMeta(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if no compound. */
+    class NcNoCompound : public NcmpiException
+    {
+    public:
+      NcNoCompound(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if attribute exists. */
+    class NcmpiAttExists : public NcmpiException
+    {
+    public:
+      NcmpiAttExists(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if attempting netcdf-4 operation on netcdf-3 file. */
+    class NcNotNc4 : public NcmpiException
+    {
+    public:
+      NcNotNc4(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if attempting netcdf-4 operation on strict nc3 netcdf-4 file. */
+    class NcStrictNc3 : public NcmpiException
+    {
+    public:
+      NcStrictNc3(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if bad group id. */
+    class NcBadGroupId : public NcmpiException
+    {
+    public:
+      NcBadGroupId(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if bad type id. */
+    class NcBadTypeId : public NcmpiException
+    {
+    public:
+      NcBadTypeId(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if bad field id. */
+    class NcBadFieldId : public NcmpiException
+    {
+    public:
+      NcBadFieldId(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if cannot find the field id. */
+    class NcUnknownName : public NcmpiException
+    {
+    public:
+      NcUnknownName(const char* complaint,const char* file,int line);
+    };
+
+    /*! Thrown if cannot return a netCDF group. */
+    class NcEnoGrp : public NcmpiException
+    {
+    public:
+      NcEnoGrp(const char* complaint,const char* file,int line);
+    };
+
+    /*! 
+      Thrown if the requested operation is on a NULL group.
+    
+      This exception is thrown if an operation on a NcmpiGroup object is requested which is empty. To test if the object is empty used NcmpiGroup::isNull()
+     */
+    class NcNullGrp : public NcmpiException
+    {
+    public:
+      NcNullGrp(const char* complaint,const char* file,int line);
+    };
+
+    /*! 
+      Thrown if the requested operation is on a NULL type.
+    
+      This exception is thrown if an operation on a NcmpiType object is requested which is empty. To test if the object is empty used NcmpiType::isNull()
+     */
+    class NcNullType : public NcmpiException
+    {
+    public:
+      NcNullType(const char* complaint,const char* file,int line);
+    };
+
+    /*! 
+      Thrown if the requested operation is on a NULL dimension.
+    
+      This exception is thrown if an operation on a NcmpiDim object is requested which is empty. To test if the object is empty used NcmpiDim::isNull()
+     */
+    class NcNullDim : public NcmpiException
+    {
+    public:
+      NcNullDim(const char* complaint,const char* file,int line);
+    };
+
+    /*! 
+      Thrown if an operation to set the chunking, endianness, fill of a NcmpiVar object is issued after a 
+      call to NcmpiVar::getVar or NcmpiVar::putVar has been made.
+    */
+    class NcElateDef : public NcmpiException
+    {
+    public:
+      NcElateDef(const char* complaint,const char* file,int line);
+    };
+
+  }
+
+}
+
+#endif
+
diff --git a/src/libcxx/ncmpiFile.cpp b/src/libcxx/ncmpiFile.cpp
new file mode 100644
index 0000000..fb018a7
--- /dev/null
+++ b/src/libcxx/ncmpiFile.cpp
@@ -0,0 +1,205 @@
+#include "ncmpiFile.h"
+#include "ncmpiCheck.h"
+#include "ncmpiException.h"
+#include "ncmpiByte.h"
+#include<iostream>
+#include<string>
+#include<sstream>
+using namespace std;
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+// destructor
+NcmpiFile::~NcmpiFile()
+{
+  // destructor may be called due to an exception being thrown
+  // hence throwing an exception from within a destructor 
+  // causes undefined behaviour! so just printing a warning message
+  try
+  {
+    if (!nullObject)
+      ncmpiCheck(ncmpi_close(myId),__FILE__,__LINE__);
+  }
+  catch (NcmpiException &e) 
+  {
+    cerr << e.what() << endl;
+  }
+}
+
+// Constructor generates a null object.
+NcmpiFile::NcmpiFile() : 
+    NcmpiGroup()  // invoke base class constructor
+{}
+
+// constructor
+NcmpiFile::NcmpiFile(const MPI_Comm  &comm,
+                     const string    &filePath,
+                     const FileMode   fMode,
+                     const MPI_Info  &info /* = MPI_INFO_NULL */ )
+{
+  switch (fMode) 
+    {
+    case NcmpiFile::write:
+      ncmpiCheck(ncmpi_open(comm, filePath.c_str(), NC_WRITE, info, &myId),__FILE__,__LINE__);
+      break;
+    case NcmpiFile::read:
+      ncmpiCheck(ncmpi_open(comm, filePath.c_str(), NC_NOWRITE, info, &myId),__FILE__,__LINE__);
+      break;
+    case NcmpiFile::newFile:
+      ncmpiCheck(ncmpi_create(comm, filePath.c_str(), NC_NOCLOBBER, info, &myId),__FILE__,__LINE__);
+      break;
+    case NcmpiFile::replace:
+      ncmpiCheck(ncmpi_create(comm, filePath.c_str(), NC_CLOBBER, info, &myId),__FILE__,__LINE__);
+      break;
+    }
+  nullObject=false;
+}
+
+// constructor with file type specified
+NcmpiFile::NcmpiFile(const MPI_Comm   &comm,
+                     const string     &filePath,
+                     const FileMode    fMode,
+                     const FileFormat  fFormat,
+                     const MPI_Info   &info /* = MPI_INFO_NULL */)
+{
+  int format=0;
+  switch (fFormat)
+    {
+    case NcmpiFile::classic:
+	format = 0;
+	break;
+    case NcmpiFile::classic2:
+	format = NC_64BIT_OFFSET;
+	break;
+    case NcmpiFile::nc4:
+	format = NC_NETCDF4;
+	break;
+    case NcmpiFile::nc4classic:
+	format = NC_NETCDF4 | NC_CLASSIC_MODEL;
+	break;
+    case NcmpiFile::classic5:
+	format = NC_64BIT_DATA;
+	break;
+    case NcmpiFile::BadFormat:
+        throw NcNotNCF("NetCDF: Unknown file format",__FILE__,__LINE__);
+    }
+  switch (fMode) 
+    {
+    case NcmpiFile::write:
+      ncmpiCheck(ncmpi_open(comm, filePath.c_str(), format | NC_WRITE, info, &myId),__FILE__,__LINE__);
+      break;
+    case NcmpiFile::read:
+      ncmpiCheck(ncmpi_open(comm, filePath.c_str(), format | NC_NOWRITE, info, &myId),__FILE__,__LINE__);
+      break;
+    case NcmpiFile::newFile:
+      ncmpiCheck(ncmpi_create(comm, filePath.c_str(), format | NC_NOCLOBBER, info, &myId),__FILE__,__LINE__);
+      break;
+    case NcmpiFile::replace:
+      ncmpiCheck(ncmpi_create(comm, filePath.c_str(), format | NC_CLOBBER, info, &myId),__FILE__,__LINE__);
+      break;
+    }
+  nullObject=false;
+}
+
+// Synchronize an open netcdf dataset to disk
+void NcmpiFile::sync(){
+  ncmpiCheck(ncmpi_sync(myId),__FILE__,__LINE__);
+}
+
+// Leave define mode, used for classic model
+void NcmpiFile::enddef() {
+    ncmpiCheck(ncmpi_enddef(myId),__FILE__,__LINE__);
+}
+
+NcmpiFile::FileFormat NcmpiFile::getFormat( void ) const
+{
+    int the_format;
+    ncmpiCheck(ncmpi_inq_format(myId, &the_format),__FILE__,__LINE__);
+
+    switch (the_format) {
+        case NC_FORMAT_CLASSIC:
+            return classic;
+        case NC_FORMAT_CDF2:
+            return classic2;
+        case NC_FORMAT_NETCDF4:
+            return nc4;
+        case NC_FORMAT_NETCDF4_CLASSIC:
+            return nc4classic;
+        case NC_FORMAT_CDF5:
+            return classic5;
+        default:
+            return BadFormat;
+    }
+}
+
+void NcmpiFile::Wait_all(int  num,
+                         int *array_of_requests,
+                         int *array_of_statuses)
+{
+    ncmpiCheck(ncmpi_wait_all(myId, num, array_of_requests, array_of_statuses),__FILE__,__LINE__);
+}
+
+void NcmpiFile::Wait(int  num,
+                     int *array_of_requests,
+                     int *array_of_statuses)
+{
+    ncmpiCheck(ncmpi_wait(myId, num, array_of_requests, array_of_statuses),__FILE__,__LINE__);
+}
+
+void NcmpiFile::Cancel(int  num,
+                       int *array_of_requests,
+                       int *array_of_statuses)
+{
+    ncmpiCheck(ncmpi_cancel(myId, num, array_of_requests, array_of_statuses),__FILE__,__LINE__);
+}
+
+void NcmpiFile::Buffer_attach(MPI_Offset bufsize)
+{
+    ncmpiCheck(ncmpi_buffer_attach(myId, bufsize),__FILE__,__LINE__);
+}
+
+void NcmpiFile::Buffer_detach(void)
+{
+    ncmpiCheck(ncmpi_buffer_detach(myId),__FILE__,__LINE__);
+}
+
+void NcmpiFile::Inq_buffer_usage(MPI_Offset *usage)
+{
+    ncmpiCheck(ncmpi_inq_buffer_usage(myId, usage),__FILE__,__LINE__);
+}
+
+void NcmpiFile::Inq_buffer_size(MPI_Offset *buf_size)
+{
+    ncmpiCheck(ncmpi_inq_buffer_size(myId, buf_size),__FILE__,__LINE__);
+}
+
+void NcmpiFile::Inq_nreqs(int *nreqs)
+{
+    ncmpiCheck(ncmpi_inq_nreqs(myId, nreqs),__FILE__,__LINE__);
+}
+
+void NcmpiFile::Inq_file_info(MPI_Info *info)
+{
+    ncmpiCheck(ncmpi_inq_file_info(myId, info),__FILE__,__LINE__);
+}
+
+void NcmpiFile::Inq_put_size(MPI_Offset *put_size)
+{
+    ncmpiCheck(ncmpi_inq_put_size(myId, put_size),__FILE__,__LINE__);
+}
+
+void NcmpiFile::Inq_get_size(MPI_Offset *get_size)
+{
+    ncmpiCheck(ncmpi_inq_get_size(myId, get_size),__FILE__,__LINE__);
+}
+
+void NcmpiFile::Inq_header_size(MPI_Offset *header_size)
+{
+    ncmpiCheck(ncmpi_inq_header_size(myId, header_size),__FILE__,__LINE__);
+}
+
+void NcmpiFile::Inq_header_extent(MPI_Offset *header_extent)
+{
+    ncmpiCheck(ncmpi_inq_header_extent(myId, header_extent),__FILE__,__LINE__);
+}
+
diff --git a/src/libcxx/ncmpiFile.h b/src/libcxx/ncmpiFile.h
new file mode 100644
index 0000000..515286f
--- /dev/null
+++ b/src/libcxx/ncmpiFile.h
@@ -0,0 +1,125 @@
+#include <string>
+#include "ncmpiGroup.h"
+
+#ifndef NcmpiFileClass
+#define NcmpiFileClass
+
+//!  C++ API for PnetCDF.
+namespace PnetCDF
+{
+
+  /*! 
+    Class represents a netCDF root group.
+    The Ncfile class is the same as the NcmpiGroup class with the additional
+    functionality for opening and closing files.
+   */
+  class NcmpiFile : public NcmpiGroup
+   {
+   public:
+    
+      enum FileMode 
+	 {
+	    read,	//!< File exists, open read-only.
+	    write,      //!< File exists, open for writing.
+	    replace,	//!< Create new file, even if already exists.
+	    newFile	//!< Create new file, fail if already exists.
+	 };
+
+      enum FileFormat
+         {
+	    classic,    //!< Classic format, classic data model
+	    classic2,   //!< 64-bit offset format, classic data model
+	    nc4,        //!< (default) netCDF-4/HDF5 format, enhanced data model
+	    nc4classic, //!< netCDF-4/HDF5 format, classic data model
+	    classic5,   //!< CDF-5 format, classic data model
+            BadFormat
+         };
+    
+         
+      /*! Constructor generates a \ref isNull "null object". */
+      NcmpiFile();
+
+      /*! 
+	Creates/opens a netCDF file.
+	\param comm        MPI intra-communicator
+	\param filePath    Name of netCDF optional path.
+	\param fMode       The file mode:
+	                    - 'read'    File exists, open for read-only.
+	                    - 'write'   File exists, open for writing.
+	                    - 'replace' Create new file, even it already exists.
+	                    - 'newFile' Create new file, fail it exists already.
+        \param info        MPI info object containing MPI and PnetCDF IO hints
+      */
+      NcmpiFile(const MPI_Comm    &comm,
+                const std::string &filePath,
+                FileMode           fMode,
+                const MPI_Info    &info = MPI_INFO_NULL);
+
+      /*! 
+	Creates a netCDF file of a specified format.
+	\param comm        MPI intra-communicator
+	\param filePath    Name of netCDF optional path.
+	\param fMode       The file mode:
+	                    - 'replace' Create new file, even it already exists.
+	                    - 'newFile' Create new file, fail it exists already.
+        \param info        MPI info object containing MPI and PnetCDF IO hints
+      */
+      NcmpiFile(const MPI_Comm    &comm,
+                const std::string &filePath,
+                FileMode           fMode,
+                FileFormat         fFormat,
+                const MPI_Info    &info = MPI_INFO_NULL);
+    
+      /*! destructor */
+      virtual ~NcmpiFile(); //closes file and releases all resources
+     
+      //! Synchronize an open netcdf dataset to disk
+      void sync();
+
+      //! Leave define mode, used for classic model
+      void enddef();
+
+      FileFormat getFormat( void ) const;
+
+      void Wait_all(int num, int *array_of_requests, int *array_of_statuses);
+
+      void Wait(int num, int *array_of_requests, int *array_of_statuses);
+
+      void Cancel(int num, int *array_of_requests, int *array_of_statuses);
+
+      void Buffer_attach(MPI_Offset bufsize);
+
+      void Buffer_detach(void);
+
+      void Inq_nreqs(int *nreqs);
+
+      void Inq_buffer_usage(MPI_Offset *usage);
+
+      void Inq_buffer_size(MPI_Offset *buf_size);
+
+      void Inq_file_info(MPI_Info *info);
+
+      void Inq_put_size(MPI_Offset *put_size);
+
+      void Inq_get_size(MPI_Offset *get_size);
+
+      void Inq_header_size(MPI_Offset *header_size);
+
+      void Inq_header_extent(MPI_Offset *header_extent);
+
+   private:
+	/* Do not allow definition of NcmpiFile involving copying any NcmpiFile
+           or NcmpiGroup.  Because the destructor closes the file and releases
+           al resources such an action could leave NcmpiFile objects in an
+           invalid state
+         */
+	NcmpiFile& operator =(const NcmpiGroup & rhs);
+	NcmpiFile& operator =(const NcmpiFile & rhs);
+	NcmpiFile(const NcmpiGroup& rhs);
+	NcmpiFile(const NcmpiFile& rhs);
+   };
+  
+}
+
+#endif
+
diff --git a/src/libcxx/ncmpiFloat.cpp b/src/libcxx/ncmpiFloat.cpp
new file mode 100644
index 0000000..2fc1c95
--- /dev/null
+++ b/src/libcxx/ncmpiFloat.cpp
@@ -0,0 +1,22 @@
+#include "ncmpiFloat.h"
+#include <pnetcdf.h>
+using namespace PnetCDF;
+
+// create an instance of NcmpiFloat  called PnetCDF::ncmpiFloat
+namespace PnetCDF {
+  NcmpiFloat ncmpiFloat;
+}
+
+// constructor
+NcmpiFloat::NcmpiFloat() : NcmpiType(NC_FLOAT){
+}
+
+NcmpiFloat::~NcmpiFloat() {
+}
+
+
+// equivalence operator
+bool NcmpiFloat::operator==(const NcmpiFloat & rhs)    {
+  // simply check the netCDF id.
+  return myId == rhs.myId;
+}  
diff --git a/src/libcxx/ncmpiFloat.h b/src/libcxx/ncmpiFloat.h
new file mode 100644
index 0000000..4ed7176
--- /dev/null
+++ b/src/libcxx/ncmpiFloat.h
@@ -0,0 +1,28 @@
+#include "ncmpiType.h"
+
+#ifndef NcmpiFloatClass
+#define NcmpiFloatClass
+
+namespace PnetCDF
+{
+  
+  /*! Class represents a netCDF atomic Float type. */
+  class NcmpiFloat : public NcmpiType
+  {
+  public: 
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiFloat & rhs);
+    
+    /*!  destructor */
+    ~NcmpiFloat();
+    
+    /*! Constructor */
+    NcmpiFloat();
+  };
+
+  /*! A global instance  of the NcmpiFloat class within the netCDF namespace. */
+  extern NcmpiFloat ncmpiFloat;
+
+}
+#endif
diff --git a/src/libcxx/ncmpiGroup.cpp b/src/libcxx/ncmpiGroup.cpp
new file mode 100644
index 0000000..8759e25
--- /dev/null
+++ b/src/libcxx/ncmpiGroup.cpp
@@ -0,0 +1,1456 @@
+#include "ncmpiGroup.h"
+#include "ncmpiVar.h"
+#include "ncmpiDim.h"
+#include "ncmpiVlenType.h"
+#include "ncmpiCompoundType.h"
+#include "ncmpiOpaqueType.h"
+#include "ncmpiGroupAtt.h"
+#include "ncmpiByte.h"
+#include "ncmpiUbyte.h"
+#include "ncmpiChar.h"
+#include "ncmpiShort.h"
+#include "ncmpiUshort.h"
+#include "ncmpiInt.h"
+#include "ncmpiUint.h"
+#include "ncmpiInt64.h"
+#include "ncmpiUint64.h"
+#include "ncmpiFloat.h"
+#include "ncmpiDouble.h"
+#include "ncmpiException.h"
+#include "ncmpiCheck.h"
+using namespace std;
+using namespace PnetCDF::exceptions;
+
+namespace PnetCDF {
+  //  Global comparator operator ==============
+  // comparator operator 
+  bool operator<(const NcmpiGroup& lhs,const NcmpiGroup& rhs)
+  {
+    return false;
+  }
+  
+  // comparator operator 
+  bool operator>(const NcmpiGroup& lhs,const NcmpiGroup& rhs)
+  {
+    return true;
+  }
+}
+
+using namespace PnetCDF;
+    
+/////////////////////////////////////////////
+
+NcmpiGroup::~NcmpiGroup()
+{
+}
+
+// Constructor generates a null object.
+NcmpiGroup::NcmpiGroup() :
+  nullObject(true)
+{}
+
+   
+// constructor
+NcmpiGroup::NcmpiGroup(const int groupId) :
+  nullObject(false),
+  myId(groupId)
+{ }
+
+// assignment operator
+NcmpiGroup& NcmpiGroup::operator=(const NcmpiGroup & rhs)
+{
+  nullObject = rhs.nullObject;
+  myId = rhs.myId;
+  return *this;
+}
+
+// The copy constructor.
+NcmpiGroup::NcmpiGroup(const NcmpiGroup& rhs): 
+  nullObject(rhs.nullObject),
+  myId(rhs.myId)
+{}
+
+
+// equivalence operator
+bool NcmpiGroup::operator==(const NcmpiGroup & rhs) const
+{
+  if(nullObject) 
+    return nullObject == rhs.nullObject;
+  else
+    return myId == rhs.myId;
+}  
+  
+//  !=  operator
+bool NcmpiGroup::operator!=(const NcmpiGroup & rhs) const
+{
+  return !(*this == rhs);
+}  
+  
+  
+// /////////////
+// NcmpiGroup-related methods
+// /////////////
+  
+// Get the group name.
+string NcmpiGroup::getName(bool fullName) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getName on a Null group",__FILE__,__LINE__);
+  string groupName;
+  if(fullName){
+    // return full name of group with foward "/" separarating sub-groups.
+    MPI_Offset lenp;
+    ncmpiCheck(ncmpi_inq_grpname_len(myId,&lenp),__FILE__,__LINE__);
+    char* charName= new char[lenp+1];
+    ncmpiCheck(ncmpi_inq_grpname_full(myId,&lenp,charName),__FILE__,__LINE__);
+    groupName = charName;
+    delete charName;
+  }
+  else {
+    // return the (local) name of this group.
+    char charName[NC_MAX_NAME+1];
+    // ncmpiCheck(ncmpi_inq_grpname(myId,charName),__FILE__,__LINE__);
+    charName[0] = '/'; charName[1] = '\0';
+    groupName = charName;
+  }
+  return groupName;
+}
+
+// returns true if this is the root group.
+bool NcmpiGroup::isRootGroup()  const{
+  bool result = getName() == "/";
+  return result;
+}
+  
+// Get the parent group.
+NcmpiGroup NcmpiGroup::getParentGroup() const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getParentGroup on a Null group",__FILE__,__LINE__);
+  try {
+    int parentId;
+    ncmpiCheck(ncmpi_inq_grp_parent(myId,&parentId),__FILE__,__LINE__);
+    NcmpiGroup ncmpiGroupParent(parentId);
+    return ncmpiGroupParent;
+  }
+  catch (NcEnoGrp& e) {
+    // no group found, so return null group
+    return NcmpiGroup();
+  }
+}
+  
+  
+// Get the group id.
+int  NcmpiGroup::getId() const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getId on a Null group",__FILE__,__LINE__);
+  return myId;
+}
+  
+// Get the number of NcmpiGroup objects.
+int NcmpiGroup::getGroupCount(NcmpiGroup::GroupLocation location) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getGroupCount on a Null group",__FILE__,__LINE__);
+  // initialize group counter
+  int ngroups=0;
+
+  // record this group
+  if(location == ParentsAndCurrentGrps || location == AllGrps) {
+    ngroups ++;
+  }
+
+  // number of children in current group
+  if(location == ChildrenGrps || location == AllChildrenGrps || location == AllGrps ) {
+    int numgrps;
+    int* ncids=NULL;
+    ncmpiCheck(ncmpi_inq_grps(getId(), &numgrps,ncids),__FILE__,__LINE__);
+    ngroups += numgrps;
+  }
+
+  // search in parent groups
+  if(location == ParentsGrps || location == ParentsAndCurrentGrps || location == AllGrps ) {
+    multimap<string,NcmpiGroup> groups(getGroups(ParentsGrps));
+    ngroups += groups.size();
+  }
+
+
+  // get the number of all children that are childreof children
+  if(location == ChildrenOfChildrenGrps || location == AllChildrenGrps || location == AllGrps ) {
+    multimap<string,NcmpiGroup> groups(getGroups(ChildrenOfChildrenGrps));
+    ngroups += groups.size();
+  }
+
+  return ngroups;
+}
+
+  
+// Get the set of child NcmpiGroup objects.
+multimap<std::string,NcmpiGroup> NcmpiGroup::getGroups(NcmpiGroup::GroupLocation location) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getGroups on a Null group",__FILE__,__LINE__);
+  // create a container to hold the NcmpiGroup's.
+  multimap<string,NcmpiGroup> ncmpiGroups;
+
+  // record this group
+  if(location == ParentsAndCurrentGrps || location == AllGrps) {
+    ncmpiGroups.insert(pair<const string,NcmpiGroup>(getName(),*this));
+  }
+
+  // the child groups of the current group
+  if(location == ChildrenGrps || location == AllChildrenGrps || location == AllGrps ) {
+    // get the number of groups
+    int groupCount = getGroupCount();
+    if (groupCount){
+      vector<int> ncids(groupCount);
+      int* numgrps=NULL;
+      // now get the id of each NcmpiGroup and populate the ncmpiGroups container.
+      ncmpiCheck(ncmpi_inq_grps(myId, numgrps,&ncids[0]),__FILE__,__LINE__);
+      for(int i=0; i<groupCount;i++){
+        NcmpiGroup tmpGroup(ncids[i]);
+        ncmpiGroups.insert(pair<const string,NcmpiGroup>(tmpGroup.getName(),tmpGroup));
+      }
+    }
+  }
+
+  // search in parent groups.
+  if(location == ParentsGrps || location == ParentsAndCurrentGrps || location == AllGrps ) {
+    NcmpiGroup tmpGroup(*this); 
+    if(!tmpGroup.isRootGroup()) {
+      while(1) {
+	const NcmpiGroup parentGroup(tmpGroup.getParentGroup());
+	if(parentGroup.isNull()) break;
+	ncmpiGroups.insert(pair<const string,NcmpiGroup>(parentGroup.getName(),parentGroup));
+	tmpGroup=parentGroup;
+      }
+    }
+  }
+ 
+  // search in child groups of the children
+  if(location == ChildrenOfChildrenGrps || location == AllChildrenGrps || location == AllGrps ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups(ChildrenGrps));
+    for (it=groups.begin();it!=groups.end();it++) {
+      multimap<string,NcmpiGroup> childGroups(it->second.getGroups(AllChildrenGrps));
+      ncmpiGroups.insert(childGroups.begin(),childGroups.end());
+    }
+  }
+  
+  return ncmpiGroups;
+}
+  
+// Get the named child NcmpiGroup object.
+NcmpiGroup NcmpiGroup::getGroup(const string& name,NcmpiGroup::GroupLocation location) const{
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getGroup on a Null group",__FILE__,__LINE__);
+  multimap<string,NcmpiGroup> ncmpiGroups(getGroups(location));
+  pair<multimap<string,NcmpiGroup>::iterator,multimap<string,NcmpiGroup>::iterator> ret;
+  ret = ncmpiGroups.equal_range(name);
+  if(ret.first == ret.second) 
+    return NcmpiGroup();  // null group is returned
+  else 
+    return ret.first->second;
+}
+
+  
+
+// Get all NcmpiGroup objects with a given name.
+set<NcmpiGroup> NcmpiGroup::getGroups(const std::string& name,NcmpiGroup::GroupLocation location) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getGroups on a Null group",__FILE__,__LINE__);
+  // get the set of ncmpiGroups in this group and above.
+  multimap<std::string,NcmpiGroup> ncmpiGroups(getGroups(location));
+  pair<multimap<string,NcmpiGroup>::iterator,multimap<string,NcmpiGroup>::iterator> ret;
+  multimap<string,NcmpiGroup>::iterator it;
+  ret = ncmpiGroups.equal_range(name);
+  set<NcmpiGroup> tmpGroup;
+  for (it=ret.first; it!=ret.second; ++it) {
+    tmpGroup.insert(it->second);
+  }
+  return tmpGroup;
+}
+
+// Add a new child NcmpiGroup object.
+NcmpiGroup NcmpiGroup::addGroup(const string& name) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::addGroup on a Null group",__FILE__,__LINE__);
+  int new_ncid;
+  ncmpiCheck(ncmpi_def_grp(myId,const_cast<char*> (name.c_str()),&new_ncid),__FILE__,__LINE__);
+  return NcmpiGroup(new_ncid);
+}
+
+
+  
+// /////////////
+// NcmpiVar-related accessors
+// /////////////
+  
+// Get the number of NcmpiVar objects in this group.
+int NcmpiGroup::getVarCount(NcmpiGroup::Location location) const {
+
+  // search in current group.
+  NcmpiGroup tmpGroup(*this); 
+  int nvars=0;
+  // search in current group
+  if((location == ParentsAndCurrent || location == ChildrenAndCurrent || location == Current || location ==All) && !tmpGroup.isNull()) {
+    ncmpiCheck(ncmpi_inq_nvars(tmpGroup.getId(), &nvars),__FILE__,__LINE__);
+  }
+
+  // search recursively in all parent groups.
+  if(location == Parents || location == ParentsAndCurrent || location ==All) {
+    tmpGroup=getParentGroup();
+    while(!tmpGroup.isNull()) {
+      int nvarsp;
+      ncmpiCheck(ncmpi_inq_nvars(tmpGroup.getId(), &nvarsp),__FILE__,__LINE__);
+      nvars += nvarsp;
+      // continue loop with the parent.
+      tmpGroup=tmpGroup.getParentGroup();
+    }
+  }
+
+  // search recursively in all child groups
+  if(location == ChildrenAndCurrent || location == Children || location == All) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups());
+    for (it=groups.begin();it!=groups.end();it++) {
+      nvars += it->second.getVarCount(ChildrenAndCurrent);
+    }
+  }
+  return nvars;
+}
+
+// Get the number of record variable NcmpiVar objects in this group.
+int NcmpiGroup::getRecVarCount(NcmpiGroup::Location location) const {
+
+  // search in current group.
+  NcmpiGroup tmpGroup(*this); 
+  int nvars=0;
+  // search in current group
+  if((location == ParentsAndCurrent || location == ChildrenAndCurrent || location == Current || location ==All) && !tmpGroup.isNull()) {
+    ncmpiCheck(ncmpi_inq_num_rec_vars(tmpGroup.getId(), &nvars),__FILE__,__LINE__);
+  }
+
+  // search recursively in all parent groups.
+  if(location == Parents || location == ParentsAndCurrent || location ==All) {
+    tmpGroup=getParentGroup();
+    while(!tmpGroup.isNull()) {
+      int nvarsp;
+      ncmpiCheck(ncmpi_inq_num_rec_vars(tmpGroup.getId(), &nvarsp),__FILE__,__LINE__);
+      nvars += nvarsp;
+      // continue loop with the parent.
+      tmpGroup=tmpGroup.getParentGroup();
+    }
+  }
+
+  // search recursively in all child groups
+  if(location == ChildrenAndCurrent || location == Children || location == All) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups());
+    for (it=groups.begin();it!=groups.end();it++) {
+      nvars += it->second.getRecVarCount(ChildrenAndCurrent);
+    }
+  }
+  return nvars;
+}
+
+// Get the number of fixed-size variable NcmpiVar objects in this group.
+int NcmpiGroup::getFixVarCount(NcmpiGroup::Location location) const {
+
+  // search in current group.
+  NcmpiGroup tmpGroup(*this); 
+  int nvars=0;
+  // search in current group
+  if((location == ParentsAndCurrent || location == ChildrenAndCurrent || location == Current || location ==All) && !tmpGroup.isNull()) {
+    ncmpiCheck(ncmpi_inq_num_fix_vars(tmpGroup.getId(), &nvars),__FILE__,__LINE__);
+  }
+
+  // search recursively in all parent groups.
+  if(location == Parents || location == ParentsAndCurrent || location ==All) {
+    tmpGroup=getParentGroup();
+    while(!tmpGroup.isNull()) {
+      int nvarsp;
+      ncmpiCheck(ncmpi_inq_num_fix_vars(tmpGroup.getId(), &nvarsp),__FILE__,__LINE__);
+      nvars += nvarsp;
+      // continue loop with the parent.
+      tmpGroup=tmpGroup.getParentGroup();
+    }
+  }
+
+  // search recursively in all child groups
+  if(location == ChildrenAndCurrent || location == Children || location == All) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups());
+    for (it=groups.begin();it!=groups.end();it++) {
+      nvars += it->second.getFixVarCount(ChildrenAndCurrent);
+    }
+  }
+  return nvars;
+}
+
+// Get the size of record block, sum of single record of all record variables
+MPI_Offset NcmpiGroup::getRecSize(NcmpiGroup::Location location) const {
+
+  // search in current group.
+  NcmpiGroup tmpGroup(*this); 
+  MPI_Offset recsize=0;
+  // search in current group
+  if((location == ParentsAndCurrent || location == ChildrenAndCurrent || location == Current || location ==All) && !tmpGroup.isNull()) {
+    ncmpiCheck(ncmpi_inq_recsize(tmpGroup.getId(), &recsize),__FILE__,__LINE__);
+  }
+  return recsize;
+}
+
+// Get the collection of NcmpiVar objects.
+multimap<std::string,NcmpiVar> NcmpiGroup::getVars(NcmpiGroup::Location location) const {
+
+  // create a container to hold the NcmpiVar's.
+  multimap<string,NcmpiVar> ncmpiVars;
+
+  // search in current group.
+  NcmpiGroup tmpGroup(*this); 
+  if((location == ParentsAndCurrent || location == ChildrenAndCurrent || location == Current || location ==All) && !tmpGroup.isNull()) {
+    // get the number of variables.
+    int varCount = getVarCount();
+    if (varCount){
+      // now get the name of each NcmpiVar object and populate the ncmpiVars container.
+      // int* nvars=NULL;
+      // vector<int> varids(varCount);
+      // ncmpiCheck(ncmpi_inq_varids(myId, nvars,&varids[0]),__FILE__,__LINE__);
+      for(int i=0; i<varCount;i++){
+        // NcmpiVar tmpVar(*this,varids[i]);
+        NcmpiVar tmpVar(*this,i);
+        ncmpiVars.insert(pair<const string,NcmpiVar>(tmpVar.getName(),tmpVar));
+      }
+    }
+  }
+
+  
+  // search recursively in all parent groups.
+  if(location == Parents || location == ParentsAndCurrent || location ==All) {
+    tmpGroup=getParentGroup();
+    while(!tmpGroup.isNull()) {
+      // get the number of variables
+      int varCount = tmpGroup.getVarCount();
+      if (varCount){
+        // now get the name of each NcmpiVar object and populate the ncmpiVars container.
+        int* nvars=NULL;
+        vector<int> varids(varCount);
+        ncmpiCheck(ncmpi_inq_varids(tmpGroup.getId(), nvars,&varids[0]),__FILE__,__LINE__);
+        for(int i=0; i<varCount;i++){
+          NcmpiVar tmpVar(tmpGroup,varids[i]);
+          ncmpiVars.insert(pair<const string,NcmpiVar>(tmpVar.getName(),tmpVar));
+        }
+      }
+      // continue loop with the parent.
+      tmpGroup=tmpGroup.getParentGroup();
+    }
+  }
+
+  // search recusively in all child groups.
+  if(location == ChildrenAndCurrent || location == Children  || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups());
+    for (it=groups.begin();it!=groups.end();it++) {
+      multimap<string,NcmpiVar> vars=it->second.getVars(ChildrenAndCurrent);
+      ncmpiVars.insert(vars.begin(),vars.end());
+    }
+  }
+
+  return ncmpiVars;
+}
+  
+
+// Get all NcmpiVar objects with a given name.
+set<NcmpiVar> NcmpiGroup::getVars(const string& name,NcmpiGroup::Location location) const {
+  // get the set of ncmpiVars in this group and above.
+  multimap<std::string,NcmpiVar> ncmpiVars(getVars(location));
+  pair<multimap<string,NcmpiVar>::iterator,multimap<string,NcmpiVar>::iterator> ret;
+  multimap<string,NcmpiVar>::iterator it;
+  ret = ncmpiVars.equal_range(name);
+  set<NcmpiVar> tmpVar;
+  for (it=ret.first; it!=ret.second; ++it) {
+    tmpVar.insert(it->second);
+  }
+  return tmpVar;
+}
+
+
+
+// Get the named NcmpiVar object.
+NcmpiVar NcmpiGroup::getVar(const string& name,NcmpiGroup::Location location) const {
+  multimap<std::string,NcmpiVar> ncmpiVars(getVars(location));
+  pair<multimap<string,NcmpiVar>::iterator,multimap<string,NcmpiVar>::iterator> ret;
+  ret = ncmpiVars.equal_range(name);
+  if(ret.first == ret.second) 
+    // no matching netCDF variable found so return null object.
+    return NcmpiVar();
+  else 
+    return ret.first->second;
+}
+
+// Adds a new netCDF scalar variable.
+NcmpiVar NcmpiGroup::addVar(const std::string& name, const NcmpiType& ncmpiType) const {
+  return NcmpiGroup::addVar(name, ncmpiType, std::vector<NcmpiDim>());
+}   
+
+// Add a new netCDF variable.
+NcmpiVar NcmpiGroup::addVar(const string& name, const string& typeName, const string& dimName) const {
+  ncmpiCheckDefineMode(myId);
+    
+  // get an NcmpiType object with the given type name.
+  NcmpiType tmpType(getType(typeName,NcmpiGroup::ParentsAndCurrent));
+  if(tmpType.isNull()) throw NcNullType("Attempt to invoke NcmpiGroup::addVar failed: typeName must be defined in either the current group or a parent group",__FILE__,__LINE__);
+
+  // get a NcmpiDim object with the given dimension name
+  NcmpiDim tmpDim(getDim(dimName,NcmpiGroup::ParentsAndCurrent));
+  if(tmpDim.isNull()) throw NcNullDim("Attempt to invoke NcmpiGroup::addVar failed: dimName must be defined in either the current group or a parent group",__FILE__,__LINE__);
+
+  // finally define a new netCDF  variable
+  int varId;
+  int dimId(tmpDim.getId());
+  ncmpiCheck(ncmpi_def_var(myId,name.c_str(),tmpType.getId(),1,&dimId,&varId),__FILE__,__LINE__);
+  // return an NcmpiVar object for this new variable
+  return NcmpiVar(*this,varId);
+}
+
+
+// Add a new netCDF variable.
+NcmpiVar NcmpiGroup::addVar(const string& name, const NcmpiType& ncmpiType, const NcmpiDim& ncmpiDim) const {
+  ncmpiCheckDefineMode(myId);
+    
+  // check NcmpiType object is valid
+  if(ncmpiType.isNull()) throw NcNullType("Attempt to invoke NcmpiGroup::addVar with a Null NcmpiType object",__FILE__,__LINE__);
+  NcmpiType tmpType(getType(ncmpiType.getName(),NcmpiGroup::ParentsAndCurrent));
+  if(tmpType.isNull()) throw NcNullType("Attempt to invoke NcmpiGroup::addVar failed: NcmpiType must be defined in either the current group or a parent group",__FILE__,__LINE__);
+  
+  // check NcmpiDim object is valid
+  if(ncmpiDim.isNull()) throw NcNullDim("Attempt to invoke NcmpiGroup::addVar with a Null NcmpiDim object",__FILE__,__LINE__);
+  NcmpiDim tmpDim(getDim(ncmpiDim.getName(),NcmpiGroup::ParentsAndCurrent));
+  if(tmpDim.isNull()) throw NcNullDim("Attempt to invoke NcmpiGroup::addVar failed: NcmpiDim must be defined in either the current group or a parent group",__FILE__,__LINE__);
+  
+  // finally define a new netCDF variable
+  int varId;
+  int dimId(tmpDim.getId());
+  ncmpiCheck(ncmpi_def_var(myId,name.c_str(),tmpType.getId(),1,&dimId,&varId),__FILE__,__LINE__);
+  // return an NcmpiVar object for this new variable
+  return NcmpiVar(*this,varId);
+}
+
+
+// Add a new netCDF multi-dimensional variable.
+NcmpiVar NcmpiGroup::addVar(const string& name, const string& typeName, const vector<string>& dimNames) const {
+  ncmpiCheckDefineMode(myId);
+    
+  // get an NcmpiType object with the given name.
+  NcmpiType tmpType(getType(typeName,NcmpiGroup::ParentsAndCurrent));
+  if(tmpType.isNull()) throw NcNullType("Attempt to invoke NcmpiGroup::addVar failed: typeName must be defined in either the current group or a parent group",__FILE__,__LINE__);
+
+  // get a set of NcmpiDim objects corresponding to the given dimension names.
+  vector<int> dimIds;
+  dimIds.reserve(dimNames.size());
+  for (size_t i=0; i<dimNames.size();i++){
+    NcmpiDim tmpDim(getDim(dimNames[i],NcmpiGroup::ParentsAndCurrent));
+    if(tmpDim.isNull()) throw NcNullDim("Attempt to invoke NcmpiGroup::addVar failed: dimNames must be defined in either the current group or a parent group",__FILE__,__LINE__);
+    dimIds.push_back(tmpDim.getId());
+  }
+
+  // finally define a new netCDF variable
+  int varId;
+  int *dimIdsPtr = dimIds.empty() ? 0 : &dimIds[0];
+  ncmpiCheck(ncmpi_def_var(myId,name.c_str(),tmpType.getId(),dimIds.size(), dimIdsPtr,&varId),__FILE__,__LINE__);
+  // return an NcmpiVar object for this new variable
+  return NcmpiVar(*this,varId);
+}
+
+// Add a new netCDF multi-dimensional variable.
+NcmpiVar NcmpiGroup::addVar(const string& name, const NcmpiType& ncmpiType, const vector<NcmpiDim>& ncmpiDimVector) const {
+  ncmpiCheckDefineMode(myId);
+    
+  // check NcmpiType object is valid
+  if(ncmpiType.isNull()) throw NcNullType("Attempt to invoke NcmpiGroup::addVar with a Null NcmpiType object",__FILE__,__LINE__);
+  NcmpiType tmpType(getType(ncmpiType.getName(),NcmpiGroup::ParentsAndCurrent));
+  if(tmpType.isNull()) throw NcNullType("Attempt to invoke NcmpiGroup::addVar failed: NcmpiType must be defined in either the current group or a parent group",__FILE__,__LINE__);
+  
+  // check NcmpiDim objects are valid
+  vector<NcmpiDim>::const_iterator iter;
+  vector<int> dimIds;
+  dimIds.reserve(ncmpiDimVector.size());
+  for (iter=ncmpiDimVector.begin();iter < ncmpiDimVector.end(); iter++) {
+    if(iter->isNull()) throw NcNullDim("Attempt to invoke NcmpiGroup::addVar with a Null NcmpiDim object",__FILE__,__LINE__);
+    NcmpiDim tmpDim(getDim(iter->getName(),NcmpiGroup::ParentsAndCurrent));
+    if(tmpDim.isNull()) throw NcNullDim("Attempt to invoke NcmpiGroup::addVar failed: NcmpiDim must be defined in either the current group or a parent group",__FILE__,__LINE__);
+    dimIds.push_back(tmpDim.getId());
+  }
+
+  // finally define a new netCDF variable
+  int varId;
+  int *dimIdsPtr = dimIds.empty() ? 0 : &dimIds[0];
+  ncmpiCheck(ncmpi_def_var(myId,name.c_str(),tmpType.getId(),dimIds.size(), dimIdsPtr,&varId),__FILE__,__LINE__);
+  // return an NcmpiVar object for this new variable
+  return NcmpiVar(*this,varId);
+}
+
+
+// /////////////
+// NcmpiAtt-related methods
+// /////////////
+  
+// Get the number of group attributes.
+int NcmpiGroup::getAttCount(NcmpiGroup::Location location) const {
+
+  // search in current group.
+  NcmpiGroup tmpGroup(*this); 
+  int ngatts=0;
+  // search in current group
+  if((location == ParentsAndCurrent || location == ChildrenAndCurrent || location == Current || location ==All) && !tmpGroup.isNull()) {
+    ncmpiCheck(ncmpi_inq_natts(tmpGroup.getId(), &ngatts),__FILE__,__LINE__);
+  }
+
+  // search recursively in all parent groups.
+  if(location == Parents || location == ParentsAndCurrent || location ==All) {
+    tmpGroup=getParentGroup();
+    while(!tmpGroup.isNull()) {
+      int ngattsp;
+      ncmpiCheck(ncmpi_inq_natts(tmpGroup.getId(), &ngattsp),__FILE__,__LINE__);
+      ngatts += ngattsp;
+      // continue loop with the parent.
+      tmpGroup=tmpGroup.getParentGroup();
+    }
+  }
+
+  // search recursively in all child groups
+  if(location == ChildrenAndCurrent || location == Children || location == All) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups());
+    for (it=groups.begin();it!=groups.end();it++) {
+      ngatts += it->second.getAttCount(ChildrenAndCurrent);
+    }
+  }
+
+  return ngatts;
+}
+  
+// Get the collection of NcmpiGroupAtt objects.
+multimap<std::string,NcmpiGroupAtt> NcmpiGroup::getAtts(NcmpiGroup::Location location) const {
+
+  // create a container to hold the NcmpiAtt's.
+  multimap<string,NcmpiGroupAtt> ncmpiAtts;
+
+  // search in current group.
+  NcmpiGroup tmpGroup(*this); 
+  if((location == ParentsAndCurrent || location == ChildrenAndCurrent || location == Current || location ==All) && !tmpGroup.isNull()) {
+    // get the number of attributes
+    int attCount = tmpGroup.getAttCount();
+    // now get the name of each NcmpiAtt and populate the ncmpiAtts container.
+    for(int i=0; i<attCount;i++){
+      char charName[NC_MAX_NAME+1];
+      ncmpiCheck(ncmpi_inq_attname(tmpGroup.getId(),NC_GLOBAL,i,charName),__FILE__,__LINE__);
+      NcmpiGroupAtt tmpAtt(tmpGroup.getId(),i);
+      ncmpiAtts.insert(pair<const string,NcmpiGroupAtt>(string(charName),tmpAtt));
+    }
+  }
+  
+  // search recursively in all parent groups.
+  if(location == Parents || location == ParentsAndCurrent || location ==All) {
+    tmpGroup=getParentGroup();
+    while(!tmpGroup.isNull()) {
+      // get the number of attributes
+      int attCount = tmpGroup.getAttCount();
+      // now get the name of each NcmpiAtt and populate the ncmpiAtts container.
+      for(int i=0; i<attCount;i++){
+        char charName[NC_MAX_NAME+1];
+        ncmpiCheck(ncmpi_inq_attname(tmpGroup.getId(),NC_GLOBAL,i,charName),__FILE__,__LINE__);
+        NcmpiGroupAtt tmpAtt(tmpGroup.getId(),i);
+        ncmpiAtts.insert(pair<const string,NcmpiGroupAtt>(string(charName),tmpAtt));
+      }
+      // continue loop with the parent.
+      tmpGroup=tmpGroup.getParentGroup();
+    }
+  }
+
+  // search recusively in all child groups.
+  if(location == ChildrenAndCurrent || location == Children  || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups());
+    for (it=groups.begin();it!=groups.end();it++) {
+      multimap<string,NcmpiGroupAtt> atts=it->second.getAtts(ChildrenAndCurrent);
+      ncmpiAtts.insert(atts.begin(),atts.end());
+    }
+  }
+
+  return ncmpiAtts;
+}
+  
+// Get the named NcmpiGroupAtt object.
+NcmpiGroupAtt NcmpiGroup::getAtt(const std::string& name,NcmpiGroup::Location location) const {
+  multimap<std::string,NcmpiGroupAtt> ncmpiAtts(getAtts(location));
+  pair<multimap<string,NcmpiGroupAtt>::iterator,multimap<string,NcmpiGroupAtt>::iterator> ret;
+  ret = ncmpiAtts.equal_range(name);
+  if(ret.first == ret.second) 
+    // no matching groupAttribute so return null object.
+    return NcmpiGroupAtt();
+  else 
+    return ret.first->second;
+}
+
+// Get all NcmpiGroupAtt objects with a given name.
+set<NcmpiGroupAtt> NcmpiGroup::getAtts(const string& name,NcmpiGroup::Location location) const {
+  // get the set of ncmpiGroupAtts in this group and above.
+  multimap<std::string,NcmpiGroupAtt> ncmpiAtts(getAtts(location));
+  pair<multimap<string,NcmpiGroupAtt>::iterator,multimap<string,NcmpiGroupAtt>::iterator> ret;
+  multimap<string,NcmpiGroupAtt>::iterator it;
+  ret = ncmpiAtts.equal_range(name);
+  set<NcmpiGroupAtt> tmpAtt;
+  for (it=ret.first; it!=ret.second; ++it) {
+    tmpAtt.insert(it->second);
+  }
+  return tmpAtt;
+}
+
+
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const string& dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  ncmpiCheck(ncmpi_put_att_text(myId,NC_GLOBAL,name.c_str(),dataValues.size(),dataValues.c_str()),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const unsigned char* dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_uchar(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const signed char* dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_schar(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, short datumValue) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_short(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, int datumValue) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_int(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, long datumValue) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_long(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, float datumValue) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_float(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, double datumValue) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_double(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, unsigned short datumValue) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_ushort(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, unsigned int datumValue) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_uint(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, long long datumValue) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_longlong(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, unsigned long long datumValue) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_ulonglong(myId,NC_GLOBAL,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const short* dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_short(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const int* dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_int(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const long* dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_long(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const float* dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_float(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const double* dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_double(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const unsigned short* dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_ushort(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const unsigned int* dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_uint(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const long long* dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_longlong(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const unsigned long long* dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_ulonglong(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+//  Creates a new NetCDF group attribute or if already exisiting replaces it.
+ NcmpiGroupAtt NcmpiGroup::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const void* dataValues) const {
+  ncmpiCheckDefineMode(myId);
+  ncmpiCheck(ncmpi_put_att(myId,NC_GLOBAL,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+  
+// /////////////
+// NcmpiDim-related methods
+// /////////////
+  
+// Get the number of NcmpiDim objects.
+int NcmpiGroup::getDimCount(NcmpiGroup::Location location) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getDimCount on a Null group",__FILE__,__LINE__);
+
+  // intialize counter
+  int ndims=0;
+
+  // search in current group
+  if(location == Current || location == ParentsAndCurrent || location == ChildrenAndCurrent || location == All ) {
+    int ndimsp;
+    ncmpiCheck(ncmpi_inq_ndims(getId(), &ndimsp),__FILE__,__LINE__);
+    ndims += ndimsp;
+  }
+
+  // search in parent groups.
+  if(location == Parents || location == ParentsAndCurrent || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups(ParentsGrps));
+    for (it=groups.begin();it!=groups.end();it++) {
+      ndims += it->second.getDimCount();
+    }
+  }
+  
+  // search in child groups.
+  if(location == Children || location == ChildrenAndCurrent || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups(AllChildrenGrps));
+    for (it=groups.begin();it!=groups.end();it++) {
+      ndims += it->second.getDimCount();
+    }
+  }
+  return ndims;
+}
+
+
+// Get the set of NcmpiDim objects.
+multimap<string,NcmpiDim> NcmpiGroup::getDims(NcmpiGroup::Location location) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getDims on a Null group",__FILE__,__LINE__);
+  // create a container to hold the NcmpiDim's.
+  multimap<string,NcmpiDim> ncmpiDims;
+
+  // search in current group
+  if(location == Current || location == ParentsAndCurrent || location == ChildrenAndCurrent || location == All ) {
+    int dimCount = getDimCount();
+    if (dimCount){
+      vector<int> dimids(dimCount);
+      // ncmpiCheck(ncmpi_inq_dimids(getId(), &dimCount, &dimids[0], 0),__FILE__,__LINE__);
+      ncmpiCheck(ncmpi_inq_ndims(getId(), &dimCount),__FILE__,__LINE__);
+      // now get the name of each NcmpiDim and populate the nDims container.
+      for(int i=0; i<dimCount;i++){
+        dimids[i] = i;
+        NcmpiDim tmpDim(*this,dimids[i]); 
+        ncmpiDims.insert(pair<const string,NcmpiDim>(tmpDim.getName(),tmpDim));
+      }
+    }
+  }
+
+  // search in parent groups.
+  if(location == Parents || location == ParentsAndCurrent || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups(ParentsGrps));
+    for (it=groups.begin();it!=groups.end();it++) {
+      multimap<string,NcmpiDim> dimTmp(it->second.getDims());
+      ncmpiDims.insert(dimTmp.begin(),dimTmp.end());
+    }
+  }
+
+  // search in child groups (makes recursive calls).
+  if(location == Children || location == ChildrenAndCurrent || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups(AllChildrenGrps));
+    for (it=groups.begin();it!=groups.end();it++) {
+      multimap<string,NcmpiDim> dimTmp(it->second.getDims());
+      ncmpiDims.insert(dimTmp.begin(),dimTmp.end());
+    }
+  }
+
+  return ncmpiDims;
+}
+
+
+
+// Get the named NcmpiDim object.
+NcmpiDim NcmpiGroup::getDim(const string& name,NcmpiGroup::Location location) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getDim on a Null group",__FILE__,__LINE__);
+  multimap<string,NcmpiDim> ncmpiDims(getDims(location));
+  pair<multimap<string,NcmpiDim>::iterator,multimap<string,NcmpiDim>::iterator> ret;
+  ret = ncmpiDims.equal_range(name);
+  if(ret.first == ret.second) 
+    return NcmpiDim(); // null group is returned
+  else 
+    return ret.first->second;
+}
+
+
+// Get all NcmpiDim objects with a given name.
+set<NcmpiDim> NcmpiGroup::getDims(const string& name,NcmpiGroup::Location location) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getDims on a Null group",__FILE__,__LINE__);
+  // get the set of ncmpiDims in this group and above.
+  multimap<string,NcmpiDim> ncmpiDims(getDims(location));
+  pair<multimap<string,NcmpiDim>::iterator,multimap<string,NcmpiDim>::iterator> ret;
+  multimap<string,NcmpiDim>::iterator it;
+  ret = ncmpiDims.equal_range(name);
+  set<NcmpiDim> tmpDim;
+  for (it=ret.first; it!=ret.second; ++it) {
+    tmpDim.insert(it->second);
+  }
+  return tmpDim;
+}
+
+// Add a new NcmpiDim object.
+NcmpiDim NcmpiGroup::addDim(const string& name, MPI_Offset dimSize) const {
+  ncmpiCheckDefineMode(myId);
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::addDim on a Null group",__FILE__,__LINE__);
+  int dimId;
+  ncmpiCheck(ncmpi_def_dim(myId,name.c_str(),dimSize,&dimId),__FILE__,__LINE__);
+  // finally return NcmpiDim object for this new variable
+  return NcmpiDim(*this,dimId);
+}
+
+// Add a new NcmpiDim object with unlimited size..
+NcmpiDim NcmpiGroup::addDim(const string& name) const {
+  ncmpiCheckDefineMode(myId);
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::addDim on a Null group",__FILE__,__LINE__);
+  int dimId;
+  ncmpiCheck(ncmpi_def_dim(myId,name.c_str(),NC_UNLIMITED,&dimId),__FILE__,__LINE__);
+  // finally return NcmpiDim object for this new variable
+  return NcmpiDim(*this,dimId);
+}
+
+
+
+
+
+// /////////////
+// type-object related methods
+// /////////////
+
+// Gets the number of type objects.
+int NcmpiGroup::getTypeCount(NcmpiGroup::Location location) const {
+
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getTypeCount on a Null group",__FILE__,__LINE__);
+
+  // intialize counter
+  int ntypes=0;
+
+  // search in current group
+  if(location == Current || location == ParentsAndCurrent || location == ChildrenAndCurrent || location == All ) {
+    int ntypesp=0;
+    int* typeidsp=NULL;
+    ncmpiCheck(ncmpi_inq_typeids(getId(), &ntypesp,typeidsp),__FILE__,__LINE__);
+    ntypes+= ntypesp;
+  }
+
+  // search in parent groups.
+  if(location == Parents || location == ParentsAndCurrent || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups(ParentsGrps));
+    for (it=groups.begin();it!=groups.end();it++) {
+      ntypes += it->second.getTypeCount();
+    }
+  }
+  
+  // search in child groups.
+  if(location == Children || location == ChildrenAndCurrent || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups(AllChildrenGrps));
+    for (it=groups.begin();it!=groups.end();it++) {
+      ntypes += it->second.getTypeCount();
+    }
+  }
+  return ntypes;
+}
+
+
+  
+// Gets the number of type objects with a given enumeration type.
+int NcmpiGroup::getTypeCount(NcmpiType::ncmpiType enumType, NcmpiGroup::Location location) const {
+
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getTypeCount on a Null group",__FILE__,__LINE__);
+
+  // intialize counter
+  int ntypes=0;
+
+  // search in current group
+  if(location == Current || location == ParentsAndCurrent || location == ChildrenAndCurrent || location == All ) {
+    int ntypesp=0;
+    int* typeidsp=NULL;
+    ncmpiCheck(ncmpi_inq_typeids(getId(), &ntypesp,typeidsp),__FILE__,__LINE__);
+    if (ntypesp){
+      vector<int> typeids(ntypesp);
+      ncmpiCheck(ncmpi_inq_typeids(getId(), &ntypesp,&typeids[0]),__FILE__,__LINE__);
+      for (int i=0; i<ntypesp;i++){
+        NcmpiType tmpType(*this,typeids[i]);
+        if(tmpType.getTypeClass() == enumType) ntypes++;
+      }
+    }
+  }
+
+  // search in parent groups.
+  if(location == Parents || location == ParentsAndCurrent || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups(ParentsGrps));
+    for (it=groups.begin();it!=groups.end();it++) {
+      ntypes += it->second.getTypeCount(enumType);
+    }
+  }
+  
+  // search in child groups.
+  if(location == Children || location == ChildrenAndCurrent || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups(AllChildrenGrps));
+    for (it=groups.begin();it!=groups.end();it++) {
+      ntypes += it->second.getTypeCount(enumType);
+    }
+  }
+  return ntypes;
+}
+
+
+// Gets the collection of NcmpiType objects.
+multimap<string,NcmpiType> NcmpiGroup::getTypes(NcmpiGroup::Location location) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getTypes on a Null group",__FILE__,__LINE__);
+  // create a container to hold the NcmpiType's.
+  multimap<string,NcmpiType> ncmpiTypes;
+
+  // search in current group
+  if(location == Current || location == ParentsAndCurrent || location == ChildrenAndCurrent || location == All ) {
+    int typeCount = getTypeCount();
+    if (typeCount){
+      vector<int> typeids(typeCount);
+      ncmpiCheck(ncmpi_inq_typeids(getId(), &typeCount,&typeids[0]),__FILE__,__LINE__);
+      // now get the name of each NcmpiType and populate the nTypes container.
+      for(int i=0; i<typeCount;i++){
+        NcmpiType tmpType(*this,typeids[i]); 
+        ncmpiTypes.insert(pair<const string,NcmpiType>(tmpType.getName(),tmpType));
+      }
+    }
+  }
+
+  // search in parent groups.
+  if(location == Parents || location == ParentsAndCurrent || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups(ParentsGrps));
+    for (it=groups.begin();it!=groups.end();it++) {
+      multimap<string,NcmpiType> typeTmp(it->second.getTypes());
+      ncmpiTypes.insert(typeTmp.begin(),typeTmp.end());
+    }
+  }
+
+  // search in child groups (makes recursive calls).
+  if(location == Children || location == ChildrenAndCurrent || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups(AllChildrenGrps));
+    for (it=groups.begin();it!=groups.end();it++) {
+      multimap<string,NcmpiType> typeTmp(it->second.getTypes());
+      ncmpiTypes.insert(typeTmp.begin(),typeTmp.end());
+    }
+  }
+
+  return ncmpiTypes;
+}
+
+
+// Gets the collection of NcmpiType objects with a given name.
+set<NcmpiType> NcmpiGroup::getTypes(const string& name, NcmpiGroup::Location location) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getTypes on a Null group",__FILE__,__LINE__);
+  // iterator for the multimap container.
+  multimap<string,NcmpiType>::iterator it;
+  // return argument of equal_range: iterators to lower and upper bounds of the range.
+  pair<multimap<string,NcmpiType>::iterator,multimap<string,NcmpiType>::iterator> ret;
+  // get the entire collection of types.
+  multimap<string,NcmpiType> types(getTypes(location));
+  // define STL set object to hold the result
+  set<NcmpiType> tmpType;
+  // get the set of NcmpiType objects with a given name
+  ret=types.equal_range(name);
+  for (it=ret.first;it!=ret.second;it++) {
+    tmpType.insert(it->second);
+  }
+  return tmpType;
+}
+
+
+// Gets the collection of NcmpiType objects with a given data type.
+set<NcmpiType> NcmpiGroup::getTypes(NcmpiType::ncmpiType enumType, NcmpiGroup::Location location) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getTypes on a Null group",__FILE__,__LINE__);
+  // iterator for the multimap container.
+  multimap<string,NcmpiType>::iterator it;
+  // get the entire collection of types.
+  multimap<string,NcmpiType> types(getTypes(location));
+  // define STL set object to hold the result
+  set<NcmpiType> tmpType;
+  // get the set of NcmpiType objects with a given data type
+  for (it=types.begin();it!=types.end();it++) {
+    if(it->second.getTypeClass() == enumType) {
+      tmpType.insert(it->second);
+    }
+  }
+  return(tmpType);
+}
+
+
+// Gets the collection of NcmpiType objects with a given name and data type.
+set<NcmpiType> NcmpiGroup::getTypes(const string& name, NcmpiType::ncmpiType enumType, NcmpiGroup::Location location) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getTypes on a Null group",__FILE__,__LINE__);
+  // iterator for the multimap container.
+  multimap<string,NcmpiType>::iterator it;
+  // return argument of equal_range: iterators to lower and upper bounds of the range.
+  pair<multimap<string,NcmpiType>::iterator,multimap<string,NcmpiType>::iterator> ret;
+  // get the entire collection of types.
+  multimap<string,NcmpiType> types(getTypes(location));
+  // define STL set object to hold the result
+  set<NcmpiType> tmpType;
+  // get the set of NcmpiType objects with a given name
+  ret=types.equal_range(name);
+  for (it=ret.first;it!=ret.second;it++) {
+    if((*it).second.getTypeClass() == enumType) {
+      tmpType.insert(it->second);
+    }
+  }
+  return(tmpType);
+}
+
+
+// Gets the NcmpiType object with a given name.
+NcmpiType NcmpiGroup::getType(const string& name, NcmpiGroup::Location location) const {
+  if(isNull()) throw NcNullGrp("Attempt to invoke NcmpiGroup::getType on a Null group",__FILE__,__LINE__);
+  if(name ==  "byte"    ) return ncmpiByte;
+  if(name ==  "ubyte"   ) return ncmpiUbyte;
+  if(name ==  "char"    ) return ncmpiChar;
+  if(name ==  "short"   ) return ncmpiShort;
+  if(name ==  "ushort"  ) return ncmpiUshort;
+  if(name ==  "int"     ) return ncmpiInt;
+  if(name ==  "uint"    ) return ncmpiUint;  
+  if(name ==  "int64"   ) return ncmpiInt64; 
+  if(name ==  "uint64"  ) return ncmpiUint64;
+  if(name ==  "float"   ) return ncmpiFloat;
+  if(name ==  "double"  ) return ncmpiDouble;
+
+  // this is a user defined type
+  // iterator for the multimap container.
+  multimap<string,NcmpiType>::iterator it;
+  // return argument of equal_range: iterators to lower and upper bounds of the range.
+  pair<multimap<string,NcmpiType>::iterator,multimap<string,NcmpiType>::iterator> ret;
+  // get the entire collection of types.
+  multimap<string,NcmpiType> types(getTypes(location));
+  // define STL set object to hold the result
+  set<NcmpiType> tmpType;
+    // get the set of NcmpiType objects with a given name
+  ret=types.equal_range(name);
+  if(ret.first == ret.second) 
+    return NcmpiType();
+  else
+    return ret.first->second;
+}
+
+
+// Adds a new netCDF Enum type.
+NcmpiEnumType NcmpiGroup::addEnumType(const string& name,NcmpiEnumType::ncmpiEnumType baseType) const {
+  ncmpiCheckDefineMode(myId);
+  nc_type typeId;
+  ncmpiCheck(ncmpi_def_enum(myId, baseType, name.c_str(), &typeId),__FILE__,__LINE__);
+  NcmpiEnumType ncmpiTypeTmp(*this,name);
+  return ncmpiTypeTmp;
+}
+
+
+// Adds a new netCDF Vlen type.
+NcmpiVlenType NcmpiGroup::addVlenType(const string& name,NcmpiType& baseType) const {
+  ncmpiCheckDefineMode(myId);
+  nc_type typeId;
+  ncmpiCheck(ncmpi_def_vlen(myId,  const_cast<char*>(name.c_str()),baseType.getId(),&typeId),__FILE__,__LINE__);
+  NcmpiVlenType ncmpiTypeTmp(*this,name);
+  return ncmpiTypeTmp;
+}
+
+
+// Adds a new netCDF Opaque type.
+NcmpiOpaqueType NcmpiGroup::addOpaqueType(const string& name, MPI_Offset size) const {
+  ncmpiCheckDefineMode(myId);
+  nc_type typeId;
+  ncmpiCheck(ncmpi_def_opaque(myId, size,const_cast<char*>(name.c_str()), &typeId),__FILE__,__LINE__);
+  NcmpiOpaqueType ncmpiTypeTmp(*this,name);
+  return ncmpiTypeTmp;
+}
+    
+// Adds a new netCDF UserDefined type.
+NcmpiCompoundType NcmpiGroup::addCompoundType(const string& name, MPI_Offset size) const {
+  ncmpiCheckDefineMode(myId);
+  nc_type typeId;
+  ncmpiCheck(ncmpi_def_compound(myId, size,const_cast<char*>(name.c_str()),&typeId),__FILE__,__LINE__);
+  NcmpiCompoundType ncmpiTypeTmp(*this,name);
+  return ncmpiTypeTmp;
+}
+  
+  
+// Get the collection of coordinate variables.
+map<string,NcmpiGroup> NcmpiGroup::getCoordVars(NcmpiGroup::Location location) const {
+  map<string,NcmpiGroup> coordVars;
+
+  // search in current group and parent groups.
+  NcmpiGroup tmpGroup(*this); 
+  multimap<string,NcmpiDim>::iterator itD;
+  multimap<string,NcmpiVar>::iterator itV;
+  while(1) {
+    // get the collection of NcmpiDim objects defined in this group.
+    multimap<string,NcmpiDim> dimTmp(tmpGroup.getDims());
+    multimap<string,NcmpiVar> varTmp(tmpGroup.getVars());
+    for (itD=dimTmp.begin();itD!=dimTmp.end();itD++) {
+      string coordName(itD->first);
+      itV = varTmp.find(coordName);
+      if(itV != varTmp.end()) {
+	coordVars.insert(pair<const string,NcmpiGroup>(string(coordName),tmpGroup));
+      }
+    }
+    if(location != ParentsAndCurrent || location != All || tmpGroup.isRootGroup()) {
+      break;
+    }
+    // continue loop with the parent.
+    tmpGroup=tmpGroup.getParentGroup();
+  }
+
+  // search in child groups (makes recursive calls).
+  if(location == ChildrenAndCurrent || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups());
+    for (it=groups.begin();it!=groups.end();it++) {
+      map<string,NcmpiGroup> coordVarsTmp=getCoordVars(ChildrenAndCurrent);
+      coordVars.insert(coordVarsTmp.begin(),coordVarsTmp.end());
+    }
+  }
+  
+  return coordVars;
+}
+
+// Get the NcmpiDim and NcmpiVar object pair for a named coordinate variables.
+void NcmpiGroup::getCoordVar(string& coordVarName, NcmpiDim& ncmpiDim, NcmpiVar& ncmpiVar, NcmpiGroup::Location location) const {
+
+  // search in current group and parent groups.
+  multimap<string,NcmpiDim>::iterator itD;
+  NcmpiGroup tmpGroup(*this); 
+  multimap<string,NcmpiVar>::iterator itV;
+  while(1) {
+    // get the collection of NcmpiDim objects defined in this group.
+    multimap<string,NcmpiDim> dimTmp(tmpGroup.getDims());
+    multimap<string,NcmpiVar> varTmp(tmpGroup.getVars());
+    itD=dimTmp.find(coordVarName);
+    itV=varTmp.find(coordVarName);
+    if(itD != dimTmp.end() && itV != varTmp.end()) {
+      ncmpiDim=itD->second;
+      ncmpiVar=itV->second;
+      return;
+    }
+    if(location != ParentsAndCurrent || location != All || tmpGroup.isRootGroup()) {
+      break;
+    }
+    // continue loop with the parent.
+    tmpGroup=tmpGroup.getParentGroup();
+  }
+
+  // search in child groups (makes recursive calls).
+  if(location == ChildrenAndCurrent || location == All ) {
+    multimap<string,NcmpiGroup>::iterator it;
+    multimap<string,NcmpiGroup> groups(getGroups());
+    for (it=groups.begin();it!=groups.end();it++) {
+      getCoordVar(coordVarName,ncmpiDim,ncmpiVar,ChildrenAndCurrent);
+      if(!ncmpiDim.isNull()) break;
+    }
+  }
+
+  if(ncmpiDim.isNull()) {
+    // return null objects as no coordinates variables were obtained.
+    NcmpiDim dimTmp;
+    NcmpiVar varTmp;
+    ncmpiDim=dimTmp;
+    ncmpiVar=varTmp;
+    return;
+  }
+
+}
diff --git a/src/libcxx/ncmpiGroup.h b/src/libcxx/ncmpiGroup.h
new file mode 100644
index 0000000..311b101
--- /dev/null
+++ b/src/libcxx/ncmpiGroup.h
@@ -0,0 +1,596 @@
+#include <string>
+#include <vector>
+#include <set>
+#include <map>
+#include "ncmpiType.h"
+#include "ncmpiEnumType.h"
+#include "ncmpiGroupAtt.h"
+
+
+
+#ifndef NcmpiGroupClass
+#define NcmpiGroupClass
+
+
+namespace PnetCDF
+{
+  class NcmpiVar;          // forward declaration.
+  class NcmpiDim;          // forward declaration.
+  class NcmpiVlenType;     // forward declaration.
+  class NcmpiCompoundType; // forward declaration.
+  class NcmpiOpaqueType;   // forward declaration.
+
+  /*! Class represents a netCDF group. */
+  class NcmpiGroup
+  {	
+    
+  public:
+    
+    /*!
+      The enumeration list contains the options for selecting groups (used for returned set of NcmpiGroup objects).
+    */
+    enum GroupLocation
+      {
+	ChildrenGrps,              //!< Select from the set of children in the current group.
+	ParentsGrps,               //!< Select from set of parent groups (excludes the current group).
+	ChildrenOfChildrenGrps,    //!< Select from set of all children of children in the current group.
+	AllChildrenGrps,           //!< Select from set of all children of the current group and beneath.
+	ParentsAndCurrentGrps,     //!< Select from set of parent groups(includes the current group).
+	AllGrps                    //!< Select from set of parent groups, current groups and all the children beneath.
+      };
+    
+    /*!
+      The enumeration list contains the options for selecting groups.
+    */
+    enum Location
+      {
+	Current,            //!< Select from contents of current group.
+	Parents,            //!< Select from contents of parents groups.
+	Children,           //!< Select from contents of children groups.
+	ParentsAndCurrent,  //!< Select from contents of current and parents groups.
+	ChildrenAndCurrent, //!< Select from contents of current and child groups.
+	All                 //!< Select from contents of current, parents and child groups.
+      };
+    
+
+    /*! assignment operator  */
+    NcmpiGroup& operator=(const NcmpiGroup& rhs);
+    
+    /*! Constructor generates a \ref isNull "null object". */
+    NcmpiGroup();
+
+    //* constructor */
+    NcmpiGroup(int groupId);
+
+    /*! The copy constructor. */
+    NcmpiGroup(const NcmpiGroup& rhs);
+
+    /*! destructor  */
+    virtual ~NcmpiGroup();
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiGroup& rhs) const;     
+    
+    /*!  != operator */
+    bool operator!=(const NcmpiGroup& rhs) const;     
+
+    /*! comparator operator  */
+    friend bool operator<(const NcmpiGroup& lhs,const NcmpiGroup& rhs);
+    
+    /*! comparator operator  */
+    friend bool operator>(const NcmpiGroup& lhs,const NcmpiGroup& rhs);
+    
+    // /////////////
+    // NcmpiGroup-related methods
+    // /////////////
+    
+    /*! Gets the group name. */
+    /*!
+      Method will throw an PnetCDF::exceptions::NcNullgrp exception if the group is null (ie NcmpiGroup::isNull()=true).
+      \param fullName If true then the full name is returned with subgroups separated by a forward slash "/" (default is false)
+      \return         The group name.
+    */
+    std::string getName(bool fullName=false) const;
+
+    /*! 
+      Gets the parent group.
+      Method will throw an PnetCDF::exceptions::NcNullgrp exception if the  group is null (ie NcmpiGroup::isNull()=true).
+      If the current root is the parent group, then return a null group.
+    */
+    NcmpiGroup getParentGroup() const ;
+
+    /*! 
+      Gets the group id.
+      Method will throw an PnetCDF::exceptions::NcNullgrp exception if the group is null (ie NcmpiGroup::isNull()=true).
+    */
+    int  getId() const;
+    
+    /*! 
+      Gets the number of  NcmpiGroup objects.
+      Method will throw an PnetCDF::exceptions::NcNullgrp exception if the group is null (ie NcmpiGroup::isNull()=true).
+      \param location Enumeration type controlling the groups to search.
+      \return         Number of groups.
+    */
+    int getGroupCount(NcmpiGroup::GroupLocation location=ChildrenGrps) const;
+
+    /*! 
+      Gets the collection of NcmpiGroup objects.
+      Method will throw an PnetCDF::exceptions::NcNullgrp exception if the group is null (ie NcmpiGroup::isNull()=true).
+      \param location Enumeration type controlling the groups to search.
+      \return         A STL multimap object, containing pairs of <attribute name, NcmpiGroup object> entities.
+    */
+    std::multimap<std::string,NcmpiGroup> getGroups(NcmpiGroup::GroupLocation location=ChildrenGrps) const;
+
+
+    /*! 
+      Gets NcmpiGroup objects with a given name.
+      Method will throw an PnetCDF::exceptions::NcNullgrp exception if the group is null (ie NcmpiGroup::isNull()=true).
+      \param name     Name of group.
+      \param location Enumeration type controlling the groups to search.
+      \return         Set of NcmpiGroup objects with given name.
+    */
+    std::set<NcmpiGroup> getGroups(const std::string& name,NcmpiGroup::GroupLocation location=ChildrenGrps) const;
+
+    /*!
+      Gets the named child NcmpiGroup object.
+      Method will throw an PnetCDF::exceptions::NcNullgrp exception if the group is null (ie NcmpiGroup::isNull()=true).
+      \param name  Group name.
+      \param location   Enumeration type controlling the groups to search.
+      \return      An NcmpiGroup object. If there are multiple objects indentied with the same name, 
+      the object closest to the current group is returned. If no valid object is found , 
+      a \ref NcmpiGroup::isNull "null node" is returned.
+    */
+    NcmpiGroup getGroup(const std::string& name,NcmpiGroup::GroupLocation location=ChildrenGrps) const;
+
+    /*! 
+      Adds a new child netCDF group object.
+      Method will throw an PnetCDF::exceptions::NcNullgrp exception if the group is null (ie NcmpiGroup::isNull()=true).
+      \param   name     Variable name.
+      \return  NcmpiGroup  The NcmpiGroup object for this new netCDF group.
+    */
+    NcmpiGroup addGroup(const std::string& name) const;
+
+
+    /*! Returns true if this object is null (i.e. it has no contents); otherwise returns false. */
+    bool isNull() const  {return nullObject;}
+
+    /*! Returns true if this is the root group, otherwise returns false. */
+    bool isRootGroup() const;
+
+    // /////////////
+    // NcmpiVar-related accessors
+    // /////////////
+
+    /*! 
+      Gets the number of NcmpiVar objects in this group.
+      \param location Enumeration type controlling the groups to search.
+      \return         Number of variables.
+    */
+    int getVarCount(NcmpiGroup::Location location=Current) const;
+
+    /*! 
+      Gets the number of record variable NcmpiVar objects in this group.
+      \param location Enumeration type controlling the groups to search.
+      \return         Number of record variables.
+    */
+    int getRecVarCount(NcmpiGroup::Location location=Current) const;
+
+    /*! 
+      Gets the size of record block, i.e. the sume of single records of all
+      the record variables.
+      \param location Enumeration type controlling the groups to search.
+      \return         size of record bock.
+    */
+    MPI_Offset getRecSize(NcmpiGroup::Location location=Current) const;
+
+    /*! 
+      Gets the number of fixed-size variable NcmpiVar objects in this group.
+      \param location Enumeration type controlling the groups to search.
+      \return         Number of fixed-size variables.
+    */
+    int getFixVarCount(NcmpiGroup::Location location=Current) const;
+
+    /*!
+      Get the collection of NcmpiVar objects.
+      \param location Enumeration type controlling the groups to search.
+      \return         A STL multimap object, containing pairs of <attribute name, NcmpiVar object> entities.
+    */
+   std::multimap<std::string,NcmpiVar> getVars(NcmpiGroup::Location location=Current) const;
+
+   /*! 
+     Gets all NcmpiVar objects with a given name.
+      \param name     Name of attribute
+      \param location Enumeration type controlling the groups to search.
+      \return         Set of NcmpiVar objects.
+    */
+    std::set<NcmpiVar> getVars(const std::string& name,NcmpiGroup::Location location=Current) const;
+    
+    /*! 
+      Gets the named NcmpiVar object..
+      \param name     Variable name.
+      \param location Enumeration type controlling the groups to search.
+      \return         A NcmpiVar object. If there are multiple objects indentied with the 
+      same name, the object closest  to the current group is returned.  
+      If no valid object is found , a \ref NcmpiVar::isNull "null node" is returned.
+     */
+    NcmpiVar getVar(const std::string& name,NcmpiGroup::Location location=Current) const;
+
+    /*! 
+      Adds a new netCDF scalar variable.
+      The NcmpiType must be non-null, and be defined in either the current group or a parent group.
+      An NcNullType exception is thrown if the NcmpiType object is invalid.
+      \param    name     Variable name.
+      \param   typeName  Type name.
+      \return            The NcmpiVar object for this new netCDF variable.
+    */
+    NcmpiVar addVar(const std::string& name, const NcmpiType& ncmpiType) const;
+
+    /*!
+      Adds a new netCDF variable.
+      The NcmpiType and NcmpiDim objects must be non-null, and be defined in either the current group or a parent group.
+      An NcNullType exception is thrown if the NcmpiType object is invalid.
+      An NcNullDim exception is thrown if the NcmpiDim object is invalid.
+      \param    name     Variable name.
+      \param   typeName  Type name.
+      \param   dimName   Dimension name.
+      \return            The NcmpiVar object for this new netCDF variable.
+    */
+    NcmpiVar addVar(const std::string& name, const std::string& typeName, const std::string& dimName) const;
+
+    /*! 
+      Adds a new netCDF variable.
+      The NcmpiType and NcmpiDim objects must be non-null, and be defined in either the current group or a parent group.
+      An NcNullType exception is thrown if the NcmpiType object is invalid.
+      An NcNullDim exception is thrown if the NcmpiDim object is invalid.
+      \param    name      Variable name.
+      \param    ncmpiType    NcmpiType object.
+      \param    ncmpiDim     NcmpiDim object.
+      \return             The NcmpiVar object for this new netCDF variable.
+    */
+    NcmpiVar addVar(const std::string& name, const NcmpiType& ncmpiType, const NcmpiDim& ncmpiDim) const;
+
+    /*! 
+      Adds a new netCDF multi-dimensional variable.
+      The NcmpiType and NcmpiDim objects must be non-null, and be defined in either the current group or a parent group.
+      An NcNullType exception is thrown if the NcmpiType object is invalid.
+      An NcNullDim exception is thrown if the NcmpiDim object is invalid.
+      \param   name     Variable name.
+      \param   typeName Type name.
+      \param   dimNames Vector of dimension names.
+      \return           The NcmpiVar object for this new netCDF variable.
+    */
+    NcmpiVar addVar(const std::string& name, const std::string& typeName, const std::vector<std::string>& dimNames) const;
+    
+
+    /*! 
+      Adds a new multi-dimensional netCDF variable.
+      The NcmpiType and NcmpiDim objects must be non-null, and be defined in either the current group or a parent group.
+      An NcNullType exception is thrown if the NcmpiType object is invalid.
+      An NcNullDim exception is thrown if any of the the NcmpiDim objects are invalid.
+      \param    name        Variable name.
+      \param    ncmpiType      NcmpiType object.
+      \param    ncmpiDimvector Vector of NcmpiDim objects.
+      \return               The NcmpiVar object for this new netCDF variable.
+    */
+    NcmpiVar addVar(const std::string& name, const NcmpiType& ncmpiType, const std::vector<NcmpiDim>& ncmpiDimVector) const;
+
+    // /////////////
+    // NcmpiGroupAtt-related methods
+    // /////////////
+
+    /*! 
+      Gets the number of group attributes.
+      \param location Enumeration type controlling the groups to search.
+      \return         Number of attributes.
+    */
+    int getAttCount(NcmpiGroup::Location location=Current) const;
+
+    /*! 
+      Gets the collection of NcmpiGroupAtt objects.
+      \param location Enumeration type controlling the groups to search.
+      \return         A STL multimap object, containing pairs of <attribute name, NcmpiGroupAtt object> entities.
+    */
+    std::multimap<std::string,NcmpiGroupAtt> getAtts(NcmpiGroup::Location location=Current) const;
+    
+    /*! 
+    Gets all NcmpiGroupAtt objects with a given name.
+      \param name     Name of attribute
+      \param location Enumeration type controlling the groups to search.
+      \return         Set of NcmpiGroupAtt objects.
+    */
+    std::set<NcmpiGroupAtt> getAtts(const std::string& name,NcmpiGroup::Location location=Current) const;
+    
+    /*! 
+      Gets the named NcmpiGroupAtt object.
+      \param name     Name of attribute
+      \param location Enumeration type controlling the groups to search.
+      \return         A NcmpiGroupAtt object. If there are multiple objects indentied with the 
+      same name, the object closest  to the current group is returned.  If no valid object is found , 
+      a \ref NcmpiGroupAtt::isNull "null node" is returned.
+    */
+    NcmpiGroupAtt getAtt(const std::string& name,NcmpiGroup::Location location=Current) const;
+    
+
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, MPI_Offset len, const char** dataValues) const ;
+
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const std::string& dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, short datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, int datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, long datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, float datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, double datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, unsigned short datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, unsigned int datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, unsigned long long datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, long long datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const unsigned char* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const signed char* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const short* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const int* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const long* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const float* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const double* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const unsigned short* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const unsigned int* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const unsigned long long* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const long long* dataValues) const ;
+    /*! 
+      Creates a new NetCDF group attribute or if already exisiting replaces it.
+      If you are writing a _Fill_Value_ attribute, and will tell the HDF5 layer to use 
+      the specified fill value for that variable. 
+      \par 
+      Although it's possible to create attributes of all types, text and double attributes are adequate for most purposes. 
+      \param name        Name of attribute.
+      \param type    The attribute type.
+      \param len         The length of the attribute (number of Nctype repeats).
+      \param dataValues  Data Values to put into the new attribute.
+      If the type of data values differs from the netCDF variable type, type conversion will occur. 
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+      \return            The NcmpiGroupAtt object for this new netCDF attribute.
+    */
+    NcmpiGroupAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const void* dataValues) const ;
+
+
+
+    // /////////////
+    // NcmpiDim-related methods
+    // /////////////
+
+    /*! 
+      Gets the number of NcmpiDim objects.
+      \param location Enumeration type controlling the groups to search.
+      \return         Number of dimensions.
+    */
+    int getDimCount(NcmpiGroup::Location location=Current) const;
+    
+    /*! 
+      Gets the collection of NcmpiDim objects.
+      \param location Enumeration type controlling the groups to search.
+      \return         A STL multimap object, containing pairs of <attribute name, NcmpiDim object> entities.
+    */
+    std::multimap<std::string,NcmpiDim> getDims(NcmpiGroup::Location location=Current) const;
+    
+    /*! 
+      Gets NcmpiDim objects with a given name.
+      \param name     Name of dimension.
+      \param location Enumeration type controlling the groups to search.
+      \return         Set of NcmpiDim objects with given name.
+    */
+    std::set<NcmpiDim> getDims(const std::string& name,NcmpiGroup::Location location=Current) const;
+
+    /*! 
+      Gets the named NcmpiDim object.
+      \param name       Name of dimension.
+      \param location   Enumeration type controlling the groups to search.
+      \return           An NcmpiDim object. If there are multiple objects indentied with the same name, 
+      the object closest to the current group is returned. If no valid object is found , a \ref NcmpiDim::isNull "null node" is returned.
+    */
+    NcmpiDim getDim(const std::string& name,NcmpiGroup::Location location=Current) const;
+
+    /*! 
+      Adds a new netCDF dimension.
+      \param The name of new dimension.
+      \param Length of dimension; that is, number of values for this dimension as an index to variables 
+      that use it.
+      \return   The NcmpiDim object for this new netCDF dimension.
+    */
+    NcmpiDim addDim(const std::string& name, MPI_Offset dimSize) const;
+
+    /*! 
+      Adds a new unlimited netCDF dimension.
+      \param The name of new dimension.
+      \return   The NcmpiDim object for this new netCDF dimension.
+    */
+    NcmpiDim addDim(const std::string& name) const;
+
+    // /////////////
+    // NcmpiType-related methods
+    // /////////////
+
+    /*! 
+      Gets the number of type objects.
+      \param location Enumeration type controlling the groups to search.
+      \return         Number of types.
+    */
+    int getTypeCount(NcmpiGroup::Location location=Current) const;
+    
+    
+    /*! 
+      Gets the number of type objects with a given enumeration type.
+      \param enumType The enumeration value of the object type.
+      \param location Enumeration type controlling the groups to search.
+      \return         Number of types of the given enumeration type.
+    */
+    int getTypeCount(NcmpiType::ncmpiType enumType, NcmpiGroup::Location location=Current) const;
+    
+    
+    /*! 
+      Gets the collection of NcmpiType objects.
+      \param location Enumeration type controlling the groups to search.
+      \return         A STL multimap object, on return contains pairs of <Type name, NcmpiType object> entities.
+                      For atomic types, the type returned is the CDL name.
+    */
+    std::multimap<std::string,NcmpiType> getTypes(NcmpiGroup::Location location=Current) const;
+
+  
+    /*! 
+      Gets the collection of NcmpiType objects with a given name.
+      \param name     Name of type. For atomic types, the CDL name is expected. This is consistent with the 
+                         string returned from NcmpiType::getName().
+      \param location Enumeration type controlling the groups to search.
+      \return         Set of  NcmpiType objects.
+    */
+    std::set<NcmpiType> getTypes(const std::string& name, NcmpiGroup::Location location=Current) const;
+
+    /*! 
+      Gets the collection of NcmpiType objects with a given data type.
+      \param enumType Enumeration type specifying the data type.
+      \param location Enumeration type controlling the groups to search.
+      \return         Set of Nctype objects.
+    */
+    std::set<NcmpiType> getTypes(NcmpiType::ncmpiType enumType, NcmpiGroup::Location location=Current) const;
+
+
+    /*! 
+      Gets the collection of NcmpiType objects with a given name and data type.
+      \param name     Name of type. For atomic types, the CDL name is expected. This is consistent with the 
+                         string returned from NcmpiType::getName().
+      \param enumType Enumeration type specifying the data type.
+      \param location Enumeration type controlling the groups to search.
+      \return         Set of Nctype objects.
+    */
+    std::set<NcmpiType> getTypes(const std::string& name, NcmpiType::ncmpiType enumType, NcmpiGroup::Location location=Current) const;
+
+
+    /*! 
+      Gets the NcmpiType object with a given name.
+      \param name     Name of type. For atomic types, the CDL name is expected. This is consistent with the 
+                         string returned from NcmpiType::getName().
+      \param location Enumeration type controlling the groups to search.
+      \return         NcmpiType object. If there are multiple objects indentied with the same name, 
+      the object closest to the current group is returned.  If no valid object is found , a \ref NcmpiType::isNull "null node" is returned.
+
+    */
+    NcmpiType getType(const std::string& name, NcmpiGroup::Location location=Current) const;
+    
+    
+    /*! 
+      Adds a new netCDF enum type.
+      \param name        Name of type. For atomic types, the CDL name is expected. This is consistent with the 
+                         string returned from NcmpiType::getName().
+      \param enumType    The enumeration value of the object type.
+      \return            The NcmpiEnumType object for this new netCDF enum type.
+    */
+    NcmpiEnumType addEnumType(const std::string& name,NcmpiEnumType::ncmpiEnumType basetype) const;
+
+
+    /*! 
+      Adds a new netCDF Vlen type.
+      \param name        Name of type.
+      \param basetype    A NcmpiType object to be used for the basetype.
+      \return            The NcmpiVlenType object for this new netCDF vlen type.
+    */
+    NcmpiVlenType addVlenType(const std::string& name,NcmpiType& basetype) const;
+
+
+    /*! 
+      Adds a new netCDF Opaque type.
+      \param name     Name of type.
+      \param size     The size of the new type in bytes.
+      \return         The NcmpiOpaqueType object for this new netCDF opaque type..
+    */
+    NcmpiOpaqueType addOpaqueType(const std::string& name, MPI_Offset size) const;
+
+
+    /*! 
+      Adds a new netCDF UserDefined type.
+      \param name     Name of type.
+      \param size     The size of the new type in bytes.
+      \return         The new NcmpiCompoundType object for this new netCDF userDefined type.
+    */
+    NcmpiCompoundType addCompoundType(const std::string& name, MPI_Offset size) const; 
+
+
+    /*! 
+      Gets a collection of  coordinate variables.
+      Coordinate variable have  an NcmpiDim and NcmpiVar object with the same name defined in the same group.
+      \par
+      The method returns STL map object containing a coordinate variables in the current group  and optionally
+      in the parent and child groups. It is expected that within each group, the names of dimensions are unique and
+      the the names of variables are unique. However, if this is not the case, this method will still work correctly.
+      
+      \param location Enumeration type controlling the groups to search.
+      \return         The NcmpiVar dimension variable. If no valid object is found , a \ref NcmpiVar::isNull "null node" is returned.
+    */
+    std::map<std::string,NcmpiGroup> getCoordVars(NcmpiGroup::Location location=Current) const;
+
+    /*! 
+      Gets the NcmpiDim and NcmpiVar object pair for a named coordinate variable.
+      Coordinate variable have  an NcmpiDim and NcmpiVar object with the same name defined in the same group.
+      \par
+      The method returns two objects for the named coordinate variable. The method searches first in the current 
+      group and optionally in the parent and child group and returns the first instance found.
+      \param location Enumeration type controlling the groups to search.
+      \return         The set of names of dimension variables. 
+    */
+    void getCoordVar(std::string& coordVarName, NcmpiDim& ncmpiDim, NcmpiVar& ncmpiVar, NcmpiGroup::Location location=Current) const;
+
+
+  protected:
+    
+    /*! assignment operator  */
+    /* NcmpiGroup& operator=(const NcmpiGroup& rhs); */
+    
+    bool nullObject;
+
+    int myId;	
+    
+  };
+
+}
+#endif
diff --git a/src/libcxx/ncmpiGroupAtt.cpp b/src/libcxx/ncmpiGroupAtt.cpp
new file mode 100644
index 0000000..722090c
--- /dev/null
+++ b/src/libcxx/ncmpiGroupAtt.cpp
@@ -0,0 +1,65 @@
+#include "ncmpiGroupAtt.h"
+#include "ncmpiGroup.h"
+#include "ncmpiCheck.h"
+#include <pnetcdf.h>
+using namespace std;
+
+
+namespace PnetCDF {
+  //  Global comparator operator ==============
+  // comparator operator 
+  bool operator<(const NcmpiGroupAtt& lhs,const NcmpiGroupAtt& rhs)
+  {
+    return false;
+  }
+  
+  // comparator operator 
+  bool operator>(const NcmpiGroupAtt& lhs,const NcmpiGroupAtt& rhs)
+  {
+    return true;
+  }
+}
+
+
+using namespace PnetCDF;
+
+// assignment operator
+NcmpiGroupAtt& NcmpiGroupAtt::operator=(const NcmpiGroupAtt & rhs)
+{
+  NcmpiAtt::operator=(rhs);    // assign base class parts
+  return *this;
+}
+
+//! The copy constructor.
+NcmpiGroupAtt::NcmpiGroupAtt(const NcmpiGroupAtt& rhs): 
+  NcmpiAtt(rhs)   // invoke base class copy constructor
+{}
+
+
+// Constructor generates a null object.
+NcmpiGroupAtt::NcmpiGroupAtt() : 
+  NcmpiAtt()  // invoke base class constructor
+{}
+
+// equivalence operator (doesn't bother compaing varid's of each object).
+bool NcmpiGroupAtt::operator==(const NcmpiGroupAtt & rhs)
+{
+  if(nullObject) 
+    return nullObject == rhs.isNull();
+  else
+    return myName == rhs.myName && groupId == rhs.groupId;
+}  
+
+// Constructor for an existing global attribute.
+NcmpiGroupAtt::NcmpiGroupAtt(const NcmpiGroup& grp, const int index):
+  NcmpiAtt(false)
+{
+  groupId =  grp.getId();
+  varId = NC_GLOBAL;
+  // get the name of this attribute
+  char attName[NC_MAX_NAME+1];
+  ncmpiCheck(ncmpi_inq_attname(groupId,varId, index, attName),__FILE__,__LINE__);
+  ncmpiCheck(ncmpi_inq_attname(groupId,varId,index,attName),__FILE__,__LINE__);
+  myName = attName;
+}
+
diff --git a/src/libcxx/ncmpiGroupAtt.h b/src/libcxx/ncmpiGroupAtt.h
new file mode 100644
index 0000000..809dc52
--- /dev/null
+++ b/src/libcxx/ncmpiGroupAtt.h
@@ -0,0 +1,44 @@
+#include "ncmpiAtt.h"
+
+#ifndef NcmpiGroupAttClass
+#define NcmpiGroupAttClass
+
+namespace PnetCDF
+{
+  class NcmpiGroup;  // forward declaration.
+
+  /*! Class represents a netCDF group attribute */
+  class NcmpiGroupAtt : public NcmpiAtt
+  {
+  public:
+    
+    /*! assignment operator */
+    NcmpiGroupAtt& operator= (const NcmpiGroupAtt& rhs);
+   
+    /*! Constructor generates a \ref isNull "null object". */
+    NcmpiGroupAtt ();
+    
+    /*! The copy constructor. */
+    NcmpiGroupAtt(const NcmpiGroupAtt& rhs) ;
+      
+    /*! 
+      Constructor for an existing global attribute.
+      \param  grp        Parent Group object.
+      \param  index      The index (id) of the attribute.
+    */
+    NcmpiGroupAtt(const NcmpiGroup& grp, const int index);
+    
+    /*! equivalence operator */
+    bool operator== (const NcmpiGroupAtt& rhs);
+      
+    /*! comparator operator */
+    friend bool operator<(const NcmpiGroupAtt& lhs,const NcmpiGroupAtt& rhs);
+    
+    /*! comparator operator */
+    friend bool operator>(const NcmpiGroupAtt& lhs,const NcmpiGroupAtt& rhs);
+    
+  };
+  
+}
+
+#endif
diff --git a/src/libcxx/ncmpiInt.cpp b/src/libcxx/ncmpiInt.cpp
new file mode 100644
index 0000000..d23c7e5
--- /dev/null
+++ b/src/libcxx/ncmpiInt.cpp
@@ -0,0 +1,22 @@
+#include "ncmpiInt.h"
+#include <pnetcdf.h>
+using namespace PnetCDF;
+
+// create an instance of NcmpiInt  called PnetCDF::ncmpiInt
+namespace PnetCDF {
+  NcmpiInt ncmpiInt;
+}
+
+// constructor
+NcmpiInt::NcmpiInt() : NcmpiType(NC_INT){
+}
+
+NcmpiInt::~NcmpiInt() {
+}
+
+
+// equivalence operator
+bool NcmpiInt::operator==(const NcmpiInt & rhs)    {
+  // simply check the netCDF id.
+  return myId == rhs.myId;
+}  
diff --git a/src/libcxx/ncmpiInt.h b/src/libcxx/ncmpiInt.h
new file mode 100644
index 0000000..fcbb88d
--- /dev/null
+++ b/src/libcxx/ncmpiInt.h
@@ -0,0 +1,28 @@
+#include "ncmpiType.h"
+
+#ifndef NcmpiIntClass
+#define NcmpiIntClass
+
+namespace PnetCDF
+{
+  
+  /*! Class represents a netCDF atomic Int type. */
+  class NcmpiInt : public NcmpiType
+  {
+  public: 
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiInt & rhs);
+    
+    /*!  destructor */
+    ~NcmpiInt();
+    
+    /*! Constructor */
+    NcmpiInt();
+  };
+
+  /*! A global instance  of the NcmpiInt class within the netCDF namespace. */
+  extern NcmpiInt ncmpiInt;
+
+}
+#endif
diff --git a/src/libcxx/ncmpiInt64.cpp b/src/libcxx/ncmpiInt64.cpp
new file mode 100644
index 0000000..99024d3
--- /dev/null
+++ b/src/libcxx/ncmpiInt64.cpp
@@ -0,0 +1,22 @@
+#include "ncmpiInt64.h"
+#include <pnetcdf.h>
+using namespace PnetCDF;
+
+// create an instance of NcmpiInt64  called PnetCDF::ncmpiInt64
+namespace PnetCDF {
+  NcmpiInt64 ncmpiInt64;
+}
+
+// constructor
+NcmpiInt64::NcmpiInt64() : NcmpiType(NC_INT64){
+}
+
+NcmpiInt64::~NcmpiInt64() {
+}
+
+
+// equivalence operator
+bool NcmpiInt64::operator==(const NcmpiInt64 & rhs)    {
+  // simply check the netCDF id.
+  return myId == rhs.myId;
+}  
diff --git a/src/libcxx/ncmpiInt64.h b/src/libcxx/ncmpiInt64.h
new file mode 100644
index 0000000..c1c1b23
--- /dev/null
+++ b/src/libcxx/ncmpiInt64.h
@@ -0,0 +1,28 @@
+#include "ncmpiType.h"
+
+#ifndef NcmpiInt64Class
+#define NcmpiInt64Class
+
+namespace PnetCDF
+{
+  
+  /*! Class represents a netCDF atomic Int64 type. */
+  class NcmpiInt64 : public NcmpiType
+  {
+  public: 
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiInt64 & rhs);
+    
+    /*!  destructor */
+    ~NcmpiInt64();
+    
+    /*! Constructor */
+    NcmpiInt64();
+  };
+
+  /*! A global instance  of the NcmpiInt64 class within the netCDF namespace. */
+  extern NcmpiInt64 ncmpiInt64;
+
+}
+#endif
diff --git a/src/libcxx/ncmpiOpaqueType.cpp b/src/libcxx/ncmpiOpaqueType.cpp
new file mode 100644
index 0000000..1d33ec1
--- /dev/null
+++ b/src/libcxx/ncmpiOpaqueType.cpp
@@ -0,0 +1,68 @@
+#include "ncmpiOpaqueType.h"
+#include "ncmpiGroup.h"
+#include "ncmpiCheck.h"
+#include "ncmpiException.h"
+#include <pnetcdf.h>
+using namespace std;
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+// Class represents a netCDF variable.
+using namespace PnetCDF;
+  
+// assignment operator
+NcmpiOpaqueType& NcmpiOpaqueType::operator=(const NcmpiOpaqueType& rhs)
+{
+  // assign base class parts
+  NcmpiType::operator=(rhs);    
+  return *this;
+}
+  
+// assignment operator
+NcmpiOpaqueType& NcmpiOpaqueType::operator=(const NcmpiType& rhs)
+{
+  if (&rhs != this) {
+    // check the rhs is the base of an Opaque type
+    if(getTypeClass() != NC_OPAQUE) 	throw NcmpiException("The NcmpiType object must be the base of an Opaque type.",__FILE__,__LINE__);
+    // assign base class parts
+    NcmpiType::operator=(rhs);
+  }
+  return *this;
+}
+
+// The copy constructor.
+NcmpiOpaqueType::NcmpiOpaqueType(const NcmpiOpaqueType& rhs): 
+  NcmpiType(rhs)
+{
+}
+
+
+// Constructor generates a null object.
+NcmpiOpaqueType::NcmpiOpaqueType() :
+  NcmpiType()   // invoke base class constructor
+{}
+
+
+// constructor
+NcmpiOpaqueType::NcmpiOpaqueType(const NcmpiGroup& grp, const string& name) :
+  NcmpiType(grp,name)
+{}
+  
+  
+// constructor
+NcmpiOpaqueType::NcmpiOpaqueType(const NcmpiType& ncmpiType) :
+  NcmpiType(ncmpiType)
+{
+  // check the nctype object is the base of a Opaque type
+  if(getTypeClass() != NC_OPAQUE) 	throw NcmpiException("The NcmpiType object must be the base of an Opaque type.",__FILE__,__LINE__);
+}
+  
+// Returns the size of the opaque type in bytes.
+MPI_Offset  NcmpiOpaqueType::getTypeSize() const
+{
+  char* charName;
+  charName=NULL;
+  MPI_Offset sizep;
+  ncmpiCheck(ncmpi_inq_opaque(groupId,myId,charName,&sizep),__FILE__,__LINE__);
+  return sizep;
+}
diff --git a/src/libcxx/ncmpiOpaqueType.h b/src/libcxx/ncmpiOpaqueType.h
new file mode 100644
index 0000000..e7a8527
--- /dev/null
+++ b/src/libcxx/ncmpiOpaqueType.h
@@ -0,0 +1,58 @@
+#include <string>
+#include "ncmpiType.h"
+
+#ifndef NcmpiOpaqueTypeClass
+#define NcmpiOpaqueTypeClass
+
+
+namespace PnetCDF
+{
+  class NcmpiGroup;  // forward declaration.
+
+  /*! Class represents a netCDF opaque type */
+  class NcmpiOpaqueType : public NcmpiType
+  {
+  public:
+
+    /*! Constructor generates a \ref isNull "null object". */
+    NcmpiOpaqueType();
+
+    /*! 
+      Constructor.
+      The opaque Type must already exist in the netCDF file. New netCDF opaque types #
+      can be added using NcmpiGroup::addNcmpiOpaqueType();
+      \param grp        The parent group where this type is defined.
+      \param name       Name of new type.
+    */
+    NcmpiOpaqueType(const NcmpiGroup& grp, const std::string& name);
+
+    /*! 
+      Constructor.
+      Constructs from the base type NcmpiType object. Will throw an exception if the NcmpiType is not the base of a Opaque type.
+      \param ncmpiType     A Nctype object.
+    */
+    NcmpiOpaqueType(const NcmpiType& ncmpiType);
+
+    /*! assignment operator */
+    NcmpiOpaqueType& operator=(const NcmpiOpaqueType& rhs);
+      
+    /*! 
+      Assignment operator.
+      This assigns from the base type NcmpiType object. Will throw an exception if the NcmpiType is not the base of an Opaque type.
+    */
+    NcmpiOpaqueType& operator=(const NcmpiType& rhs);
+      
+    /*! The copy constructor.*/
+    NcmpiOpaqueType(const NcmpiOpaqueType& rhs);
+      
+    /*!  destructor */
+    ~NcmpiOpaqueType(){;}
+
+    /*! Returns the size of the opaque type in bytes. */
+    MPI_Offset  getTypeSize() const;
+
+  };
+  
+}
+
+#endif
diff --git a/src/libcxx/ncmpiShort.cpp b/src/libcxx/ncmpiShort.cpp
new file mode 100644
index 0000000..aeae3b9
--- /dev/null
+++ b/src/libcxx/ncmpiShort.cpp
@@ -0,0 +1,22 @@
+#include "ncmpiShort.h"
+#include <pnetcdf.h>
+using namespace PnetCDF;
+
+// create an instance of NcmpiShort  called PnetCDF::ncmpiShort
+namespace PnetCDF {
+  NcmpiShort ncmpiShort;
+}
+
+// constructor
+NcmpiShort::NcmpiShort() : NcmpiType(NC_SHORT){
+}
+
+NcmpiShort::~NcmpiShort() {
+}
+
+
+// equivalence operator
+bool NcmpiShort::operator==(const NcmpiShort & rhs)    {
+  // simply check the netCDF id.
+  return myId == rhs.myId;
+}  
diff --git a/src/libcxx/ncmpiShort.h b/src/libcxx/ncmpiShort.h
new file mode 100644
index 0000000..f5145af
--- /dev/null
+++ b/src/libcxx/ncmpiShort.h
@@ -0,0 +1,28 @@
+#include "ncmpiType.h"
+
+#ifndef NcmpiShortClass
+#define NcmpiShortClass
+
+namespace PnetCDF
+{
+  
+  /*! Class represents a netCDF atomic Short type. */
+  class NcmpiShort : public NcmpiType
+  {
+  public: 
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiShort & rhs);
+    
+    /*! destructor */
+    ~NcmpiShort();
+    
+    /*! Constructor */
+    NcmpiShort();
+  };
+
+  /*! A global instance  of the NcmpiShort class within the netCDF namespace. */
+  extern NcmpiShort ncmpiShort;
+
+}
+#endif
diff --git a/src/libcxx/ncmpiType.cpp b/src/libcxx/ncmpiType.cpp
new file mode 100644
index 0000000..74e93fd
--- /dev/null
+++ b/src/libcxx/ncmpiType.cpp
@@ -0,0 +1,179 @@
+#include <string>
+#include "ncmpiType.h"
+#include "ncmpiGroup.h"
+#include "ncmpiCheck.h"
+using namespace std;
+
+
+namespace PnetCDF {
+  //  Global comparator operator ==============
+  // comparator operator 
+  bool operator<(const NcmpiType& lhs,const NcmpiType& rhs)
+  {
+    return false;
+  }
+  
+  // comparator operator 
+  bool operator>(const NcmpiType& lhs,const NcmpiType& rhs)
+  {
+    return true;
+  }
+}
+
+using namespace PnetCDF;
+
+// assignment operator
+NcmpiType& NcmpiType::operator=(const NcmpiType & rhs)
+{
+  nullObject = rhs.nullObject;
+  myId= rhs.myId;
+  groupId = rhs.groupId;
+  return *this;
+}
+
+// The copy constructor.
+NcmpiType::NcmpiType(const NcmpiType& rhs): 
+  nullObject(rhs.nullObject),
+  myId(rhs.myId), 
+  groupId(rhs.groupId)
+{}
+
+
+// Constructor generates a null object.
+NcmpiType::NcmpiType() : 
+  nullObject(true) 
+{}
+
+// constructor
+NcmpiType::NcmpiType(const NcmpiGroup& grp, const string& name) :
+  nullObject (false)
+{
+  groupId= grp.getId();
+  NcmpiType typTmp(grp.getType(name,NcmpiGroup::ParentsAndCurrent));
+  myId = typTmp.getId();
+}
+
+// constructor for a global type 
+NcmpiType::NcmpiType(nc_type id) :
+  nullObject(false),
+  myId(id),
+  groupId(0)
+{
+}
+  
+
+// Constructor for a non-global type
+NcmpiType::NcmpiType(const PnetCDF::NcmpiGroup& grp, nc_type id):
+  nullObject(false),
+  myId(id),
+  groupId(grp.getId())
+{}
+
+
+// equivalence operator
+bool NcmpiType::operator==(const NcmpiType & rhs) const
+{
+  if(nullObject) 
+    return nullObject == rhs.nullObject;
+  else
+    return groupId == rhs.groupId && myId == rhs.myId;
+}  
+  
+//  !=  operator
+bool NcmpiType::operator!=(const NcmpiType & rhs) const
+{
+  return !(*this == rhs);
+}  
+  
+// Gets parent group.
+NcmpiGroup  NcmpiType::getParentGroup() const {
+  if(groupId == 0) return NcmpiGroup(); else  return NcmpiGroup(groupId);
+}
+  
+static
+string inq_type(int myId) {
+    switch (myId) {
+        case NC_BYTE   : return string("byte");
+        case NC_UBYTE  : return string("ubyte");
+        case NC_CHAR   : return string("char");
+        case NC_SHORT  : return string("short");
+        case NC_USHORT : return string("ushort");
+        case NC_INT    : return string("int");
+        case NC_UINT   : return string("uint");
+        case NC_INT64  : return string("int64");
+        case NC_UINT64 : return string("uint64");
+        case NC_FLOAT  : return string("float");
+        case NC_DOUBLE : return string("double");
+        default: break;
+    }
+    return string("");
+}
+
+// Returns the type name.
+string  NcmpiType::getName() const{
+  // char charName[NC_MAX_NAME+1];
+  // MPI_Offset *sizep=NULL;
+  // ncmpiCheck(ncmpi_inq_type(groupId,myId,charName,sizep),__FILE__,__LINE__);
+  // return string(charName);
+  return inq_type(myId);
+};
+
+// Returns the size in bytes
+MPI_Offset NcmpiType::getSize() const{
+  char* charName=NULL;
+  MPI_Offset sizep;
+  ncmpiCheck(ncmpi_inq_type(groupId,myId,charName,&sizep),__FILE__,__LINE__);
+  return sizep;
+};
+  
+// The type class returned as an enumeration type.
+NcmpiType::ncmpiType NcmpiType::getTypeClass() const{
+  switch (myId) {
+  case NC_BYTE    : return ncmpi_BYTE;
+  case NC_UBYTE   : return ncmpi_UBYTE;
+  case NC_CHAR    : return ncmpi_CHAR;
+  case NC_SHORT   : return ncmpi_SHORT;
+  case NC_USHORT  : return ncmpi_USHORT;
+  case NC_INT     : return ncmpi_INT;
+  case NC_UINT    : return ncmpi_UINT;  
+  case NC_INT64   : return ncmpi_INT64; 
+  case NC_UINT64  : return ncmpi_UINT64;
+  case NC_FLOAT   : return ncmpi_FLOAT;
+  case NC_DOUBLE  : return ncmpi_DOUBLE;
+  default:  
+    // this is a user defined type
+    // establish its type class, ie whether it is: NC_VLEN, NC_OPAQUE, NC_ENUM, or NC_COMPOUND. 
+    char* name=NULL;
+    MPI_Offset* sizep=NULL;
+    nc_type* base_nc_typep=NULL;
+    MPI_Offset* nfieldsp=NULL;
+    int classp;
+    ncmpiCheck(ncmpi_inq_user_type(groupId,myId,name,sizep,base_nc_typep,nfieldsp,&classp),__FILE__,__LINE__);
+    return static_cast<ncmpiType>(classp);
+  }
+}
+  
+// The type class returned as a string.
+string NcmpiType::getTypeClassName() const{
+  ncmpiType typeClass=getTypeClass();
+  switch (typeClass) {
+  case ncmpi_BYTE    : return string("ncmpi_BYTE");
+  case ncmpi_UBYTE   : return string("ncmpi_UBYTE");
+  case ncmpi_CHAR    : return string("ncmpi_CHAR");
+  case ncmpi_SHORT   : return string("ncmpi_SHORT");
+  case ncmpi_USHORT  : return string("ncmpi_USHORT");
+  case ncmpi_INT     : return string("ncmpi_INT");
+  case ncmpi_UINT    : return string("ncmpi_UINT");  
+  case ncmpi_INT64   : return string("ncmpi_INT64"); 
+  case ncmpi_UINT64  : return string("ncmpi_UINT64");
+  case ncmpi_FLOAT   : return string("ncmpi_FLOAT");
+  case ncmpi_DOUBLE  : return string("ncmpi_DOUBLE");
+  case ncmpi_STRING  : return string("ncmpi_STRING");
+  case ncmpi_VLEN    : return string("ncmpi_VLEN");
+  case ncmpi_OPAQUE  : return string("ncmpi_OPAQUE");
+  case ncmpi_ENUM    : return string("ncmpi_ENUM");
+  case ncmpi_COMPOUND: return string("ncmpi_COMPOUND");
+  }
+  // we never get here!
+  return "Dummy";
+}
diff --git a/src/libcxx/ncmpiType.h b/src/libcxx/ncmpiType.h
new file mode 100644
index 0000000..932d9fe
--- /dev/null
+++ b/src/libcxx/ncmpiType.h
@@ -0,0 +1,157 @@
+#include <string>
+#include <pnetcdf.h>
+
+#ifndef NcmpiTypeClass
+#define NcmpiTypeClass
+
+
+namespace PnetCDF
+{
+  class NcmpiGroup; // forward declaration to avoid cyclic reference.
+
+  /*! Base class inherited by NcOpaque, NcVlen, NcCompound and NcEnum classes. */
+  class NcmpiType
+  {	
+    
+  public:
+    
+    /*!
+      List of netCDF types that can be represented.
+      The enumeration list contains the complete set of netCDF variable types. In addition, the type NC_TYPE
+      is included. This enables the user to instantiate a netCDF type object without explcitly needing to know
+      it precise type.
+    */
+    enum ncmpiType
+    {
+      ncmpi_BYTE     = NC_BYTE, 	//!< signed 1 byte integer
+      ncmpi_CHAR     = NC_CHAR,		//!< ISO/ASCII character
+      ncmpi_SHORT    = NC_SHORT, 	//!< signed 2 byte integer
+      ncmpi_INT      = NC_INT,		//!< signed 4 byte integer
+      ncmpi_FLOAT    = NC_FLOAT, 	//!< single precision floating point number
+      ncmpi_DOUBLE   = NC_DOUBLE, 	//!< double precision floating point number
+      ncmpi_UBYTE    = NC_UBYTE,	//!< unsigned 1 byte int
+      ncmpi_USHORT   = NC_USHORT,	//!< unsigned 2-byte int
+      ncmpi_UINT     = NC_UINT,		//!< unsigned 4-byte int
+      ncmpi_INT64    = NC_INT64,	//!< signed 8-byte int
+      ncmpi_UINT64   = NC_UINT64,	//!< unsigned 8-byte int
+
+      // PnetCDF does not support types below
+      ncmpi_STRING   = NC_STRING, 	//!< string
+      ncmpi_VLEN     = NC_VLEN,   	//!< "NcVlen type"
+      ncmpi_OPAQUE   = NC_OPAQUE, 	//!< "NcOpaque type"
+      ncmpi_ENUM     = NC_ENUM, 	//!< "NcEnum type"
+      ncmpi_COMPOUND = NC_COMPOUND	//!< "NcCompound type"
+    };
+    
+    /*! Constructor generates a \ref isNull "null object". */
+    NcmpiType();
+
+    /*! 
+      Constructor for a non-global type.
+      This object describes the "essential" information for all netCDF types required by NcmpiVar, NcmpiAtt objects.
+      New netCDF types can be added using the appropriate "add" method in the NcmpiGroup object.
+      \param grp    Parent NcmpiGroup object.
+      \param name   Name of this type.
+    */
+    NcmpiType(const PnetCDF::NcmpiGroup& grp, const std::string& name);
+
+
+    /*! 
+      Constructor for a non-global type.
+      This object describes the "essential" information for all netCDF types required by NcmpiVar, NcmpiAtt objects.
+      New netCDF types can be added using the appropriate "add" method in the NcmpiGroup object.
+      \param grp    Parent NcmpiGroup object.
+      \param id     type id
+    */
+    NcmpiType(const PnetCDF::NcmpiGroup& grp, nc_type id);
+
+    /*! 
+      Constructor for a global type
+      This object describes the "essential" information for a netCDF global type.
+      \param id     type id
+    */
+    NcmpiType(nc_type id);
+
+    /*! The copy constructor. */
+    NcmpiType(const NcmpiType& rhs);
+
+    /*! destructor  */
+    virtual ~NcmpiType() {}
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiType&) const;     
+    
+    /*!  != operator */
+    bool operator!=(const NcmpiType &) const;
+
+    // accessors to private data.
+    /*! The netCDF Id of this type. */
+    nc_type getId() const {return myId;} 
+
+    /*! Gets parent group. For an atomic type, returns a Null object.*/
+    PnetCDF::NcmpiGroup getParentGroup() const;
+
+    /*! 
+      The name of this type. For atomic types, the CDL type names are returned. These are as follows: 
+        - NcmpiByte   String returned is "byte".
+        - NcmpiUbyte  String returned is "ubyte".
+        - NcmpiChar   String returned is "char".   
+        - NcmpiShort  String returned is "short".  
+        - NcmpiUshort String returned is "ushort". 
+        - NcmpiInt    String returned is "int".    
+        - NcmpiUint   String returned is "uint".   
+        - NcmpiInt64  String returned is "int64".  
+        - NcmpiUint64 String returned is "uint64". 
+        - NcmpiFloat  String returned is "float".  
+        - NcmpiDouble String returned is "double". 
+     */
+    std::string getName() const;                        
+
+    /*! 
+      The size in bytes. 
+      This function will work on any type, including atomic and any user defined type, whether 
+      compound, opaque, enumeration, or variable length array. 
+     */
+    MPI_Offset getSize() const;                         
+
+    /*! 
+      The type class returned as enumeration type.
+      Valid for all types, whether atomic or user-defined. User-defined types are returned as one of the following
+      enumeration types: ncmpi_VLEN, ncmpi_OPAQUE, ncmpi_ENUM, or ncmpi_COMPOUND. 
+     */
+    ncmpiType getTypeClass() const;                       
+
+    /*! 
+      Return a string containing the name of the enumerated type.  (ie one of the following strings:
+      "ncmpi_BYTE", "ncmpi_CHAR", "ncmpi_SHORT", "ncmpi_INT", "ncmpi_FLOAT", "ncmpi_DOUBLE", "ncmpi_UBYTE", "ncmpi_USHORT", 
+      "ncmpi_UINT", "ncmpi_INT64", "ncmpi_UINT64", "ncmpi_STRING", "ncmpi_VLEN", "ncmpi_OPAQUE", "ncmpi_ENUM", "ncmpi_COMPOUND"
+     */
+    std::string getTypeClassName() const;
+    
+    /*! Returns true if this object is null (i.e. it has no contents); otherwise returns false. */
+    bool isNull() const  {return nullObject;}
+
+    /*! comparator operator  */
+    friend bool operator<(const NcmpiType& lhs,const NcmpiType& rhs);
+    
+    /*! comparator operator  */
+    friend bool operator>(const NcmpiType& lhs,const NcmpiType& rhs);
+    
+  protected:
+
+    /*! assignment operator  */
+    NcmpiType& operator=(const NcmpiType& rhs);
+    
+    bool nullObject;
+
+    /*! the type Id */
+    nc_type myId;
+    
+    /*! the group Id */
+    int groupId;
+
+  };
+
+}
+#endif
+
diff --git a/src/libcxx/ncmpiUbyte.cpp b/src/libcxx/ncmpiUbyte.cpp
new file mode 100644
index 0000000..debe553
--- /dev/null
+++ b/src/libcxx/ncmpiUbyte.cpp
@@ -0,0 +1,22 @@
+#include "ncmpiUbyte.h"
+#include <pnetcdf.h>
+using namespace PnetCDF;
+
+// create an instance of NcmpiUbyte  called PnetCDF::ncmpiUbyte
+namespace PnetCDF {
+  NcmpiUbyte ncmpiUbyte;
+}
+
+// constructor
+NcmpiUbyte::NcmpiUbyte() : NcmpiType(NC_UBYTE){
+}
+
+NcmpiUbyte::~NcmpiUbyte() {
+}
+
+
+// equivalence operator
+bool NcmpiUbyte::operator==(const NcmpiUbyte & rhs)    {
+  // simply check the netCDF id.
+  return myId == rhs.myId;
+}  
diff --git a/src/libcxx/ncmpiUbyte.h b/src/libcxx/ncmpiUbyte.h
new file mode 100644
index 0000000..3361351
--- /dev/null
+++ b/src/libcxx/ncmpiUbyte.h
@@ -0,0 +1,28 @@
+#include "ncmpiType.h"
+
+#ifndef NcmpiUbyteClass
+#define NcmpiUbyteClass
+
+namespace PnetCDF
+{
+  
+  /*! Class represents a netCDF atomic Ubyte type. */
+  class NcmpiUbyte : public NcmpiType
+  {
+  public: 
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiUbyte & rhs);
+    
+    /*! destructor */
+    ~NcmpiUbyte();
+    
+    /*! Constructor */
+    NcmpiUbyte();
+  };
+
+  /*! A global instance  of the NcmpiUbyte class within the netCDF namespace. */
+  extern NcmpiUbyte ncmpiUbyte;
+
+}
+#endif
diff --git a/src/libcxx/ncmpiUint.cpp b/src/libcxx/ncmpiUint.cpp
new file mode 100644
index 0000000..14bf349
--- /dev/null
+++ b/src/libcxx/ncmpiUint.cpp
@@ -0,0 +1,22 @@
+#include "ncmpiUint.h"
+#include <pnetcdf.h>
+using namespace PnetCDF;
+
+// create an instance of NcmpiUint  called PnetCDF::ncmpiUint
+namespace PnetCDF {
+  NcmpiUint ncmpiUint;
+}
+
+// constructor
+NcmpiUint::NcmpiUint() : NcmpiType(NC_UINT){
+}
+
+NcmpiUint::~NcmpiUint() {
+}
+
+
+// equivalence operator
+bool NcmpiUint::operator==(const NcmpiUint & rhs)    {
+  // simply check the netCDF id.
+  return myId == rhs.myId;
+}  
diff --git a/src/libcxx/ncmpiUint.h b/src/libcxx/ncmpiUint.h
new file mode 100644
index 0000000..2098ebf
--- /dev/null
+++ b/src/libcxx/ncmpiUint.h
@@ -0,0 +1,28 @@
+#include "ncmpiType.h"
+
+#ifndef NcmpiUintClass
+#define NcmpiUintClass
+
+namespace PnetCDF
+{
+  
+  /*! Class represents a netCDF atomic Uint type. */
+  class NcmpiUint : public NcmpiType
+  {
+  public: 
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiUint & rhs);
+    
+    /*! destructor */
+    ~NcmpiUint();
+    
+    /*! Constructor */
+    NcmpiUint();
+  };
+
+  /*! A global instance  of the NcmpiUint class within the netCDF namespace. */
+  extern NcmpiUint ncmpiUint;
+
+}
+#endif
diff --git a/src/libcxx/ncmpiUint64.cpp b/src/libcxx/ncmpiUint64.cpp
new file mode 100644
index 0000000..11074c8
--- /dev/null
+++ b/src/libcxx/ncmpiUint64.cpp
@@ -0,0 +1,22 @@
+#include "ncmpiUint64.h"
+#include <pnetcdf.h>
+using namespace PnetCDF;
+
+// create an instance of NcmpiUint64  called PnetCDF::ncmpiUint64
+namespace PnetCDF {
+  NcmpiUint64 ncmpiUint64;
+}
+
+// constructor
+NcmpiUint64::NcmpiUint64() : NcmpiType(NC_UINT64){
+}
+
+NcmpiUint64::~NcmpiUint64() {
+}
+
+
+// equivalence operator
+bool NcmpiUint64::operator==(const NcmpiUint64 & rhs)    {
+  // simply check the netCDF id.
+  return myId == rhs.myId;
+}  
diff --git a/src/libcxx/ncmpiUint64.h b/src/libcxx/ncmpiUint64.h
new file mode 100644
index 0000000..5581815
--- /dev/null
+++ b/src/libcxx/ncmpiUint64.h
@@ -0,0 +1,28 @@
+#include "ncmpiType.h"
+
+#ifndef NcmpiUint64Class
+#define NcmpiUint64Class
+
+namespace PnetCDF
+{
+  
+  /*! Class represents a netCDF atomic Uint64 type.*/
+  class NcmpiUint64 : public NcmpiType
+  {
+  public: 
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiUint64 & rhs);
+    
+    /*! destructor */
+    ~NcmpiUint64();
+    
+    /*! Constructor */
+    NcmpiUint64();
+  };
+
+  /*! A global instance  of the NcmpiUint64 class within the netCDF namespace. */
+  extern NcmpiUint64 ncmpiUint64;
+
+}
+#endif
diff --git a/src/libcxx/ncmpiUshort.cpp b/src/libcxx/ncmpiUshort.cpp
new file mode 100644
index 0000000..80de2ab
--- /dev/null
+++ b/src/libcxx/ncmpiUshort.cpp
@@ -0,0 +1,22 @@
+#include "ncmpiUshort.h"
+#include <pnetcdf.h>
+using namespace PnetCDF;
+
+// create an instance of NcmpiUshort  called PnetCDF::ncmpiUshort
+namespace PnetCDF {
+  NcmpiUshort ncmpiUshort;
+}
+
+// constructor
+NcmpiUshort::NcmpiUshort() : NcmpiType(NC_USHORT){
+}
+
+NcmpiUshort::~NcmpiUshort() {
+}
+
+
+// equivalence operator
+bool NcmpiUshort::operator==(const NcmpiUshort & rhs)    {
+  // simply check the netCDF id.
+  return myId == rhs.myId;
+}  
diff --git a/src/libcxx/ncmpiUshort.h b/src/libcxx/ncmpiUshort.h
new file mode 100644
index 0000000..dfffb21
--- /dev/null
+++ b/src/libcxx/ncmpiUshort.h
@@ -0,0 +1,28 @@
+#include "ncmpiType.h"
+
+#ifndef NcmpiUshortClass
+#define NcmpiUshortClass
+
+namespace PnetCDF
+{
+  
+  /*! Class represents a netCDF atomic Ushort type. */
+  class NcmpiUshort : public NcmpiType
+  {
+  public: 
+    
+    /*! equivalence operator */
+    bool operator==(const NcmpiUshort & rhs);
+    
+    /*! destructor */
+    ~NcmpiUshort();
+    
+    /*! Constructor */
+    NcmpiUshort();
+  };
+
+  // declare that the class instance ncmpiUshort is known by all....
+  extern NcmpiUshort ncmpiUshort;
+
+}
+#endif
diff --git a/src/libcxx/ncmpiVar.cpp b/src/libcxx/ncmpiVar.cpp
new file mode 100644
index 0000000..5e82abf
--- /dev/null
+++ b/src/libcxx/ncmpiVar.cpp
@@ -0,0 +1,3289 @@
+#include "ncmpiVarAtt.h"
+#include "ncmpiDim.h"
+#include "ncmpiVar.h"
+#include "ncmpiGroup.h"
+#include "ncmpiCheck.h"
+#include "ncmpiException.h"
+#include<pnetcdf.h>
+using namespace std;
+using namespace PnetCDF::exceptions;
+  
+namespace PnetCDF {
+  //  Global comparator operator ==============
+  // comparator operator 
+  bool operator<(const NcmpiVar& lhs,const NcmpiVar& rhs)
+  {
+    return false;
+  }
+  
+  // comparator operator 
+  bool operator>(const NcmpiVar& lhs,const NcmpiVar& rhs)
+  {
+    return true;
+  }
+}
+
+using namespace PnetCDF;
+
+// assignment operator
+NcmpiVar& NcmpiVar::operator=(const NcmpiVar & rhs)
+{
+  nullObject = rhs.nullObject;
+  myId = rhs.myId;
+  groupId = rhs.groupId;
+  return *this;
+}
+
+// The copy constructor.
+NcmpiVar::NcmpiVar(const NcmpiVar& rhs) : 
+  nullObject(rhs.nullObject),
+  myId(rhs.myId),
+  groupId(rhs.groupId)
+{}
+
+
+// equivalence operator
+bool NcmpiVar::operator==(const NcmpiVar & rhs) const
+{
+  // simply check the netCDF id.
+  return (myId == rhs.myId);
+}  
+
+//  !=  operator
+bool NcmpiVar::operator!=(const NcmpiVar & rhs) const
+{
+  return !(*this == rhs);
+}  
+
+/////////////////
+  
+// Constructors and intialization
+  
+/////////////////
+  
+// Constructor generates a null object.
+NcmpiVar::NcmpiVar() : nullObject(true) {}
+  
+// Constructor for a variable (must already exist in the netCDF file.)
+NcmpiVar::NcmpiVar (const NcmpiGroup& grp, const int& varId) :
+  nullObject (false),
+  myId (varId),
+  groupId(grp.getId())
+{}
+
+  
+  
+// Gets parent group.
+NcmpiGroup  NcmpiVar::getParentGroup() const {
+  return NcmpiGroup(groupId);
+}
+  
+
+// Get the variable id.
+int  NcmpiVar::getId() const {return myId;}
+    
+//////////////////////
+
+//  Information about the variable type
+
+/////////////////////
+
+
+// Gets the NcmpiType object with a given name.
+NcmpiType NcmpiVar::getType() const {
+
+  // if this variable has not been defined, return a NULL type
+  if(isNull()) return NcmpiType();
+
+  // first get the typeid
+  nc_type xtypep;
+  ncmpiCheck(ncmpi_inq_vartype(groupId,myId,&xtypep),__FILE__,__LINE__);
+
+  if(xtypep ==  ncmpiByte.getId()    ) return ncmpiByte;
+  if(xtypep ==  ncmpiUbyte.getId()   ) return ncmpiUbyte;
+  if(xtypep ==  ncmpiChar.getId()    ) return ncmpiChar;
+  if(xtypep ==  ncmpiShort.getId()   ) return ncmpiShort;
+  if(xtypep ==  ncmpiUshort.getId()  ) return ncmpiUshort;
+  if(xtypep ==  ncmpiInt.getId()     ) return ncmpiInt;
+  if(xtypep ==  ncmpiUint.getId()    ) return ncmpiUint;  
+  if(xtypep ==  ncmpiInt64.getId()   ) return ncmpiInt64; 
+  if(xtypep ==  ncmpiUint64.getId()  ) return ncmpiUint64;
+  if(xtypep ==  ncmpiFloat.getId()   ) return ncmpiFloat;
+  if(xtypep ==  ncmpiDouble.getId()  ) return ncmpiDouble;
+
+  multimap<string,NcmpiType>::const_iterator it;
+  multimap<string,NcmpiType> types(NcmpiGroup(groupId).getTypes(NcmpiGroup::ParentsAndCurrent));
+  for(it=types.begin(); it!=types.end(); it++) {
+    if(it->second.getId() == xtypep) return it->second;
+  }
+  // we will never reach here
+  return true;
+}
+
+
+
+
+
+
+
+  
+/////////////////
+  
+// Information about Dimensions
+  
+/////////////////
+
+  
+// Gets the number of dimensions.
+int NcmpiVar::getDimCount() const
+{
+  // get the number of dimensions
+  int dimCount;
+  ncmpiCheck(ncmpi_inq_varndims(groupId,myId, &dimCount),__FILE__,__LINE__);
+  return dimCount;
+}  
+
+// Gets the set of Ncdim objects.
+vector<NcmpiDim> NcmpiVar::getDims() const
+{
+  // get the number of dimensions
+  int dimCount = getDimCount();  
+  // create a vector of dimensions.
+  vector<NcmpiDim> ncmpiDims;
+  if (dimCount){
+    vector<int> dimids(dimCount);
+    ncmpiCheck(ncmpi_inq_vardimid(groupId,myId, &dimids[0]),__FILE__,__LINE__);
+    ncmpiDims.reserve(dimCount);
+    for (int i=0; i<dimCount; i++){
+      NcmpiDim tmpDim(getParentGroup(),dimids[i]);
+      ncmpiDims.push_back(tmpDim);
+    }
+  }
+  return ncmpiDims;
+}  
+
+  
+// Gets the i'th NcmpiDim object.
+NcmpiDim NcmpiVar::getDim(int i) const
+{
+  vector<NcmpiDim> ncmpiDims = getDims();
+  if((size_t)i >= ncmpiDims.size() || i < 0) throw NcmpiException("Index out of range",__FILE__,__LINE__);
+  return ncmpiDims[i];
+}
+
+
+/////////////////
+  
+// Information about Attributes
+  
+/////////////////
+
+  
+// Gets the number of attributes.
+int NcmpiVar::getAttCount() const
+{
+  // get the number of attributes
+  int attCount;
+  ncmpiCheck(ncmpi_inq_varnatts(groupId,myId, &attCount),__FILE__,__LINE__);
+  return attCount;
+}  
+
+// Gets the set of attributes.
+map<string,NcmpiVarAtt> NcmpiVar::getAtts() const
+{
+  // get the number of attributes
+  int attCount = getAttCount();  
+  // create a container of attributes.
+  map<string,NcmpiVarAtt> ncmpiAtts;
+  for (int i=0; i<attCount; i++){
+    NcmpiVarAtt tmpAtt(getParentGroup(),*this,i);
+    ncmpiAtts.insert(pair<const string,NcmpiVarAtt>(tmpAtt.getName(),tmpAtt));
+  }
+  return ncmpiAtts;
+}  
+
+  
+// Gets attribute by name.
+NcmpiVarAtt NcmpiVar::getAtt(const string& name) const
+{
+  map<string,NcmpiVarAtt> attributeList = getAtts();
+  map<string,NcmpiVarAtt>::iterator myIter;
+  myIter = attributeList.find(name);
+  if(myIter == attributeList.end()){
+    string msg("Attribute '"+name+"' not found");
+    throw NcmpiException(msg.c_str(),__FILE__,__LINE__);
+  }
+  return NcmpiVarAtt(myIter->second);
+}
+
+
+
+/////////////////////////
+
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const string& dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  ncmpiCheck(ncmpi_put_att_text(groupId,myId,name.c_str(),dataValues.size(),dataValues.c_str()),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const unsigned char* dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_uchar(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const signed char* dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_schar(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+
+/////////////////////////////////
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, short datumValue) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_short(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, int datumValue) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_int(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, long datumValue) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_long(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, float datumValue) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_float(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, double datumValue) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_double(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, unsigned short datumValue) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_ushort(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, unsigned int datumValue) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_uint(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, long long datumValue) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_longlong(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, unsigned long long datumValue) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_ulonglong(groupId,myId,name.c_str(),type.getId(),1,&datumValue),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+/////////////////////////////////
+
+
+
+
+
+
+
+
+
+
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const short* dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_short(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const int* dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_int(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const long* dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_long(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const float* dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_float(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const double* dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_double(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const unsigned short* dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_ushort(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const unsigned int* dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_uint(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const long long* dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_longlong(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const unsigned long long* dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  NcmpiType::ncmpiType typeClass(type.getTypeClass());
+  if(typeClass == NcmpiType::ncmpi_VLEN || typeClass == NcmpiType::ncmpi_OPAQUE || typeClass == NcmpiType::ncmpi_ENUM || typeClass == NcmpiType::ncmpi_COMPOUND) 
+    ncmpiCheck(ncmpi_put_att(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  else
+    ncmpiCheck(ncmpi_put_att_ulonglong(groupId,myId,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+// Creates a new NetCDF variable attribute or if already exisiting replaces it.
+NcmpiVarAtt NcmpiVar::putAtt(const string& name, const NcmpiType& type, MPI_Offset len, const void* dataValues) const {
+  ncmpiCheckDefineMode(groupId);
+  ncmpiCheck(ncmpi_put_att(groupId,myId ,name.c_str(),type.getId(),len,dataValues),__FILE__,__LINE__);
+  // finally instantiate this attribute and return
+  return getAtt(name);
+}
+
+
+
+
+////////////////////
+  
+// Other Basic variable info
+  
+////////////////////
+  
+// The name of this variable.
+string NcmpiVar::getName() const{
+  char charName[NC_MAX_NAME+1];
+  ncmpiCheck(ncmpi_inq_varname(groupId, myId, charName),__FILE__,__LINE__);
+  return string(charName);
+}
+
+
+////////////////////
+  
+// Chunking details
+  
+////////////////////
+
+
+// Sets chunking parameters.
+void NcmpiVar::setChunking(ChunkMode chunkMode, vector<MPI_Offset>& chunkSizes) const {
+  MPI_Offset *chunkSizesPtr = chunkSizes.empty() ? 0 : &chunkSizes[0];
+  ncmpiCheck(ncmpi_def_var_chunking(groupId,myId,static_cast<int> (chunkMode), chunkSizesPtr),__FILE__,__LINE__);
+}
+  
+  
+// Gets the chunking parameters
+void NcmpiVar::getChunkingParameters(ChunkMode& chunkMode, vector<MPI_Offset>& chunkSizes) const {
+  int chunkModeInt;
+  chunkSizes.resize(getDimCount());
+  MPI_Offset *chunkSizesPtr = chunkSizes.empty() ? 0 : &chunkSizes[0];
+  ncmpiCheck(ncmpi_inq_var_chunking(groupId,myId, &chunkModeInt, chunkSizesPtr),__FILE__,__LINE__);
+  chunkMode = static_cast<ChunkMode> (chunkModeInt);
+}
+  
+  
+  
+  
+////////////////////
+  
+// Fill details
+  
+////////////////////
+
+
+// Sets the fill parameters
+void NcmpiVar::setFill(bool fillMode, void* fillValue) const {
+  // If fillMode is enabled, check that fillValue has a legal pointer.
+  // if(fillMode && fillValue == NULL)
+    // throw NcmpiException("FillMode was set to zero but fillValue has invalid pointer",__FILE__,__LINE__);
+  
+  ncmpiCheck(ncmpi_def_var_fill(groupId,myId,static_cast<int> (!fillMode),fillValue),__FILE__,__LINE__);
+}
+
+// Sets the fill parameters
+/*
+void NcmpiVar::setFill(bool fillMode, const void* fillValue) const {
+  setFill(fillMode,const_cast<void*>(fillValue));
+}
+*/
+
+
+// Gets the fill parameters
+void NcmpiVar::getFillModeParameters(bool& fillMode, void* fillValue)const{
+    
+  int fillModeInt;
+  ncmpiCheck(ncmpi_inq_var_fill(groupId,myId,&fillModeInt,fillValue),__FILE__,__LINE__);
+  fillMode= static_cast<bool> (fillModeInt == 0);
+}
+  
+/* fill variable */
+void NcmpiVar::fillRec(MPI_Offset recno) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_fill_var_rec(groupId, myId, recno),__FILE__,__LINE__);
+}
+
+
+////////////////////
+  
+// Compression details
+  
+////////////////////
+
+
+// Sets the compression parameters
+void NcmpiVar::setCompression(bool enableShuffleFilter, bool enableDeflateFilter, int deflateLevel) const {
+    
+  // Check that the deflate level is legal
+  if(enableDeflateFilter & (deflateLevel < 0 || deflateLevel >9))
+    throw NcmpiException("The deflateLevel must be set between 0 and 9.",__FILE__,__LINE__);
+    
+  ncmpiCheck(ncmpi_def_var_deflate(groupId,myId,
+			     static_cast<int> (enableShuffleFilter),
+			     static_cast<int> (enableDeflateFilter),
+			     deflateLevel),__FILE__,__LINE__);
+}
+  
+
+// Gets the compression parameters
+void NcmpiVar::getCompressionParameters(bool& shuffleFilterEnabled, bool& deflateFilterEnabled, int& deflateLevel) const {
+    
+  int enableShuffleFilterInt;
+  int enableDeflateFilterInt;
+  ncmpiCheck(ncmpi_inq_var_deflate(groupId,myId,
+			     &enableShuffleFilterInt,
+			     &enableDeflateFilterInt,
+			     &deflateLevel),__FILE__,__LINE__);
+  shuffleFilterEnabled =  static_cast<bool> (enableShuffleFilterInt);
+  deflateFilterEnabled =  static_cast<bool> (enableDeflateFilterInt);
+}
+  
+
+
+////////////////////
+  
+// Endianness details
+  
+////////////////////
+      
+
+// Sets the endianness of the variable.
+void NcmpiVar::setEndianness(EndianMode endianMode) const {
+    
+  ncmpiCheck(ncmpi_def_var_endian(groupId,myId,static_cast<int> (endianMode)),__FILE__,__LINE__);
+}
+  
+  
+// Gets the endianness of the variable.
+NcmpiVar::EndianMode NcmpiVar::getEndianness() const {
+    
+  int endianInt;
+  ncmpiCheck(ncmpi_inq_var_endian(groupId,myId,&endianInt),__FILE__,__LINE__);
+  return static_cast<EndianMode> (endianInt);
+}
+  
+      
+  
+////////////////////
+  
+// Checksum details
+  
+////////////////////
+  
+  
+// Sets the checksum parameters of a variable.
+void NcmpiVar::setChecksum(ChecksumMode checksumMode) const {
+  ncmpiCheck(ncmpi_def_var_fletcher32(groupId,myId,static_cast<int> (checksumMode)),__FILE__,__LINE__);
+}
+  
+  
+// Gets the checksum parameters of the variable.
+NcmpiVar::ChecksumMode NcmpiVar::getChecksum() const {
+  int checksumInt;
+  ncmpiCheck(ncmpi_inq_var_fletcher32(groupId,myId,&checksumInt),__FILE__,__LINE__);
+  return static_cast<ChecksumMode> (checksumInt);
+}
+  
+  
+
+  
+////////////////////
+  
+//  renaming the variable
+  
+////////////////////
+  
+void NcmpiVar::rename( const string& newname ) const 
+{
+  ncmpiCheck(ncmpi_rename_var(groupId,myId,newname.c_str()),__FILE__,__LINE__);
+}
+
+
+
+
+
+////////////////////
+
+//  data writing (independent I/O APIs)
+
+////////////////////
+
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar(const char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_text(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar(const unsigned char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_uchar(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar(const signed char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_schar(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar(const short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_short(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar(const int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_int(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar(const long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_long(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar(const float* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_float(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar(const double* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_double(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar(const unsigned short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_ushort(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar(const unsigned int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_uint(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar(const long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_longlong(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar(const unsigned long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_ulonglong(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable with no data conversion.
+void NcmpiVar::putVar(const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var(groupId, myId,dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+
+///////////////////
+
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& index, const unsigned char* datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_uchar(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& index, const signed char* datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_schar(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& index, const short datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_short(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& index, const int datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_int(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& index, const long datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_long(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& index, const float datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_float(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& index, const double datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_double(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& index, const unsigned short datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_ushort(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& index, const unsigned int datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_uint(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& index, const long long datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_longlong(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& index, const unsigned long long datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_ulonglong(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable with no data conversion.
+void NcmpiVar::putVar(const vector<MPI_Offset>& index, const void* datumValue, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1(groupId, myId,&index[0],datumValue, bufcount, buftype),__FILE__,__LINE__);
+}
+
+
+////////////////////
+
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_text(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_uchar(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const signed char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_schar(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_short(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_int(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_long(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const float* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_float(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const double* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_double(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_ushort(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_uint(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_longlong(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_ulonglong(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable with no data conversion.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara(groupId, myId,&startp[0],&countp[0],dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+////////////////////
+
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_text(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_uchar(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const signed char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_schar(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_short(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_int(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_long(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const float* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_float(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const double* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_double(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_ushort(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_uint(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_longlong(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_ulonglong(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable with no data conversion.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+////////////////////
+
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_text(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_uchar(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const signed char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_schar(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_short(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_int(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_long(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const float* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_float(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const double* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_double(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_ushort(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_uint(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_longlong(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_ulonglong(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable with no data conversion.
+void NcmpiVar::putVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+////////////////////
+
+//  data writing (collective data mode)
+
+////////////////////
+
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar_all(const char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_text_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar_all(const unsigned char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_uchar_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar_all(const signed char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_schar_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar_all(const short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_short_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar_all(const int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_int_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar_all(const long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_long_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar_all(const float* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_float_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar_all(const double* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_double_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar_all(const unsigned short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_ushort_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar_all(const unsigned int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_uint_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar_all(const long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_longlong_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::putVar_all(const unsigned long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_ulonglong_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable with no data conversion.
+void NcmpiVar::putVar_all(const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var_all(groupId, myId,dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+///////////////////
+
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& index, const unsigned char* datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_uchar_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& index, const signed char* datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_schar_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& index, const short datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_short_all(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& index, const int datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_int_all(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& index, const long datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_long_all(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& index, const float datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_float_all(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& index, const double datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_double_all(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& index, const unsigned short datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_ushort_all(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& index, const unsigned int datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_uint_all(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& index, const long long datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_longlong_all(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& index, const unsigned long long datumValue) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_ulonglong_all(groupId, myId,&index[0],&datumValue),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable with no data conversion.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& index, const void* datumValue, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_var1_all(groupId, myId,&index[0],datumValue, bufcount, buftype),__FILE__,__LINE__);
+}
+
+
+////////////////////
+
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_text_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_uchar_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const signed char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_schar_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_short_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_int_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_long_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const float* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_float_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const double* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_double_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_ushort_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_uint_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_longlong_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_ulonglong_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable with no data conversion.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vara_all(groupId, myId,&startp[0],&countp[0],dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+////////////////////
+
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_text_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_uchar_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const signed char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_schar_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_short_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_int_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_long_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const float* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_float_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const double* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_double_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_ushort_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_uint_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_longlong_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_ulonglong_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable with no data conversion.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vars_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+////////////////////
+
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_text_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_uchar_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const signed char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_schar_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_short_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_int_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_long_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const float* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_float_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const double* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_double_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_ushort_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_uint_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_longlong_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_ulonglong_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable with no data conversion.
+void NcmpiVar::putVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varm_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+////////////////////
+
+// Writes a list of subarrays into the netCDF variable. (independent I/O APIs)
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_text(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_uchar(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const signed char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_schar(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_short(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_int(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_long(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const float* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_float(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const double* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_double(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_ushort(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_uint(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_longlong(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_ulonglong(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable with no data conversion.
+void NcmpiVar::putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn(groupId, myId, num, starts, counts, dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+////////////////////
+
+// Writes a list of subarrays into the netCDF variable. (collective I/O APIs)
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_text_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_uchar_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const signed char* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_schar_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_short_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_int_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_long_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const float* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_float_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const double* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_double_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned short* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_ushort_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned int* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_uint_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_longlong_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned long long* dataValues) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_ulonglong_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable with no data conversion.
+void NcmpiVar::putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_varn_all(groupId, myId, num, starts, counts, dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+////////////////////
+
+// Writes an array of values into the netCDF variable with filetype and buftype.
+void NcmpiVar::putVard(MPI_Datatype filetype, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vard(groupId, myId, filetype, dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+void NcmpiVar::putVard_all(MPI_Datatype filetype, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_put_vard_all(groupId, myId, filetype, dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+////////////////////
+
+//  Nonblocking data writing
+
+////////////////////
+
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::iputVar(const char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var_text(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::iputVar(const unsigned char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var_uchar(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::iputVar(const signed char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var_schar(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::iputVar(const short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var_short(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::iputVar(const int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var_int(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::iputVar(const long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var_long(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::iputVar(const float* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var_float(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::iputVar(const double* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var_double(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::iputVar(const unsigned short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var_ushort(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::iputVar(const unsigned int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var_uint(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::iputVar(const long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var_longlong(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::iputVar(const unsigned long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var_ulonglong(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable with no data conversion.
+void NcmpiVar::iputVar(const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var(groupId, myId,dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+///////////////////
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& index, const unsigned char* datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var1_uchar(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& index, const signed char* datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var1_schar(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& index, const short datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var1_short(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& index, const int datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var1_int(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& index, const long datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var1_long(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& index, const float datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var1_float(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& index, const double datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var1_double(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& index, const unsigned short datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var1_ushort(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& index, const unsigned int datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var1_uint(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& index, const long long datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var1_longlong(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& index, const unsigned long long datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var1_ulonglong(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable with no data conversion.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& index, const void* datumValue, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_var1(groupId, myId,&index[0],datumValue, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+////////////////////
+
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara_text(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara_uchar(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const signed char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara_schar(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara_short(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara_int(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara_long(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const float* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara_float(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const double* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara_double(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara_ushort(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara_uint(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara_longlong(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara_ulonglong(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable with no data conversion.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vara(groupId, myId,&startp[0],&countp[0],dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+
+////////////////////
+
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars_text(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars_uchar(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const signed char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars_schar(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars_short(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars_int(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars_long(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const float* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars_float(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const double* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars_double(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars_ushort(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars_uint(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars_longlong(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars_ulonglong(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable with no data conversion.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_vars(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+////////////////////
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm_text(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm_uchar(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const signed char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm_schar(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm_short(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm_int(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm_long(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const float* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm_float(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const double* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm_double(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm_ushort(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm_uint(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm_longlong(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm_ulonglong(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable with no data conversion.
+void NcmpiVar::iputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varm(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+////////////////////
+
+// Nonblocking writes a list of subarrays into the netCDF variable.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn_text(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn_uchar(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const signed char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn_schar(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn_short(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn_int(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn_long(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const float* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn_float(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const double* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn_double(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn_ushort(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn_uint(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn_longlong(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn_ulonglong(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable with no data conversion.
+void NcmpiVar::iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_iput_varn(groupId, myId, num, starts, counts, dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+////////////////////
+
+//  Buffered nonblocking data writing
+
+////////////////////
+
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::bputVar(const char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var_text(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::bputVar(const unsigned char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var_uchar(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::bputVar(const signed char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var_schar(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::bputVar(const short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var_short(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::bputVar(const int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var_int(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::bputVar(const long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var_long(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::bputVar(const float* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var_float(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::bputVar(const double* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var_double(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::bputVar(const unsigned short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var_ushort(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::bputVar(const unsigned int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var_uint(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::bputVar(const long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var_longlong(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable.
+void NcmpiVar::bputVar(const unsigned long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var_ulonglong(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Writes the entire data into the netCDF variable with no data conversion.
+void NcmpiVar::bputVar(const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var(groupId, myId,dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+///////////////////
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& index, const unsigned char* datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var1_uchar(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& index, const signed char* datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var1_schar(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& index, const short datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var1_short(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& index, const int datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var1_int(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& index, const long datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var1_long(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& index, const float datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var1_float(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& index, const double datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var1_double(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& index, const unsigned short datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var1_ushort(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& index, const unsigned int datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var1_uint(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& index, const long long datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var1_longlong(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& index, const unsigned long long datumValue, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var1_ulonglong(groupId, myId,&index[0],&datumValue, req),__FILE__,__LINE__);
+}
+// Writes a single datum value into the netCDF variable with no data conversion.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& index, const void* datumValue, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_var1(groupId, myId,&index[0],datumValue, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+////////////////////
+
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara_text(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara_uchar(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const signed char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara_schar(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara_short(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara_int(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara_long(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const float* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara_float(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const double* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara_double(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara_ushort(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara_uint(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara_longlong(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const unsigned long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara_ulonglong(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes an array of values into the netCDF variable with no data conversion.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vara(groupId, myId,&startp[0],&countp[0],dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+
+////////////////////
+
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars_text(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars_uchar(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const signed char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars_schar(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars_short(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars_int(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars_long(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const float* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars_float(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const double* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars_double(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars_ushort(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars_uint(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars_longlong(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const unsigned long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars_ulonglong(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a set of subsampled array values into the netCDF variable with no data conversion.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep,  const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_vars(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+////////////////////
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm_text(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm_uchar(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const signed char* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm_schar(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm_short(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm_int(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm_long(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const float* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm_float(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const double* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm_double(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned short* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm_ushort(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned int* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm_uint(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm_longlong(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const unsigned long long* dataValues, int *req) const {
+  ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm_ulonglong(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Writes a mapped array section of values into the netCDF variable with no data conversion.
+void NcmpiVar::bputVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>&countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheckDataMode(groupId);
+    ncmpiCheck(ncmpi_bput_varm(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+// Data reading (independent I/O APIs)
+
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar(char* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_text(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar(unsigned char* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_uchar(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar(signed char* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_schar(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar(short* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_short(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar(int* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_int(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar(long* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_long(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar(float* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_float(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar(double* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_double(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar(unsigned short* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_ushort(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar(unsigned int* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_uint(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar(long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_longlong(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar(unsigned long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_ulonglong(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable with no data conversion.
+void NcmpiVar::getVar(void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_var(groupId, myId,dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+///////////
+
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, char* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_text(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, unsigned char* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_uchar(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, signed char* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_schar(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, short* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_short(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, int* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_int(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, long* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_long(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, float* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_float(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, double* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_double(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, unsigned short* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_ushort(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, unsigned int* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_uint(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, long long* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_longlong(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, unsigned long long* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_ulonglong(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable with no data conversion.
+void NcmpiVar::getVar(const vector<MPI_Offset>& index, void* datumValue, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_var1(groupId, myId,&index[0],datumValue, bufcount, buftype),__FILE__,__LINE__);
+}
+
+///////////
+
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, char* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_text(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, unsigned char* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_uchar(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, signed char* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_schar(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, short* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_short(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, int* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_int(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, long* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_long(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, float* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_float(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, double* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_double(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, unsigned short* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_ushort(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, unsigned int* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_uint(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_longlong(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, unsigned long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_ulonglong(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable with no data conversion.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_vara(groupId, myId,&startp[0],&countp[0],dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+
+///////////
+
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, char* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_text(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, unsigned char* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_uchar(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, signed char* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_schar(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, short* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_short(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, int* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_int(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, long* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_long(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, float* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_float(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, double* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_double(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, unsigned short* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_ushort(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, unsigned int* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_uint(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_longlong(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, unsigned long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_ulonglong(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable with no data conversion.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_vars(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+
+///////////
+
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, char* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_text(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, unsigned char* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_uchar(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, signed char* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_schar(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, short* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_short(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, int* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_int(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, long* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_long(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, float* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_float(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, double* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_double(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, unsigned short* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_ushort(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, unsigned int* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_uint(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_longlong(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, unsigned long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_ulonglong(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable with no data conversion.
+void NcmpiVar::getVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_varm(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+//
+// Data reading (collective data mode)
+//
+
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar_all(char* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_text_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar_all(unsigned char* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_uchar_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar_all(signed char* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_schar_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar_all(short* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_short_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar_all(int* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_int_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar_all(long* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_long_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar_all(float* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_float_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar_all(double* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_double_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar_all(unsigned short* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_ushort_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar_all(unsigned int* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_uint_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar_all(long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_longlong_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::getVar_all(unsigned long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_var_ulonglong_all(groupId, myId,dataValues),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable with no data conversion.
+void NcmpiVar::getVar_all(void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_var_all(groupId, myId,dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+
+///////////
+
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, char* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_text_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, unsigned char* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_uchar_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, signed char* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_schar_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, short* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_short_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, int* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_int_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, long* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_long_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, float* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_float_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, double* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_double_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, unsigned short* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_ushort_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, unsigned int* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_uint_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, long long* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_longlong_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, unsigned long long* datumValue) const {
+    ncmpiCheck(ncmpi_get_var1_ulonglong_all(groupId, myId,&index[0],datumValue),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable with no data conversion.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& index, void* datumValue, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_var1_all(groupId, myId,&index[0],datumValue, bufcount, buftype),__FILE__,__LINE__);
+}
+
+///////////
+
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, char* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_text_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, unsigned char* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_uchar_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, signed char* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_schar_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, short* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_short_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, int* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_int_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, long* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_long_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, float* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_float_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, double* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_double_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, unsigned short* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_ushort_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, unsigned int* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_uint_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_longlong_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, unsigned long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_vara_ulonglong_all(groupId, myId,&startp[0],&countp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable with no data conversion.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_vara_all(groupId, myId,&startp[0],&countp[0],dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+
+///////////
+
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, char* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_text_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, unsigned char* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_uchar_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, signed char* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_schar_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, short* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_short_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, int* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_int_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, long* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_long_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, float* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_float_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, double* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_double_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, unsigned short* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_ushort_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, unsigned int* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_uint_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_longlong_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, unsigned long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_vars_ulonglong_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable with no data conversion.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_vars_all(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+
+///////////
+
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, char* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_text_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, unsigned char* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_uchar_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, signed char* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_schar_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, short* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_short_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, int* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_int_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, long* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_long_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, float* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_float_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, double* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_double_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, unsigned short* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_ushort_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, unsigned int* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_uint_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_longlong_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, unsigned long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_varm_ulonglong_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable with no data conversion.
+void NcmpiVar::getVar_all(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_varm_all(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+//////////////////////
+
+// Reads a list of subarrays from  a netCDF variable. (independent I/O APIs)
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], char* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_text(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned char* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_uchar(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], signed char* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_schar(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], short* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_short(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], int* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_int(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], long* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_long(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], float* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_float(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], double* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_double(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned short* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_ushort(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned int* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_uint(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_longlong(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_ulonglong(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable with no data conversion.
+void NcmpiVar::getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_varn(groupId, myId, num, starts, counts, dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+//////////////////////
+
+// Reads a list of subarrays from  a netCDF variable. (collective I/O APIs)
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], char* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_text_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned char* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_uchar_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], signed char* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_schar_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], short* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_short_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], int* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_int_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], long* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_long_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], float* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_float_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], double* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_double_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned short* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_ushort_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned int* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_uint_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_longlong_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned long long* dataValues) const {
+    ncmpiCheck(ncmpi_get_varn_ulonglong_all(groupId, myId, num, starts, counts, dataValues),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable with no data conversion.
+void NcmpiVar::getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_varn_all(groupId, myId, num, starts, counts, dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+
+// Reads an array of values from a netCDF variable with filetype and buftype.
+void NcmpiVar::getVard(MPI_Datatype filetype, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_vard(groupId, myId, filetype, dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+// Reads an array of values from a netCDF variable with filetype and buftype.
+void NcmpiVar::getVard_all(MPI_Datatype filetype, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const {
+    ncmpiCheck(ncmpi_get_vard_all(groupId, myId, filetype, dataValues, bufcount, buftype),__FILE__,__LINE__);
+}
+
+// Nonblocking data reading
+
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::igetVar(char* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_var_text(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::igetVar(unsigned char* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_var_uchar(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::igetVar(signed char* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_var_schar(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::igetVar(short* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_var_short(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::igetVar(int* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_var_int(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::igetVar(long* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_var_long(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::igetVar(float* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_var_float(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::igetVar(double* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_var_double(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::igetVar(unsigned short* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_var_ushort(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::igetVar(unsigned int* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_var_uint(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::igetVar(long long* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_var_longlong(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable.
+void NcmpiVar::igetVar(unsigned long long* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_var_ulonglong(groupId, myId,dataValues, req),__FILE__,__LINE__);
+}
+// Reads the entire data of the netCDF variable with no data conversion.
+void NcmpiVar::igetVar(void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheck(ncmpi_iget_var(groupId, myId,dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+
+///////////
+
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, char* datumValue, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1_text(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, unsigned char* datumValue, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1_uchar(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, signed char* datumValue, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1_schar(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, short* datumValue, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1_short(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, int* datumValue, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1_int(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, long* datumValue, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1_long(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, float* datumValue, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1_float(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, double* datumValue, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1_double(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, unsigned short* datumValue, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1_ushort(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, unsigned int* datumValue, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1_uint(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, long long* datumValue, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1_longlong(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, unsigned long long* datumValue, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1_ulonglong(groupId, myId,&index[0],datumValue, req),__FILE__,__LINE__);
+}
+// Reads a single datum value of a netCDF variable with no data conversion.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& index, void* datumValue, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheck(ncmpi_iget_var1(groupId, myId,&index[0],datumValue, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+
+///////////
+
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, char* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara_text(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, unsigned char* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara_uchar(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, signed char* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara_schar(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, short* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara_short(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, int* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara_int(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, long* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara_long(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, float* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara_float(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, double* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara_double(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, unsigned short* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara_ushort(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, unsigned int* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara_uint(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, long long* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara_longlong(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, unsigned long long* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara_ulonglong(groupId, myId,&startp[0],&countp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable with no data conversion.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheck(ncmpi_iget_vara(groupId, myId,&startp[0],&countp[0],dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+///////////
+
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, char* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars_text(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, unsigned char* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars_uchar(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, signed char* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars_schar(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, short* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars_short(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, int* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars_int(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, long* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars_long(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, float* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars_float(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, double* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars_double(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, unsigned short* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars_ushort(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, unsigned int* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars_uint(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, long long* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars_longlong(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, unsigned long long* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars_ulonglong(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a subsampled (strided) array section of values from a netCDF variable with no data conversion.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheck(ncmpi_iget_vars(groupId, myId,&startp[0],&countp[0],&stridep[0],dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+
+///////////
+
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, char* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm_text(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, unsigned char* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm_uchar(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, signed char* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm_schar(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, short* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm_short(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, int* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm_int(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, long* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm_long(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, float* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm_float(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, double* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm_double(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, unsigned short* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm_ushort(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, unsigned int* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm_uint(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, long long* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm_longlong(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, unsigned long long* dataValues, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm_ulonglong(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, req),__FILE__,__LINE__);
+}
+// Reads a mapped array section of values from a netCDF variable with no data conversion.
+void NcmpiVar::igetVar(const vector<MPI_Offset>& startp, const vector<MPI_Offset>& countp, const vector<MPI_Offset>& stridep, const vector<MPI_Offset>& imapp, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const {
+    ncmpiCheck(ncmpi_iget_varm(groupId, myId,&startp[0],&countp[0],&stridep[0],&imapp[0],dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+//////////////////////
+
+// Reads a list of subarrays from  a netCDF variable. (independent I/O APIs)
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], char* dataValues, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn_text(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned char* dataValues, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn_uchar(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], signed char* dataValues, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn_schar(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], short* dataValues, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn_short(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], int* dataValues, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn_int(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], long* dataValues, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn_long(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], float* dataValues, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn_float(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], double* dataValues, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn_double(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned short* dataValues, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn_ushort(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned int* dataValues, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn_uint(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable.
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], long long* dataValues, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn_longlong(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned long long* dataValues, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn_ulonglong(groupId, myId, num, starts, counts, dataValues, req),__FILE__,__LINE__);
+}
+// Reads an array of values from  a netCDF variable with no data conversion.
+void NcmpiVar::igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int*req) const {
+    ncmpiCheck(ncmpi_iget_varn(groupId, myId, num, starts, counts, dataValues, bufcount, buftype, req),__FILE__,__LINE__);
+}
+
+//////////////////////
+
+void NcmpiVar::Inq_file_offset(MPI_Offset *offset)
+{
+    ncmpiCheck(ncmpi_inq_varoffset(groupId, myId, offset),__FILE__,__LINE__);
+}
+
diff --git a/src/libcxx/ncmpiVar.h b/src/libcxx/ncmpiVar.h
new file mode 100644
index 0000000..ec20240
--- /dev/null
+++ b/src/libcxx/ncmpiVar.h
@@ -0,0 +1,3322 @@
+#include <exception>
+#include <string>
+#include <typeinfo>
+#include <map>
+#include <vector>
+#include <pnetcdf.h>
+#include "ncmpiVarAtt.h"
+#include "ncmpiGroup.h"
+#include "ncmpiByte.h"
+#include "ncmpiUbyte.h"
+#include "ncmpiChar.h"
+#include "ncmpiShort.h"
+#include "ncmpiUshort.h"
+#include "ncmpiInt.h"
+#include "ncmpiUint.h"
+#include "ncmpiInt64.h"
+#include "ncmpiUint64.h"
+#include "ncmpiFloat.h"
+#include "ncmpiDouble.h"
+
+#ifndef NcmpiVarClass
+#define NcmpiVarClass
+
+namespace PnetCDF
+{
+  //  class NcmpiGroup;  // forward declaration.
+  class NcmpiDim;    // forward declaration.
+  //  class NcmpiVarAtt; // forward declaration.
+  class NcmpiType;   // forward declaration.
+
+  /*! Class represents a netCDF variable. */
+  class NcmpiVar
+  {
+  public:
+    
+    /*! Used for chunking specifications (see NcmpiVar::setChunking,  NcmpiVar::getChunkingParameters). */
+    enum ChunkMode
+      {
+	/*!
+	  Chunked storage is used for this variable.
+	*/
+	ncmpi_CHUNKED    = NC_CHUNKED,   
+	/*! Contiguous storage is used for this variable. Variables with one or more unlimited 
+	  dimensions cannot use contiguous storage. If contiguous storage is turned on, the 
+	  chunkSizes parameter is ignored. 
+	*/
+	ncmpi_CONTIGUOUS = NC_CONTIGUOUS
+      };
+
+    /*!
+      Used to specifying the endianess of the data, (see NcmpiVar::setEndianness, NcmpiVar::getEndianness). By default this is NC_ENDIAN_NATIVE.
+    */
+    enum EndianMode
+      {
+	ncmpi_ENDIAN_NATIVE = NC_ENDIAN_NATIVE, //!< Native endian.
+	ncmpi_ENDIAN_LITTLE = NC_ENDIAN_LITTLE, //!< Little endian.
+	ncmpi_ENDIAN_BIG    = NC_ENDIAN_BIG     //!< Big endian.
+      };
+
+    /*! Used for checksum specification (see NcmpiVar::setChecksum, NcmpiVar::getChecksum). */
+    enum ChecksumMode
+      {
+	ncmpi_NOCHECKSUM = NC_NOCHECKSUM, //!< No checksum (the default).
+	ncmpi_FLETCHER32 = NC_FLETCHER32  //!< Selects the Fletcher32 checksum filter. 
+      };
+
+    /*! destructor */
+    ~NcmpiVar(){};
+      
+    /*! Constructor generates a \ref isNull "null object". */
+    NcmpiVar ();
+
+    /*! Constructor for a variable .
+    
+      The variable must already exist in the netCDF file. New netCDF variables can be added using NcmpiGroup::addNcmpiVar();
+      \param grp    Parent NcmpiGroup object.
+      \param varId  Id of the is NcmpiVar object.
+    */
+    NcmpiVar (const NcmpiGroup& grp, const int& varId);
+
+    /*! assignment operator  */
+    NcmpiVar& operator =(const NcmpiVar& rhs);
+      
+    /*! equivalence operator */
+    bool operator==(const NcmpiVar& rhs) const;     
+      
+    /*!  != operator */
+    bool operator!=(const NcmpiVar& rhs) const;     
+
+    /*! The copy constructor. */
+    NcmpiVar(const NcmpiVar& ncmpiVar);
+      
+    /*! Name of this NcmpiVar object.*/
+    std::string getName() const;
+
+    /*! Gets parent group. */
+    NcmpiGroup  getParentGroup() const;
+
+    /*! Returns the variable type. */
+    NcmpiType getType() const;              
+      
+      
+    /*! Rename the variable. */
+    void rename( const std::string& newname ) const;
+      
+
+    /*! Get the variable id. */
+    int  getId() const;
+    
+    /*! Returns true if this object variable is not defined. */
+    bool isNull() const  {return nullObject;}
+
+    /*! comparator operator  */
+    friend bool operator<(const NcmpiVar& lhs,const NcmpiVar& rhs);
+    
+    /*! comparator operator  */
+    friend bool operator>(const NcmpiVar& lhs,const NcmpiVar& rhs);
+    
+    /////////////////
+      
+    // Information about Dimensions
+      
+    /////////////////
+      
+    /*! The the number of dimensions. */
+    int getDimCount() const ;
+
+    /*! Gets the i'th NcmpiDim object. */
+    NcmpiDim getDim(int i) const;
+
+    /*! Gets the set of NcmpiDim objects. */
+    std::vector<NcmpiDim> getDims() const;
+
+    /////////////////
+      
+    // Information about Attributes
+      
+    /////////////////
+      
+    /*! Gets the number of attributes. */
+    int getAttCount() const;
+      
+    /*! Gets attribute by name */
+    NcmpiVarAtt getAtt(const std::string& name) const;
+
+    /*! Gets the set of attributes. */
+    std::map<std::string,NcmpiVarAtt> getAtts() const;
+
+
+
+
+    /////////////////////////
+
+
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const std::string& dataValues) const ;
+
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const unsigned char* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const signed char* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, short datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, int datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, long datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, float datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, double datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, unsigned short datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, unsigned int datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, unsigned long long datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, long long datumValue) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const short* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const int* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const long* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const float* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const double* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const unsigned short* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const unsigned int* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const unsigned long long* dataValues) const ;
+    /*! \overload
+     */ 
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const long long* dataValues) const ;
+    /*! 
+      Creates a new variable attribute or if already exisiting replaces it.
+      If you are writing a _Fill_Value_ attribute, and will tell the HDF5 layer to use 
+      the specified fill value for that variable. 
+      \par 
+      Although it's possible to create attributes of all types, text and double attributes are adequate for most purposes. 
+      \param name        Name of attribute.
+      \param type        The attribute type. 
+      \param len         The length of the attribute (number of Nctype repeats).
+      \param dataValues  Data Values to put into the new attribute.
+      If the type of data values differs from the netCDF variable type, type conversion will occur. 
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+      \return            The NcmpiVarAtt object for this new netCDF attribute.
+    */
+    NcmpiVarAtt putAtt(const std::string& name, const NcmpiType& type, MPI_Offset len, const void* dataValues) const ;
+
+
+
+    ////////////////////
+      
+    // Chunking details
+      
+    ////////////////////
+      
+    /*! Sets chunking parameters.
+      \param chunkMode   Enumeration type. Allowable parameters are: "ncmpi_CONTIGUOUS", "ncmpi_CHUNKED"
+      \param chunksizes  Shape of chunking, used if ChunkMode=ncmpi_CHUNKED.
+    */
+    void setChunking(ChunkMode chunkMode, std::vector<MPI_Offset>& chunksizes) const;
+      
+    /*! Gets the chunking parameters
+      \param chunkMode   On return contains either: "ncmpi_CONTIGUOUS" or "ncmpi_CHUNKED"
+      \param chunksizes  On return contains shape of chunking, used if ChunkMode=ncmpi_CHUNKED.
+    */
+    void getChunkingParameters(ChunkMode& chunkMode, std::vector<MPI_Offset>& chunkSizes) const;
+      
+      
+      
+    ////////////////////
+      
+    // Fill details
+      
+    ////////////////////
+      
+    // Sets the fill parameters
+    /*!
+      \overload
+    */
+    void setFill(bool fillMode, void *fillValue=NULL) const;
+
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      The function can be used for any type, including user-defined types. 
+      \param fillMode   Setting to true, turns on fill mode.
+      \param fillValue  Pointer to fill value.
+      Must be the same type as the variable. Ignored if fillMode=.false.
+    */
+    // void setFill(bool fillMode,const void* fillValue=NULL) const;
+
+    /*! Sets the fill parameters
+      \param fillMode   Setting to true, turns on fill mode.
+      \param fillValue  Fill value for the variable. 
+      Must be the same type as the variable. Ignored if fillMode=.false.
+    */
+/*
+    template<class T>
+      void setFill(bool fillMode, T fillValue) const
+      {
+	ncmpiCheck(ncmpi_def_var_fill(groupId,myId,static_cast<int> (!fillMode),&fillValue),__FILE__,__LINE__);
+      }
+*/
+
+    
+    
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      The function can be used for any type, including user-defined types. 
+      \param fillMode   On return set to true  if fill mode is enabled.
+      \param fillValue  On return containts a pointer to fill value.
+      Must be the same type as the variable. Ignored if fillMode=.false.
+    */
+    void getFillModeParameters(bool& fillMode, void* fillValue=NULL) const;
+    
+
+    /*! Gets the fill parameters
+      \param On return set to true  if fill mode is enabled.
+      \param On return  is set to the fill value.
+    */
+    template <class T> void getFillModeParameters(bool& fillMode,T& fillValue) const{
+       int fillModeInt;
+      ncmpiCheck(ncmpi_inq_var_fill(groupId,myId,&fillModeInt,&fillValue),__FILE__,__LINE__);
+      fillMode= static_cast<bool> (fillModeInt == 0);
+    }
+  
+
+    /* fill variable */
+    void fillRec(MPI_Offset recno) const;
+      
+    ////////////////////
+      
+    // Compression details
+      
+    ////////////////////
+      
+      
+    /*! Sets the compression parameters
+      \param enableShuffleFilter Set to true to turn on shuffle filter.
+      \param enableDeflateFilter Set to true to turn on deflate filter.
+      \param deflateLevel        The deflate level, must be 0 and 9.
+    */
+    void setCompression(bool enableShuffleFilter, bool enableDeflateFilter, int deflateLevel) const;
+      
+    /*! Gets the compression parameters
+      \param enableShuffleFilter  On return set to true if the shuffle filter is enabled.
+      \param enableDeflateFilter  On return set to true if the deflate filter is enabled.
+      \param deflateLevel         On return set to the deflate level.
+    */
+    void getCompressionParameters(bool& shuffleFilterEnabled, bool& deflateFilterEnabled, int& deflateLevel) const;
+      
+      
+      
+    ////////////////////
+      
+    // Endianness details
+      
+    ////////////////////
+      
+      
+    /*! Sets the endianness of the variable.
+      \param Endianness enumeration type. Allowable parameters are: "ncmpi_ENDIAN_NATIVE" (the default), "ncmpi_ENDIAN_LITTLE", "ncmpi_ENDIAN_BIG"
+    */
+    void setEndianness(EndianMode endianMode) const;
+      
+    /*! Gets the endianness of the variable.
+      \return Endianness enumeration type. Allowable parameters are: "ncmpi_ENDIAN_NATIVE" (the default), "ncmpi_ENDIAN_LITTLE", "ncmpi_ENDIAN_BIG"
+    */
+    EndianMode getEndianness() const;
+      
+      
+      
+    ////////////////////
+      
+    // Checksum details
+      
+    ////////////////////
+      
+      
+    /*! Sets the checksum parameters of a variable.
+      \param ChecksumMode Enumeration type. Allowable parameters are: "ncmpi_NOCHECKSUM", "ncmpi_FLETCHER32".
+    */
+    void setChecksum(ChecksumMode checksumMode) const;
+      
+    /*! Gets the checksum parameters of the variable.
+      \return ChecksumMode Enumeration type. Allowable parameters are: "ncmpi_NOCHECKSUM", "ncmpi_FLETCHER32".
+    */
+    ChecksumMode getChecksum() const;
+    
+    
+    
+    ////////////////////
+    
+    //  data  reading
+    
+    ////////////////////
+      
+      
+
+    // Reads the entire data into the netCDF variable. (independent data mode)
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void getVar(void* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(unsigned char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(signed char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(long* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(float* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(double* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(unsigned short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(unsigned int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(unsigned long long* dataValues) const;
+    /*! 
+      Reads the entire data from an netCDF variable.
+      This is the simplest interface to use for reading the value of a scalar variable 
+      or when all the values of a multidimensional variable can be read at once. The values 
+      are read into consecutive locations with the last dimension varying fastest. 
+      
+      Take care when using the simplest forms of this interface with record variables when you 
+      don't specify how many records are to be read. If you try to read all the values of a 
+      record variable into an array but there are more records in the file than you assume, 
+      more data will be read than you expect, which may cause a segmentation violation.
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getVar(long long* dataValues) const;
+
+    void getVar(void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+
+    //////////////////////
+
+    // Reads a single datum value from a variable of an open netCDF dataset.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void getVar(const std::vector<MPI_Offset>& index, void* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& index, char* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& index, unsigned char* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& index, signed char* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& index, short* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& index, int* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& index, long* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& index, float* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& index, double* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& index, unsigned short* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& index, unsigned int* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& index, unsigned long long* dataumValue) const;
+    /*! Reads a single datum value from a variable of an open netCDF dataset.
+      The value is converted from the external data type of the variable, if necessary.
+
+      \param index       Vector specifying the index of the data value to be read. 
+      The indices are relative to 0, so for example, the first data value of a two-dimensional 
+      variable would have index (0,0). The elements of index must correspond to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first index is the record number.
+
+      \param datumValue Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getVar(const std::vector<MPI_Offset>& index, long long* dataumValue) const;
+
+    void getVar(const std::vector<MPI_Offset>& index, void* dataumValue, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    //////////////////////
+
+    // Reads an array of values from a netCDF variable of an open netCDF dataset. 
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, void* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, unsigned char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, signed char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, long* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, float* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, double* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, unsigned short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, unsigned int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, unsigned long long* dataValues) const;
+    /*! 
+      Reads an array of values from a netCDF variable of an open netCDF dataset. 
+      The array is specified by giving a corner and a vector of edge lengths. 
+      The values are read into consecutive locations with the last dimension varying fastest.
+
+      \param start
+      Vector specifying the index in the variable where the first of the data values will be read. 
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of start must be the same as the number of dimensions of the specified variable. 
+      The elements of start correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first index would correspond to the starting record number for reading the data values.
+
+      \param count
+      Vector specifying the edge lengths along each dimension of the block of data values to be read. 
+      To read a single value, for example, specify count as (1, 1, ... , 1). The length of count is the number of 
+      dimensions of the specified variable. The elements of count correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count corresponds to a count of the number of records to read.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, long long* dataValues) const;
+
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    //////////////////////
+
+    // Reads a subsampled (strided) array section of values from a netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, void* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, unsigned char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, signed char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, long* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, float* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, double* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, unsigned short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, unsigned int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, unsigned long long* dataValues) const;
+    /*! 
+      Reads a subsampled (strided) array section of values from a netCDF variable.
+      The subsampled array section is specified by giving a corner, a vector of edge lengths, and a stride vector. 
+      The values are read with the last dimension of the netCDF variable varying fastest.
+
+      \param start
+      Vector specifying the index in the variable where the first of the data values will be read. 
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of start must be the same as the number of dimensions of the specified variable. 
+      The elements of start correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first index would correspond to the starting record number for reading the data values.
+
+      \param count
+      Vector specifying the edge lengths along each dimension of the block of data values to be read. 
+      To read a single value, for example, specify count as (1, 1, ... , 1). The length of count is the number of 
+      dimensions of the specified variable. The elements of count correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count corresponds to a count of the number of records to read.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stride
+      Vector specifying the interval between selected indices. The elements of the stride vector correspond, in order, 
+      to the variable's dimensions. A value of 1 accesses adjacent values of the netCDF variable in the corresponding 
+      dimension; a value of 2 accesses every other value of the netCDF variable in the corresponding dimension; and so 
+      on. A NULL stride argument is treated as (1, 1, ... , 1). 
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, long long* dataValues) const;
+
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+
+    //////////////////////
+
+    // Reads a mapped array section of values from a netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, void* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, unsigned char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, signed char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, long* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, float* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, double* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, unsigned short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, unsigned int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, unsigned long long* dataValues) const;
+    /*! 
+      Reads a mapped array section of values from a netCDF variable.
+      The mapped array section is specified by giving a corner, a vector of edge lengths, a stride vector, and an 
+      index mapping vector. The index mapping vector is a vector of integers that specifies the mapping between the 
+      dimensions of a netCDF variable and the in-memory structure of the internal data array. No assumptions are 
+      made about the ordering or length of the dimensions of the data array. 
+
+      \param start
+      Vector specifying the index in the variable where the first of the data values will be read. 
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of start must be the same as the number of dimensions of the specified variable. 
+      The elements of start correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first index would correspond to the starting record number for reading the data values.
+
+      \param count
+      Vector specifying the edge lengths along each dimension of the block of data values to be read. 
+      To read a single value, for example, specify count as (1, 1, ... , 1). The length of count is the number of 
+      dimensions of the specified variable. The elements of count correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count corresponds to a count of the number of records to read.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stride
+      Vector specifying the interval between selected indices. The elements of the stride vector correspond, in order, 
+      to the variable's dimensions. A value of 1 accesses adjacent values of the netCDF variable in the corresponding 
+      dimension; a value of 2 accesses every other value of the netCDF variable in the corresponding dimension; and so 
+      on. A NULL stride argument is treated as (1, 1, ... , 1). 
+
+      \param imap
+      Vector of integers that specifies the mapping between the dimensions of a netCDF variable and the in-memory 
+      structure of the internal data array. imap[0] gives the distance between elements of the internal array corresponding 
+      to the most slowly varying dimension of the netCDF variable. imap[n-1] (where n is the rank of the netCDF variable) 
+      gives the distance between elements of the internal array corresponding to the most rapidly varying dimension of the 
+      netCDF variable. Intervening imap elements correspond to other dimensions of the netCDF variable in the obvious way. 
+      Distances between elements are specified in type-independent units of elements (the distance between internal elements 
+      that occupy adjacent memory locations is 1 and not the element's byte-length as in netCDF 2). 
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, long long* dataValues) const;
+
+    void getVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    //////////////////////
+
+    // Reads the entire data into the netCDF variable. (collective data mode)
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void getVar_all(void* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(unsigned char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(signed char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(long* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(float* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(double* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(unsigned short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(unsigned int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(unsigned long long* dataValues) const;
+    /*! 
+      Reads the entire data from an netCDF variable.
+      This is the simplest interface to use for reading the value of a scalar variable 
+      or when all the values of a multidimensional variable can be read at once. The values 
+      are read into consecutive locations with the last dimension varying fastest. 
+      
+      Take care when using the simplest forms of this interface with record variables when you 
+      don't specify how many records are to be read. If you try to read all the values of a 
+      record variable into an array but there are more records in the file than you assume, 
+      more data will be read than you expect, which may cause a segmentation violation.
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getVar_all(long long* dataValues) const;
+
+    void getVar_all(void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    ////////////////////
+    
+    // Reads a single datum value from a variable of an open netCDF dataset.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void getVar_all(const std::vector<MPI_Offset>& index, void* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& index, char* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& index, unsigned char* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& index, signed char* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& index, short* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& index, int* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& index, long* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& index, float* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& index, double* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& index, unsigned short* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& index, unsigned int* dataumValue) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& index, unsigned long long* dataumValue) const;
+    /*! Reads a single datum value from a variable of an open netCDF dataset.
+      The value is converted from the external data type of the variable, if necessary.
+
+      \param index       Vector specifying the index of the data value to be read. 
+      The indices are relative to 0, so for example, the first data value of a two-dimensional 
+      variable would have index (0,0). The elements of index must correspond to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first index is the record number.
+
+      \param datumValue Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getVar_all(const std::vector<MPI_Offset>& index, long long* dataumValue) const;
+
+    void getVar_all(const std::vector<MPI_Offset>& index, void* dataumValue, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    //////////////////////
+
+    // Reads an array of values from a netCDF variable of an open netCDF dataset. 
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, void* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, unsigned char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, signed char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, long* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, float* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, double* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, unsigned short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, unsigned int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, unsigned long long* dataValues) const;
+    /*! 
+      Reads an array of values from a netCDF variable of an open netCDF dataset. 
+      The array is specified by giving a corner and a vector of edge lengths. 
+      The values are read into consecutive locations with the last dimension varying fastest.
+
+      \param start
+      Vector specifying the index in the variable where the first of the data values will be read. 
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of start must be the same as the number of dimensions of the specified variable. 
+      The elements of start correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first index would correspond to the starting record number for reading the data values.
+
+      \param count
+      Vector specifying the edge lengths along each dimension of the block of data values to be read. 
+      To read a single value, for example, specify count as (1, 1, ... , 1). The length of count is the number of 
+      dimensions of the specified variable. The elements of count correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count corresponds to a count of the number of records to read.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, long long* dataValues) const;
+
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    //////////////////////
+
+    // Reads a subsampled (strided) array section of values from a netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, void* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, unsigned char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, signed char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, long* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, float* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, double* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, unsigned short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, unsigned int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, unsigned long long* dataValues) const;
+    /*! 
+      Reads a subsampled (strided) array section of values from a netCDF variable.
+      The subsampled array section is specified by giving a corner, a vector of edge lengths, and a stride vector. 
+      The values are read with the last dimension of the netCDF variable varying fastest.
+
+      \param start
+      Vector specifying the index in the variable where the first of the data values will be read. 
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of start must be the same as the number of dimensions of the specified variable. 
+      The elements of start correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first index would correspond to the starting record number for reading the data values.
+
+      \param count
+      Vector specifying the edge lengths along each dimension of the block of data values to be read. 
+      To read a single value, for example, specify count as (1, 1, ... , 1). The length of count is the number of 
+      dimensions of the specified variable. The elements of count correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count corresponds to a count of the number of records to read.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stride
+      Vector specifying the interval between selected indices. The elements of the stride vector correspond, in order, 
+      to the variable's dimensions. A value of 1 accesses adjacent values of the netCDF variable in the corresponding 
+      dimension; a value of 2 accesses every other value of the netCDF variable in the corresponding dimension; and so 
+      on. A NULL stride argument is treated as (1, 1, ... , 1). 
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, long long* dataValues) const;
+
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+
+    //////////////////////
+
+    // Reads a mapped array section of values from a netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, void* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, unsigned char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, signed char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, long* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, float* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, double* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, unsigned short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, unsigned int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, unsigned long long* dataValues) const;
+    /*! 
+      Reads a mapped array section of values from a netCDF variable.
+      The mapped array section is specified by giving a corner, a vector of edge lengths, a stride vector, and an 
+      index mapping vector. The index mapping vector is a vector of integers that specifies the mapping between the 
+      dimensions of a netCDF variable and the in-memory structure of the internal data array. No assumptions are 
+      made about the ordering or length of the dimensions of the data array. 
+
+      \param start
+      Vector specifying the index in the variable where the first of the data values will be read. 
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of start must be the same as the number of dimensions of the specified variable. 
+      The elements of start correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first index would correspond to the starting record number for reading the data values.
+
+      \param count
+      Vector specifying the edge lengths along each dimension of the block of data values to be read. 
+      To read a single value, for example, specify count as (1, 1, ... , 1). The length of count is the number of 
+      dimensions of the specified variable. The elements of count correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count corresponds to a count of the number of records to read.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stride
+      Vector specifying the interval between selected indices. The elements of the stride vector correspond, in order, 
+      to the variable's dimensions. A value of 1 accesses adjacent values of the netCDF variable in the corresponding 
+      dimension; a value of 2 accesses every other value of the netCDF variable in the corresponding dimension; and so 
+      on. A NULL stride argument is treated as (1, 1, ... , 1). 
+
+      \param imap
+      Vector of integers that specifies the mapping between the dimensions of a netCDF variable and the in-memory 
+      structure of the internal data array. imap[0] gives the distance between elements of the internal array corresponding 
+      to the most slowly varying dimension of the netCDF variable. imap[n-1] (where n is the rank of the netCDF variable) 
+      gives the distance between elements of the internal array corresponding to the most rapidly varying dimension of the 
+      netCDF variable. Intervening imap elements correspond to other dimensions of the netCDF variable in the obvious way. 
+      Distances between elements are specified in type-independent units of elements (the distance between internal elements 
+      that occupy adjacent memory locations is 1 and not the element's byte-length as in netCDF 2). 
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, long long* dataValues) const;
+
+    void getVar_all(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+
+   
+    ////////////////////
+
+    //  Nonblocking data reading
+
+    ////////////////////
+
+    // Reads the entire data into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void igetVar(void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(unsigned char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(signed char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(short* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(int* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(long* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(float* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(double* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(unsigned short* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(unsigned int* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(unsigned long long* dataValues, int *req) const;
+    /*! 
+      Reads the entire data from an netCDF variable.
+      This is the simplest interface to use for reading the value of a scalar variable 
+      or when all the values of a multidimensional variable can be read at once. The values 
+      are read into consecutive locations with the last dimension varying fastest. 
+      
+      Take care when using the simplest forms of this interface with record variables when you 
+      don't specify how many records are to be read. If you try to read all the values of a 
+      record variable into an array but there are more records in the file than you assume, 
+      more data will be read than you expect, which may cause a segmentation violation.
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void igetVar(long long* dataValues, int *req) const;
+
+    void igetVar(void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+
+    //////////////////////
+
+    // Reads a single datum value from a variable of an open netCDF dataset.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void igetVar(const std::vector<MPI_Offset>& index, void* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& index, char* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& index, unsigned char* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& index, signed char* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& index, short* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& index, int* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& index, long* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& index, float* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& index, double* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& index, unsigned short* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& index, unsigned int* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& index, unsigned long long* dataumValue, int *req) const;
+    /*! Reads a single datum value from a variable of an open netCDF dataset.
+      The value is converted from the external data type of the variable, if necessary.
+
+      \param index       Vector specifying the index of the data value to be read. 
+      The indices are relative to 0, so for example, the first data value of a two-dimensional 
+      variable would have index (0,0). The elements of index must correspond to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first index is the record number.
+
+      \param datumValue Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void igetVar(const std::vector<MPI_Offset>& index, long long* dataumValue, int *req) const;
+
+    void igetVar(const std::vector<MPI_Offset>& index, void* dataumValue, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    //////////////////////
+
+    // Reads an array of values from a netCDF variable of an open netCDF dataset. 
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, unsigned char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, signed char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, short* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, int* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, long* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, float* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, double* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, unsigned short* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, unsigned int* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, unsigned long long* dataValues, int *req) const;
+    /*! 
+      Reads an array of values from a netCDF variable of an open netCDF dataset. 
+      The array is specified by giving a corner and a vector of edge lengths. 
+      The values are read into consecutive locations with the last dimension varying fastest.
+
+      \param start
+      Vector specifying the index in the variable where the first of the data values will be read. 
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of start must be the same as the number of dimensions of the specified variable. 
+      The elements of start correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first index would correspond to the starting record number for reading the data values.
+
+      \param count
+      Vector specifying the edge lengths along each dimension of the block of data values to be read. 
+      To read a single value, for example, specify count as (1, 1, ... , 1). The length of count is the number of 
+      dimensions of the specified variable. The elements of count correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count corresponds to a count of the number of records to read.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, long long* dataValues, int *req) const;
+
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    //////////////////////
+
+    // Reads a subsampled (strided) array section of values from a netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, unsigned char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, signed char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, short* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, int* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, long* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, float* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, double* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, unsigned short* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, unsigned int* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, unsigned long long* dataValues, int *req) const;
+    /*! 
+      Reads a subsampled (strided) array section of values from a netCDF variable.
+      The subsampled array section is specified by giving a corner, a vector of edge lengths, and a stride vector. 
+      The values are read with the last dimension of the netCDF variable varying fastest.
+
+      \param start
+      Vector specifying the index in the variable where the first of the data values will be read. 
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of start must be the same as the number of dimensions of the specified variable. 
+      The elements of start correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first index would correspond to the starting record number for reading the data values.
+
+      \param count
+      Vector specifying the edge lengths along each dimension of the block of data values to be read. 
+      To read a single value, for example, specify count as (1, 1, ... , 1). The length of count is the number of 
+      dimensions of the specified variable. The elements of count correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count corresponds to a count of the number of records to read.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stride
+      Vector specifying the interval between selected indices. The elements of the stride vector correspond, in order, 
+      to the variable's dimensions. A value of 1 accesses adjacent values of the netCDF variable in the corresponding 
+      dimension; a value of 2 accesses every other value of the netCDF variable in the corresponding dimension; and so 
+      on. A NULL stride argument is treated as (1, 1, ... , 1). 
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, long long* dataValues, int *req) const;
+
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+
+    //////////////////////
+
+    // Reads a mapped array section of values from a netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, unsigned char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, signed char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, short* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, int* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, long* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, float* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, double* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, unsigned short* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, unsigned int* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, unsigned long long* dataValues, int *req) const;
+    /*! 
+      Reads a mapped array section of values from a netCDF variable.
+      The mapped array section is specified by giving a corner, a vector of edge lengths, a stride vector, and an 
+      index mapping vector. The index mapping vector is a vector of integers that specifies the mapping between the 
+      dimensions of a netCDF variable and the in-memory structure of the internal data array. No assumptions are 
+      made about the ordering or length of the dimensions of the data array. 
+
+      \param start
+      Vector specifying the index in the variable where the first of the data values will be read. 
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of start must be the same as the number of dimensions of the specified variable. 
+      The elements of start correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first index would correspond to the starting record number for reading the data values.
+
+      \param count
+      Vector specifying the edge lengths along each dimension of the block of data values to be read. 
+      To read a single value, for example, specify count as (1, 1, ... , 1). The length of count is the number of 
+      dimensions of the specified variable. The elements of count correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count corresponds to a count of the number of records to read.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stride
+      Vector specifying the interval between selected indices. The elements of the stride vector correspond, in order, 
+      to the variable's dimensions. A value of 1 accesses adjacent values of the netCDF variable in the corresponding 
+      dimension; a value of 2 accesses every other value of the netCDF variable in the corresponding dimension; and so 
+      on. A NULL stride argument is treated as (1, 1, ... , 1). 
+
+      \param imap
+      Vector of integers that specifies the mapping between the dimensions of a netCDF variable and the in-memory 
+      structure of the internal data array. imap[0] gives the distance between elements of the internal array corresponding 
+      to the most slowly varying dimension of the netCDF variable. imap[n-1] (where n is the rank of the netCDF variable) 
+      gives the distance between elements of the internal array corresponding to the most rapidly varying dimension of the 
+      netCDF variable. Intervening imap elements correspond to other dimensions of the netCDF variable in the obvious way. 
+      Distances between elements are specified in type-independent units of elements (the distance between internal elements 
+      that occupy adjacent memory locations is 1 and not the element's byte-length as in netCDF 2). 
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, long long* dataValues, int *req) const;
+
+    void igetVar(const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count,  const std::vector<MPI_Offset>& stride, const std::vector<MPI_Offset>& imap, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    //////////////////////
+
+    // Reads a list of subarrays of values from a netCDF variable of an open netCDF dataset. (independent I/O APIs)
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], void* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], signed char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], long* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], float* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], double* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned long long* dataValues) const;
+    /*! 
+      Reads a list of subarrays from a netCDF variable of an open netCDF dataset. 
+      Each subarray i is specified by giving a corner (starts[i][*]) and a vector of edge lengths (counts[i][*]). 
+      The values are read into consecutive locations with the last dimension varying fastest.
+
+      \param num
+      Number of subarrays.
+
+      \param starts
+      2D array of size [num][ndims] where num is the number of subarrays to get and ndims if the number of dimensions of the specified variable.
+      Each subarray i is specified by starts[i][*], the first of the data values will be read, and counts[i][*], edge lengths of the subarray.
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of the second dimension of starts and counts must be the same as the number of dimensions of the specified variable. 
+      The elements of starts's second dimension correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first element starts[*][0] would correspond to the starting record number for reading the data values.
+
+      \param counts
+      2D array of size [num][ndims] where num is the number of subarrays to get and ndims if the number of dimensions of the specified variable.
+      To read a single value, for example, specify count as (1, 1, ... , 1). The length of each count[i] is the number of 
+      dimensions of the specified variable. The elements of each count[i] correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count[i] corresponds to a count of the number of records to read.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], long long* dataValues) const;
+
+    void getVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    // Reads a list of subarrays of values from a netCDF variable of an open netCDF dataset. (collective I/O APIs)
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], void* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], signed char* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], long* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], float* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], double* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned short* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned int* dataValues) const;
+    /*! \overload
+     */ 
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned long long* dataValues) const;
+    /*! 
+      Reads a list of subarrays from a netCDF variable of an open netCDF dataset. 
+      Each subarray i is specified by giving a corner (starts[i][*]) and a vector of edge lengths (counts[i][*]). 
+      The values are read into consecutive locations with the last dimension varying fastest.
+
+      \param num
+      Number of subarrays.
+
+      \param starts
+      2D array of size [num][ndims] where num is the number of subarrays to get and ndims if the number of dimensions of the specified variable.
+      Each subarray i is specified by starts[i][*], the first of the data values will be read, and counts[i][*], edge lengths of the subarray.
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of the second dimension of starts and counts must be the same as the number of dimensions of the specified variable. 
+      The elements of starts's second dimension correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first element starts[*][0] would correspond to the starting record number for reading the data values.
+
+      \param counts
+      2D array of size [num][ndims] where num is the number of subarrays to get and ndims if the number of dimensions of the specified variable.
+      To read a single value, for example, specify count as (1, 1, ... , 1). The length of each count[i] is the number of 
+      dimensions of the specified variable. The elements of each count[i] correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count[i] corresponds to a count of the number of records to read.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], long long* dataValues) const;
+
+    void getVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    /* vard APIs take filetype and buftype */
+    void getVard    (MPI_Datatype filetype, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+    void getVard_all(MPI_Datatype filetype, void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    //////////////////////
+
+    // Nonblocking reads a list of subarrays of values from a netCDF variable of an open netCDF dataset.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], signed char* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], short* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], int* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], long* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], float* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], double* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned short* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned int* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], unsigned long long* dataValues, int *req) const;
+    /*! 
+      Reads a list of subarrays from a netCDF variable of an open netCDF dataset. 
+      Each subarray i is specified by giving a corner (starts[i][*]) and a vector of edge lengths (counts[i][*]). 
+      The values are read into consecutive locations with the last dimension varying fastest.
+
+      \param num
+      Number of subarrays.
+
+      \param starts
+      2D array of size [num][ndims] where num is the number of subarrays to get and ndims if the number of dimensions of the specified variable.
+      Each subarray i is specified by starts[i][*], the first of the data values will be read, and counts[i][*], edge lengths of the subarray.
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of the second dimension of starts and counts must be the same as the number of dimensions of the specified variable. 
+      The elements of starts's second dimension correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first element starts[*][0] would correspond to the starting record number for reading the data values.
+
+      \param counts
+      2D array of size [num][ndims] where num is the number of subarrays to get and ndims if the number of dimensions of the specified variable.
+      To read a single value, for example, specify count as (1, 1, ... , 1). The length of each count[i] is the number of 
+      dimensions of the specified variable. The elements of each count[i] correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count[i] corresponds to a count of the number of records to read.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues Pointer to the location into which the data value is read. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], long long* dataValues, int *req) const;
+
+    void igetVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    //////////////////////
+
+
+    //  data writing (independent data mode)
+
+    ////////////////////
+   
+    // Writes the entire data into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVar(const void* dataValues) const;
+    /*! \overload
+     */ 
+    void putVar(const char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const unsigned char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const signed char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const long* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const float* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const double* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const unsigned short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const unsigned int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const unsigned long long* dataValues) const;
+    /*! 
+      Writes the entire data into the netCDF variable.
+      This is the simplest interface to use for writing a value in a scalar variable 
+      or whenever all the values of a multidimensional variable can all be 
+      written at once. The values to be written are associated with the 
+      netCDF variable by assuming that the last dimension of the netCDF 
+      variable varies fastest in the C interface. 
+      
+      Take care when using the simplest forms of this interface with 
+      record variables when you don't specify how many records are to be 
+      written. If you try to write all the values of a record variable 
+      into a netCDF file that has no record data yet (hence has 0 records), 
+      nothing will be written. Similarly, if you try to write all of a record 
+      variable but there are more records in the file than you assume, more data 
+      may be written to the file than you supply, which may result in a 
+      segmentation violation.
+      
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable type, type conversion will occur. 
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void putVar(const long long* dataValues) const;
+
+    void putVar(const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    /////////////////////////
+
+    // Writes a single datum into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVar(const std::vector<MPI_Offset>& index, const void* dataumValue) const;
+    /*! \overload
+     */ 
+    void putVar(const std::vector<MPI_Offset>& index, const std::string& dataumValue) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& index, const unsigned char* dataumValue) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& index, const signed char* dataumValue) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& index, const short dataumValue) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& index, const int dataumValue) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& index, const long dataumValue) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& index, const float dataumValue) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& index, const double dataumValue) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& index, const unsigned short dataumValue) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& index, const unsigned int dataumValue) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& index, const unsigned long long dataumValue) const;
+    /*! 
+      Writes a single datum into the netCDF variable.
+
+      \param index      Vector specifying the index where the data values will be written. The indices are relative to 0, so for example, 
+      the first data value of a two-dimensional variable would have index (0,0). The elements of index must correspond to the variable's dimensions. 
+      Hence, if the variable uses the unlimited dimension, the first index would correspond to the unlimited dimension.
+
+      \param datumValue The data value. If the type of data values differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void putVar(const std::vector<MPI_Offset>& index, const long long dataumValue) const;
+
+    void putVar(const std::vector<MPI_Offset>& index, const void* dataumValue, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    /////////////////////////
+
+    // Writes an array of values into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const void* dataValues) const;
+    /*! \overload
+     */ 
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const signed char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const long* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const float* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const double* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned long long* dataValues) const;
+    /*! 
+      Writes an array of values into the netCDF variable.
+      The portion of the netCDF variable to write is specified by giving a corner and a vector of edge lengths 
+      that refer to an array section of the netCDF variable. The values to be written are associated with 
+      the netCDF variable by assuming that the last dimension of the netCDF variable varies fastest. 
+
+      \param startp  Vector specifying the index where the first data values will be written.  The indices are relative to 0, so for 
+      example, the first data value of a variable would have index (0, 0, ... , 0). The elements of start correspond, in order, to the 
+      variable's dimensions. Hence, if the variable is a record variable, the first index corresponds to the starting record number for writing the data values.
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable 
+      type, type conversion will occur. (However, no type conversion is 
+      carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const long long* dataValues) const;
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    ////////////////
+
+    // Writes a set of subsampled array values into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const void* dataValues) const;
+    /*! \overload
+     */ 
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const signed char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const long* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const float* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const double* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned long long* dataValues) const;
+    /*! 
+      Writes an array of values into the netCDF variable.
+      The subsampled array section is specified by giving a corner, a vector of counts, and a stride vector. 
+
+      \param startp  Vector specifying the index where the first data values will be written.  The indices are relative to 0, so for 
+      example, the first data value of a variable would have index (0, 0, ... , 0). The elements of start correspond, in order, to the 
+      variable's dimensions. Hence, if the variable is a record variable, the first index corresponds to the starting record number for writing the data values.
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stridep  A vector of MPI_Offset integers that specifies the sampling interval along each dimension of the netCDF variable. 
+      The elements of the stride vector correspond, in order, to the netCDF variable's dimensions (stride[0] gives the sampling interval 
+      along the most slowly varying dimension of the netCDF variable). Sampling intervals are specified in type-independent units of 
+      elements (a value of 1 selects consecutive elements of the netCDF variable along the corresponding dimension, a value of 2 selects 
+      every other element, etc.). A NULL stride argument is treated as (1, 1, ... , 1).
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable type, type conversion will occur. 
+      (However, no type conversion is  carried out for variables using the user-defined data types: ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const long long* dataValues) const;
+
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    ////////////////
+
+    // Writes a mapped array section of values into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const void* dataValues) const;
+    /*! \overload
+     */ 
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const signed char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const long* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const float* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const double* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned long long* dataValues) const;
+    /*! 
+      Writes a mapped array section of values into the netCDF variable.
+      The mapped array section is specified by giving a corner, a vector of counts, a stride vector, and an index mapping vector. 
+      The index mapping vector is a vector of integers that specifies the mapping between the dimensions of a netCDF variable and the in-memory structure of the internal data array. 
+      No assumptions are made about the ordering or length of the dimensions of the data array. 
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stridep  A vector of MPI_Offset integers that specifies the sampling interval along each dimension of the netCDF variable. 
+      The elements of the stride vector correspond, in order, to the netCDF variable's dimensions (stride[0] gives the sampling interval 
+      along the most slowly varying dimension of the netCDF variable). Sampling intervals are specified in type-independent units of 
+      elements (a value of 1 selects consecutive elements of the netCDF variable along the corresponding dimension, a value of 2 selects 
+      every other element, etc.). A NULL stride argument is treated as (1, 1, ... , 1).
+
+      \param imap Vector  specifies the mapping between the dimensions of a netCDF variable and the in-memory structure of the internal data array. 
+      The elements of the index mapping vector correspond, in order, to the netCDF variable's dimensions (imap[0] gives the distance between elements 
+      of the internal array corresponding to the most slowly varying dimension of the netCDF variable). Distances between elements are 
+      specified in type-independent units of elements (the distance between internal elements that occupy adjacent memory locations is 
+      1 and not the element's byte-length as in netCDF 2). A NULL argument means the memory-resident values have the same structure as 
+      the associated netCDF variable.
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable type, type conversion will occur. 
+     (However, no type conversion is carried out for variables using the user-defined data types:  ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+*/
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const long long* dataValues) const;
+
+    void putVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    ////////////////////
+
+    //  data writing (collective data mode)
+
+    ////////////////////
+
+    // Writes the entire data into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVar_all(const void* dataValues) const;
+    /*! \overload
+     */ 
+    void putVar_all(const char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const unsigned char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const signed char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const long* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const float* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const double* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const unsigned short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const unsigned int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const unsigned long long* dataValues) const;
+    /*! 
+      Writes the entire data into the netCDF variable.
+      This is the simplest interface to use for writing a value in a scalar variable 
+      or whenever all the values of a multidimensional variable can all be 
+      written at once. The values to be written are associated with the 
+      netCDF variable by assuming that the last dimension of the netCDF 
+      variable varies fastest in the C interface. 
+      
+      Take care when using the simplest forms of this interface with 
+      record variables when you don't specify how many records are to be 
+      written. If you try to write all the values of a record variable 
+      into a netCDF file that has no record data yet (hence has 0 records), 
+      nothing will be written. Similarly, if you try to write all of a record 
+      variable but there are more records in the file than you assume, more data 
+      may be written to the file than you supply, which may result in a 
+      segmentation violation.
+      
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable type, type conversion will occur. 
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void putVar_all(const long long* dataValues) const;
+
+    void putVar_all(const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    /////////////////////////
+
+    // Writes a single datum into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVar_all(const std::vector<MPI_Offset>& index, const void* dataumValue) const;
+    /*! \overload
+     */ 
+    void putVar_all(const std::vector<MPI_Offset>& index, const std::string& dataumValue) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& index, const unsigned char* dataumValue) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& index, const signed char* dataumValue) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& index, const short dataumValue) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& index, const int dataumValue) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& index, const long dataumValue) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& index, const float dataumValue) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& index, const double dataumValue) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& index, const unsigned short dataumValue) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& index, const unsigned int dataumValue) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& index, const unsigned long long dataumValue) const;
+    /*! 
+      Writes a single datum into the netCDF variable.
+
+      \param index      Vector specifying the index where the data values will be written. The indices are relative to 0, so for example, 
+      the first data value of a two-dimensional variable would have index (0,0). The elements of index must correspond to the variable's dimensions. 
+      Hence, if the variable uses the unlimited dimension, the first index would correspond to the unlimited dimension.
+
+      \param datumValue The data value. If the type of data values differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void putVar_all(const std::vector<MPI_Offset>& index, const long long dataumValue) const;
+
+    void putVar_all(const std::vector<MPI_Offset>& index, const void* dataumValue, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    /////////////////////////
+
+    // Writes an array of values into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const void* dataValues) const;
+    /*! \overload
+     */ 
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const signed char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const long* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const float* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const double* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned long long* dataValues) const;
+    /*! 
+      Writes an array of values into the netCDF variable.
+      The portion of the netCDF variable to write is specified by giving a corner and a vector of edge lengths 
+      that refer to an array section of the netCDF variable. The values to be written are associated with 
+      the netCDF variable by assuming that the last dimension of the netCDF variable varies fastest. 
+
+      \param startp  Vector specifying the index where the first data values will be written.  The indices are relative to 0, so for 
+      example, the first data value of a variable would have index (0, 0, ... , 0). The elements of start correspond, in order, to the 
+      variable's dimensions. Hence, if the variable is a record variable, the first index corresponds to the starting record number for writing the data values.
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable 
+      type, type conversion will occur. (However, no type conversion is 
+      carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const long long* dataValues) const;
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    ////////////////
+
+    // Writes a set of subsampled array values into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const void* dataValues) const;
+    /*! \overload
+     */ 
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const signed char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const long* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const float* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const double* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned long long* dataValues) const;
+    /*! 
+      Writes an array of values into the netCDF variable.
+      The subsampled array section is specified by giving a corner, a vector of counts, and a stride vector. 
+
+      \param startp  Vector specifying the index where the first data values will be written.  The indices are relative to 0, so for 
+      example, the first data value of a variable would have index (0, 0, ... , 0). The elements of start correspond, in order, to the 
+      variable's dimensions. Hence, if the variable is a record variable, the first index corresponds to the starting record number for writing the data values.
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stridep  A vector of MPI_Offset integers that specifies the sampling interval along each dimension of the netCDF variable. 
+      The elements of the stride vector correspond, in order, to the netCDF variable's dimensions (stride[0] gives the sampling interval 
+      along the most slowly varying dimension of the netCDF variable). Sampling intervals are specified in type-independent units of 
+      elements (a value of 1 selects consecutive elements of the netCDF variable along the corresponding dimension, a value of 2 selects 
+      every other element, etc.). A NULL stride argument is treated as (1, 1, ... , 1).
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable type, type conversion will occur. 
+      (However, no type conversion is  carried out for variables using the user-defined data types: ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const long long* dataValues) const;
+
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    ////////////////
+
+    // Writes a mapped array section of values into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const void* dataValues) const;
+    /*! \overload
+     */ 
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const signed char* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const long* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const float* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const double* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned short* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned int* dataValues) const;
+    /*!  \overload
+    */
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned long long* dataValues) const;
+    /*! 
+      Writes a mapped array section of values into the netCDF variable.
+      The mapped array section is specified by giving a corner, a vector of counts, a stride vector, and an index mapping vector. 
+      The index mapping vector is a vector of integers that specifies the mapping between the dimensions of a netCDF variable and the in-memory structure of the internal data array. 
+      No assumptions are made about the ordering or length of the dimensions of the data array. 
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stridep  A vector of MPI_Offset integers that specifies the sampling interval along each dimension of the netCDF variable. 
+      The elements of the stride vector correspond, in order, to the netCDF variable's dimensions (stride[0] gives the sampling interval 
+      along the most slowly varying dimension of the netCDF variable). Sampling intervals are specified in type-independent units of 
+      elements (a value of 1 selects consecutive elements of the netCDF variable along the corresponding dimension, a value of 2 selects 
+      every other element, etc.). A NULL stride argument is treated as (1, 1, ... , 1).
+
+      \param imap Vector  specifies the mapping between the dimensions of a netCDF variable and the in-memory structure of the internal data array. 
+      The elements of the index mapping vector correspond, in order, to the netCDF variable's dimensions (imap[0] gives the distance between elements 
+      of the internal array corresponding to the most slowly varying dimension of the netCDF variable). Distances between elements are 
+      specified in type-independent units of elements (the distance between internal elements that occupy adjacent memory locations is 
+      1 and not the element's byte-length as in netCDF 2). A NULL argument means the memory-resident values have the same structure as 
+      the associated netCDF variable.
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable type, type conversion will occur. 
+     (However, no type conversion is carried out for variables using the user-defined data types:  ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+*/
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const long long* dataValues) const;
+
+    void putVar_all(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    ////////////////////
+
+    // Writes a list of subarrays into the netCDF variable. (independent I/O APIs)
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const void* dataValues) const;
+    /*! \overload
+     */ 
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const char* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned char* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const signed char* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const short* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const int* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const long* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const float* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const double* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned short* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned int* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned long long* dataValues) const;
+    /*! 
+      Writes a list of subarrays into the netCDF variable.
+      Each subarray i is specified by giving a corner (starts[i][*]) and a vector of edge lengths (counts[i][*]). 
+      The values to be written are associated with the netCDF variable by assuming that the last dimension of the netCDF variable varies fastest. 
+
+      \param num
+      Number of subarrays.
+
+      \param starts
+      2D array of size [num][ndims] where num is the number of subarrays to get and ndims if the number of dimensions of the specified variable.
+      Each subarray i is specified by starts[i][*], the first of the data values will be written, and counts[i][*], edge lengths of the subarray.
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of the second dimension of starts and counts must be the same as the number of dimensions of the specified variable. 
+      The elements of starts's second dimension correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first element starts[*][0] would correspond to the starting record number for writing the data values.
+
+      \param counts
+      2D array of size [num][ndims] where num is the number of subarrays to get and ndims if the number of dimensions of the specified variable.
+      To write a single value, for example, specify count as (1, 1, ... , 1). The length of each count[i] is the number of 
+      dimensions of the specified variable. The elements of each count[i] correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count[i] corresponds to a count of the number of records to write.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues Pointer to the location into which the data value is written. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+    */
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const long long* dataValues) const;
+    void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    ////////////////
+
+    // Writes an array of values into the netCDF variable. (collective I/O APIs)
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const void* dataValues) const;
+    /*! \overload
+     */ 
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const char* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned char* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const signed char* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const short* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const int* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const long* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const float* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const double* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned short* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned int* dataValues) const;
+    /*!  \overload
+    */
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned long long* dataValues) const;
+    /*! 
+      Writes an array of values into the netCDF variable.
+      The portion of the netCDF variable to write is specified by giving a corner and a vector of edge lengths 
+      that refer to an array section of the netCDF variable. The values to be written are associated with 
+      the netCDF variable by assuming that the last dimension of the netCDF variable varies fastest. 
+
+      \param startp  Vector specifying the index where the first data values will be written.  The indices are relative to 0, so for 
+      example, the first data value of a variable would have index (0, 0, ... , 0). The elements of start correspond, in order, to the 
+      variable's dimensions. Hence, if the variable is a record variable, the first index corresponds to the starting record number for writing the data values.
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable 
+      type, type conversion will occur. (However, no type conversion is 
+      carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const long long* dataValues) const;
+    void putVarn_all(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    /* vard APIs take filetype and buftype */
+    void putVard    (MPI_Datatype filetype, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+    void putVard_all(MPI_Datatype filetype, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype) const;
+
+    ////////////////
+
+    //  Nonblocking data writing
+
+    ////////////////////
+   
+   
+    // Writes the entire data into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void iputVar(const void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void iputVar(const char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const unsigned char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const signed char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const long* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const float* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const double* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const unsigned short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const unsigned int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const unsigned long long* dataValues, int *req) const;
+    /*! 
+      Writes the entire data into the netCDF variable.
+      This is the simplest interface to use for writing a value in a scalar variable 
+      or whenever all the values of a multidimensional variable can all be 
+      written at once. The values to be written are associated with the 
+      netCDF variable by assuming that the last dimension of the netCDF 
+      variable varies fastest in the C interface. 
+      
+      Take care when using the simplest forms of this interface with 
+      record variables when you don't specify how many records are to be 
+      written. If you try to write all the values of a record variable 
+      into a netCDF file that has no record data yet (hence has 0 records), 
+      nothing will be written. Similarly, if you try to write all of a record 
+      variable but there are more records in the file than you assume, more data 
+      may be written to the file than you supply, which may result in a 
+      segmentation violation.
+      
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable type, type conversion will occur. 
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void iputVar(const long long* dataValues, int *req) const;
+
+    void iputVar(const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    /////////////////////////
+
+    // Writes a single datum into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void iputVar(const std::vector<MPI_Offset>& index, const void* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void iputVar(const std::vector<MPI_Offset>& index, const std::string& dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& index, const unsigned char* dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& index, const signed char* dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& index, const short dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& index, const int dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& index, const long dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& index, const float dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& index, const double dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& index, const unsigned short dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& index, const unsigned int dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& index, const unsigned long long dataumValue, int *req) const;
+    /*! 
+      Writes a single datum into the netCDF variable.
+
+      \param index      Vector specifying the index where the data values will be written. The indices are relative to 0, so for example, 
+      the first data value of a two-dimensional variable would have index (0,0). The elements of index must correspond to the variable's dimensions. 
+      Hence, if the variable uses the unlimited dimension, the first index would correspond to the unlimited dimension.
+
+      \param datumValue The data value. If the type of data values differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void iputVar(const std::vector<MPI_Offset>& index, const long long dataumValue, int *req) const;
+
+    void iputVar(const std::vector<MPI_Offset>& index, const void* dataumValue, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    /////////////////////////
+
+    // Writes an array of values into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const signed char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const long* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const float* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const double* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned long long* dataValues, int *req) const;
+    /*! 
+      Writes an array of values into the netCDF variable.
+      The portion of the netCDF variable to write is specified by giving a corner and a vector of edge lengths 
+      that refer to an array section of the netCDF variable. The values to be written are associated with 
+      the netCDF variable by assuming that the last dimension of the netCDF variable varies fastest. 
+
+      \param startp  Vector specifying the index where the first data values will be written.  The indices are relative to 0, so for 
+      example, the first data value of a variable would have index (0, 0, ... , 0). The elements of start correspond, in order, to the 
+      variable's dimensions. Hence, if the variable is a record variable, the first index corresponds to the starting record number for writing the data values.
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable 
+      type, type conversion will occur. (However, no type conversion is 
+      carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const long long* dataValues, int *req) const;
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    ////////////////
+
+    // Writes a set of subsampled array values into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const signed char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const long* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const float* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const double* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned long long* dataValues, int *req) const;
+    /*! 
+      Writes an array of values into the netCDF variable.
+      The subsampled array section is specified by giving a corner, a vector of counts, and a stride vector. 
+
+      \param startp  Vector specifying the index where the first data values will be written.  The indices are relative to 0, so for 
+      example, the first data value of a variable would have index (0, 0, ... , 0). The elements of start correspond, in order, to the 
+      variable's dimensions. Hence, if the variable is a record variable, the first index corresponds to the starting record number for writing the data values.
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stridep  A vector of MPI_Offset integers that specifies the sampling interval along each dimension of the netCDF variable. 
+      The elements of the stride vector correspond, in order, to the netCDF variable's dimensions (stride[0] gives the sampling interval 
+      along the most slowly varying dimension of the netCDF variable). Sampling intervals are specified in type-independent units of 
+      elements (a value of 1 selects consecutive elements of the netCDF variable along the corresponding dimension, a value of 2 selects 
+      every other element, etc.). A NULL stride argument is treated as (1, 1, ... , 1).
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable type, type conversion will occur. 
+      (However, no type conversion is  carried out for variables using the user-defined data types: ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const long long* dataValues, int *req) const;
+
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    ////////////////
+
+    // Writes a mapped array section of values into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const signed char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const long* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const float* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const double* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned long long* dataValues, int *req) const;
+    /*! 
+      Writes a mapped array section of values into the netCDF variable.
+      The mapped array section is specified by giving a corner, a vector of counts, a stride vector, and an index mapping vector. 
+      The index mapping vector is a vector of integers that specifies the mapping between the dimensions of a netCDF variable and the in-memory structure of the internal data array. 
+      No assumptions are made about the ordering or length of the dimensions of the data array. 
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stridep  A vector of MPI_Offset integers that specifies the sampling interval along each dimension of the netCDF variable. 
+      The elements of the stride vector correspond, in order, to the netCDF variable's dimensions (stride[0] gives the sampling interval 
+      along the most slowly varying dimension of the netCDF variable). Sampling intervals are specified in type-independent units of 
+      elements (a value of 1 selects consecutive elements of the netCDF variable along the corresponding dimension, a value of 2 selects 
+      every other element, etc.). A NULL stride argument is treated as (1, 1, ... , 1).
+
+      \param imap Vector  specifies the mapping between the dimensions of a netCDF variable and the in-memory structure of the internal data array. 
+      The elements of the index mapping vector correspond, in order, to the netCDF variable's dimensions (imap[0] gives the distance between elements 
+      of the internal array corresponding to the most slowly varying dimension of the netCDF variable). Distances between elements are 
+      specified in type-independent units of elements (the distance between internal elements that occupy adjacent memory locations is 
+      1 and not the element's byte-length as in netCDF 2). A NULL argument means the memory-resident values have the same structure as 
+      the associated netCDF variable.
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable type, type conversion will occur. 
+     (However, no type conversion is carried out for variables using the user-defined data types:  ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+*/
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const long long* dataValues, int *req) const;
+
+    void iputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    ////////////////////
+
+    // Writes a list of subarrays into the netCDF variable. (independent I/O APIs)
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void putVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const void* dataValues) const;
+    /*! \overload
+     */ 
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const signed char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const long* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const float* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const double* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const unsigned long long* dataValues, int *req) const;
+    /*! 
+      Writes a list of subarrays into the netCDF variable.
+      Each subarray i is specified by giving a corner (starts[i][*]) and a vector of edge lengths (counts[i][*]). 
+      The values to be written are associated with the netCDF variable by assuming that the last dimension of the netCDF variable varies fastest. 
+
+      \param num
+      Number of subarrays.
+
+      \param starts
+      2D array of size [num][ndims] where num is the number of subarrays to get and ndims if the number of dimensions of the specified variable.
+      Each subarray i is specified by starts[i][*], the first of the data values will be written, and counts[i][*], edge lengths of the subarray.
+      The indices are relative to 0, so for example, the first data value of a variable would have index (0, 0, ... , 0). 
+      The length of the second dimension of starts and counts must be the same as the number of dimensions of the specified variable. 
+      The elements of starts's second dimension correspond, in order, to the variable's dimensions. Hence, if the variable is a record variable, 
+      the first element starts[*][0] would correspond to the starting record number for writing the data values.
+
+      \param counts
+      2D array of size [num][ndims] where num is the number of subarrays to get and ndims if the number of dimensions of the specified variable.
+      To write a single value, for example, specify count as (1, 1, ... , 1). The length of each count[i] is the number of 
+      dimensions of the specified variable. The elements of each count[i] correspond, in order, to the variable's dimensions. 
+      Hence, if the variable is a record variable, the first element of count[i] corresponds to a count of the number of records to write.
+      Note: setting any element of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues Pointer to the location into which the data value is written. If the type of 
+      data value differs from the netCDF variable type, type conversion will occur.
+    */
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const long long* dataValues, int *req) const;
+    void iputVarn(const int num, MPI_Offset* const starts[], MPI_Offset* const counts[], const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    ////////////////////
+
+    //  Buffered nonblocking data writing
+
+    ////////////////////
+   
+    // Writes the entire data into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void bputVar(const void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void bputVar(const char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const unsigned char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const signed char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const long* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const float* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const double* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const unsigned short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const unsigned int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const unsigned long long* dataValues, int *req) const;
+    /*! 
+      Writes the entire data into the netCDF variable.
+      This is the simplest interface to use for writing a value in a scalar variable 
+      or whenever all the values of a multidimensional variable can all be 
+      written at once. The values to be written are associated with the 
+      netCDF variable by assuming that the last dimension of the netCDF 
+      variable varies fastest in the C interface. 
+      
+      Take care when using the simplest forms of this interface with 
+      record variables when you don't specify how many records are to be 
+      written. If you try to write all the values of a record variable 
+      into a netCDF file that has no record data yet (hence has 0 records), 
+      nothing will be written. Similarly, if you try to write all of a record 
+      variable but there are more records in the file than you assume, more data 
+      may be written to the file than you supply, which may result in a 
+      segmentation violation.
+      
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable type, type conversion will occur. 
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void bputVar(const long long* dataValues, int *req) const;
+
+    void bputVar(const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    /////////////////////////
+
+    // Writes a single datum into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void bputVar(const std::vector<MPI_Offset>& index, const void* dataumValue, int *req) const;
+    /*! \overload
+     */ 
+    void bputVar(const std::vector<MPI_Offset>& index, const std::string& dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& index, const unsigned char* dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& index, const signed char* dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& index, const short dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& index, const int dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& index, const long dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& index, const float dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& index, const double dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& index, const unsigned short dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& index, const unsigned int dataumValue, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& index, const unsigned long long dataumValue, int *req) const;
+    /*! 
+      Writes a single datum into the netCDF variable.
+
+      \param index      Vector specifying the index where the data values will be written. The indices are relative to 0, so for example, 
+      the first data value of a two-dimensional variable would have index (0,0). The elements of index must correspond to the variable's dimensions. 
+      Hence, if the variable uses the unlimited dimension, the first index would correspond to the unlimited dimension.
+
+      \param datumValue The data value. If the type of data values differs from the netCDF variable type, type conversion will occur.
+      (However, no type conversion is carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void bputVar(const std::vector<MPI_Offset>& index, const long long dataumValue, int *req) const;
+
+    void bputVar(const std::vector<MPI_Offset>& index, const void* dataumValue, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    /////////////////////////
+
+    // Writes an array of values into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const signed char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const long* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const float* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const double* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const unsigned long long* dataValues, int *req) const;
+    /*! 
+      Writes an array of values into the netCDF variable.
+      The portion of the netCDF variable to write is specified by giving a corner and a vector of edge lengths 
+      that refer to an array section of the netCDF variable. The values to be written are associated with 
+      the netCDF variable by assuming that the last dimension of the netCDF variable varies fastest. 
+
+      \param startp  Vector specifying the index where the first data values will be written.  The indices are relative to 0, so for 
+      example, the first data value of a variable would have index (0, 0, ... , 0). The elements of start correspond, in order, to the 
+      variable's dimensions. Hence, if the variable is a record variable, the first index corresponds to the starting record number for writing the data values.
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable 
+      type, type conversion will occur. (However, no type conversion is 
+      carried out for variables using the user-defined data types:
+      ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const long long* dataValues, int *req) const;
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    ////////////////
+
+    // Writes a set of subsampled array values into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const signed char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const long* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const float* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const double* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const unsigned long long* dataValues, int *req) const;
+    /*! 
+      Writes an array of values into the netCDF variable.
+      The subsampled array section is specified by giving a corner, a vector of counts, and a stride vector. 
+
+      \param startp  Vector specifying the index where the first data values will be written.  The indices are relative to 0, so for 
+      example, the first data value of a variable would have index (0, 0, ... , 0). The elements of start correspond, in order, to the 
+      variable's dimensions. Hence, if the variable is a record variable, the first index corresponds to the starting record number for writing the data values.
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stridep  A vector of MPI_Offset integers that specifies the sampling interval along each dimension of the netCDF variable. 
+      The elements of the stride vector correspond, in order, to the netCDF variable's dimensions (stride[0] gives the sampling interval 
+      along the most slowly varying dimension of the netCDF variable). Sampling intervals are specified in type-independent units of 
+      elements (a value of 1 selects consecutive elements of the netCDF variable along the corresponding dimension, a value of 2 selects 
+      every other element, etc.). A NULL stride argument is treated as (1, 1, ... , 1).
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable type, type conversion will occur. 
+      (However, no type conversion is  carried out for variables using the user-defined data types: ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const long long* dataValues, int *req) const;
+
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    ////////////////
+
+    // Writes a mapped array section of values into the netCDF variable.
+    /*!
+      This is an overloaded member function, provided for convenience. 
+      It differs from the above function in what argument(s) it accepts. 
+      In addition, no data conversion is carried out. This means that 
+      the type of the data in memory must match the type of the variable.
+    */
+    // void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const void* dataValues, int *req) const;
+    /*! \overload
+     */ 
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const signed char* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const long* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const float* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const double* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned short* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned int* dataValues, int *req) const;
+    /*!  \overload
+    */
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const unsigned long long* dataValues, int *req) const;
+    /*! 
+      Writes a mapped array section of values into the netCDF variable.
+      The mapped array section is specified by giving a corner, a vector of counts, a stride vector, and an index mapping vector. 
+      The index mapping vector is a vector of integers that specifies the mapping between the dimensions of a netCDF variable and the in-memory structure of the internal data array. 
+      No assumptions are made about the ordering or length of the dimensions of the data array. 
+
+      \param countp  Vector specifying the number of indices selected along each dimension. 
+      To write a single value, for example, specify count as (1, 1, ... , 1). The elements of 
+      count correspond, in order, to the variable's dimensions. Hence, if the variable is a record 
+      variable, the first element of count corresponds to a count of the number of records to write. Note: setting any element 
+      of the count array to zero causes the function to exit without error, and without doing anything. 
+
+      \param stridep  A vector of MPI_Offset integers that specifies the sampling interval along each dimension of the netCDF variable. 
+      The elements of the stride vector correspond, in order, to the netCDF variable's dimensions (stride[0] gives the sampling interval 
+      along the most slowly varying dimension of the netCDF variable). Sampling intervals are specified in type-independent units of 
+      elements (a value of 1 selects consecutive elements of the netCDF variable along the corresponding dimension, a value of 2 selects 
+      every other element, etc.). A NULL stride argument is treated as (1, 1, ... , 1).
+
+      \param imap Vector  specifies the mapping between the dimensions of a netCDF variable and the in-memory structure of the internal data array. 
+      The elements of the index mapping vector correspond, in order, to the netCDF variable's dimensions (imap[0] gives the distance between elements 
+      of the internal array corresponding to the most slowly varying dimension of the netCDF variable). Distances between elements are 
+      specified in type-independent units of elements (the distance between internal elements that occupy adjacent memory locations is 
+      1 and not the element's byte-length as in netCDF 2). A NULL argument means the memory-resident values have the same structure as 
+      the associated netCDF variable.
+
+      \param dataValues The data values. The order in which the data will be written to the netCDF variable is with the last 
+      dimension of the specified variable varying fastest. If the type of data values differs from the netCDF variable type, type conversion will occur. 
+     (However, no type conversion is carried out for variables using the user-defined data types:  ncmpi_Vlen, ncmpi_Opaque, ncmpi_Compound and ncmpi_Enum.)
+*/
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const long long* dataValues, int *req) const;
+
+    void bputVar(const std::vector<MPI_Offset>& startp, const std::vector<MPI_Offset>& countp, const std::vector<MPI_Offset>& stridep, const std::vector<MPI_Offset>& imapp, const void* dataValues, MPI_Offset bufcount, MPI_Datatype buftype, int *req) const;
+
+    void Inq_file_offset(MPI_Offset *offset);
+
+  private:
+      
+    bool nullObject;
+
+    int myId;	
+
+    int groupId;
+       
+  };
+
+
+}
+
+
+
+#endif
+
diff --git a/src/libcxx/ncmpiVarAtt.cpp b/src/libcxx/ncmpiVarAtt.cpp
new file mode 100644
index 0000000..902a782
--- /dev/null
+++ b/src/libcxx/ncmpiVarAtt.cpp
@@ -0,0 +1,63 @@
+#include "ncmpiVar.h"
+#include "ncmpiVarAtt.h"
+#include "ncmpiGroup.h"
+#include "ncmpiCheck.h"
+#include <pnetcdf.h>
+using namespace std;
+
+
+namespace PnetCDF {
+  //  Global comparator operator ==============
+  // comparator operator 
+  bool operator<(const NcmpiVarAtt& lhs,const NcmpiVarAtt& rhs)
+  {
+    return false;
+  }
+  
+  // comparator operator 
+  bool operator>(const NcmpiVarAtt& lhs,const NcmpiVarAtt& rhs)
+  {
+    return true;
+  }
+}
+
+
+using namespace PnetCDF;
+
+
+// assignment operator
+NcmpiVarAtt& NcmpiVarAtt::operator=(const NcmpiVarAtt & rhs)
+{
+  NcmpiAtt::operator=(rhs);    // assign base class parts
+  return *this;
+}
+
+//! The copy constructor.
+NcmpiVarAtt::NcmpiVarAtt(const NcmpiVarAtt& rhs): 
+  NcmpiAtt(rhs) // invoke base class copy constructor
+{}
+
+
+// Constructor generates a null object.
+NcmpiVarAtt::NcmpiVarAtt() :
+  NcmpiAtt()  // invoke base class constructor
+{}
+
+
+// Constructor for an existing local attribute.
+NcmpiVarAtt::NcmpiVarAtt(const NcmpiGroup& grp, const NcmpiVar& ncmpiVar, const int index):
+  NcmpiAtt(false)
+{
+  groupId =  grp.getId();
+  varId = ncmpiVar.getId();
+  // get the name of this attribute
+  char attName[NC_MAX_NAME+1];
+  ncmpiCheck(ncmpi_inq_attname(groupId,varId, index, attName),__FILE__,__LINE__);
+  ncmpiCheck(ncmpi_inq_attname(groupId,varId,index,attName),__FILE__,__LINE__);
+  myName = attName;
+}
+
+// Returns the NcmpiVar parent object.
+NcmpiVar NcmpiVarAtt::getParentVar() const {
+  return NcmpiVar(groupId,varId);
+}
diff --git a/src/libcxx/ncmpiVarAtt.h b/src/libcxx/ncmpiVarAtt.h
new file mode 100644
index 0000000..0059e69
--- /dev/null
+++ b/src/libcxx/ncmpiVarAtt.h
@@ -0,0 +1,46 @@
+#include "ncmpiAtt.h"
+
+#ifndef NcmpiVarAttClass
+#define NcmpiVarAttClass
+
+namespace PnetCDF
+{
+  class NcmpiGroup;  // forward declaration.
+  class NcmpiVar;    // forward declaration.
+
+  /*! Class represents a netCDF attribute local to a netCDF variable. */
+  class NcmpiVarAtt : public NcmpiAtt
+  {
+  public:
+    
+    /*! assignment operator */
+    NcmpiVarAtt& operator= (const NcmpiVarAtt& rhs);
+      
+    /*! Constructor generates a \ref isNull "null object". */
+    NcmpiVarAtt ();
+
+    /*! The copy constructor. */
+    NcmpiVarAtt(const NcmpiVarAtt& rhs) ;
+      
+    /*! 
+      Constructor for an existing local attribute.
+      \param  grp        Parent Group object.
+      \param  NcmpiVar      Parent NcmpiVar object.
+      \param  index      The index (id) of the attribute.
+    */
+    NcmpiVarAtt(const NcmpiGroup& grp, const NcmpiVar& ncmpiVar, const int index);
+    
+    /*! Returns the NcmpiVar parent object. */
+    NcmpiVar getParentVar() const;
+
+    /*! comparator operator */
+    friend bool operator<(const NcmpiVarAtt& lhs,const NcmpiVarAtt& rhs);
+    
+    /*! comparator operator  */
+    friend bool operator>(const NcmpiVarAtt& lhs,const NcmpiVarAtt& rhs);
+    
+  };
+  
+}
+
+#endif
diff --git a/src/libcxx/ncmpiVlenType.cpp b/src/libcxx/ncmpiVlenType.cpp
new file mode 100644
index 0000000..8027313
--- /dev/null
+++ b/src/libcxx/ncmpiVlenType.cpp
@@ -0,0 +1,91 @@
+#include "ncmpiVlenType.h"
+#include "ncmpiGroup.h"
+#include "ncmpiCheck.h"
+#include "ncmpiException.h"
+#include "ncmpiByte.h"
+#include "ncmpiUbyte.h"
+#include "ncmpiChar.h"
+#include "ncmpiShort.h"
+#include "ncmpiUshort.h"
+#include "ncmpiInt.h"
+#include "ncmpiUint.h"
+#include "ncmpiInt64.h"
+#include "ncmpiUint64.h"
+#include "ncmpiFloat.h"
+#include "ncmpiDouble.h"
+#include <pnetcdf.h>
+using namespace std;
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+// Class represents a netCDF variable.
+using namespace PnetCDF;
+
+// assignment operator
+NcmpiVlenType& NcmpiVlenType::operator=(const NcmpiVlenType& rhs)
+{
+  NcmpiType::operator=(rhs);    // assign base class parts
+  return *this;
+}
+
+// assignment operator
+NcmpiVlenType& NcmpiVlenType::operator=(const NcmpiType& rhs)
+{
+  if (&rhs != this) {
+    // check the rhs is the base of an Opaque type
+    if(getTypeClass() != NC_VLEN) 	throw NcmpiException("The NcmpiType object must be the base of an Vlen type.",__FILE__,__LINE__);
+    // assign base class parts
+    NcmpiType::operator=(rhs);
+  }
+  return *this;
+}
+
+// The copy constructor.
+NcmpiVlenType::NcmpiVlenType(const NcmpiVlenType& rhs):   
+  NcmpiType(rhs)
+{
+}
+
+
+// Constructor generates a null object.
+NcmpiVlenType::NcmpiVlenType() :
+  NcmpiType()   // invoke base class constructor
+{}
+
+// constructor
+NcmpiVlenType::NcmpiVlenType(const NcmpiGroup& grp, const string& name) :
+  NcmpiType(grp,name)
+{}
+  
+// constructor
+NcmpiVlenType::NcmpiVlenType(const NcmpiType& ncmpiType): 
+  NcmpiType(ncmpiType)
+{
+  // check the nctype object is the base of a Vlen type
+  if(getTypeClass() != NC_VLEN) throw NcmpiException("The NcmpiType object must be the base of a Vlen type.",__FILE__,__LINE__);
+}
+
+// Returns the base type.
+NcmpiType NcmpiVlenType::getBaseType() const
+{
+  char charName[NC_MAX_NAME+1];
+  nc_type base_nc_typep;
+  MPI_Offset datum_sizep;
+  ncmpiCheck(ncmpi_inq_vlen(groupId,myId,charName,&datum_sizep,&base_nc_typep),__FILE__,__LINE__);
+  switch (base_nc_typep) {
+  case NC_BYTE    : return ncmpiByte;
+  case NC_UBYTE   : return ncmpiUbyte;
+  case NC_CHAR    : return ncmpiChar;
+  case NC_SHORT   : return ncmpiShort;
+  case NC_USHORT  : return ncmpiUshort;
+  case NC_INT     : return ncmpiInt;
+  case NC_UINT    : return ncmpiUint;  
+  case NC_INT64   : return ncmpiInt64; 
+  case NC_UINT64  : return ncmpiUint64;
+  case NC_FLOAT   : return ncmpiFloat;
+  case NC_DOUBLE  : return ncmpiDouble;
+  default:  
+    // this is a user defined type
+    return NcmpiType(getParentGroup(),base_nc_typep);
+  }
+}
diff --git a/src/libcxx/ncmpiVlenType.h b/src/libcxx/ncmpiVlenType.h
new file mode 100644
index 0000000..1491d9f
--- /dev/null
+++ b/src/libcxx/ncmpiVlenType.h
@@ -0,0 +1,57 @@
+#include <string>
+#include "ncmpiType.h"
+
+#ifndef NcmpiVlenTypeClass
+#define NcmpiVlenTypeClass
+
+
+namespace PnetCDF
+{
+  class NcmpiGroup;  // forward declaration.
+
+  /*! Class represents a netCDF VLEN type */
+  class NcmpiVlenType : public NcmpiType
+  {
+  public:
+
+    /*! Constructor generates a \ref isNull "null object". */
+    NcmpiVlenType();
+
+    /*! 
+      Constructor.
+      The vlen Type must already exist in the netCDF file. New netCDF vlen types can be added 
+      using NcmpiGroup::addNcmpiVlenType();
+      \param grp        The parent group where this type is defined.
+      \param name       Name of new type.
+    */
+    NcmpiVlenType(const NcmpiGroup& grp, const std::string& name);
+
+    /*! 
+      Constructor.
+      Constructs from the base type NcmpiType object. Will throw an exception if the NcmpiType is not the base of a Vlen type.
+      \param ncmpiType     A Nctype object.
+    */
+    NcmpiVlenType(const NcmpiType& ncmpiType);
+
+    /*! assignment operator */
+    NcmpiVlenType& operator=(const NcmpiVlenType& rhs);
+      
+    /*! 
+      Assignment operator.
+      This assigns from the base type NcmpiType object. Will throw an exception if the NcmpiType is not the base of a Vlen type.
+    */
+    NcmpiVlenType& operator=(const NcmpiType& rhs);
+      
+    /*! The copy constructor. */
+    NcmpiVlenType(const NcmpiVlenType& rhs);
+      
+    ~NcmpiVlenType(){;}
+      
+    /*! Returns the base type. */
+    NcmpiType  getBaseType() const;
+      
+  };
+  
+}
+
+#endif
diff --git a/src/libcxx/ncmpi_notyet.cpp b/src/libcxx/ncmpi_notyet.cpp
new file mode 100644
index 0000000..be1af0f
--- /dev/null
+++ b/src/libcxx/ncmpi_notyet.cpp
@@ -0,0 +1,318 @@
+#include <pnetcdf.h>
+#include <iostream>
+#include "ncmpi_notyet.h"
+
+#ifndef __func__
+#define __func__ __FUNCTION__
+#endif
+
+ int
+ncmpi_insert_compound(int ncid, nc_type xtype, const char *name,
+                   MPI_Offset offset, nc_type field_typeid){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Insert a named array into a compound type. */
+ int
+ncmpi_insert_array_compound(int ncid, nc_type xtype, const char *name,
+                         MPI_Offset offset, nc_type field_typeid,
+                         int ndims, const int *dim_sizes){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+ int
+ncmpi_insert_enum(int ncid, nc_type xtype, const char *name,
+               const void *value){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+ int
+ncmpi_def_compound(int ncid, MPI_Offset size, const char *name, nc_type *typeidp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_inq_enum(int ncid, nc_type xtype, char *name, nc_type *base_nc_typep,
+            MPI_Offset *base_sizep, MPI_Offset *num_membersp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Get information about an enum member: a name and value. Name size
+ *  * will be <= NC_MAX_NAME. */
+ int
+ncmpi_inq_enum_member(int ncid, nc_type xtype, int idx, char *name,
+                   void *value){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_inq_compound_nfields(int ncid, nc_type xtype, MPI_Offset *nfieldsp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_inq_compound_name(int ncid, nc_type xtype, char *name){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Get the size of a compound type. */
+ int
+ncmpi_inq_compound_size(int ncid, nc_type xtype, MPI_Offset *sizep){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Given the xtype and the fieldid, get all info about it. */
+ int
+ncmpi_inq_compound_field(int ncid, nc_type xtype, int fieldid, char *name,
+                      MPI_Offset *offsetp, nc_type *field_typeidp, int *ndimsp,
+                      int *dim_sizesp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Given the typeid and the fieldid, get the name. */
+ int
+ncmpi_inq_compound_fieldname(int ncid, nc_type xtype, int fieldid,
+                          char *name){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+ int
+ncmpi_inq_compound(int ncid, nc_type xtype, char *name, MPI_Offset *sizep,
+                MPI_Offset *nfieldsp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+/* Given the xtype and the name, get the fieldid. */
+ int
+ncmpi_inq_compound_fieldindex(int ncid, nc_type xtype, const char *name,
+                           int *fieldidp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Given the xtype and fieldid, get the offset. */
+ int
+ncmpi_inq_compound_fieldoffset(int ncid, nc_type xtype, int fieldid,
+                            MPI_Offset *offsetp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Given the xtype and the fieldid, get the type of that field. */
+ int
+ncmpi_inq_compound_fieldtype(int ncid, nc_type xtype, int fieldid,
+                          nc_type *field_typeidp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Given the xtype and the fieldid, get the number of dimensions for
+ *  * that field (scalars are 0). */
+ int
+ncmpi_inq_compound_fieldndims(int ncid, nc_type xtype, int fieldid,
+                           int *ndimsp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+ int
+ncmpi_inq_compound_fielddim_sizes(int ncid, nc_type xtype, int fieldid,
+                               int *dim_sizes){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_inq_grpname_len(int ncid, MPI_Offset *lenp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Given an ncid, find the ncid of its parent group. */
+ int
+ncmpi_inq_grp_parent(int ncid, int *parent_ncid){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Given a name and parent ncid, find group ncid. */
+ int
+ncmpi_inq_grp_ncid(int ncid, const char *grp_name, int *grp_ncid){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+/* Given a full name and ncid, find group ncid. */
+ int
+ncmpi_inq_grp_full_ncid(int ncid, const char *full_name, int *grp_ncid){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Get a list of ids for all the variables in a group. */
+ int
+ncmpi_inq_varids(int ncid, int *nvars, int *varids){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Find all dimids for a location. This finds all dimensions in a
+ *  * group, or any of its parents. */
+ int
+ncmpi_inq_dimids(int ncid, int *ndims, int *dimids, int include_parents){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_inq_type(int ncid, nc_type xtype, char *name, MPI_Offset *size){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Find all user-defined types for a location. This finds all
+ *  * user-defined types in a group. */
+ int
+ncmpi_inq_typeids(int ncid, int *ntypes, int *typeids){*ntypes=0; std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Are two types equal? */
+ int
+ncmpi_inq_type_equal(int ncid1, nc_type typeid1, int ncid2,
+                  nc_type typeid2, int *equal){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+/* Create a group. its ncid is returned in the new_ncid pointer. */
+ int
+ncmpi_def_grp(int parent_ncid, const char *name, int *new_ncid){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Rename a group */
+ int
+ncmpi_rename_grp(int grpid, const char *name){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_inq_grps(int ncid, int *numgrps, int *ncids){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Given locid, find name of group. (Root group is named "/".) */
+ int
+ncmpi_inq_grpname(int ncid, char *name){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Given ncid, find full name and len of full name. (Root group is
+ *  * named "/", with length 1.) */
+ int
+ncmpi_inq_grpname_full(int ncid, MPI_Offset *lenp, char *full_name){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_def_enum(int ncid, nc_type base_typeid, const char *name,
+            nc_type *typeidp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_def_vlen(int ncid, const char *name, nc_type base_typeid, nc_type *xtypep){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Find out about a vlen. */
+ int
+ncmpi_inq_vlen(int ncid, nc_type xtype, char *name, MPI_Offset *datum_sizep,
+            nc_type *base_nc_typep){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_free_vlen(nc_vlen_t *vl){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_free_vlens(MPI_Offset len, nc_vlen_t vlens[]){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Put or get one element in a vlen array. */
+ int
+ncmpi_put_vlen_element(int ncid, int typeid1, void *vlen_element,
+                    MPI_Offset len, const void *data){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_get_vlen_element(int ncid, int typeid1, const void *vlen_element,
+                    MPI_Offset *len, void *data){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+ int
+ncmpi_def_opaque(int ncid, MPI_Offset size, const char *name, nc_type *xtypep){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Get information about an opaque type. */
+ int
+ncmpi_inq_opaque(int ncid, nc_type xtype, char *name, MPI_Offset *sizep){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_inq_user_type(int ncid, nc_type xtype, char *name, MPI_Offset *size,
+                 nc_type *base_nc_typep, MPI_Offset *nfieldsp, int *classp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_def_var_chunking(int ncid, int varid, int storage, const MPI_Offset *chunksizesp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+ int
+ncmpi_inq_var_chunking(int ncid, int varid, int *storagep, MPI_Offset *chunksizesp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_def_var_endian(int ncid, int varid, int endian){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Learn about the endianness of a variable. */
+ int
+ncmpi_inq_var_endian(int ncid, int varid, int *endianp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+ int
+ncmpi_set_chunk_cache(MPI_Offset size, MPI_Offset nelems, float preemption){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_def_var_deflate(int ncid, int varid, int shuffle, int deflate,
+                   int deflate_level){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+ int
+ncmpi_inq_var_deflate(int ncid, int varid, int *shufflep,
+                   int *deflatep, int *deflate_levelp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+ int
+ncmpi_inq_var_szip(int ncid, int varid, int *options_maskp, int *pixels_per_blockp){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Set fletcher32 checksum for a var. This must be done after nc_def_var
+ *    and before nc_enddef. */
+ int
+ncmpi_def_var_fletcher32(int ncid, int varid, int fletcher32){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+/* Inquire about fletcher32 checksum for a var. */
+ int
+ncmpi_inq_var_fletcher32(int ncid, int varid, int *fletcher32p){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_put_var1_string(int ncid, int varid, const MPI_Offset *indexp,
+                   const char **op){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_get_var1_string(int ncid, int varid, const MPI_Offset *indexp,
+                   char **ip){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_put_var_string(int ncid, int varid,
+                   const char **op){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_get_var_string(int ncid, int varid,
+                   char **ip){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_put_vara_string(int ncid, int varid, const MPI_Offset *startp,
+                   const MPI_Offset *countp,
+                   const char **op){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_get_vara_string(int ncid, int varid, const MPI_Offset *startp,
+                   const MPI_Offset *countp,
+                   char **ip){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_put_vars_string(int ncid, int varid, const MPI_Offset *startp,
+                   const MPI_Offset *countp, const MPI_Offset *stridep,
+                   const char **op){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_get_vars_string(int ncid, int varid, const MPI_Offset *startp,
+                   const MPI_Offset *countp, const MPI_Offset *stridep,
+                   char **ip){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_put_varm_string(int ncid, int varid, const MPI_Offset *startp,
+                   const MPI_Offset *countp, const MPI_Offset *stridep,
+                   const MPI_Offset * imapp, const char **op){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_get_varm_string(int ncid, int varid, const MPI_Offset *startp,
+                   const MPI_Offset *countp, const MPI_Offset *stridep,
+                   const MPI_Offset * imapp, char **ip){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_put_varn_string(int ncid, int varid, int num, MPI_Offset* const starts[],
+                   MPI_Offset* const count[], const char **op){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_get_varn_string(int ncid, int varid, int num, MPI_Offset* const starts[],
+                   MPI_Offset* const count[], char **ip){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_put_varn_string_all(int ncid, int varid, int num, MPI_Offset* const starts[],
+                   MPI_Offset* const count[], const char **op){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_get_varn_string_all(int ncid, int varid, int num, MPI_Offset* const starts[],
+                   MPI_Offset* const count[], char **ip){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_iput_var1_string(int ncid, int varid, const MPI_Offset *indexp, const char **op, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_bput_var1_string(int ncid, int varid, const MPI_Offset *indexp, const char **op, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_iget_var1_string(int ncid, int varid, const MPI_Offset *indexp, char **ip, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_iput_var_string(int ncid, int varid, const char **op, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_bput_var_string(int ncid, int varid, const char **op, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_iget_var_string(int ncid, int varid, char **ip, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_iput_vara_string(int ncid, int varid, const MPI_Offset *startp, const MPI_Offset *countp, const char **op, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_bput_vara_string(int ncid, int varid, const MPI_Offset *startp, const MPI_Offset *countp, const char **op, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_iget_vara_string(int ncid, int varid, const MPI_Offset *startp, const MPI_Offset *countp, char **ip, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_iput_vars_string(int ncid, int varid, const MPI_Offset *startp, const MPI_Offset *countp, const MPI_Offset *stridep, const char **op, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_bput_vars_string(int ncid, int varid, const MPI_Offset *startp, const MPI_Offset *countp, const MPI_Offset *stridep, const char **op, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_iget_vars_string(int ncid, int varid, const MPI_Offset *startp, const MPI_Offset *countp, const MPI_Offset *stridep, char **ip, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_iput_varm_string(int ncid, int varid, const MPI_Offset *startp, const MPI_Offset *countp, const MPI_Offset *stridep, const MPI_Offset * imapp, const char **op, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_bput_varm_string(int ncid, int varid, const MPI_Offset *startp, const MPI_Offset *countp, const MPI_Offset *stridep, const MPI_Offset * imapp, const char **op, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+ int
+ncmpi_iget_varm_string(int ncid, int varid, const MPI_Offset *startp, const MPI_Offset *countp, const MPI_Offset *stridep, const MPI_Offset * imapp, char **ip, int *req){std::cout << __func__ << " not implemented" << std::endl; return NC_EINVAL;}
+
+
diff --git a/src/libcxx/ncmpi_notyet.h b/src/libcxx/ncmpi_notyet.h
new file mode 100644
index 0000000..0970746
--- /dev/null
+++ b/src/libcxx/ncmpi_notyet.h
@@ -0,0 +1,214 @@
+#ifndef H_NC
+#define H_NC
+extern int
+ncmpi_insert_compound(int ncid, nc_type xtype, const char *name,
+                   MPI_Offset offset, nc_type field_typeid);
+
+/* Insert a named array into a compound type. */
+extern int
+ncmpi_insert_array_compound(int ncid, nc_type xtype, const char *name,
+                         MPI_Offset offset, nc_type field_typeid,
+                         int ndims, const int *dim_sizes);
+extern int
+ncmpi_insert_enum(int ncid, nc_type xtype, const char *name,
+               const void *value);
+extern int
+ncmpi_def_compound(int ncid, MPI_Offset size, const char *name, nc_type *typeidp);
+
+extern int
+ncmpi_inq_enum(int ncid, nc_type xtype, char *name, nc_type *base_nc_typep,
+            MPI_Offset *base_sizep, MPI_Offset *num_membersp);
+
+/* Get information about an enum member: a name and value. Name size
+ *  * will be <= NC_MAX_NAME. */
+extern int
+ncmpi_inq_enum_member(int ncid, nc_type xtype, int idx, char *name,
+                   void *value);
+
+extern int
+ncmpi_inq_enum_ident(int ncid, nc_type xtype, long long value, char *identifier);
+
+extern int
+ncmpi_inq_compound_nfields(int ncid, nc_type xtype, MPI_Offset *nfieldsp);
+
+extern int
+ncmpi_inq_compound_name(int ncid, nc_type xtype, char *name);
+
+/* Get the size of a compound type. */
+extern int
+ncmpi_inq_compound_size(int ncid, nc_type xtype, MPI_Offset *sizep);
+
+/* Get the number of fields in this compound type. */
+extern int
+ncmpi_inq_compound_nfields(int ncid, nc_type xtype, MPI_Offset *nfieldsp);
+
+/* Given the xtype and the fieldid, get all info about it. */
+extern int
+ncmpi_inq_compound_field(int ncid, nc_type xtype, int fieldid, char *name,
+                      MPI_Offset *offsetp, nc_type *field_typeidp, int *ndimsp,
+                      int *dim_sizesp);
+
+/* Given the typeid and the fieldid, get the name. */
+extern int
+ncmpi_inq_compound_fieldname(int ncid, nc_type xtype, int fieldid,
+                          char *name);
+extern int
+ncmpi_inq_compound(int ncid, nc_type xtype, char *name, MPI_Offset *sizep,
+                MPI_Offset *nfieldsp);
+/* Given the xtype and the name, get the fieldid. */
+extern int
+ncmpi_inq_compound_fieldindex(int ncid, nc_type xtype, const char *name,
+                           int *fieldidp);
+
+/* Given the xtype and fieldid, get the offset. */
+extern int
+ncmpi_inq_compound_fieldoffset(int ncid, nc_type xtype, int fieldid,
+                            MPI_Offset *offsetp);
+
+/* Given the xtype and the fieldid, get the type of that field. */
+extern int
+ncmpi_inq_compound_fieldtype(int ncid, nc_type xtype, int fieldid,
+                          nc_type *field_typeidp);
+
+/* Given the xtype and the fieldid, get the number of dimensions for
+ *  * that field (scalars are 0). */
+extern int
+ncmpi_inq_compound_fieldndims(int ncid, nc_type xtype, int fieldid,
+                           int *ndimsp);
+extern int
+ncmpi_inq_compound_fielddim_sizes(int ncid, nc_type xtype, int fieldid,
+                               int *dim_sizes);
+
+extern int
+ncmpi_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp);
+
+extern int
+ncmpi_inq_grpname_len(int ncid, MPI_Offset *lenp);
+
+/* Given an ncid, find the ncid of its parent group. */
+extern int
+ncmpi_inq_grp_parent(int ncid, int *parent_ncid);
+
+/* Given a name and parent ncid, find group ncid. */
+extern int
+ncmpi_inq_grp_ncid(int ncid, const char *grp_name, int *grp_ncid);
+/* Given a full name and ncid, find group ncid. */
+extern int
+ncmpi_inq_grp_full_ncid(int ncid, const char *full_name, int *grp_ncid);
+
+/* Get a list of ids for all the variables in a group. */
+extern int
+ncmpi_inq_varids(int ncid, int *nvars, int *varids);
+
+/* Find all dimids for a location. This finds all dimensions in a
+ *  * group, or any of its parents. */
+extern int
+ncmpi_inq_dimids(int ncid, int *ndims, int *dimids, int include_parents);
+
+extern int
+ncmpi_inq_type(int ncid, nc_type xtype, char *name, MPI_Offset *size);
+
+/* Find all user-defined types for a location. This finds all
+ *  * user-defined types in a group. */
+extern int
+ncmpi_inq_typeids(int ncid, int *ntypes, int *typeids);
+
+/* Are two types equal? */
+extern int
+ncmpi_inq_type_equal(int ncid1, nc_type typeid1, int ncid2,
+                  nc_type typeid2, int *equal);
+/* Create a group. its ncid is returned in the new_ncid pointer. */
+extern int
+ncmpi_def_grp(int parent_ncid, const char *name, int *new_ncid);
+
+/* Rename a group */
+extern int
+ncmpi_rename_grp(int grpid, const char *name);
+
+extern int
+ncmpi_inq_grps(int ncid, int *numgrps, int *ncids);
+
+/* Given locid, find name of group. (Root group is named "/".) */
+extern int
+ncmpi_inq_grpname(int ncid, char *name);
+
+/* Given ncid, find full name and len of full name. (Root group is
+ *  * named "/", with length 1.) */
+extern int
+ncmpi_inq_grpname_full(int ncid, MPI_Offset *lenp, char *full_name);
+
+extern int
+ncmpi_def_enum(int ncid, nc_type base_typeid, const char *name,
+            nc_type *typeidp);
+
+extern int
+ncmpi_def_vlen(int ncid, const char *name, nc_type base_typeid, nc_type *xtypep);
+
+/* Find out about a vlen. */
+extern int
+ncmpi_inq_vlen(int ncid, nc_type xtype, char *name, MPI_Offset *datum_sizep,
+            nc_type *base_nc_typep);
+
+typedef struct {
+    MPI_Offset len; /**< Length of VL data (in base type units) */
+    void *p;    /**< Pointer to VL data */
+} nc_vlen_t;
+
+extern int
+ncmpi_free_vlen(nc_vlen_t *vl);
+
+extern int
+ncmpi_free_vlens(MPI_Offset len, nc_vlen_t vlens[]);
+
+/* Put or get one element in a vlen array. */
+extern int
+ncmpi_put_vlen_element(int ncid, int typeid1, void *vlen_element,
+                    MPI_Offset len, const void *data);
+
+extern int
+ncmpi_get_vlen_element(int ncid, int typeid1, const void *vlen_element,
+                    MPI_Offset *len, void *data);
+extern int
+ncmpi_def_opaque(int ncid, MPI_Offset size, const char *name, nc_type *xtypep);
+
+/* Get information about an opaque type. */
+extern int
+ncmpi_inq_opaque(int ncid, nc_type xtype, char *name, MPI_Offset *sizep);
+
+extern int
+ncmpi_inq_user_type(int ncid, nc_type xtype, char *name, MPI_Offset *size,
+                 nc_type *base_nc_typep, MPI_Offset *nfieldsp, int *classp);
+
+extern int
+ncmpi_def_var_chunking(int ncid, int varid, int storage, const MPI_Offset *chunksizesp);
+extern int
+ncmpi_inq_var_chunking(int ncid, int varid, int *storagep, MPI_Offset *chunksizesp);
+
+extern int
+ncmpi_def_var_endian(int ncid, int varid, int endian);
+
+/* Learn about the endianness of a variable. */
+extern int
+ncmpi_inq_var_endian(int ncid, int varid, int *endianp);
+extern int
+ncmpi_set_chunk_cache(MPI_Offset size, MPI_Offset nelems, float preemption);
+
+extern int
+ncmpi_def_var_deflate(int ncid, int varid, int shuffle, int deflate,
+                   int deflate_level);
+extern int
+ncmpi_inq_var_deflate(int ncid, int varid, int *shufflep,
+                   int *deflatep, int *deflate_levelp);
+extern int
+ncmpi_inq_var_szip(int ncid, int varid, int *options_maskp, int *pixels_per_blockp);
+
+/* Set fletcher32 checksum for a var. This must be done after nc_def_var
+ *    and before nc_enddef. */
+extern int
+ncmpi_def_var_fletcher32(int ncid, int varid, int fletcher32);
+
+/* Inquire about fletcher32 checksum for a var. */
+extern int
+ncmpi_inq_var_fletcher32(int ncid, int varid, int *fletcher32p);
+
+#endif
diff --git a/src/libcxx/pnetcdf.in b/src/libcxx/pnetcdf.in
new file mode 100644
index 0000000..310e30e
--- /dev/null
+++ b/src/libcxx/pnetcdf.in
@@ -0,0 +1,14 @@
+//
+// generic include file for the PnetCDF C++ API
+//
+using namespace std;
+
+#include <exception>
+#include <string>
+#include <typeinfo>
+#include <vector>
+#include <set>
+#include <map>
+
+#include <pnetcdf.h>
+
diff --git a/src/libf/Makefile.in b/src/libf/Makefile.in
new file mode 100644
index 0000000..e2dfeee
--- /dev/null
+++ b/src/libf/Makefile.in
@@ -0,0 +1,403 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2285 2015-12-30 20:48:25Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+# generated by configure, so it's in the build dir, not srcdirr
+include ../../macros.make
+
+# For VPATH build:
+# Add ../lib into search path because ../lib/pnetcdf.h is created at the
+# configure time and included by all C2F_SRCS files in this folder.
+# Add $(srcdir) into search path because the C2F_SRCS files created at the
+# configure time in this folder all include $(srcdir)/mpinetcdf_impl.h.
+INCLUDES = -I../lib -I$(srcdir)
+
+HEADER    = ../lib/pnetcdf.h
+LIBRARY   = ../lib/libpnetcdf.a
+ld_netcdf = -L../lib -lpnetcdf
+
+UTIL_SRCS = issyserrf.c \
+	nfxutil.c \
+	xstrerrorf.c \
+	xinq_libversf.c
+
+C2F_SRCS = createf.c \
+	openf.c \
+	inq_file_infof.c \
+	get_file_infof.c \
+	deletef.c \
+	enddeff.c \
+	_enddeff.c \
+	redeff.c \
+	set_default_formatf.c inq_default_formatf.c \
+	syncf.c \
+	sync_numrecsf.c \
+	abortf.c \
+	begin_indep_dataf.c \
+	end_indep_dataf.c \
+	closef.c \
+	set_fillf.c def_var_fillf.c inq_var_fillf.c fill_var_recf.c \
+	def_dimf.c \
+	def_varf.c \
+	rename_dimf.c \
+	rename_varf.c \
+	inqf.c \
+	inq_formatf.c \
+	inq_file_formatf.c \
+	inq_versionf.c \
+	inq_stripingf.c \
+	inq_ndimsf.c \
+	inq_nvarsf.c \
+        inq_num_rec_varsf.c \
+        inq_num_fix_varsf.c \
+	inq_nattsf.c \
+	inq_unlimdimf.c \
+	inq_dimidf.c \
+	inq_dimf.c \
+	inq_dimnamef.c \
+	inq_dimlenf.c \
+	inq_varf.c \
+	inq_varidf.c \
+	inq_varnamef.c \
+	inq_vartypef.c \
+	inq_varndimsf.c \
+	inq_vardimidf.c \
+	inq_varnattsf.c \
+	inq_varoffsetf.c \
+	inq_attf.c \
+	inq_attidf.c \
+	inq_atttypef.c \
+	inq_attlenf.c \
+	inq_attnamef.c \
+	copy_attf.c \
+	rename_attf.c \
+	del_attf.c \
+	put_attf.c \
+	put_att_textf.c \
+	put_att_int1f.c \
+	put_att_int2f.c \
+	put_att_intf.c \
+	put_att_realf.c \
+	put_att_doublef.c \
+	put_att_int8f.c \
+	get_attf.c \
+	get_att_textf.c \
+	get_att_int1f.c \
+	get_att_int2f.c \
+	get_att_intf.c \
+	get_att_realf.c \
+	get_att_doublef.c \
+	get_att_int8f.c \
+	put_var1f.c        put_var1_allf.c \
+	put_var1_textf.c   put_var1_text_allf.c \
+	put_var1_int1f.c   put_var1_int1_allf.c \
+	put_var1_int2f.c   put_var1_int2_allf.c \
+	put_var1_intf.c    put_var1_int_allf.c \
+	put_var1_realf.c   put_var1_real_allf.c \
+	put_var1_doublef.c put_var1_double_allf.c \
+	put_var1_int8f.c   put_var1_int8_allf.c \
+	get_var1f.c        get_var1_allf.c \
+	get_var1_textf.c   get_var1_text_allf.c \
+	get_var1_int1f.c   get_var1_int1_allf.c \
+	get_var1_int2f.c   get_var1_int2_allf.c \
+	get_var1_intf.c    get_var1_int_allf.c \
+	get_var1_realf.c   get_var1_real_allf.c \
+	get_var1_doublef.c get_var1_double_allf.c \
+	get_var1_int8f.c   get_var1_int8_allf.c \
+	put_varf.c         put_var_allf.c \
+	put_var_textf.c    put_var_text_allf.c \
+	put_var_int1f.c    put_var_int1_allf.c \
+	put_var_int2f.c    put_var_int2_allf.c \
+	put_var_intf.c     put_var_int_allf.c \
+	put_var_realf.c    put_var_real_allf.c \
+	put_var_doublef.c  put_var_double_allf.c \
+	put_var_int8f.c    put_var_int8_allf.c \
+	get_varf.c         get_var_allf.c \
+	get_var_textf.c    get_var_text_allf.c \
+	get_var_int1f.c    get_var_int1_allf.c \
+	get_var_int2f.c    get_var_int2_allf.c \
+	get_var_intf.c     get_var_int_allf.c \
+	get_var_realf.c    get_var_real_allf.c \
+	get_var_doublef.c  get_var_double_allf.c \
+	get_var_int8f.c    get_var_int8_allf.c \
+	put_varaf.c        put_vara_allf.c \
+	put_vara_textf.c   put_vara_text_allf.c \
+	put_vara_int1f.c   put_vara_int1_allf.c \
+	put_vara_int2f.c   put_vara_int2_allf.c \
+	put_vara_intf.c    put_vara_int_allf.c \
+	put_vara_realf.c   put_vara_real_allf.c \
+	put_vara_doublef.c put_vara_double_allf.c \
+	put_vara_int8f.c   put_vara_int8_allf.c \
+	get_varaf.c        get_vara_allf.c \
+	get_vara_textf.c   get_vara_text_allf.c \
+	get_vara_int1f.c   get_vara_int1_allf.c \
+	get_vara_int2f.c   get_vara_int2_allf.c \
+	get_vara_intf.c    get_vara_int_allf.c \
+	get_vara_realf.c   get_vara_real_allf.c \
+	get_vara_doublef.c get_vara_double_allf.c \
+	get_vara_int8f.c   get_vara_int8_allf.c \
+	put_varsf.c        put_vars_allf.c \
+	put_vars_textf.c   put_vars_text_allf.c \
+	put_vars_int1f.c   put_vars_int1_allf.c \
+	put_vars_int2f.c   put_vars_int2_allf.c \
+	put_vars_intf.c    put_vars_int_allf.c \
+	put_vars_realf.c   put_vars_real_allf.c \
+	put_vars_doublef.c put_vars_double_allf.c \
+	put_vars_int8f.c   put_vars_int8_allf.c \
+	get_varsf.c        get_vars_allf.c \
+	get_vars_int1f.c   get_vars_int1_allf.c \
+	get_vars_textf.c   get_vars_text_allf.c \
+	get_vars_int2f.c   get_vars_int2_allf.c \
+	get_vars_intf.c    get_vars_int_allf.c \
+	get_vars_realf.c   get_vars_real_allf.c \
+	get_vars_doublef.c get_vars_double_allf.c \
+	get_vars_int8f.c   get_vars_int8_allf.c \
+	put_varmf.c        put_varm_allf.c \
+	put_varm_textf.c   put_varm_text_allf.c \
+	put_varm_int1f.c   put_varm_int1_allf.c \
+	put_varm_int2f.c   put_varm_int2_allf.c \
+	put_varm_intf.c    put_varm_int_allf.c \
+	put_varm_realf.c   put_varm_real_allf.c \
+	put_varm_doublef.c put_varm_double_allf.c \
+	put_varm_int8f.c   put_varm_int8_allf.c \
+	get_varmf.c        get_varm_allf.c \
+	get_varm_int1f.c   get_varm_int1_allf.c \
+	get_varm_textf.c   get_varm_text_allf.c \
+	get_varm_int2f.c   get_varm_int2_allf.c \
+	get_varm_intf.c    get_varm_int_allf.c \
+	get_varm_realf.c   get_varm_real_allf.c \
+	get_varm_doublef.c get_varm_double_allf.c \
+	get_varm_int8f.c   get_varm_int8_allf.c \
+	waitf.c \
+	wait_allf.c \
+	cancelf.c \
+	iput_var1f.c \
+	iput_var1_textf.c \
+	iput_var1_int1f.c \
+	iput_var1_int2f.c \
+	iput_var1_intf.c \
+	iput_var1_realf.c \
+	iput_var1_doublef.c \
+	iput_var1_int8f.c \
+	iget_var1f.c \
+	iget_var1_textf.c \
+	iget_var1_int1f.c \
+	iget_var1_int2f.c \
+	iget_var1_intf.c \
+	iget_var1_realf.c \
+	iget_var1_doublef.c \
+	iget_var1_int8f.c \
+	bput_var1f.c \
+	bput_var1_textf.c \
+	bput_var1_int1f.c \
+	bput_var1_int2f.c \
+	bput_var1_intf.c \
+	bput_var1_realf.c \
+	bput_var1_doublef.c \
+	bput_var1_int8f.c \
+	iput_varf.c \
+	iput_var_textf.c \
+	iput_var_int1f.c \
+	iput_var_int2f.c \
+	iput_var_intf.c \
+	iput_var_realf.c \
+	iput_var_doublef.c \
+	iput_var_int8f.c \
+	iget_varf.c \
+	iget_var_textf.c \
+	iget_var_int1f.c \
+	iget_var_int2f.c \
+	iget_var_intf.c \
+	iget_var_realf.c \
+	iget_var_doublef.c \
+	iget_var_int8f.c \
+	bput_varf.c \
+	bput_var_textf.c \
+	bput_var_int1f.c \
+	bput_var_int2f.c \
+	bput_var_intf.c \
+	bput_var_realf.c \
+	bput_var_doublef.c \
+	bput_var_int8f.c \
+	iput_varaf.c \
+	iput_vara_textf.c \
+	iput_vara_int1f.c \
+	iput_vara_int2f.c \
+	iput_vara_intf.c \
+	iput_vara_realf.c \
+	iput_vara_doublef.c \
+	iput_vara_int8f.c \
+	iget_varaf.c \
+	iget_vara_textf.c \
+	iget_vara_int1f.c \
+	iget_vara_int2f.c \
+	iget_vara_intf.c \
+	iget_vara_realf.c \
+	iget_vara_doublef.c \
+	iget_vara_int8f.c \
+	bput_varaf.c \
+	bput_vara_textf.c \
+	bput_vara_int1f.c \
+	bput_vara_int2f.c \
+	bput_vara_intf.c \
+	bput_vara_realf.c \
+	bput_vara_doublef.c \
+	bput_vara_int8f.c \
+	iput_varsf.c \
+	iput_vars_textf.c \
+	iput_vars_int1f.c \
+	iput_vars_int2f.c \
+	iput_vars_intf.c \
+	iput_vars_realf.c \
+	iput_vars_doublef.c \
+	iput_vars_int8f.c \
+	iget_varsf.c \
+	iget_vars_textf.c \
+	iget_vars_int1f.c \
+	iget_vars_int2f.c \
+	iget_vars_intf.c \
+	iget_vars_realf.c \
+	iget_vars_doublef.c \
+	iget_vars_int8f.c \
+	bput_varsf.c \
+	bput_vars_textf.c \
+	bput_vars_int1f.c \
+	bput_vars_int2f.c \
+	bput_vars_intf.c \
+	bput_vars_realf.c \
+	bput_vars_doublef.c \
+	bput_vars_int8f.c \
+	iput_varmf.c \
+	iput_varm_textf.c \
+	iput_varm_int1f.c \
+	iput_varm_int2f.c \
+	iput_varm_intf.c \
+	iput_varm_realf.c \
+	iput_varm_doublef.c \
+	iput_varm_int8f.c \
+	iget_varmf.c \
+	iget_varm_textf.c \
+	iget_varm_int1f.c \
+	iget_varm_int2f.c \
+	iget_varm_intf.c \
+	iget_varm_realf.c \
+	iget_varm_doublef.c \
+	iget_varm_int8f.c \
+	bput_varmf.c \
+	bput_varm_textf.c \
+	bput_varm_int1f.c \
+	bput_varm_int2f.c \
+	bput_varm_intf.c \
+	bput_varm_realf.c \
+	bput_varm_doublef.c \
+	bput_varm_int8f.c \
+	bufattachf.c \
+	bufdetachf.c \
+	inq_buffer_usagef.c \
+	inq_buffer_sizef.c \
+	inq_put_sizef.c \
+	inq_get_sizef.c \
+	inq_header_sizef.c \
+	inq_header_extentf.c \
+	inq_malloc_sizef.c inq_malloc_max_sizef.c inq_malloc_listf.c \
+	inq_files_openedf.c \
+	inq_nreqsf.c \
+	inq_recsizef.c \
+	get_varnf.c            get_varn_allf.c \
+	get_varn_textf.c       get_varn_text_allf.c \
+	get_varn_int1f.c       get_varn_int1_allf.c \
+	get_varn_int2f.c       get_varn_int2_allf.c \
+	get_varn_intf.c        get_varn_int_allf.c \
+	get_varn_realf.c       get_varn_real_allf.c \
+	get_varn_doublef.c     get_varn_double_allf.c \
+	get_varn_int8f.c       get_varn_int8_allf.c \
+	put_varnf.c            put_varn_allf.c \
+	put_varn_textf.c       put_varn_text_allf.c \
+	put_varn_int1f.c       put_varn_int1_allf.c \
+	put_varn_int2f.c       put_varn_int2_allf.c \
+	put_varn_intf.c        put_varn_int_allf.c \
+	put_varn_realf.c       put_varn_real_allf.c \
+	put_varn_doublef.c     put_varn_double_allf.c \
+	put_varn_int8f.c       put_varn_int8_allf.c \
+	iget_varnf.c        \
+	iget_varn_textf.c   \
+	iget_varn_int1f.c   \
+	iget_varn_int2f.c   \
+	iget_varn_intf.c    \
+	iget_varn_realf.c   \
+	iget_varn_doublef.c \
+	iget_varn_int8f.c   \
+	iput_varnf.c        \
+	iput_varn_textf.c   \
+	iput_varn_int1f.c   \
+	iput_varn_int2f.c   \
+	iput_varn_intf.c    \
+	iput_varn_realf.c   \
+	iput_varn_doublef.c \
+	iput_varn_int8f.c   \
+	bput_varnf.c        \
+	bput_varn_textf.c   \
+	bput_varn_int1f.c   \
+	bput_varn_int2f.c   \
+	bput_varn_intf.c    \
+	bput_varn_realf.c   \
+	bput_varn_doublef.c \
+	bput_varn_int8f.c   \
+        get_vardf.c            get_vard_allf.c \
+        put_vardf.c            put_vard_allf.c
+
+LIB_CSRCS = $(C2F_SRCS) $(UTIL_SRCS)
+
+LIB_FSRCS = strerrorf.f inq_libversf.f
+
+PACKING_LIST = $(LIB_FSRCS) \
+	       nfconfig_inc.in \
+	       pnetcdf.inc.in \
+	       mpinetcdf_impl.h \
+	       buildiface \
+	       defs \
+	       createffiles \
+	       Makefile.in
+
+LIB_OBJS = $(LIB_CSRCS:.c=.o) $(LIB_FSRCS:.f=.o)
+
+GARBAGE		= nfconfig.inc $(LIB_CSRCS) mpifnetcdf.h
+DIST_GARBAGE	= nfconfig_inc pnetcdf.inc
+
+all: $(LIB_CSRCS) nfconfig.inc $(LIBRARY)
+
+library $(LIBRARY): $(LIB_OBJS)
+	$(AR) $(ARFLAGS) $(LIBRARY) $(LIB_OBJS)
+	$(RANLIB) $(LIBRARY)
+
+$(LIB_CSRCS): mpifnetcdf.h
+$(LIB_OBJS): mpifnetcdf.h
+
+mpifnetcdf.h: defs buildiface $(HEADER)
+	$(srcdir)/buildiface -infile=$(HEADER) -deffile=$(srcdir)/defs
+
+# Starting from 1.4.0, nfconfig.inc is only used in test/nf_test/tests.inc and
+# test/nf90_test/tests.inc
+#
+# the sed command below is for generating a fortran-friendly header files by
+# replacing C comment starter '/*' with '!' in Fortran and remove '*/'
+#
+nfconfig.inc: nfconfig_inc
+	$(RM) -f $@
+	$(SED) -e "s%/\*%!%g" -e "s%\*/%%g" $< > $@
+
+install:
+	$(INSTALL) -d -m 755 $(INCDIR)
+	$(INSTALL_DATA) pnetcdf.inc $(INCDIR)
+
+uninstall:
+	$(RM) -f $(INCDIR)/pnetcdf.inc
+
+include $(srcdir)/../../rules.make
diff --git a/src/libf/buildiface b/src/libf/buildiface
new file mode 100755
index 0000000..22eade4
--- /dev/null
+++ b/src/libf/buildiface
@@ -0,0 +1,4068 @@
+#! /usr/bin/env perl
+#
+# This file builds candidate interface files from the descriptions in 
+# mpi.h
+#
+# Here are the steps:
+# 1) Find the prototypes in mpi.h.in (Look for *Begin Prototypes*)
+# 2) For each function, match the name and args:
+#    int MPI_xxxx( ... )
+# 3) Create a new file with the name lc(xxxx)f.c (lowercase of name), 
+#    containing 
+#    Copyright
+#    Profiling block indicator
+#    Fortran name version of function, with MPI objects replaced by 
+#    MPI_Fint etc. as appropriate
+#    
+#
+
+use warnings;
+
+# Setup global variables
+%CtoFName = ();
+ at ExtraRoutines = ();
+
+$buildfiles = 1;
+$build_prototypes = 1;
+$buildMakefile = 1;
+$prototype_header_file = "fproto.h";
+$build_io = 1;
+$print_line_len = 0;
+$write_mpif = 1;
+$is_MPI = 1;
+$do_profiling = 1;
+$routine_prefix = "MPI_";
+$routine_pattern = "[A-Z][a-z0-9_]*";
+$out_prefix="mpi_";
+$malloc = "MPIU_Malloc";
+$free   = "MPIU_Free";
+$header_file = "mpi_fortimpl.h";
+$debug = 0;
+$writeRoutineList = 0;   # Set to 1 to get a list of MPI routines
+
+ at arg_addresses = ();
+#
+# Error return handling
+$errparmtype = "MPI_Fint *";
+$errparm = "MPI_Fint *ierr";
+$errparmlval = "*ierr";
+$errparmrval = "*ierr";
+$returnErrval = 0;
+$returnType   = "void";
+
+%altweak = ();    # Alternate weak declarations
+%altweakrtype = ();
+
+#feature variables
+$do_logical = 1;
+$do_weak    = 1;
+$do_subdecls = 1;
+$do_bufptr = 1;
+$prototype_file = "../../include/mpi.h.in";
+
+# Global hashes used for definitions and to record the locations of the
+# defintions.
+%mpidef = ();
+%mpidefFile = ();
+%mpiRoutinesFile = ();
+
+# Handle special initializations
+#
+# Notes on this string.  Some symbols need to be initialized at runtime.
+# These are typically the addresses of the "special" Fortran symbols, 
+# such as MPIR_F_MPI_BOTTOM.  Because MPI-2 requires that MPI_Init and 
+# MPI_Init_thread, called in *any* language, initalize MPI for *all*
+# languages, we can't depend on having the Fortran versions of MPI_Init or
+# MPI_Init_thread called before these values might be used in a Fortran
+# wrapper function.
+# We also cannot have the C version of MPI_Init and MPI_Init_thread call 
+# the initialization routine, because some Fortran compilers will require
+# special routines from that particular vendors Fortran runtime library for
+# any executable that uses routines that are compiled with the Fortran 
+# compiler, forcing user programs that are entirely C to link with the 
+# Fortran runtime.  Thus, we must check whether the values are initialized
+# before any use in any routine.
+#
+# Having said the above, however, if the environment (specifically, the
+# C and Fortran compilers) makes it easy for the C init routines to initialize
+# the Fortran environment, then we should make that easy.  This is indicated
+# by the CPP name HAVE_MPI_F_INIT_WORKS_WITH_C.  If that is defined, then
+# there is no lazy initialization of these values.
+$specialInitAdded = 0;
+$specialInitString = "\
+#ifndef HAVE_MPI_F_INIT_WORKS_WITH_C
+    if (MPIR_F_NeedInit){ mpirinitf_(); MPIR_F_NeedInit = 0; }
+#endif";
+
+# Process arguments
+#
+# Args
+# -feature={logical,fint,subdecls,weak,bufptr}, separated by :, value given 
+# by =on or =off, eg
+# -feature=logical=on:fint=off
+# The feature names mean:
+#    logical - Fortran logicals are converted to/from C
+#    fint    - Fortran integers and C ints are different size (not implemented)
+#    subdecls - Declarations for PC-Fortran compilers added
+#    weak    - Use weak symbols 
+#    bufptr  - Check for MPI_BOTTOM as a special address.  This is
+#              not needed if a POINTER declaration is available.
+foreach $_ (@ARGV) {
+    if (/-noprototypes/) { $build_prototypes = 0; }
+    elsif (/-infile=(.*)/) {
+	# Special arg to help with debugging
+	$prototype_file = $1;
+	$write_mpif = 0;
+	$build_prototypes = 0;
+	$do_weak    = 0;
+    }
+    elsif (/-noromio/) { $build_io = 0; }
+    elsif (/-debug/) {
+	$debug = 1;
+    }
+    elsif (/-prefix=(.*)/) {
+	$routine_prefix = $1;
+	$is_MPI = 0;
+    }
+    elsif (/-pattern=(.*)/) {
+	$routine_pattern = $1;
+    }	
+    elsif (/-feature=(.*)/) {
+	foreach $feature (split(/:/,$1)) {
+	    print STDERR "Processing feature $feature\n" if $debug;
+	    # Feature values are foo=on,off
+	    ($name,$value) = split(/=/,$feature);
+	    if ($value eq "on") { $value = 1; } 
+	    elsif ($value eq "off") { $value = 0; }
+	    # Set the variable based on the string
+	    $varname = "do_$name";
+	    $$varname = $value;
+	}
+    }
+    elsif (/deffile=(.*)/) {
+	$definition_file = $1;
+	$is_MPI = 0;
+    }
+    else {
+	print STDERR "Unrecognized argument $_\n";
+    }
+}
+
+# Note that the code that looks up values strips blanks out of the type name
+# No blanks should be used in the key.
+%tof77 = ( 'MPI_Datatype' => 'MPI_Fint *',
+	   'MPI_Comm' => 'MPI_Fint *',
+#MPI_File must be handled specially, since ROMIO still uses pointers
+	   'MPI_File' => 'MPI_Fint *',
+	   'MPI_Win' => 'MPI_Fint *',
+	   'MPI_Request' => 'MPI_Fint *',
+	   'MPI_Group' => 'MPI_Fint *',
+	   'MPI_Op' => 'MPI_Fint *',
+	   'MPI_Info' => 'MPI_Fint *',
+	   'MPI_Errhandler' => 'MPI_Fint *',
+	   'MPI_Aint' => 'MPI_Fint *',   # Should be MPIR_FAint
+	   'MPI_FAintp' => 'MPI_Aint *', # Used to force an MPI_Aint*
+	   'MPI_Offset' => 'MPI_Offset *', # Should be MPIR_FOint
+	   'int' => 'MPI_Fint *',
+	   'int[]' => 'MPI_Fint',        # no * because we'll use array form
+	   'int[][3]' => 'MPI_Fint',     # no * because we'll use array form
+	   'MPI_Datatype*' => 'MPI_Fint *',
+	   'MPI_Datatype[]' => 'MPI_Fint', # no * because we'll use array form
+	   'MPI_Comm*' => 'MPI_Fint *',
+	   'MPI_File*' => 'MPI_Fint *',
+	   'MPI_Win*' => 'MPI_Fint *', 
+	   'MPI_Group*' => 'MPI_Fint *',
+	   'MPI_Request*' => 'MPI_Fint *',
+	   'MPI_Aint*' => 'MPI_Fint *',   # Should be MPIR_FAint
+	   'int *' => 'MPI_Fint *',
+	   'int*' => 'MPI_Fint *',         # Catch missing space
+	   'MPI_Op*' => 'MPI_Fint *',
+	   'MPI_Status*' => 'MPI_Fint *',
+	   'MPI_Info*' => 'MPI_Fint *',
+	   'MPI_Errhandler*' => 'MPI_Fint *',
+	   );
+
+# declarg is special parameters for certain routines
+%declarg = ( 'type_extent-2' => 'MPI_Fint *',
+	     'type_lb-2' => 'MPI_Fint *',
+	     'type_ub-2' => 'MPI_Fint *', 
+	     'type_struct-3' => 'MPI_Fint *',   # Really [], but * is easier
+             'type_hindexed-3' => 'MPI_Fint *', # As above
+             'type_hvector-3' => 'MPI_Fint *',
+	     # The following are MPI-2 routines with address args.
+	     # For these, the user must pass in the correct arguments
+	     'file_get_type_extent-3' => 'MPI_FAint *',
+	     'pack_external-6' => 'MPI_Aint *',        # Value in C call
+	     'pack_external-7' => 'MPI_Aint *',
+	     'pack_external_size-4' => 'MPI_Aint *',
+	     'type_create_hvector-3' => 'MPI_Aint *',  # Value in C call
+	     'type_create_hindexed-3' => 'MPI_Aint *',
+	     'type_create_struct-3' => 'MPI_Aint *',
+             'type_get_contents-6' => 'MPI_Aint *',
+	     'type_get_extent-2' => 'MPI_Aint *',
+	     'type_get_extent-3' => 'MPI_Aint *',
+	     'type_get_true_extent-2' => 'MPI_Aint *',
+	     'type_get_true_extent-3' => 'MPI_Aint *',
+	     'type_create_resized-2' => 'MPI_Aint *',  # Value in C call
+	     'type_create_resized-3' => 'MPI_Aint *',  # Value in C call
+	     'unpack_external-3' => 'MPI_Aint *',      # Value in C call
+	     'unpack_external-4' => 'MPI_Aint *',
+	     'win_create-2' => 'MPI_Aint *',
+	     'accumulate-5' => 'MPI_Aint *',
+	     'put-5' => 'MPI_Aint *',
+	     'get-5' => 'MPI_Aint *',
+	     'alloc_mem-1' => 'MPI_Aint *',
+	    );
+
+%argsneedcast = ( 'MPI_Request *' => '(MPI_Request *)(ARG)',
+		  'MPI_Status *'  => '(MPI_Status *)(ARG)',
+		  'MPI_File' => 'MPI_File_f2c(ARG)',
+		  'MPI_Comm' => '(MPI_Comm)(ARG)',
+		  'MPI_Comm *' => '(MPI_Comm *)(ARG)',
+                  'MPI_Datatype' => '(MPI_Datatype)(ARG)',
+                  'MPI_Datatype *' => '(MPI_Datatype *)(ARG)',
+		  'MPI_Info *' => '(MPI_Info *)(ARG)',
+		  'MPI_Info' => '(MPI_Info)(ARG)',
+		  'int [][3]' => '(int (*)[3])(ARG)'
+);
+
+##
+## For implementations other than MPICH2, we'll need to consider using
+## MPI_C2f_<name> and MPI_F2c_<name>, as in 
+## 'MPI_Info' => 'MPI_F2c_info(ARG)'
+##
+# name_map maps the filenames.  Most filenames are created automatically
+# from the routine name, but some names have too many characters (15, 
+# including the extension(.o) is a limit for ar in some systems).
+%name_map = ( 'add_error_class' => 'adderrclass',
+	      'add_error_code' => 'adderrcode',
+	      'add_error_string' => 'adderrstring',
+	      'buffer_attach' => 'bufattach',
+	      'buffer_detach' => 'bufdetach',
+	      'comm_call_errhandler' => 'commcallerr',
+	      'comm_create_errhandler' => 'commcreerr',
+	      'comm_create_keyval' => 'commnewkey',
+	      'comm_delete_attr' => 'commdelattr',
+	      'comm_disconnect' => 'commdisc',
+	      'comm_free_keyval' => 'commfreekey',
+	      'comm_get_errhandler' => 'commgeterr',
+	      'comm_get_name' => 'commgetnam',
+	      'comm_get_parent' => 'commparent',
+	      'comm_remote_group' => 'commrgroup',
+	      'comm_remote_size' => 'commrsize',
+	      'comm_set_errhandler' => 'commseterr',
+	      'comm_spawn_multiple' => 'spawnmult',
+	      'comm_test_inter' => 'commtestic',
+	      'errhandler_create' => 'errhcreate',
+	      'errhandler_free' => 'errhfree',
+	      'errhandler_get' => 'errhget',
+	      'errhandler_set' => 'errhset',
+	      'file_call_errhandler' => 'filecallerr',
+	      'file_create_errhandler' => 'filecreerr',
+	      'file_get_errhandler' => 'filegeterr',
+	      'file_set_errhandler' => 'fileseterr',
+	      'get_processor_name' => 'getpname',
+	      'graph_neighbors_count' => 'grfnbcount',
+	      'graph_neighbors' => 'grfnbrs',
+	      'grequest_complete' => 'greqcomplete',
+	      'grequest_start' => 'greqstart',
+	      'group_difference' => 'groupdiff',
+	      'group_intersection' => 'groupinter',
+	      'group_range_excl' => 'grouprexcl',
+	      'group_range_incl' => 'grouprincl',
+	      'group_translate_ranks' => 'grouptranks',
+	      'info_get_nkeys' => 'infognk',
+	      'info_get_nthkey' => 'infognthk',
+	      'info_get_valuelen' => 'infovallen',
+	      'intercomm_create' => 'iccreate',
+	      'intercomm_merge' => 'icmerge',
+	      'is_thread_main' => 'isthrmain',
+	      'pack_external_size' => 'packesize',
+	      'reduce_scatter' => 'redscat',
+	      'request_get_status' => 'reqgetstat',
+	      'sendrecv_replace' => 'sndrcvrpl',
+	      'status_set_cancelled' => 'statgetcl',
+	      'status_set_elements' => 'statsetel',
+	      'test_cancelled' => 'testcancel',
+	      'type_contiguous' => 'typecontig',
+	      'type_create_darray' => 'typedarray',
+	      'type_create_f90_integer' => 'typef90int',
+	      'type_create_f90_real' => 'typef90real',
+	      'type_create_f90_complex' => 'typef90cmplx',
+	      'type_create_hindexed' => 'typechind',
+	      'type_create_hvector' => 'typechvec',
+	      'type_create_indexed_block' => 'typecindb',
+	      'type_create_keyval' => 'typenewkey',
+	      'type_create_resized' => 'typecresize', 
+	      'type_create_struct' => 'typecstruct',
+	      'type_create_subarray' => 'typecsubarr',
+	      'type_delete_attr' => 'typedelattr',
+	      'type_free_keyval' => 'typefreekey',
+	      'type_get_contents' => 'typegetcnts',
+	      'type_get_envelope' => 'typegetenv',
+	      'type_get_extent' => 'typegetextent',  # there is already a type_extent
+	      'type_get_name' => 'typegname',
+	      'type_get_true_extent' => 'typegtext',
+	      'type_set_attr' => 'typesetattr',
+	      'type_set_name' => 'typesetname',
+	      'unpack_external' => 'unpackext',
+	      'unpublish_name' => 'unpubname',
+	      'win_call_errhandler' => 'wincallerr',
+	      'win_create_errhandler' => 'wincreerr',
+	      'win_create_keyval' => 'winnewkey',
+	      'win_delete_attr' => 'windelattr',
+	      'win_free_keyval' => 'winfreekey',
+	      'win_get_errhandler' => 'wingeterr',
+	      'win_set_errhandler' => 'winseterr',
+);
+
+#
+# Special routines have very different calling seqences in C and Fortran
+# or different behavior.
+# Init and Init thread have different arg lists (no argc, argv)
+# Pcontrol has no varargs
+# Address and Get_address require special integer types and
+# possibly handling for MPI_BOTTOM
+# Keyval routines require setting the language to Fortran (Attribute
+# routines are handled with the special argument processing)
+#
+# The Type_create_f90_xxx routines are only available as part of the
+# extended Fortran support, and are excluded from the f77 routines.
+%special_routines = ( 'Init' => 1, 'Init_thread' => 1, 'Pcontrol' => '1',
+		      'Address' => 1, 'Get_address' => 1,
+		      'Keyval_create' => 1, 'Status_f2c' => 1,
+		      'Status_c2f' => 1,
+		      'Type_create_f90_integer' => 1,
+		      'Type_create_f90_real' => 1,
+		      'Type_create_f90_complex' => 1,
+		      );
+
+# Some routines have special needs and must call a different routine.  For
+# similicity, we make the requirement that the replacement routine take
+# all of the arguments of the original routine, but all additional arguments
+# at the end.  This is used with the attribute routines which must 
+# pass an additional argument to a special attribute routine that handles
+# the differences between C and Fortran attributes.
+%ChangeCall = ( 'Comm_get_attr' => 'MPIR_CommGetAttr:!MPIR_ATTR_AINT' ,
+		'Type_get_attr' => 'MPIR_TypeGetAttr:!MPIR_ATTR_AINT',
+		'Win_get_attr'  => 'MPIR_WinGetAttr:!MPIR_ATTR_AINT',
+		'Attr_get'      => 'MPIR_CommGetAttr:!MPIR_ATTR_INT',
+		'Comm_set_attr' => 'MPIR_CommSetAttr:!MPIR_ATTR_AINT',
+		'Type_set_attr' => 'MPIR_TypeSetAttr:!MPIR_ATTR_AINT',
+		'Win_set_attr'  => 'MPIR_WinSetAttr:!MPIR_ATTR_AINT',
+		'Attr_put'      => 'MPIR_CommSetAttr:!MPIR_ATTR_INT',
+    );
+# 
+# Note that wtime and wtick aren't found because they don't match the 
+# int MPI_xxx format.  They're handled directly by the special routine
+# code below
+
+#
+# Most routines can be processed automatically.  However, some
+# require some special processing.  For example, those routines with
+# LOGICAL arguments need some special handling.  To detect this, there
+# are two entries in a %special_args hash: the routine name, and the routine
+# name -arg#.  E.g., for MPI_Test, the hash has keys
+# "Test" and "Test-2".  The value for "Test-2" is "out:logical"; this 
+# indicates that the variable is an out variable with logical type.
+# Processing types (the second field after the :) are
+#    logical: convert to/from Fortran and C representations of logical
+#    index:   convert to/from Fortran (1-based) and C (0-based) origins
+#    array:   handle arrays of items that may have different lengths
+#             in C and Fortran because the integer types have 
+#             different sizes.  The term has an additional :expression,
+#             the third term give the array size.
+#    addnull: Add a null character to a *copy* of the input string,
+#             after trimming any blanks.
+#    blankpad: Add blanks and remove nulls.  Only used for out args;
+#             must use an allocated space to provide room for the null
+#             that the C routines may require
+#    bufptr:  Detect MPI_BOTTOM.  Note that a better alternative is to
+#             use MPI_Address and MPI_Get_address to make addresses
+#             relative to the Fortran MPI_BOTTOM.  The lines that
+#             define this are commented out below.
+#    addrint: Given the address of an int, provide the int.  Used
+#             for attr_put/set routines 
+#    attrint: Convert an attribute value to an int.
+#    addraint: Given the address of an address-sized int, provide the
+#             value of that item.  Used for the MPI-2 versions of the
+#             attribute caching routines
+#    bufaddr: Argument is *output* as a buffer address.  Discarded before
+#             passing to Fortran.
+# For MPI-2 routines that take MPI_Aints even in Fortran, we need a 
+# special mapping when the value is passed to c
+#    aintToVal: Given the address of an Aint, pass the value to the C routine
+# (This should really be done by not applying the Aint->int mapping
+# for MPI-2 routines.  But for now, this hack will work)
+%special_args = ( 
+#    'Allreduce' => '1:2', 'Allreduce-1' => 'in:bufptr',	
+#		 'Allreduce-2' => 'in:bufptr', 
+#    'Bcast' => '1', 'Bcast-1' => 'in:bufptr',		 
+#    'Gather' => '1:4', 'Gather-1' => 'in:bufptr', 'Gather-4' => 'in:bufptr',
+#    'Gatherv' => '1:4', 'Gatherv-1' => 'in:bufptr', 'Gatherv-4' => 'in:bufptr',
+#    'Scatter' => '1:4', 'Scatter-1' => 'in:bufptr', 'Scatter-4' => 'in:bufptr',
+#    'Scatterv' => '1:5', 'Scatterv-1' => 'in:bufptr', 'Scatterv-5' => 'in:bufptr',
+#    'Allgather' => '1:4', 'Allgather-1' => 'in:bufptr', 'Allgather-4' => 'in:bufptr',
+#    'Allgatherv' => '1:4', 'Allgatherv-1' => 'in:bufptr', 'Allgatherv-4' => 'in:bufptr',
+#    'Alltoall' => '1:4', 'Alltoall-1' => 'in:bufptr', 'Alltoall-4' => 'in:bufptr',
+#    'Alltoallv' => '1:5', 'Alltoallv-1' => 'in:bufptr', 'Alltoallv-5' => 'in:bufptr',
+#    'Reduce' => '1:2', 'Reduce-1' => 'in:bufptr', 'Reduce-2' => 'in:bufptr',
+#    'Reduce_scatter' => '1:2', 'Reduce_scatter-1' => 'in:bufptr', 
+#		  'Reduce_scatter-2' => 'in:bufptr',
+#    'Scan' => '1:2', 'Scan-1' => 'in:bufptr', 'Scan-2' => 'in:bufptr',
+#
+    'Gather' => '1', 'Gather-1' => 'in:inplace', 
+    'Gatherv' => '1', 'Gatherv-1' => 'in:inplace',
+    'Scatter' => '4', 'Scatter-4' => 'in:inplace',
+    'Scatterv' => '5', 'Scatterv-5' => 'in:inplace',
+    'Allgather' => '1', 'Allgather-1' => 'in:inplace',
+    'Allgatherv' => '1', 'Allgatherv-1' => 'in:inplace',
+    'Reduce' => '1', 'Reduce-1' => 'in:inplace',
+    'Allreduce' => '1', 'Allreduce-1' => 'in:inplace',
+    'Reduce_scatter' => '1', 'Reduce_scatter-1' => 'in:inplace',
+    'Scan' => '1', 'Scan-1' => 'in:inplace',
+
+  
+    'Add_error_string' => '2', 'Add_error_string-2' => 'in:addnull',
+    'Attr_put' => '3', 'Attr_put-3' => 'in:addrint',
+    'Attr_get' => '3:4', 'Attr_get-4' => 'out:logical', 
+		 'Attr_get-3' => 'out:attrint:4',
+    'Comm_set_attr' => '3', 'Comm_set_attr-3' => 'in:addraint', 
+    'Type_set_attr' => '3', 'Type_set_attr-3' => 'in:addraint',
+    'Win_set_attr' => '3', 'Win_set_attr-3' => 'in:addraint',
+    'Comm_get_attr' => '3:4', 'Comm_get_attr-4' => 'out:logical',
+		  'Comm_get_attr-3' => 'out:attraint:4',
+    'Type_get_attr' => '3:4', 'Type_get_attr-4' => 'out:logical',
+		  'Type_get_attr-3' => 'out:attraint:4',
+    'Win_get_attr' => '3:4', 'Win_get_attr-4' => 'out:logical',		   
+		  'Win_get_attr-3' => 'out:attraint:4',
+    'Buffer_detach' => '1', 'Buffer_detach-1' => 'out:bufaddr',		 
+    'Cart_create' => '4:5', 'Cart_create-4' => 'in:logical_array:*v2', 
+    'Cart_create-5' => 'in:logical', 
+    'Cart_get' => '4', 'Cart_get-4' => 'out:logical_array:*v2',
+    'Comm_accept' => '1', 'Comm_accept-1' => 'in:addnull',
+    'Comm_connect' => '1', 'Comm_connect-1' => 'in:addnull',
+    'Comm_get_name' => '2', 'Comm_get_name-2' => 'out:blankpad',
+    'Comm_set_name' => '2', 'Comm_set_name-2' => 'in:addnull',
+    'Comm_spawn' => '1:2:8', 'Comm_spawn-1' => 'in:addnull', 
+		 'Comm_spawn-2' => 'in:chararray',
+		  'Comm_spawn-8' => 'in:errcodesignore',
+    'Comm_test_inter' => '2', 'Comm_test_inter-2' => 'out:logical',
+    'Get_processor_name' => '1', 'Get_processor_name-1' => 'out:blankpad',
+    'Error_string' => '2', 'Error_string-2' => 'out:blankpad',
+    'Intercomm_merge' => '2', 'Intercomm_merge-2' => 'in:logical',
+    'Info_get' => '2:4:5', 'Info_get-2' => 'in:addnull',
+		  'Info_get-4' => 'out:blankpadonflag:l5',
+		  'Info_get-5' => 'out:logical',
+    'Info_set' => '2:3', 'Info_set-2' => 'in:addnullandtrim', 
+		  'Info_set-3' => 'in:addnullandtrim',
+    'Info_get_nthkey' => '3', 'Info_get_nthkey-3' => 'out:blankpad',
+    'Info_get_valuelen' => '2:4', 'Info_get_valuelen-2' => 'in:addnull',
+		  'Info_get_valuelen-4' => 'out:logical',
+    'Info_delete' => '2', 'Info_delete-2' => 'in:addnull',
+    'Lookup_name' => '1:3', 'Lookup_name-1' => 'in:addnull', 
+		  'Lookup_name-3' => 'out:blankpad',
+    'Open_port' => '2', 'Open_port-2' => 'out:blankpad',
+    'Close_port' => '1', 'Close_port-1' => 'in:addnull',
+    'Pack_external' => '1:6', 'Pack_external-1' => 'in:addnull',
+		  'Pack_external-6' => 'in:aintToVal',
+    'Pack_external_size' => '1', 'Pack_external_size-1' => 'in:addnull',
+    'Publish_name' => '1:3', 'Publish_name-1' => 'in:addnull',
+		  'Publish_name-3' => 'in:addnull',
+# comm spawn multiple needs slightly different routines
+    'Comm_spawn_multiple' => '2:3:9',
+		 'Comm_spawn_multiple-2' => 'in:chararray:*v1',
+		 'Comm_spawn_multiple-3' => 'in:chararray2:*v1',
+		  'Comm_spawn_multiple-9' => 'in:errcodesignore',
+    'Initialized' => '1', 'Initialized-1' => 'out:logical',
+    'Iprobe' => '4:5', 'Iprobe-4' => 'out:logical',
+		 'Iprobe-5' => 'in:status',
+    'Probe' => '4', 'Probe-4' => 'in:status',
+    'Recv' => '7', 'Recv-7' => 'in:status',
+    'Sendrecv' => '12', 'Sendrecv-12' => 'in:status',
+    'Sendrecv_replace' => '9', 'Sendrecv_replace-9' => 'in:status',
+#    'Send' => '1', 'Send-1' => 'in:bufptr',
+#    'Ssend' => '1', 'Ssend-1' => 'in:bufptr',
+#    'Rsend' => '1', 'Rsend-1' => 'in:bufptr',
+#    'Bsend' => '1', 'Bsend-1' => 'in:bufptr',
+#    'Isend' => '1', 'Isend-1' => 'in:bufptr',
+#    'Issend' => '1', 'Issend-1' => 'in:bufptr',
+#    'Irsend' => '1', 'Irsend-1' => 'in:bufptr',
+#    'Ibsend' => '1', 'Ibsend-1' => 'in:bufptr',
+#    'Irecv' => '1', 'Irecv-1' => 'in:bufptr',
+#    'Recv' => '1', 'Recv-1' => 'in:bufptr',		  
+#    'Send_init' => '1', 'Send_init-1' => 'in:bufptr',
+#    'Bsend_init' => '1', 'Bsend_init-1' => 'in:bufptr',
+#    'Ssend_init' => '1', 'Ssend_init-1' => 'in:bufptr',
+#    'Rsend_init' => '1', 'Rsend_init-1' => 'in:bufptr',
+#    'Recv_init' => '1', 'Recv_init-1' => 'in:bufptr',
+#    'Sendrecv' => '1:6', 'Sendrecv-1' => 'in:bufptr', 'Sendrecv-6' => 'in:bufptr',
+#    'Sendrecv_replace' => '1', 'Sendrecv_replace-1' => 'in:bufptr',
+    'Test_cancelled' => '2', 'Test_cancelled-2' => 'out:logical',
+    'Test' => '2:3', 'Test-2' => 'out:logical',
+		 'Test-3' => 'in:status',
+    'Testall' => '3:4', 'Testall-3' => 'out:logical', 
+		 'Testall-4' => 'in:status_array',
+    'Testany' => '3:4:5', 'Testany-4' => 'out:logical',
+		 'Testany-3' => 'out:index',
+		 'Testany-5' => 'in:status',
+    'Testsome' => '4:5', 'Testsome-4' => 'out:index_array:*v3',
+		 'Testsome-5' => 'in:status_array',
+    'Type_create_hvector' => 3, 'Type_create_hvector-3' => 'in:aintToVal',
+    'Type_create_resized' => '2:3', 
+		  'Type_create_resized-2' => 'in:aintToVal', 
+		  'Type_create_resized-3' => 'in:aintToVal',
+    'Type_get_name' => '2', 'Type_get_name-2' => 'out:blankpad',
+    'Type_set_name' => '2', 'Type_set_name-2' => 'in:addnull',
+    'Type_extent' => '2', 'Type_extent-2' => 'out:aintToInt',	      
+    'Type_lb' => '2', 'Type_lb-2' => 'out:aintToInt',	      
+    'Type_ub' => '2', 'Type_ub-2' => 'out:aintToInt',	      
+    'Type_struct' => '3', 'Type_struct-3' => 'in:intToAintArr:*v1',
+    'Type_hindexed' => '3', 'Type_hindexed-3' => 'in:intToAintArr:*v1',
+# also need
+    'Type_hvector' => '3', 'Type_hvector-3' => 'in:intToAint',
+    'Unpack_external' => '1:3', 'Unpack_external-1' => 'in:addnull',
+		  'Unpack_external-3' => 'in:aintToVal',
+    'Unpublish_name' => '1:3', 'Unpublish_name-1' => 'in:addnull',
+		  'Unpublish_name-3' => 'in:addnull',
+    'Win_create' => '2', 'Win_create-2' => 'in:aintToVal', 
+    'Accumulate' => '5', 'Accumulate-5' => 'in:aintToVal',
+    'Put' => '5', 'Put-5' => 'in:aintToVal', 
+    'Get' => '5', 'Get-5' => 'in:aintToVal',
+    'Alloc_mem' => '1', 'Alloc_mem-1' => 'in:aintToVal', 
+    'Win_get_name' => '2', 'Win_get_name-2' => 'out:blankpad',
+    'Win_set_name' => '2', 'Win_set_name-2' => 'in:addnull',		  
+    'Wait' => '2', 'Wait-2' => 'in:status',
+    'Waitall' => '3', 'Waitall-3' => 'in:status_array',		 
+    'Waitany' => '3:4', 'Waitany-3' => 'out:index',
+		 'Waitany-4' => 'in:status',
+    'Waitsome' => '4:5', 'Waitsome-4' => 'out:index_array:*v3',
+		 'Waitsome-5' => 'in:status_array',
+# File routines are separate
+    'File_open' => '2:5', 'File_open-2' => 'in:addnull',
+		 'File_open-5' => 'out:FileToFint',
+    'File_close' => '1', 'File_close-1', 'inout:FileToFint',
+    'File_delete' => '1', 'File_delete-1' => 'in:addnull',
+    'File_set_view' => '5', 'File_set_view-5' => 'in:addnull',
+    'File_get_view' => '5', 'File_get_view-5' => 'out:blankpad',
+    'File_set_atomicity' => '2', 'File_set_atomicity-2' => 'in:logical',
+    'File_get_atomicity' => '2', 'File_get_atomicity-2' => 'out:logical',
+    'Register_datarep' => '1:2:3', 'Register_datarep-1' => 'in:addnull',
+		  'Register_datarep-2' => 'in:checkdatarep',
+		  'Register_datarep-3' => 'in:checkdatarep',
+    'Op_commutative' => '2', 'Op_commutative-2' => 'out:logical',
+    );
+
+# 
+# These give special post processing after the MPI routine is called.  
+# The named routine is invoked with the argument number, e.g., 
+# &"setF90keyval"( FD,  1 );
+#
+%specialPost = (
+		'Type_create_keyval' => 3,
+		'Type_create_keyval-3' => 'setF90Type_keyval',
+		'Comm_create_keyval' => 3,
+		'Comm_create_keyval-3' => 'setF90Comm_keyval',
+		'Win_create_keyval' => 3,
+		'Win_create_keyval-3' => 'setF90Win_keyval', 
+		'Grequest_start' => 5,
+		'Grequest_start-5' => 'setF77greq',
+		);
+
+#
+# Load any definition file
+if ($definition_file) {
+    require $definition_file;
+}
+
+$arg_string = join( ' ', @ARGV );
+if ($build_prototypes) {
+    open( PROTOFD, ">$prototype_header_file.new" ) || die "Cannot open $prototype_header_file.new\n";
+    print PROTOFD "/* -*- Mode: C; c-basic-offset:4 ; -*- */\
+/*  \
+ *  (C) 2003 by Argonne National Laboratory and Northwestern University.\
+ *      See COPYRIGHT in top-level directory.\
+ *\
+ * This file is automatically generated by ./buildiface $arg_string\
+ * DO NOT EDIT\
+ */\
+/* Prototypes for Fortran Interface Functions */
+\n";
+}
+
+%skipBlocks = ();
+&ReadAndProcessInterface( $prototype_file, 0 );
+
+# if doing MPI2, we also need to read the MPI-2 protottypes
+if ( -s "../../mpi/romio/include/mpio.h.in" && $build_io) { 
+    %skipBlocks = ( 'HAVE_MPI_DARRAY_SUBARRAY' => 1, 
+ 	 	    'HAVE_MPI_INFO' => 1,
+		    'MPICH2' => 1 );
+    &ReadAndProcessInterface( "../../mpi/romio/include/mpio.h.in", 1 );
+    %skipBlocks = ();
+}
+
+# Write a list of the routines that we've found.
+if ($writeRoutineList) {
+    open LFD, ">mpi.dat" || die "Cannot open mpi.dat\n";
+    foreach my $name (sort(keys(%mpi_routines))) {
+	print LFD "$name\n";
+    }
+    close LFD;
+}
+
+if ($is_MPI) {
+    # Build the special routines
+    &build_specials;
+}
+else {
+    for ($i=0; $i<=$#ExtraRoutines; $i++) {
+	$r = $ExtraRoutines[$i];
+	&$r;
+    }
+}
+
+if ($build_prototypes) {
+    close PROTOFD;
+    &ReplaceIfDifferent( $prototype_header_file, 
+			 $prototype_header_file . ".new" );
+}
+
+#
+# This block can be used to create the Makefile
+if ("$buildMakefile") {
+    open ( MAKEFD, ">Makefile.sm.new" ) || die "Cannot create Makefile.sm.new";
+    print MAKEFD "# DO NOT EDIT\n# This file created by ./buildiface $arg_string\n";
+
+    # FIXME: Find out what happened to the code here and either restore/fix
+    # it or remove this block
+    # Check to see if autoconf works.  Autoconf 2.13 has a bug in the Fortran 
+    # language support that will break this module.  Since some sites have 
+    # corrected the bug in autoconf 2.13, CheckAutoconfs test for this bug.
+    if (&CheckAutoconf) {
+	# Autoconf does not work
+	# This isn't quite right, because any updates will be broken
+	# FIXME : but not sure how to do this.
+	;
+    }
+    else {
+	# just use the regular autoconf
+    ;
+}
+    
+    #print MAKEFD "smvar_debug = 1\n";
+    print MAKEFD "smvar_do_dependencies = ignore\n";
+    &print_line(  MAKEFD, "mpi_sources = ", 80, "\\\n\t", 8 );
+    for ($i=0; $i<=$#files; $i++) {
+	$name = $files[$i];
+	&print_line( MAKEFD, "$name ", 80, "\\\n\t", 8 );
+    }
+    &print_endline( MAKEFD );
+    print MAKEFD "MPIFLIBNAME = \@MPIFLIBNAME\@\n";
+    print MAKEFD "PMPIFLIBNAME = \@PMPIFLIBNAME\@\n";
+
+    # The definitions for the Fortran wrappers are special
+    &AddFwrapDefs;
+    print MAKEFD "\
+lib\${MPIFLIBNAME}_a_DIR = ROOTDIR/lib\
+lib\${MPIFLIBNAME}_a_SOURCES = \${mpi_sources} setbot.c setbotf.f\
+\
+HEADERS = fproto.h mpi_fortimpl.h\
+profilelib_\${MPIFLIBNAME} = \${PMPIFLIBNAME}\
+profilelib_\${MPIFLIBNAME}_SOURCES = \${mpi_sources}\
+INCLUDES = -I../../include -I\${master_top_srcdir}/src/include -I\${master_top_srcdir}/src/binding/f77 \
+maint-clean:\
+\trm -f \${mpi_sources} $prototype_header_file\n";
+
+    print MAKEFD "install_INCLUDE = mpif.h\n";
+
+    # Add the documentation
+    print MAKEFD "# Documentation sources
+doc_sources = mpif77.txt
+DOCDESTDIRS = html:www/www1,man:man/man1,latex:doc/refman
+doc_HTML_SOURCES  = \${doc_sources}
+doc_MAN_SOURCES   = \${doc_sources}
+doc_LATEX_SOURCES = \${doc_sources}
+";
+
+    # Since configure copies mpif.h to the include dir, we need to remove it
+    # in a distclean step.  Ditto for mpif77; add the generated files.
+    print MAKEFD "distclean-local:\n";
+    print MAKEFD "\trm -f mpif_bottom.h\n";
+    print MAKEFD "\trm -f ../../../src/include/mpif.h\n";
+    print MAKEFD "\trm -f ../../../bin/mpif77\n";
+
+    # Add the generated files to the maintainer clean target
+    print MAKEFD "maintainerclean-local:\n";
+    &print_line(  MAKEFD, "\trm -f ", 80, "\\\n\t", 8 );
+    for ($i=0; $i<=$#files; $i++) {
+	if ( (($i+1) % 20) == 0) {
+	    # Avoid having a line that is too long
+	    &print_endline( MAKEFD );
+	    &print_line( MAKEFD, "\trm -f ", 80, "\\n\t", 8 );
+	}
+	$name = $files[$i];
+	&print_line( MAKEFD, "$name ", 80, "\\\n\t", 8 );
+    }
+    &print_endline( MAKEFD );
+    print MAKEFD "\trm -f Makefile.sm\n";
+
+    # Add the definitions for compiling the members of the wrap file
+    &AddFwrapBuild;
+
+    close( MAKEFD );
+    &ReplaceIfDifferent( "Makefile.sm", "Makefile.sm.new" );
+}
+
+#
+# ------------------------------------------------------------------------
+# Procedures
+# print_line( FD, line, count, continue, continuelen )
+# Print line to FD; if line size > count, output continue string and
+# continue.  Use print_endline to finish a line
+sub print_line {
+    my $FD = $_[0];
+    my $line = $_[1];
+    my $count = $_[2];
+    my $continue = $_[3];
+    my $continue_len = $_[4];
+    
+    $linelen = length( $line );
+    #print "linelen = $linelen, print_line_len = $print_line_len\n";
+    if ($print_line_len + $linelen > $count) {
+	print $FD $continue;
+	$print_line_len = $continue_len;
+    }
+    print $FD $line;
+    $print_line_len += $linelen;
+}
+sub print_endline {
+    my $FD = $_[0];
+    print $FD "\n";
+    $print_line_len = 0;
+}
+
+# Print the header of the file, containing the definitions etc.
+sub print_header {
+    my $routine_name = $_[0];
+    my $lcname = $_[1];
+    my $args = $_[2];
+    my $extra = $_[3];
+ 
+    &print_copyright( );
+    if ($extra) {
+	print $OUTFD $extra;
+    }
+    &print_profiling_block( $routine_name, $lcname, $args );
+    &print_name_map_block( $routine_name, $lcname );
+
+    my $fn = "HelperFor" . $routine_name ;
+    if (defined(&$fn)) {
+	&$fn( $OUTFD );
+    }
+}
+
+sub print_copyright {
+    print $OUTFD "/* -*- Mode: C; c-basic-offset:4 ; -*- */\
+/*  \
+ *  (C) 2003 by Argonne National Laboratory and Northwestern University.\
+ *      See COPYRIGHT in top-level directory.\
+ *\
+ * This file is automatically generated by ./buildiface $arg_string\
+ * DO NOT EDIT\
+ */\
+#include \"${header_file}\"\n\n";
+}
+
+#
+# Print the (ugly) profiling name definition block.
+# This is made more complex by the need, new with gcc 3.2, to 
+# generate an extern declaration of the routine *before* the pragma
+# 
+sub print_profiling_block {
+    my $routine_name = $_[0];
+    my $lcname = $_[1];
+    my $args   = $_[2];
+    my $ucname = uc($lcname);
+
+    if ($do_weak) {
+	print $OUTFD "\
+/* Begin MPI profiling block */\
+#if defined(USE_WEAK_SYMBOLS) && !defined(USE_ONLY_MPI_NAMES) \
+#if defined(HAVE_MULTIPLE_PRAGMA_WEAK)\n";
+        &print_weak_decl( $OUTFD, "MPI_$ucname", $args, $lcname ); 
+	&print_weak_decl( $OUTFD, "mpi_${lcname}__", $args, $lcname );
+	&print_weak_decl( $OUTFD, "mpi_${lcname}", $args, $lcname );
+	&print_weak_decl( $OUTFD, "mpi_${lcname}_", $args, $lcname );
+	print $OUTFD "\
+#if defined(F77_NAME_UPPER)
+#pragma weak MPI_$ucname = PMPI_${ucname}
+#pragma weak mpi_${lcname}__ = PMPI_${ucname}
+#pragma weak mpi_${lcname}_ = PMPI_${ucname}
+#pragma weak mpi_${lcname} = PMPI_${ucname}
+#elif defined(F77_NAME_LOWER_2USCORE)
+#pragma weak MPI_$ucname = pmpi_${lcname}__
+#pragma weak mpi_${lcname}__ = pmpi_${lcname}__
+#pragma weak mpi_${lcname}_ = pmpi_${lcname}__
+#pragma weak mpi_${lcname} = pmpi_${lcname}__
+#elif defined(F77_NAME_LOWER_USCORE)
+#pragma weak MPI_$ucname = pmpi_${lcname}_
+#pragma weak mpi_${lcname}__ = pmpi_${lcname}_
+#pragma weak mpi_${lcname}_ = pmpi_${lcname}_
+#pragma weak mpi_${lcname} = pmpi_${lcname}_
+#else
+#pragma weak MPI_$ucname = pmpi_${lcname}
+#pragma weak mpi_${lcname}__ = pmpi_${lcname}
+#pragma weak mpi_${lcname}_ = pmpi_${lcname}
+#pragma weak mpi_${lcname} = pmpi_${lcname}
+#endif
+\n\n";
+
+       print $OUTFD "\
+#elif defined(HAVE_PRAGMA_WEAK)\
+
+#if defined(F77_NAME_UPPER)\n";
+        &print_weak_decl( $OUTFD, "MPI_$ucname", $args, $lcname );
+        print $OUTFD "\
+#pragma weak MPI_$ucname = PMPI_$ucname\
+#elif defined(F77_NAME_LOWER_2USCORE)\n";
+        &print_weak_decl( $OUTFD, "mpi_${lcname}__", $args, $lcname );
+	print $OUTFD "\
+#pragma weak mpi_${lcname}__ = pmpi_${lcname}__\
+#elif !defined(F77_NAME_LOWER_USCORE)\n";
+        &print_weak_decl( $OUTFD, "mpi_$lcname", $args, $lcname );
+	print $OUTFD "\
+#pragma weak mpi_$lcname = pmpi_$lcname\
+#else\n";
+        &print_weak_decl( $OUTFD, "mpi_${lcname}_", $args, $lcname );
+	print $OUTFD "\
+#pragma weak mpi_${lcname}_ = pmpi_${lcname}_\
+#endif\
+\
+#elif defined(HAVE_PRAGMA_HP_SEC_DEF)\
+#if defined(F77_NAME_UPPER)\
+#pragma _HP_SECONDARY_DEF PMPI_$ucname  MPI_$ucname\
+#elif defined(F77_NAME_LOWER_2USCORE)\
+#pragma _HP_SECONDARY_DEF pmpi_${lcname}__  mpi_${lcname}__\
+#elif !defined(F77_NAME_LOWER_USCORE)\
+#pragma _HP_SECONDARY_DEF pmpi_$lcname  mpi_$lcname\
+#else\
+#pragma _HP_SECONDARY_DEF pmpi_${lcname}_  mpi_${lcname}_\
+#endif\
+\
+#elif defined(HAVE_PRAGMA_CRI_DUP)\
+#if defined(F77_NAME_UPPER)\
+#pragma _CRI duplicate MPI_$ucname as PMPI_$ucname\
+#elif defined(F77_NAME_LOWER_2USCORE)\
+#pragma _CRI duplicate mpi_${lcname}__ as pmpi_${lcname}__\
+#elif !defined(F77_NAME_LOWER_USCORE)\
+#pragma _CRI duplicate mpi_${lcname} as pmpi_${lcname}\
+#else\
+#pragma _CRI duplicate mpi_${lcname}_ as pmpi_${lcname}_\
+#endif\
+#endif /* HAVE_PRAGMA_WEAK */\
+#endif /* USE_WEAK_SYMBOLS */\
+/* End MPI profiling block */\n\n";
+
+    &AddFwrapWeakName( $lcname, $ucname, $args );
+    }
+}
+
+#
+# Print the code that modifies the name
+# The function prototypes must be loaded *after* the name block so that the
+# name used in the function prototypes will match the one that is declared
+# in this file.
+sub print_name_map_block {
+    my $routine_name = $_[0];
+    my $lcname = $_[1];
+    my $ucname = uc($lcname);
+    
+    # This include the code to map names for the profiling interface,
+    # using the same macro as for the rest of the MPI code
+    $uc_out_prefix = uc($out_prefix);
+    if ($do_profiling) {
+	# Remove the leading MPI_ if the name has it.
+	if ($routine_name =~ /^MPI_/) {
+	    $routine_name =~ s/^MPI_//;
+	}
+	print $OUTFD "
+/* Map the name to the correct form */
+#ifndef MPICH_MPI_FROM_PMPI
+#if defined(USE_WEAK_SYMBOLS) && defined(HAVE_MULTIPLE_PRAGMA_WEAK)
+/* Define the weak versions of the PMPI routine*/
+#ifndef F77_NAME_UPPER\n";
+	&print_weak_decl( $OUTFD, "PMPI_$ucname", $args, $lcname ); 
+	print $OUTFD "#endif\n#ifndef F77_NAME_LOWER_2USCORE\n";
+	&print_weak_decl( $OUTFD, "pmpi_${lcname}__", $args, $lcname );
+	print $OUTFD "#endif\n#ifndef F77_NAME_LOWER_USCORE\n";
+	&print_weak_decl( $OUTFD, "pmpi_${lcname}_", $args, $lcname );
+	print $OUTFD "#endif\n#ifndef F77_NAME_LOWER\n";
+	&print_weak_decl( $OUTFD, "pmpi_${lcname}", $args, $lcname );
+	print $OUTFD "
+#endif
+
+#if defined(F77_NAME_UPPER)
+#pragma weak pmpi_${lcname}__ = PMPI_${ucname}
+#pragma weak pmpi_${lcname}_ = PMPI_${ucname}
+#pragma weak pmpi_${lcname} = PMPI_${ucname}
+#elif defined(F77_NAME_LOWER_2USCORE)
+#pragma weak PMPI_$ucname = pmpi_${lcname}__
+#pragma weak pmpi_${lcname}_ = pmpi_${lcname}__
+#pragma weak pmpi_${lcname} = pmpi_${lcname}__
+#elif defined(F77_NAME_LOWER_USCORE)
+#pragma weak PMPI_$ucname = pmpi_${lcname}_
+#pragma weak pmpi_${lcname}__ = pmpi_${lcname}_
+#pragma weak pmpi_${lcname} = pmpi_${lcname}_
+#else
+#pragma weak PMPI_$ucname = pmpi_${lcname}
+#pragma weak pmpi_${lcname}__ = pmpi_${lcname}
+#pragma weak pmpi_${lcname}_ = pmpi_${lcname}
+#endif /* Test on name mapping */
+#endif /* Use multiple pragma weak */
+
+#ifdef F77_NAME_UPPER
+#define ${out_prefix}${lcname}_ PMPI_${ucname}
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define ${out_prefix}${lcname}_ pmpi_${lcname}__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define ${out_prefix}${lcname}_ pmpi_${lcname}
+#else
+#define ${out_prefix}${lcname}_ pmpi_${lcname}_
+#endif /* Test on name mapping */
+
+/* This defines the routine that we call, which must be the PMPI version
+   since we're renaming the Fortran entry as the pmpi version.  The MPI name
+   must be undefined first to prevent any conflicts with previous renamings,
+   such as those put in place by the globus device when it is building on
+   top of a vendor MPI. */
+#undef MPI_${routine_name}
+#define MPI_${routine_name} PMPI_${routine_name} 
+
+#else
+";
+    }
+    print $OUTFD "
+#ifdef F77_NAME_UPPER
+#define ${out_prefix}${lcname}_ ${uc_out_prefix}${ucname}
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define ${out_prefix}${lcname}_ ${out_prefix}${lcname}__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define ${out_prefix}${lcname}_ ${out_prefix}${lcname}
+/* Else leave name alone */
+#endif
+
+";
+    if ($do_profiling) {
+	print $OUTFD "
+#endif /* MPICH_MPI_FROM_PMPI */
+";
+    }
+    if ($build_prototypes) {
+	print $OUTFD "
+/* Prototypes for the Fortran interfaces */
+#include \"$prototype_header_file\"
+";
+    }
+}
+
+# Print the arguments for the routine DEFINITION.
+sub print_args { 
+    my @parms = split(/\s*,\s*/, $_[1] );
+    my $OUTFD = $_[0];
+    my $count = 1;
+    my $last_args = "";
+    my $prototype_only = $_[2];
+    my $routine = $_[3];
+
+    # Clear the @arg_addresses and $arg_qualifiers array.
+    $#arg_addresses = -1;
+    $#arg_qualifiers = -1;
+
+    # Special case: if the only parm is "void", remove it from the list
+    print STDERR "Nparms = $#parms, parms = " . join(',', at parms) . "\n" if $debug;
+    if ($#parms == 0 && $parms[0] eq "void") {
+        print $OUTFD "( void )";
+        return
+    }
+    # argsep is used to add a comma before every argument, except for the 
+    # first
+    $argsep = "";
+    print $OUTFD "( ";
+    foreach $parm (@parms) {
+	# Match type to replacement
+	print "parm = :$parm:\n" if $debug;
+	# Remove qualifiers from the parm
+	$arg_qualifiers[$count] = "";
+	if ($parm =~ /^const\s+/) {
+	    $parm =~ s/^const\s+//;
+	    $arg_qualifiers[$count] .= "const ";
+	}
+        # remove all "const"
+        $parm =~ s/const//;
+
+	if ($parm =~ /^restrict\s+/) {
+	    $parm =~ s/restrict\s+//;
+	    $arg_qualifiers[$count] .= "restrict ";
+	}
+        # remove leading whitespace
+        $parm =~ s/^\s+//;
+
+	# Remove arg names from array types
+	if ($parm =~ /(\w+)\s+(\w+)\s*\[\]/) {
+	    # Assume that this is <type> <name>[]; convert to <type>[]
+	    print "    Removing argname $2 from parm array $parm\n" if $debug;
+	    $parm = "$1" . "[]";
+	}
+	elsif ($parm =~ /(\w+)\s*\*\s*(\w+)\s*\[\]/) {
+	    # Assume that this is <type>* <name>[]; convert to <type>*
+	    print "    Removing argname $2 from parm array $parm\n" if $debug;
+	    $parm = "$1" . "*";
+	}
+	elsif ($parm =~ /(\w+)\s*\*\s*\*\s*(\w+)/) {
+	    # Remove arg names from pointer types
+	    # Assume that this is <type>** ; convert to <type>*
+	    print "    Removing argname $2 from parm pointer\n" if $debug;
+	    $parm = "$1" . "*";
+	}
+	elsif ($parm =~ /(\w+)\s*\*\s*(\w+)/) {
+	    # Remove arg names from pointer types
+	    # Assume that this is <type>* ; convert to <type>*
+	    print "    Removing argname $2 from parm pointer\n" if $debug;
+	    $parm = "$1" . "*";
+	}
+	# Remove blanks from the parm
+	$parm =~ s/\s+//;
+	$arg_addresses[$count] = 0;
+
+	# This handles routines that have special declaration requirements
+	# for particular arguments
+	if (defined($declarg{"$routine-$count"})) {
+	    print "    Using declarg{$routine} for this parm\n" if $debug;
+	    $parm = $declarg{"$routine-$count"};
+	    if ($prototype_only) {
+		print $OUTFD "$argsep$parm";
+	    }
+	    else {
+		print $OUTFD "$argsep$parm v$count";
+	    }
+	}
+	elsif ($parm =~ /char\s*\*/) {
+	    # char's go out at char *v FORT_MIXED_LEN(d) 
+	    # and FORT_END_LEN(d) at the end
+	    # (even if an array, because at the Fortran level, it
+	    # is still a pointer to a character variable; the length
+	    # of each entry in the array is the "d" value).
+	    # FORT_END_LEN and FORT_MIXED_LEN contain the necessary comman
+	    # if they are prsent at all.
+	    print "    parm is a character string\n" if $debug;
+	    if ($prototype_only) {
+		print $OUTFD "${argsep}char * FORT_MIXED_LEN_DECL";
+		$last_args .= "FORT_END_LEN_DECL ";
+	    }
+	    else {
+		print $OUTFD "${argsep}char *v$count FORT_MIXED_LEN(d$count)";
+		$last_args .= "FORT_END_LEN(d$count) ";
+	    }
+	}
+	elsif ($parm =~/\[/) {
+	    # Argument type is array, so we need to 
+	    #  a) mark as containing a star
+	    #  b) place parameter correctly
+	    $star_count = 1;
+	    $arg_addresses[$count] = $star_count;
+	    # Split into raw type and []
+            # Use \S* instead of the equivalent [^\s]*.
+            # (\S is not-a-space)
+            # perl 5.8 is known to mishandle the latter, leading to
+	    # an empty basetype
+	    if ($parm =~ /\s*(\S*)\s*(\[\s*\])/) {
+		$basetype = $1;
+	    }
+	    else {
+		print STDERR "Internal error.  Could not find basetype\n";
+		print STDERR "This may be a bug in perl in the handling of certain expressions\n";
+	    }
+	    print "\tparm $parm is array of >$basetype<\n" if $debug;
+	    #$foundbrack = $2;
+	    if (defined($tof77{$parm})) {
+		# This is a special case; the full type is defined.
+		# This is used, for example, for int [][3] in the
+		# routines that specify a range.
+		print "Matched to full type $parm with replacement $tof77{$parm}\n" if $debug;
+		# We use the replacement type
+		$basetype = $tof77{$parm};
+		$star_count = 0;
+		$arg_addresses[$count] = $star_count;
+	    }
+	    elsif ($basetype eq "int") {
+		# Do nothing because the [] added to the arg below
+		# is all that is necessary.
+		$star_count = 0;
+		$arg_addresses[$count] = $star_count;
+	    }
+	    elsif (defined($tof77{"$basetype\[\]"})) {
+		# Use the code for handling array parameters if
+		# mapping code is provided.
+		print "Match to array type $basetype\[\]\n" if $debug;
+		$star_count = 0;
+		$arg_addresses[$count] = $star_count;
+		$basetype = $tof77{"$basetype\[\]"};
+	    }
+	    elsif (defined($tof77{$basetype})) {
+		# FIXME: This code (now commented out) is not correct
+		print STDERR "Using fall through for $basetype in $routine\n" if $debug;
+# 		if ($useOldCode eq "yes") {
+# 		$nstar_before = ($basetype =~ /\*/);
+# 		$basetype = $tof77{$basetype};
+# 		# The following fixes the case where the underlying type 
+# 		# is a simple int.
+# 		if ($basetype eq "int") {
+# 		    $arg_addresses[$count] = 0;
+# 		}
+# 		print "\tparm has defined type of $basetype\n" if $debug;
+# 		$nstar_after = ($basetype =~ /\*/);
+# 		if ($nstar_before != $nstar_after) {
+# 		    $star_count++;
+# 		}
+		# If we have an array, and a type mapping to fortran
+		# We want to simply pretend that all is well (like int
+		# above)
+		$star_count = 0;
+		$arg_addresses[$count] = $star_count;
+	    }
+	    if ($prototype_only) {
+		print $OUTFD "$argsep$basetype \[\]";
+	    }
+	    else {
+		print $OUTFD "$argsep$basetype v$count\[\]";
+	    }
+	}
+	else {
+	    $nstar_before = ($parm =~ /\*/);
+	    $nstar_after = $nstar_before;
+	    print "Nstar = $nstar_after\n" if $debug;
+	    if (defined($tof77{$parm})) {
+		$parm = $tof77{$parm};
+		$nstar_after = ($parm =~ /\*/);
+	    }
+	    $leadspace = "";
+	    if ($parm =~ /\w$/) {
+		$leadspace = " ";
+	    }
+	    if ($prototype_only) {
+		print $OUTFD "${argsep}${parm}";
+	    }
+	    else {
+	        if ($parm =~ /^(\w+)\*$/) {
+                    # make "type*" to "type *"
+                    $parm = "$1" . " *";
+                }
+		print $OUTFD "${argsep}${parm}${leadspace}v$count";
+	    }
+	    $star_count = 0;
+	    if ($nstar_before != $nstar_after) {
+		$star_count = 1;
+	    }
+	    $arg_addresses[$count] = $star_count;
+	}
+	$count++;
+	$argsep = ", ";
+    }
+    # Add the new error return code if necessary
+    $tmpargs= $errparm;
+    $tmpargs =~ s/\s*//g;
+    if ($tmpargs ne "") {
+	if ($prototype_only) {
+	    print $OUTFD "$argsep$errparmtype";
+	}
+	else {
+	    print $OUTFD "$argsep$errparm";
+	}
+    }
+    print $OUTFD " $last_args";
+    print $OUTFD ")";
+}
+
+# Print the arguments for the routine CALL.  
+# Handle the special arguments
+sub print_call_args {
+    my @parms = split(/\s*,\s*/, $_[0] );
+    my $count = 1;
+    my $first = 1;
+    print $OUTFD "( ";
+    # Special case: if the only parm is "void", remove it from the list
+    if ($#parms == 0 && $parms[0] eq "void") {
+	$#parms = -1;
+    }
+
+    foreach $parm (@parms) {
+	$parm =~ s/^const\s//;  # Remove const if present
+	# Remove variable name if present in an array arg
+	if ($parm =~ /(.*)\s+(\w+)\[\]/) {
+	    $parm = "$1 \[\]";
+	}
+	# Compress multiple spaces
+	$parm =~ s/\s\s/ /g;
+	if (!$first) { print $OUTFD ", "; } else { $first = 0; }
+
+	if (defined($special_args{"${routine_name}-$count"})) {
+	    # We must handle this argument specially
+	    &print_special_call_arg( $routine_name, $count );
+	}
+	elsif ($parm =~ /!/) {
+	    # This parameter is a special case; the exclamation point
+	    # is used to say "call with this argument as is"
+	    $parm =~ s/!//;
+	    print $OUTFD $parm;
+	}
+	else {
+	    # Convert to/from object type as required.  
+	    #print "TMP: parm = $arg_qualifiers[$count]$parm\n";
+	    $fullparm="$arg_qualifiers[$count]$parm";
+	    if (defined($argsneedcast{$fullparm})) {
+		$argval = "v$count";
+		if ($arg_addresses[$count] > 0) {
+		    $argval = "*$argval";
+		}
+		$callparm = $argsneedcast{$fullparm};
+		$callparm =~ s/ARG/$argval/;
+		print $OUTFD "$callparm";
+	    }
+	    else {
+		# Since MPICH objects are ints, we don't need to do 
+		# anything unless MPI_Fint and int are different.
+		# print STDERR "XXX $count $#arg_addresses XXX\n";
+		if ($arg_addresses[$count] > 0) {
+		    print $OUTFD "*";
+		}
+		print $OUTFD "v$count";
+	    }
+	}
+	$count++;
+    }
+    print $OUTFD " );\n";
+}
+
+# Print the option function attribute; this supports GCC, particularly 
+# the __atribute__ ((weak)) option.  Unfortunately, the name must be
+# made into a string and inserted into the attribute list.
+sub print_attr {
+    my $OUTFD = $_[0];
+    my $name  = $_[1];
+    if ($do_weak) {
+	print $OUTFD " FUNC_ATTRIBUTES($name)";
+    }
+}
+
+#
+# We allow a routine to specify an alternate weak decl by name
+sub set_weak_decl {
+    my $name = $_[0];
+    my $decl = $_[1];
+    my $rtype = $_[2];
+    $name = lc($name);
+    $altweak{$name}      = $decl;
+    $altweakrtype{$name} = $rtype;
+}
+sub print_weak_decl {
+    my $OUTFD = $_[0];
+    my $name  = $_[1];
+    my $args  = $_[2];
+    my $lcname = $_[3];
+
+    my $basename = lc($name);
+    $basename =~ s/_*$//;
+    if (defined($altweak{$basename})) {
+	print $OUTFD "extern FORTRAN_API $altweakrtype{$basename} FORT_CALL $name($altweak{$basename});\n";
+    }
+    else {
+	print $OUTFD "extern FORTRAN_API $returnType FORT_CALL $name";
+	&print_args( $OUTFD, $args, 1, $lcname );
+	print $OUTFD ";\n";
+    }
+}
+#
+# --------------------------------------------------------------------------
+# Special processing
+#
+# Each parameter can be processed by a routine, with the suffix controlling
+# the routine invoked for each step.  Roughly, these are:
+# 
+# void foo( MPI_Fint *v1, etc )
+# {
+# /* Special declarations needed for the variables */
+# <name>_<direction>_decl( <argnum> )
+# /* Special processing need for in variables */
+# <name>_ftoc( <argnum> )
+# /* Call the function.  Replace special arguments with the output from */
+# <name>_<direction>_arg( <argnum> )
+# /* Special post call processing (for out variables) */
+# <name>_ctof( l$count, v$count ) /* local (C) variable name, fortran var name */
+# 
+# Special case: For parameters that are arrays, the size of the
+# array is in $Array_size.
+# 
+# 
+# --------------------------------------------------------------------------
+# Buffer pointers
+sub bufptr_ftoc {
+    my $count = $_[0];
+}
+sub bufptr_in_decl {
+    my $count = $_[0];
+}
+sub bufptr_in_arg {
+    my $count = $_[0];
+    if ($do_bufptr) {
+	print $OUTFD "MPIR_F_PTR(v$count)";
+    }
+    else {
+	print $OUTFD "v$count";
+    }
+}
+# bufptr_ctof( cvar, fvar )
+sub bufptr_ctof {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+}
+# --------------------------------------------------------------------------
+# MPI_IN_PLACE buffer pointers
+sub inplace_ftoc {
+    my $count = $_[0];
+    &specialInitStatement( $OUTFD );
+    print $OUTFD "    if (v$count == MPIR_F_MPI_IN_PLACE) v$count = MPI_IN_PLACE;\n";
+}
+sub inplace_in_decl {
+    my $count = $_[0];
+}
+sub inplace_in_arg {
+    my $count = $_[0];
+    print $OUTFD "v$count";
+}
+# inplace_ctof( cvar, fvar )
+sub inplace_ctof {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+}
+# --------------------------------------------------------------------------
+# Logical variables
+sub logical_ftoc {
+    my $count = $_[0];
+    print $OUTFD "    l$count = MPIR_FROM_FLOG(*v$count);\n";
+}
+sub logical_in_decl {
+    my $count = $_[0];
+    if ($do_logical) {
+	print $OUTFD "    int l$count;\n";
+    }
+}
+sub logical_in_arg {
+    my $count = $_[0];
+    if ($do_logical) {
+	print $OUTFD "l$count";
+    }
+    else {
+	print $OUTFD "v$count";
+    }
+}
+# logical_ctof( cvar, fvar )
+sub logical_ctof {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+    if ($do_logical) {
+	print $OUTFD "    *$outvar = MPIR_TO_FLOG($coutvar);\n";
+    }
+}
+sub logical_out_decl {
+    my $count = $_[0];
+    if ($do_logical) {
+	print $OUTFD "    int l$count;\n";
+    }
+}
+sub logical_out_arg {
+    my $count = $_[0];
+    if ($do_logical) {
+	print $OUTFD "\&l$count";
+    }
+    else {
+	print $OUTFD "v$count";
+    }
+}
+# --------------------------------------------------------------------------
+#
+# Logical variables, but for an array.  
+# Array args can use the global $Array_size and $Array_typedef if necessary
+sub logical_array_ftoc {
+    print $OUTFD "\
+    {int li; 
+     for (li=0; li<$Array_size; li++) {
+        l$count\[li\] = MPIR_FROM_FLOG(v$count\[li\]);
+     }
+    }
+";
+}
+sub logical_array_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    int *l$count = (int *)$malloc((size_t)($Array_size) * sizeof(int));\n";
+    $clean_up .= "    $free(l$count);\n";
+}
+sub logical_array_in_arg {
+    my $count = $_[0];
+    print $OUTFD "l$count";
+}
+
+sub logical_array_ctof {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+    print $OUTFD "\
+    {int li;
+     for (li=0; li<$Array_size; li++) {
+        $outvar\[li\] = MPIR_TO_FLOG($outvar\[li\]);
+     }
+    }
+";
+}
+sub logical_array_out_decl {
+}
+sub logical_array_out_arg {
+    my $count = $_[0];
+    print $OUTFD "v$count";
+}
+# --------------------------------------------------------------------------
+# 
+# Index variables.
+# Index variables are not optional, since the values of the variable
+# are changed.
+sub index_ftoc {
+    my $count = $_[0];
+}
+sub index_ctof {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+    print $OUTFD "    *$outvar = (MPI_Fint)$coutvar;\n";
+    print $OUTFD "    if ($coutvar >= 0) *$outvar = *$outvar + 1;\n";
+}
+sub index_out_decl {
+    my $count = $_[0];
+    print $OUTFD "    int l$count;\n";
+}
+sub index_out_arg {
+    my $count = $_[0];
+    print $OUTFD " \&l$count";
+}
+#
+# Index variables, but for an array.  
+# Array args can use the global $Array_size and $Array_typedef if necessary
+sub index_array_ftoc {
+    my $count = $_[0];
+}
+sub index_array_ctof {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+    print $OUTFD "\
+    {int li;
+     for (li=0; li<$Array_size; li++) {
+        if ($outvar\[li\] >= 0) $outvar\[li\] += 1;
+     }
+    }
+"
+}
+sub index_array_out_decl {
+}
+sub index_array_out_arg {
+    my $count = $_[0];
+    print $OUTFD "v$count";
+}
+# --------------------------------------------------------------------------
+#
+# Address and attribute handling
+# Note that this construction can lead to compiler warnings on systems
+# where an address is larger than an MPI_Fint.  This is correct; these
+# routines are for the MPI-1 routines that use an MPI_Fint where the 
+# C code uses a void * (MPI_Aint in MPI-2).  
+# Instead of using MPI_Aint, we use MPIR_Pint.  This allows the MPI 
+# implementation to set MPI_Aint to be *larger* than a pointer-sized-int,
+# which is needed (as a temporary workaround) on systems like Blue Gene, which 
+# have 4 byte pointers but file systems that need 8 byte datatypes (not just 
+# offsets).
+# A possible extension is to provide an error warning (much as 
+# MPI_Address does) when the attribute value loses bits when assigned into
+# the MPI_Fint.
+#in:addrint
+#out:attrint:4
+sub addrint_ftoc {
+    my $count = $_[0];
+}
+sub addrint_in_decl {
+}
+sub addrint_in_arg {
+    my $count = $_[0];
+    print $OUTFD "(void *)(MPIR_Pint)((int)*(int *)v$count)";
+}
+
+sub attrint_ctof {
+    my $fvar = $_[0];
+    my $cvar = $_[1];
+    my $flagarg = 4; # get from option
+    # The double cast of attr$cvar first to MPIR_Pint and then to MPI_Fint
+    # keeps some compilers happy on 64-bit platforms
+    print $OUTFD "
+    if ((int)*ierr || !l$flagarg) {
+        *(MPI_Fint*)$cvar = 0;
+    }
+    else {
+        *(MPI_Fint*)$cvar = (MPI_Fint)(MPIR_Pint)attr$cvar;
+    }\n";
+}
+
+sub attrint_out_decl {
+    my $count = $_[0];
+    print $OUTFD "    void *attrv$count;\n";
+}
+
+sub attrint_out_arg {
+    my $count = $_[0];
+    print $OUTFD "&attrv$count";
+}
+# --------------------------------------------------------------------------
+# Address and attribute handling
+# This version of attrint uses Aints instead of ints, and is appropriate
+# for the MPI-2 attribute caching functions
+#in:addraint
+#out:attraint:4
+sub addraint_ftoc {
+    my $count = $_[0];
+}
+sub addraint_in_decl {
+}
+sub addraint_in_arg {
+    my $count = $_[0];
+    print $OUTFD "(void *)(*(MPI_Aint *)v$count)";
+}
+
+sub attraint_ctof {
+    my $fvar = $_[0];
+    my $cvar = $_[1];
+    my $flagarg = 4; # get from option
+    print $OUTFD "
+    if ((int)*ierr || !l$flagarg) {
+        *(MPI_Aint*)$cvar = 0;
+    }
+    else {
+        *(MPI_Aint*)$cvar = (MPI_Aint)attr$cvar;
+    }\n";
+}
+
+sub attraint_out_decl {
+    my $count = $_[0];
+    print $OUTFD "    void *attrv$count;\n";
+}
+
+sub attraint_out_arg {
+    my $count = $_[0];
+    print $OUTFD "&attrv$count";
+}
+# --------------------------------------------------------------------------
+#
+# Buffer Address output handling (Buffer_detach)
+#out:bufaddr
+sub bufaddr_ftoc {
+}
+sub bufaddr_out_decl {
+    my $count =$_[0];
+    print $OUTFD "    void *t$count = v$count;\n";
+}
+sub bufaddr_out_arg {
+    my $count = $_[0];
+    print $OUTFD "&t$count";
+}
+
+sub bufaddr_ctof {
+    my $fvar = $_[0];
+    my $cvar = $_[1];
+}
+# --------------------------------------------------------------------------
+# 
+# Handle MPI_STATUS_IGNORE and MPI_STATUSES_IGNORE
+sub status_ftoc {
+    my $count = $_[0];
+    # Cast MPI_STATUS_IGNORE back to an MPI_Fint (we'll re-cast it back
+    # to (MPI_Status *) in the call to the C version of the routine)
+    &specialInitStatement( $OUTFD );
+    print $OUTFD "\
+    if (v$count == MPI_F_STATUS_IGNORE) { v$count = (MPI_Fint*)MPI_STATUS_IGNORE; }\n";
+}
+sub status_ctof {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+}
+sub status_in_decl {
+    my $count = $_[0];
+}
+sub status_in_arg {
+    my $count = $_[0];
+    print $OUTFD "(MPI_Status *)v$count";
+}
+# --------------------------------------------------------------------------
+# 
+# Handle MPI_ERRCODES_IGNORE
+sub errcodesignore_ftoc {
+    my $count = $_[0];
+    &specialInitStatement( $OUTFD );
+    print $OUTFD "\
+    if (v$count == MPI_F_ERRCODES_IGNORE) { v$count = MPI_ERRCODES_IGNORE; }\n";
+}
+sub errcodesignore_ctof {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+}
+sub errcodesignore_in_decl {
+    my $count = $_[0];
+}
+sub errcodesignore_in_arg {
+    my $count = $_[0];
+    print $OUTFD "(int *)v$count";
+}
+# --------------------------------------------------------------------------
+#
+# Index variables, but for an array.  
+# Array args can use the global $Array_size and $Array_typedef if necessary
+sub status_array_ftoc {
+    my $count = $_[0];
+    &specialInitStatement( $OUTFD );
+    print $OUTFD "\
+    if (v$count == MPI_F_STATUSES_IGNORE) { v$count = (MPI_Fint *)MPI_STATUSES_IGNORE; }\n";
+}
+sub status_array_ctof {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+}
+sub status_array_in_decl {
+}
+sub status_array_in_arg {
+    my $count = $_[0];
+    print $OUTFD "(MPI_Status *)v$count";
+}
+# --------------------------------------------------------------------------
+# aintToint
+sub aintToInt_ctof {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+    print $OUTFD "    *$outvar = (MPI_Fint)($coutvar);\n";
+}
+sub aintToInt_out_decl {
+    my $count = $_[0];
+    print $OUTFD "    MPI_Aint l$count;\n";
+}
+sub aintToInt_out_arg {
+    my $count = $_[0];
+    print $OUTFD "\&l$count";
+}
+# --------------------------------------------------------------------------
+# aintToVal - Convert address of Aint to value
+sub aintToVal_ftoc {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+}
+sub aintToVal_in_decl {
+    my $count = $_[0];
+}
+sub aintToVal_in_arg {
+    my $count = $_[0];
+    print $OUTFD "*v$count";
+}
+# ---------------------------------------------------------------------------
+# This is the routine that handles the post-call processing
+sub print_post_call {
+    my $routine_name = $_[0];
+    my $args = $_[1];
+    if (defined($special_args{$routine_name})) { 
+	# Erg.  Special processing
+	foreach $count (split(/:/,$special_args{$routine_name})) {
+	    $rule = $special_args{"${routine_name}-$count"};
+	    ($direction,$method,$Array_size) = split(/:/,$rule);
+	    print STDERR "$routine_name: dir = $direction, method = $method\n" if $debug;
+	    $processing_in_routine = "${method}_in_ctof";
+	    if ($direction eq "out" || $direction eq "inout") {
+		$processing_routine = "${method}_ctof";
+		&$processing_routine( "l$count", "v$count" );
+	    }
+	    elsif (defined(&$processing_in_routine)) {
+		# Invoke even for "in" args incase we need to free a temp
+		&$processing_in_routine( "l$count", "v$count" );
+	    }
+	    if ($clean_up ne "") {
+		print $OUTFD $clean_up;
+		$clean_up = "";
+	    }
+	}
+    }
+    
+    # Handle here any special post-only calls
+    if (defined($specialPost{$routine_name})) {
+	my $argnum = $specialPost{$routine_name};
+	my $postRoutine = $specialPost{"$routine_name-$argnum"};
+	&$postRoutine( $OUTFD, $argnum );
+    }
+}
+#
+# ---------------------------------------------------------------------------
+#
+# Blankpad strings
+# This is complicated by the fact that the Fortran strings do not contain
+# null terminators and the MPI definitions of string lengths, such as
+# MPI_MAX_PORT_NAME, are one smaller in Fortran than in C (see 4.12.9
+# in the MPI-2 specification).  Because of this, we need to allocate a 
+# temporary that is one longer on 
+sub blankpad_out_decl {
+    my $count = $_[0];
+    print $OUTFD "    char *p$count;\n";
+}
+sub blankpad_out_arg {
+    my $count = $_[0];
+    print $OUTFD "p$count";
+}
+sub blankpad_out_ftoc {
+    my $count = $_[0];
+
+    # Allocate space to hold the C version of the output
+    $strlen = "d$count";
+    print $OUTFD "    p$count = (char *)$malloc( (size_t)$strlen + 1 );\n";
+}
+sub blankpad_ctof {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+    
+    # find the null character.  Replace with blanks from there to the
+    # end of the string.  The declared lenght is given by a variable
+    # whose name is derived from outvar
+    $strlen = $outvar;
+    $strlen =~ s/^v/d/;
+    my $cvar = $outvar; 
+    $cvar =~ s/^v/p/;
+    print $OUTFD "
+    {
+        char *p = $outvar, *pc=$cvar;
+        while (*pc) {*p++ = *pc++;}
+        while ((p-$outvar) < $strlen) { *p++ = ' '; }
+    }\n";
+    $clean_up .= "    $free($cvar);\n";
+}
+#
+# Blankpad strings if a flag is true (for info_get, perhaps others?)
+# This is complicated by the fact that the Fortran strings do not contain
+# null terminators and the MPI definitions of string lengths, such as
+# MPI_MAX_PORT_NAME, are one smaller in Fortran than in C (see 4.12.9
+# in the MPI-2 specification).  Because of this, we need to allocate a 
+# temporary that is one longer on 
+sub blankpadonflag_out_decl {
+    my $count = $_[0];
+    print $OUTFD "    char *p$count;\n";
+}
+sub blankpadonflag_out_arg {
+    my $count = $_[0];
+    print $OUTFD "p$count";
+}
+sub blankpadonflag_out_ftoc {
+    my $count = $_[0];
+
+    # Allocate space to hold the C version of the output
+    $strlen = "d$count";
+    print $OUTFD "    p$count = (char *)$malloc( (size_t)$strlen + 1 );\n";
+}
+sub blankpadonflag_ctof {
+    my $coutvar = $_[0];
+    my $outvar  = $_[1];
+    
+    # find the null character.  Replace with blanks from there to the
+    # end of the string.  The declared lenght is given by a variable
+    # whose name is derived from outvar
+    $strlen = $outvar;
+    $strlen =~ s/^v/d/;
+    my $cvar = $outvar; 
+    $cvar =~ s/^v/p/;
+    print $OUTFD "\
+    if ($Array_size) {char *p = $outvar, *pc=$cvar;
+        while (*pc) {*p++ = *pc++;}
+        while ((p-$outvar) < $strlen) { *p++ = ' '; }
+    }
+";
+    $clean_up .= "    $free( $cvar );\n";
+}
+
+# ---------------------------------------------------------------------------
+# Add null to input strings
+# We must make a copy 
+sub addnull_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    char *p$count;\n";
+}
+sub addnull_in_arg {
+    my $count = $_[0];
+    print $OUTFD "p$count";
+}
+sub addnull_ftoc {
+    my $count = $_[0];
+    
+    # Working backwards from the length argument, find the first 
+    # nonblank character
+    # end of the string.  The declared length is given by a variable
+    # whose name is derived from outvar
+    $strlen = "v$count";
+    $strlen =~ s/^v/d/;
+    print $OUTFD "\
+    {char *p = v$count + $strlen - 1;
+     int  li;
+        while (*p == ' ' && p > v$count) p--;
+        p++;
+        p$count = (char *)$malloc( (size_t)(p-v$count) + 1 );
+        for (li=0; li<(p-v$count); li++) { p$count\[li\] = v$count\[li\]; }
+        p$count\[li\] = 0; 
+    }
+";
+    $clean_up .= "    $free( p$count );\n";
+}
+# ----------------------------------------------------------------------------
+# Add null to input strings, also trim all LEADING and trailing blanks.
+# This is required by Info_set (but not explicitly for the other
+# routines).
+# We must make a copy 
+sub addnullandtrim_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    char *p$count;\n";
+}
+sub addnullandtrim_in_arg {
+    my $count = $_[0];
+    print $OUTFD "p$count";
+}
+sub addnullandtrim_ftoc {
+    my $count = $_[0];
+    
+    # Working backwards from the length argument, find the first 
+    # nonblank character
+    # end of the string.  The declared length is given by a variable
+    # whose name is derived from outvar
+    $strlen = "v$count";
+    $strlen =~ s/^v/d/;
+    print $OUTFD "\
+    {char *p = v$count + $strlen - 1;
+     char *pin = v$count;
+     int  li;
+        while (*p == ' ' && p > v$count) p--;
+        p++;
+        while (*pin == ' ' && pin < p) pin++;
+        p$count = (char *)$malloc( (size_t)(p-pin) + 1 );
+        for (li=0; li<(p-pin); li++) { p$count\[li\] = pin\[li\]; }
+        p$count\[li\] = 0; 
+    }
+";
+    $clean_up .= "    $free( p$count );\n";
+}
+
+# ----------------------------------------------------------------------------
+# Add null to arrays of input strings
+# We must make a copy 
+# chararray is used ONLY in comm_spawn
+sub chararray_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    char **p$count;\n";
+    if (!$Array_size) { print $OUTFD "    char *pcpy$count;\n"; }
+    # pcpy<digit> is used for the case where the array length is not known
+    print $OUTFD "    int  asize$count=0;\n";
+}
+sub chararray_in_arg {
+    my $count = $_[0];
+    print $OUTFD "p$count";
+}
+sub chararray_ftoc {
+    my $count = $_[0];
+
+    # There is a special case - the input is MPI_ARGV_NULL.  We
+    # detect this by checking for a null string (all blanks).
+    # The initialization of MPI_ARGV_NULL is done in the special
+    #init setup
+    &specialInitStatement( $OUTFD );
+    # First, compute the number of elements.  In Fortran, a null
+    # string terminates the array.  The array is stored as 
+    # a two-dimensional field of fixed-length characters.
+    # Then copy the strings into the new storage, appending the
+    # null at the end
+    print $OUTFD "\
+    { int i;
+      char *ptmp;\n";
+    if ($Array_size) {
+	print $OUTFD "\
+      asize$count = $Array_size + 1;\n";
+    }
+    else {
+	print $OUTFD "\
+      /* Compute the size of the array by looking for an all-blank line */
+      pcpy$count = v$count;
+      for (asize$count=1; 1; asize$count++) {
+          char *pt = pcpy$count + d$count - 1;
+          while (*pt == ' ' && pt > pcpy$count) pt--;
+          if (*pt == ' ') break;
+          pcpy$count += d$count;
+      }\n";
+    }
+    print $OUTFD "\
+      p$count = (char **)$malloc( (size_t)asize$count * sizeof(char *) );
+      ptmp    = (char *)$malloc( (size_t)asize$count * (d$count + 1) );
+      for (i=0; i<asize$count-1; i++) {
+          char *p = v$count + i * d$count, *pin, *pdest;
+          int j;
+
+          pdest = ptmp + i * (d$count + 1);
+          p$count\[i\] = pdest;
+          /* Move to the end and work back */
+          pin = p + d$count - 1;
+          while (*pin == ' ' && pin > p) pin--;
+          /* Copy and then null terminate */
+          for (j=0; j<(pin-p)+1; j++) { pdest\[j\] = p\[j\]; }
+          pdest\[j\] = 0;
+          }
+    /* Null terminate the array */
+    p$count\[asize$count-1\] = 0;
+    }\n";
+    $clean_up .= "    $free( p$count\[0\] ); $free( p$count );\n";
+}
+
+# Add null to 2-dimensional arrays of input strings.  Used only 
+# by comm_spawn_multiple
+# FIXME : THIS CODE IS NOT CORRECT YET
+# Note the special handling of MPI_ARGVS_NULL
+sub chararray2_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    char ***p$count=0;\n";
+}
+sub chararray2_in_arg {
+    my $count = $_[0];
+    print $OUTFD "p$count";
+}
+sub chararray2_ftoc {
+    my $count = $_[0];
+
+    if ($Array_size eq "") {
+	print STDERR "A leading array size is required for 2-d Character arrays\n";
+	return 1;
+    }
+
+    # First, compute the number of elements.  In Fortran, a null
+    # string terminates the array.  The array is stored as 
+    # a two-dimensional field of fixed-length characters.
+    # Then copy the strings into the new storage, appending the
+    # null at the end
+    # Since this is a 2-d array, we always know the first dimension,
+    # the second dimension must be computed, this is asize$count.
+    # The first dimension is Array_size.
+    &specialInitStatement( $OUTFD );
+    print $OUTFD "\
+    /* Check for the special case of a the null args case. */
+    if (v$count == MPI_F_ARGVS_NULL) { v$count = (char *)MPI_ARGVS_NULL; } 
+    else { 
+        /* We must convert from the 2-dimensional Fortran array of
+           fixed length strings to a C variable-sized array (really an
+           array of pointers for each command of pointers to each 
+           argument, which is null terminated.*/\n";
+
+    # We must be careful.  A blank line is ALL blank, not just leading blank
+    # We must also be careful allocating the array, as C and Fortran 
+    # arrays are not the same.  In C, for a two dimensional array
+    # sized at run time, we must
+    # allocate an array of pointers to arrays.
+    #    p = (char ***) malloc( nrows * sizeof(char **) )
+    # where we are letting using p[nrows][colindex].  
+    # For MPI_Comm_spawn_multiple, each of these rows is for one command.
+    # Each p[k] is a pointer to an array of character strings.  
+    # For MPI_Comm_spawn_multiple, all we know is that in the 
+    # corresponding Fortran code, the two-dimensional character array
+    # contains an all-blank entry as the terminating element; the
+    # corresponding C array must have a null entry (pointer) in
+    # the corresponding position.  
+    # Thus, the C code must make several allocations:
+    #    p = nrows * sizeof(char **)
+    # for p[k], (ncols + 1) * sizeof(char *)
+    # for p[k][i], space for the ith input argument.
+    # To reduce the number of allocations, we allocate space for all
+    # elements on a row at one time.
+
+    # Purely local variables don't need $count
+    print $OUTFD "\
+      int k;
+
+      /* Allocate the array of pointers for the commands */
+      p$count = (char ***)$malloc( (size_t)($Array_size) * sizeof(char **) );
+
+      for (k=0; k<$Array_size; k++) {
+        /* For each command, find the number of command-line arguments.
+           They are terminated by an empty entry. */
+        /* Find the first entry in the Fortran array for this row */
+        char *p = v$count + k * d$count;
+        int arglen = 0, argcnt=0, i;
+        char **pargs, *pdata;
+        for (argcnt=0; 1; argcnt ++) {
+            char *pin = p + d$count - 1; /* Move to the end of the
+                                            current Fortran string */
+            while (*pin == ' ' && pin > p) pin--; /* Move backwards until
+                                                    we find a non-blank
+                                                    (Fortran is blank padded)*/
+            if (pin == p && *pin == ' ') {
+                /* found the terminating empty arg */
+                break;
+            }
+            /* Keep track of the amount of space needed */
+            arglen += (pin - p) + 2;   /* add 1 for the null */
+            /* Advance to the next entry in the array */
+            p += ($Array_size) * d$count;
+        }
+
+        /* argcnt is the number of provided arguments.  
+           Allocate the necessary elements and copy, null terminating copies */
+        pargs = (char **)$malloc( (size_t)(argcnt+1)*sizeof(char *) );
+        pdata = (char *)$malloc( (size_t)arglen );
+        p$count\[k\] = pargs;
+        pargs\[argcnt\] = 0;  /* Null terminate end */
+        /* Copy each argument to consequtive locations in pdata, 
+           and set the corresponding pointer entry */
+        p = v$count + k * d$count;
+        for (i=0; i<argcnt; i++) {
+            int j;
+            char *pin;
+            p$count\[k\]\[i\] = pdata;
+            /* Move to the end and work back */
+            pin = p + d$count - 1;
+            while (*pin == ' ' && pin > p) pin--;
+            /* Copy and then null terminate */
+            for (j=0; j<(pin-p)+1; j++) { *pdata++ = p\[j\]; }
+            *pdata++ = 0;
+            /* Advance to the next entry in the array */
+            p += ($Array_size) * d$count;
+        }
+	/* Set the terminator */
+        p3[k][i] = 0;
+       }
+    }\n";
+
+    $clean_up .= "    if (v$count != (char *)MPI_ARGVS_NULL) { 
+        int i; 
+        for (i=0; i <$Array_size; i++) {
+            $free( p$count\[i\]\[0\] );  /* Free space allocated to args */
+            $free( p$count\[i\] );       /* Free space allocated to arg array */
+        }
+        /* Free the array of arrays */
+        $free( p$count );
+    }\n";
+}
+
+# ---------------------------------------------------------------------------
+# Convert from an int array to an Aint array for routines taking an Aint as 
+# input
+sub intToAintArr_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    MPI_Aint *l$count;\n";
+}
+sub intToAintArr_ftoc {
+    my $count = $_[0];
+    print $OUTFD "
+#ifdef HAVE_AINT_LARGER_THAN_FINT
+    if ($Array_size > 0) {
+        int li;
+        l$count = (MPI_Aint *)$malloc( (size_t)($Array_size) * sizeof(MPI_Aint) );
+        for (li=0; li<$Array_size; li++) 
+            l$count\[li\] = v$count\[li\];
+    }
+    else l$count = 0;
+#else 
+    l$count = v$count;
+#endif\n";
+}
+sub intToAintArr_in_arg {
+    my $count = $_[0];
+    print $OUTFD "l$count";
+}
+# This routine is invoked even for the in case (to free the result)
+sub intToAintArr_in_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+    print $OUTFD "
+#ifdef HAVE_AINT_LARGER_THAN_FINT
+    if ($lname) { $free($lname); }
+#endif\n";
+}
+# ---------------------------------------------------------------------------
+# Convert from an int to an Aint for routines taking an Aint as 
+# input
+sub intToAint_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    MPI_Aint l$count;\n";
+}
+sub intToAint_ftoc {
+    my $count = $_[0];
+    print $OUTFD "    l$count = (MPI_Aint)*v$count;\n";
+}
+sub intToAint_in_arg {
+    my $count = $_[0];
+    print $OUTFD "l$count";
+}
+
+# ---------------------------------------------------------------------------
+# Convert from an FILE to a fortran int
+# (output).  
+# -- temp
+sub FileToFint_inout_decl {
+    my $count = $_[0];
+    print $OUTFD "    MPI_File l$count = MPI_File_f2c(*v$count);\n";
+}
+sub FileToFint_inout_arg {
+    my $count = $_[0];
+    print $OUTFD "&l$count";
+}
+# -- end temp
+
+sub FileToFint_out_decl {
+    my $count = $_[0];
+    print $OUTFD "    MPI_File l$count;\n";
+}
+sub FileToFint_ctof {
+    my $lvar = $_[0];
+    my $gvar = $_[1];
+    print $OUTFD "    *$gvar = MPI_File_c2f($lvar);\n";
+}
+sub FileToFint_out_arg {
+    my $count = $_[0];
+    print $OUTFD "&l$count";
+}
+# ---------------------------------------------------------------------------
+# Check for the null datarep functions
+sub checkdatarep_in_decl {
+    my $count = $_[0];
+#     if ($count == 2) {
+# print $OUTFD "
+# #ifndef HAVE_MPI_CONVERSION_DEFN
+# #define HAVE_MPI_CONVERSION_DEFN
+# #ifdef F77_NAME_UPPER
+# #define mpi_conversion_fn_null_ MPI_CONVERSION_FN_NULL
+# #elif defined(F77_NAME_LOWER_2USCORE)
+# #define mpi_conversion_fn_null_ mpi_conversion_fn_null__
+# #elif !defined(F77_NAME_LOWER_USCORE)
+# #define mpi_conversion_fn_null_ mpi_conversion_fn_null
+# /* Else leave name alone */
+# #endif
+# /* Add the prototype so the routine knows what this is */
+# extern FORTRAN_API int FORT_CALL mpi_conversion_fn_null_ ( void*v1, MPI_Fint*v2, MPI_Fint*v3, void*v4, MPI_Offset*v5, MPI_Fint *v6, MPI_Fint*v7, MPI_Fint *ierr );
+# #endif
+# ";
+#     }
+}
+sub checkdatarep_in_arg {
+    my $count = $_[0];
+    print $OUTFD "v$count";
+}
+sub checkdatarep_ftoc {
+    my $count = $_[0];
+
+    # Check to see if the pointer is the same as the null function
+    # We do something ugly here:  we exploit the fact that we know which is
+    # the first argument that needs this definition
+    print $OUTFD "\
+    if (v$count == (MPI_Datarep_conversion_function *)mpi_conversion_fn_null_){
+         v$count = 0;
+    }\n";
+}
+# ---------------------------------------------------------------------------
+# Special post processing for some routines
+sub setF90Type_keyval {
+    my $FD = $_[0];
+    my $argnum = $_[1];
+
+    print $FD "\
+    if (*ierr == MPI_SUCCESS) {
+         MPIR_Keyval_set_proxy( *v$argnum, MPIR_Type_copy_attr_f90_proxy, MPIR_Type_delete_attr_f90_proxy );
+    }\n";
+}
+sub setF90Comm_keyval {
+    my $FD = $_[0];
+    my $argnum = $_[1];
+
+    print $FD "\
+    if (*ierr == MPI_SUCCESS) {
+         MPIR_Keyval_set_proxy( *v$argnum, MPIR_Comm_copy_attr_f90_proxy, MPIR_Comm_delete_attr_f90_proxy );
+    }\n";
+}
+sub setF90Win_keyval {
+    my $FD = $_[0];
+    my $argnum = $_[1];
+
+    print $FD "\
+    if (*ierr == MPI_SUCCESS) {
+         MPIR_Keyval_set_proxy( *v$argnum, MPIR_Win_copy_attr_f90_proxy, MPIR_Win_delete_attr_f90_proxy );
+    }\n";
+}
+sub setF77greq {
+    my $FD = $_[0];
+    my $argnum = $_[1];
+
+    print $FD "\
+    if (*ierr == MPI_SUCCESS) {
+         MPIR_Grequest_set_lang_f77( *v$argnum );
+    }\n";
+}
+
+
+# ---------------------------------------------------------------------------
+# This routine handles the special arguments in the *call*
+sub print_special_call_arg {
+    my $routine_name = $_[0];
+    my $count = $_[1];
+
+    $rule = $special_args{"${routine_name}-$count"};
+    ($direction,$method,$Array_size) = split(/:/,$rule);
+
+    $processing_routine = "${method}_${direction}_arg";
+    &$processing_routine( $count );
+}
+
+# This routine prints any declarations that are needed 
+sub print_special_decls {
+    my $routine_name = $_[0];
+
+    if ($returnErrval) {
+	print $OUTFD "    int $errparmrval;\n";
+    }
+    if (defined($special_args{$routine_name})) {
+	# First do the declarations
+	foreach $count (split(/:/,$special_args{$routine_name})) {
+	    $rule = $special_args{"${routine_name}-$count"};
+	    ($direction,$method,$Array_size) = split(/:/,$rule);
+	    # Sanity check: method and direction must be nonnull
+	    if ($method eq "" || $direction eq "") {
+		print STDERR "Error in special args for argument number $count of $routine_name\n";
+		last;
+	    }
+	    $processing_routine = "${method}_${direction}_decl";
+	    &$processing_routine( $count );
+	}
+    }
+    if (defined($special_args{$routine_name})) {
+	# Then do the precall steps
+	foreach $count (split(/:/,$special_args{$routine_name})) {
+	    $rule = $special_args{"${routine_name}-$count"};
+	    ($direction,$method,$Array_size) = split(/:/,$rule);
+	    if ($direction eq "in") {
+		$processing_routine = "${method}_ftoc";
+		&$processing_routine( $count );
+	    }
+	    else {
+		$processing_routine = "${method}_out_ftoc";
+		if (defined(&$processing_routine)) {
+		    &$processing_routine( $count );
+		}
+	    }
+	}
+    }
+}
+
+#
+# --------------------------------------------------------------------------
+# Create mpif.h.in from mpi.h
+#
+# Need to put this into a routine similar to the ReadInterface routine
+# in the c++ version.  This will allow us to read both mpi.h.in
+# and mpio.h.in (or other files)
+
+&ReadInterfaceForDefinitions( $prototype_file );
+if ( -s "../../mpi/romio/include/mpio.h.in" && $build_io) { 
+    %skipBlocks = ( 'HAVE_MPI_DARRAY_SUBARRAY' => 1, 
+		   'HAVE_MPI_INFO' => 1,
+		    'MPICH2' => 1 );
+    &ReadInterfaceForDefinitions( "../../mpi/romio/include/mpio.h.in" );
+    %skipBlocks = ();
+}
+#
+if ($write_mpif) {
+
+    # The ONLY valid comment character for Fortran 77 is a C in column 1
+    # For those Fortran compilers that support it (which is most at this point)
+    # the top-level configure will replace the "C" in column 1 with "!" 
+    # (also in column 1)
+    $cchar = "C";
+    open ( MPIFFD, ">mpif.h.in.new" ) || die "Could not open mpif.h.in.new\n";
+
+    
+    # Now, write out the file
+    # This first line makes sure that other tools know that this is a
+    # Fortran file
+    print MPIFFD "$cchar      /* -*- Mode: Fortran; -*- */\n";
+    print MPIFFD "$cchar      \n";
+    print MPIFFD "$cchar      (C) 2003 by Argonne National Laboratory and Northwestern University.\n";
+    print MPIFFD "$cchar      See COPYRIGHT in top-level directory.\n";
+    print MPIFFD "$cchar      \n";
+    print MPIFFD "$cchar      DO NOT EDIT\n";
+    print MPIFFD "$cchar      This file created by ./buildiface $arg_string\n";
+    print MPIFFD "$cchar      \n";
+    #
+    # Status elements
+    # FIXME: The offsets for the status elements are hardwired.  If they
+    # change in mpi.h.in, they need to change here as well.
+    print MPIFFD "       INTEGER MPI_SOURCE, MPI_TAG, MPI_ERROR\n";
+    print MPIFFD "       PARAMETER (MPI_SOURCE=3,MPI_TAG=4,MPI_ERROR=5)\n";
+    print MPIFFD "       INTEGER MPI_STATUS_SIZE\n";
+    print MPIFFD "       PARAMETER (MPI_STATUS_SIZE=\@MPI_STATUS_SIZE\@)\n";
+    # Temporary until configure handles these.  Define as arrays to keep
+    # Fortran compilers from complaining excessively.
+    print MPIFFD "       INTEGER MPI_STATUS_IGNORE(MPI_STATUS_SIZE)\n";
+    print MPIFFD "       INTEGER MPI_STATUSES_IGNORE(MPI_STATUS_SIZE,1)\n";
+    #
+    # Other special constants.  ERRCODES_IGNORE and ARGVS_NULL
+    # are both like STATUS(ES)_IGNORE
+    print MPIFFD "       INTEGER MPI_ERRCODES_IGNORE(1)\n";
+    print MPIFFD "       CHARACTER*1 MPI_ARGVS_NULL(1,1)\n";
+    # Unfortunately, we cannot parameter initialize this.  Further,
+    # there is no default initialization.  We could use a block data item...
+    # ARGV_NULL can actually be a single blank string, but it needs
+    # to be typed as a character array
+    print MPIFFD "       CHARACTER*1 MPI_ARGV_NULL(1)\n";
+
+    #
+    # Error Classes
+    print MPIFFD "       INTEGER MPI_SUCCESS\n";
+    print MPIFFD "       PARAMETER (MPI_SUCCESS=0)\n";
+    foreach $key (keys(%mpidef)) {
+	if ($key =~ /MPI_ERR_/) {
+	    &print_mpif_int( $key );
+	}
+    }
+    # Predefined error handlers
+    foreach $key (ERRORS_ARE_FATAL, ERRORS_RETURN) {
+	&print_mpif_int( "MPI_$key" );
+    }
+    # Compare operations
+    foreach $key (IDENT,CONGRUENT,SIMILAR,UNEQUAL) {
+	&print_mpif_int( "MPI_$key" );
+    }
+    # Collective operations
+    foreach $key (MAX, MIN, SUM, PROD, LAND, BAND, LOR, BOR, LXOR, BXOR, MINLOC, MAXLOC, REPLACE ) {
+	&print_mpif_int( "MPI_$key" );
+    }
+    # Objects
+    foreach $key ('COMM_WORLD', 'COMM_SELF', 'GROUP_EMPTY', 'COMM_NULL', 'WIN_NULL', 'FILE_NULL', 'GROUP_NULL', 'OP_NULL', 'DATATYPE_NULL', 'REQUEST_NULL', 'ERRHANDLER_NULL', 'INFO_NULL', ) {
+	&print_mpif_int( "MPI_$key" );
+    }
+    # Attributes
+    foreach $key (TAG_UB, HOST, IO, WTIME_IS_GLOBAL, UNIVERSE_SIZE, LASTUSEDCODE, APPNUM, WIN_BASE, WIN_SIZE, WIN_DISP_UNIT ) {
+	# Special cast:  The Fortran versions of these attributes have 
+	# value 1 greater than the C versions
+	$attrval = $mpidef{"MPI_$key"};
+	print "$key is $attrval\n" if $debug;
+	if ($attrval =~ /^0x/) { $attrval = hex $attrval; }
+	$attrval++;
+	$attrval = "0x" . sprintf "%x", $attrval;
+	print "$key is now $attrval\n" if $debug;
+	$mpidef{"MPI_$key"} = $attrval;
+	&print_mpif_int( "MPI_$key" );
+    } 
+    # String sizes
+    # See MPI-2 2.6.2 and 4.12.9; the constants for string lenghts are
+    # defined as one less than the C/C++ version
+
+    # Missing - max processor name!
+    # Handle max processor name here.
+    $mpidef{"MPI_MAX_PROCESSOR_NAME"} = "\@MPI_MAX_PROCESSOR_NAME\@";
+    # Other maximum values
+    foreach $key (MAX_ERROR_STRING, MAX_PORT_NAME, 
+		  MAX_OBJECT_NAME, MAX_INFO_KEY, MAX_INFO_VAL,
+		  MAX_PROCESSOR_NAME, MAX_DATAREP_STRING ) {
+	&print_mpif_int( "MPI_$key", -1 );
+    }
+    
+    # predefined constants
+    print MPIFFD "       INTEGER MPI_UNDEFINED\n";
+    print MPIFFD "       PARAMETER (MPI_UNDEFINED=$mpidef{'MPI_UNDEFINED'})\n";
+    &print_mpif_int( "MPI_KEYVAL_INVALID" );
+    foreach $key ('BSEND_OVERHEAD', 'PROC_NULL', 'ANY_SOURCE', 'ANY_TAG', 'ROOT') {
+	&print_mpif_int( "MPI_$key" );
+    }
+    #
+    # Topology types
+    foreach $key (GRAPH, CART) {
+	&print_mpif_int( "MPI_$key" );
+    }
+    #
+    # version
+    &print_mpif_int( "MPI_VERSION" );
+    &print_mpif_int( "MPI_SUBVERSION" );
+
+    # Special RMA values
+    &print_mpif_int( "MPI_LOCK_EXCLUSIVE" );
+    &print_mpif_int( "MPI_LOCK_SHARED" );
+    #
+    # Datatypes
+    # These are determined and set at configure time
+    foreach $key (COMPLEX, DOUBLE_COMPLEX, LOGICAL, REAL, DOUBLE_PRECISION, INTEGER, '2INTEGER', '2COMPLEX', '2DOUBLE_PRECISION', '2REAL', '2DOUBLE_COMPLEX', CHARACTER) {
+	print MPIFFD "       INTEGER MPI_$key\n";
+	print MPIFFD "       PARAMETER (MPI_$key=\@MPI_$key\@)\n";
+    }
+    # Value of MPI_BYTE from top level configure!
+    $mpidef{"MPI_BYTE"} = hex "0x4c00010d";
+    foreach $key (BYTE, UB, LB, PACKED) {
+	print MPIFFD "       INTEGER MPI_$key\n";
+        print MPIFFD "       PARAMETER (MPI_$key=\@MPI_F77_$key\@)\n";
+    }
+    #&print_mpif_int( "MPI_BYTE" );
+    #&print_mpif_int( "MPI_UB" );
+    #&print_mpif_int( "MPI_LB" );
+    #&print_mpif_int( "MPI_PACKED" );
+
+    # Optional types
+    # Warning: Should these use \@MPI_$key\@, since the 
+    # C-version must also compute these?
+    foreach $key (INTEGER1, INTEGER2, INTEGER4, INTEGER8, INTEGER16,
+		  REAL4, REAL8, REAL16, COMPLEX8, COMPLEX16, COMPLEX32) {
+	print MPIFFD "       INTEGER MPI_$key\n";
+	print MPIFFD "       PARAMETER (MPI_$key=\@F77_$key\@)\n";
+    }
+    #
+    # Fortran 90 types
+    print MPIFFD "       INTEGER MPI_ADDRESS_KIND, MPI_OFFSET_KIND\n";
+    print MPIFFD "       PARAMETER (MPI_ADDRESS_KIND=\@ADDRESS_KIND\@)\n";
+    print MPIFFD "       PARAMETER (MPI_OFFSET_KIND=\@OFFSET_KIND\@)\n";
+    # 
+    # C Types.  Note that we need to convert the C hex constant
+    # into a decimal constant for Fortran (there is no standard
+    # for for hex constants in Fortran, and different compilers make
+    # use of different extensions)
+    foreach $key (CHAR, SIGNED_CHAR, UNSIGNED_CHAR, WCHAR, SHORT,
+		  UNSIGNED_SHORT, INT, UNSIGNED, LONG, UNSIGNED_LONG, 
+		  FLOAT, DOUBLE, LONG_DOUBLE, LONG_LONG_INT, 
+		  UNSIGNED_LONG_LONG, LONG_LONG, FLOAT_INT, DOUBLE_INT, 
+		  LONG_INT, SHORT_INT, "2INT", LONG_DOUBLE_INT) {
+	print MPIFFD "       INTEGER MPI_$key\n";
+	print MPIFFD "       PARAMETER (MPI_$key=\@MPI_F77_$key\@)\n";
+    }
+    # C types added in MPI 2.2
+    foreach $key (INT8_T, INT16_T, INT32_T, INT64_T, UINT8_T, UINT16_T, 
+		  UINT32_T, UINT64_T, C_BOOL, C_FLOAT_COMPLEX, C_COMPLEX,
+		  C_DOUBLE_COMPLEX, C_LONG_DOUBLE_COMPLEX, AINT, OFFSET) {
+	print MPIFFD "       INTEGER MPI_$key\n";
+	print MPIFFD "       PARAMETER (MPI_$key=\@MPI_F77_$key\@)\n";
+    }
+    # Datatype combiners
+    foreach $key (NAMED, DUP, CONTIGUOUS, VECTOR, HVECTOR_INTEGER, HVECTOR, 
+                  INDEXED, HINDEXED_INTEGER, HINDEXED, INDEXED_BLOCK, 
+                  STRUCT_INTEGER, STRUCT, SUBARRAY, DARRAY, F90_REAL,
+                  F90_COMPLEX, F90_INTEGER, RESIZED) {
+	&print_mpif_int( "MPI_COMBINER_$key" );
+    }
+    # Typeclasses
+    foreach $key (REAL, INTEGER, COMPLEX) {
+	&print_mpif_int( "MPI_TYPECLASS_$key" );
+    }
+
+    # RMA Asserts
+    foreach $mode (NOCHECK, NOSTORE, NOPUT, NOPRECEDE, NOSUCCEED) {
+	&print_mpif_int( "MPI_MODE_$mode" );
+    }
+
+    # Thread values
+    foreach my $threadlevel (SINGLE, FUNNELED, SERIALIZED, MULTIPLE) {
+	&print_mpif_int( "MPI_THREAD_$threadlevel" );
+    }
+
+    # MPI-2 types: Files
+    if ($build_io) {
+	# Modes
+	foreach $mode (RDONLY, RDWR, WRONLY, DELETE_ON_CLOSE, UNIQUE_OPEN,
+		       CREATE, EXCL, APPEND, SEQUENTIAL) {
+	    &print_mpif_int( "MPI_MODE_$mode" );
+	}
+	# Seek
+	foreach $dir (SET, CUR, END) {
+	    &print_mpif_int( "MPI_SEEK_$dir" );
+	}
+	# Order
+	foreach $order (C, FORTRAN) {
+	    &print_mpif_int("MPI_ORDER_$order");
+	}
+	# direction
+	foreach $distrib (BLOCK, CYCLIC, NONE, DFLT_DARG) {
+	    &print_mpif_int("MPI_DISTRIBUTE_$distrib");
+	}
+	&print_mpif_int( "MPI_DISPLACEMENT_CURRENT", 0,
+			 "\@FORTRAN_MPI_OFFSET\@" );
+    }
+    # 
+    # Finally, the special symbols
+    print MPIFFD "       INTEGER MPI_BOTTOM, MPI_IN_PLACE\n";
+
+    # And the external names.  This are necessary to 
+    # ensure that these are passed as routines, not implicitly-defined 
+    # variables
+    print MPIFFD "       EXTERNAL MPI_DUP_FN, MPI_NULL_DELETE_FN, MPI_NULL_COPY_FN\n";
+    # Note that pmpi_wtime can cause problems with some Fortran compilers
+    # if the corresponding routines aren't available (even if not used)
+    print MPIFFD "       EXTERNAL MPI_WTIME, MPI_WTICK\n";
+    print MPIFFD "       EXTERNAL PMPI_WTIME, PMPI_WTICK\n";
+    # Add the external names for the MPI-2 attribute functions
+    print MPIFFD "       EXTERNAL MPI_COMM_DUP_FN, MPI_COMM_NULL_DELETE_FN\n";
+    print MPIFFD "       EXTERNAL MPI_COMM_NULL_COPY_FN\n";
+    print MPIFFD "       EXTERNAL MPI_WIN_DUP_FN, MPI_WIN_NULL_DELETE_FN\n";
+    print MPIFFD "       EXTERNAL MPI_WIN_NULL_COPY_FN\n";
+    print MPIFFD "       EXTERNAL MPI_TYPE_DUP_FN, MPI_TYPE_NULL_DELETE_FN\n";
+    print MPIFFD "       EXTERNAL MPI_TYPE_NULL_COPY_FN\n";
+    print MPIFFD "       EXTERNAL MPI_CONVERSION_FN_NULL\n";
+    # the time/tick functions
+    # Special option.  Some compilers (particularly IBM's xl compilers)
+    # allow the user to change the definition of the datatypes, such as
+    # making real 8 bytes and double precision 16.  To allow mpif.h
+    # to be used with such compilers, those compilers allow the
+    # use of the non-standard real*8 to force exactly 8 bytes.
+    # WARNING: REAL*8 is not standard and must not be used here. 
+    # Instead, the top level configure (in mpich2/configure) will
+    # replace DOUBLE PRECISION with REAL*8 where the Fortran compiler 
+    # supports it.  
+    print MPIFFD "       DOUBLE PRECISION MPI_WTIME, MPI_WTICK\n";
+    print MPIFFD "       DOUBLE PRECISION PMPI_WTIME, PMPI_WTICK\n";
+    # We avoid adding the external declarations because some Fortran
+    # compilers then insist on linking with the routines, even if 
+    # they are not used.  Combined with systems that do not have weak
+    # symbols, and you can get some strange link failures.
+
+    # When building the Fortran interface for Microsoft Windows, there 
+    # are some additional compiler directives needed 
+    # This provides a hook for any DLL import directives.  We need to 
+    # make this a configure-time variable because some compilers (in 
+    # particular, a version of the Intel Fortran compiler for Linux)
+    # will read directives for other compilers and then flag as fatal
+    # errors directives that it does not support but does recognize.
+    print MPIFFD "\@DLLIMPORT\@\n";
+
+    # Add the common blocks for the special constants
+    # (Use two to avoid problems with continuations)
+    print MPIFFD "\
+       COMMON /MPIPRIV1/ MPI_BOTTOM, MPI_IN_PLACE, MPI_STATUS_IGNORE\n";
+    print MPIFFD "\
+       COMMON /MPIPRIV2/ MPI_STATUSES_IGNORE, MPI_ERRCODES_IGNORE\n";
+    print MPIFFD "       SAVE /MPIPRIV1/,/MPIPRIV2/\n";
+    # Add the common block for the character parameter ARGVS_NULL (Fortran
+    # requires character data in a different common block than 
+    # non-character data)
+    print MPIFFD "\
+       COMMON /MPIPRIVC/ MPI_ARGVS_NULL, MPI_ARGV_NULL
+       SAVE   /MPIPRIVC/\n";
+
+    close( MPIFFD );
+    &ReplaceIfDifferent( "mpif.h.in", "mpif.h.in.new" );
+} # if write_mpif
+
+#
+# Look through $args for parameter names (foo\s+name)
+# and remove them
+sub clean_args {
+    my $newargs = "";
+    my $comma = "";
+    for $parm (split(',',$args)) {
+	# Remove any leading or trailing spaces
+	$parm =~ s/^\s*//;
+	$parm =~ s/\s*$//;
+	# Handle parameters with parameter names
+	# First if handles "int foo", second handles "int *foo"
+	if ( ($parm =~ /^([A-Za-z0-9_]+)\s+[A-Za-z0-9_]+$/) ) {
+	    $parm = $1;
+	}
+	elsif ( ($parm =~ /([A-Za-z0-9_]+\s*\*)\s*[A-Za-z0-9_]+$/) ) {
+	    $parm = $1;
+	}
+	$newargs .= "$comma$parm";
+	$comma = ",";
+    }
+    print STDERR "$newargs\n" if $debug;
+    $args = $newargs;
+}
+
+# print_type_decl( $FD, $lcname )
+
+sub print_routine_type_decl {
+    my $OUTFD = $_[0];
+    my $lcname = $_[1];
+    # The name "FORTRAN_API" may be use to tell the compiler that
+    # 
+    if ($do_subdecls) {
+	print $OUTFD "FORTRAN_API $returnType FORT_CALL ";
+    }
+    else {
+	print $OUTFD "$returnType ";
+    }
+    print $OUTFD "${out_prefix}${lcname}_ ";
+}
+
+#
+# Build the special routines
+sub build_specials {
+    my $filename = "";
+    # The init routine contains some configure-time values.
+    # We may not want to do this if we are supporting multiple
+    # Fortran compilers with different values for Fortran .TRUE. and
+    # .FALSE., but to get started, this is easiest.
+    $OUTFD = "INITFFD";
+    $filename = "initf.c";
+    open( $OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    &print_header( "MPI_Init", "init", "" );
+
+    &print_routine_type_decl( $OUTFD, "init" );
+    $args = "";
+    &print_args( $OUTFD, $args, 0, "init" );
+    # If an attribute can be added before the code, then do that here.
+    # Gcc only allows attributes on the prototypes, not the function
+    # definitions
+    print $OUTFD "{\n";
+    print $OUTFD "#ifndef F77_RUNTIME_VALUES
+    /* any compile/link time values go here */
+#else
+#   error \"Fortran values must be determined at configure time\"
+#endif
+";
+    # See the discussion on MPIR_F_NeedInit at the head of this file
+    print $OUTFD "    mpirinitf_(); MPIR_F_NeedInit = 0;\n";
+    print $OUTFD "    *ierr = MPI_Init( 0, 0 );\n";
+    # Still to do:
+    #   Initialize the Fortran versions of the predefined keyvals.
+    #   Find the value of MPI_BOTTOM.  
+    #     Call a Fortran routine that calls a C routine that is passed
+    #     MPI_BOTTOM from the common block.  
+    #     
+    print $OUTFD "}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    &AddPrototype( "init", $args );
+
+    $OUTFD = "INITFFD";
+    $filename = "initthreadf.c";
+    open( $OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    $args = "int, int *";
+    &print_header( "MPI_Init_thread", "init_thread", $args );
+
+    &print_routine_type_decl( $OUTFD, "init_thread" );
+    &print_args( $OUTFD, $args, 0, "init_thread" );
+    print $OUTFD "{\n";
+    # See the discussion on MPIR_F_NeedInit at the head of this file
+    print $OUTFD "    mpirinitf_(); MPIR_F_NeedInit = 0;\n";
+    print $OUTFD "    *ierr = MPI_Init_thread( 0, 0, *v1, v2 );\n";
+    print $OUTFD "}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    &AddPrototype( "init_thread", $args );
+
+    # Functions used by the C init process, but that must be called 
+    # from C
+    $OUTFD = "FORTTOC";
+    $filename = "setbot.c";
+    open( $OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    #setbot.c is not one of the mpi_sources files
+    #$files[$#files+1] = $filename;
+    &print_copyright;
+
+    print $OUTFD "
+#ifdef F77_NAME_UPPER
+#define mpirinitc_ MPIRINITC
+#define mpirinitc2_ MPIRINITC2
+#elif defined(F77_NAME_LOWER_2USCORE) || defined(F77_NAME_LOWER_USCORE)
+/* leave name alone */
+#else
+#define mpirinitc_ mpirinitc
+#define mpirinitc2_ mpirinitc2
+#endif
+/* These functions are called from Fortran so only need prototypes in 
+   this file.  Note that the last argument is a character array, so
+   we need to include the elements of the Fortran character \"dope vector\".
+*/
+FORTRAN_API void FORT_CALL mpirinitc_( void *, void *, void *, void *, 
+                                         void *, void * FORT_MIXED_LEN_DECL 
+                                         FORT_END_LEN_DECL );
+FORTRAN_API void FORT_CALL mpirinitc2_( char * FORT_MIXED_LEN_DECL 
+                                          FORT_END_LEN_DECL );
+";
+    # These are here rather than in initf.c to solve some link order 
+    # problems for Windows when separate libraries are used for the C and
+    # Fortran routines.
+    # Note that the global variables have values.  This is to work around
+    # a bug in some C environments (e.g., Mac OS/X) that don't load
+    # external symbols that don't have a value assigned at compile time 
+    # (so called common symbols)
+    print $OUTFD "
+#ifndef F77_USE_BOOLEAN_LITERALS
+#if defined(F77_RUNTIME_VALUES) || !defined(F77_TRUE_VALUE_SET)
+MPI_Fint MPIR_F_TRUE = 1, MPIR_F_FALSE = 0;
+#else
+const MPI_Fint MPIR_F_TRUE=F77_TRUE_VALUE;
+const MPI_Fint MPIR_F_FALSE=F77_FALSE_VALUE;
+#endif
+#endif
+";
+    # MPI-2, section 4.12.5, on the declaration of MPI_F_STATUS_IGNORE
+    # MPI_F_STATUSES_IGNORE as global variables in mpi.h (!)
+    print $OUTFD "
+#ifndef USE_POINTER_FOR_BOTTOM
+int  MPIR_F_NeedInit        = 1;
+void *MPIR_F_MPI_BOTTOM     = 0;
+void *MPIR_F_MPI_IN_PLACE   = 0;
+/* MPI_F_STATUS_IGNORE etc must be declared within mpi.h (MPI-2 standard 
+   requires this) */
+/* 
+void *MPI_F_STATUS_IGNORE   = 0;
+void *MPI_F_STATUSES_IGNORE = 0;
+*/
+int  *MPI_F_ERRCODES_IGNORE = 0;
+void *MPI_F_ARGVS_NULL      = 0;
+#endif
+\n";
+
+
+    print $OUTFD "
+FORTRAN_API void FORT_CALL mpirinitc_( void *a, void *b, void *c, void *d, 
+                                         void *e, void *f FORT_MIXED_LEN(d1) 
+                                         FORT_END_LEN(d1) )
+{
+    MPIR_F_MPI_BOTTOM     = a;
+    MPIR_F_MPI_IN_PLACE   = b;
+    MPI_F_STATUS_IGNORE   = (MPI_Fint *)c;
+    MPI_F_STATUSES_IGNORE = (MPI_Fint *)d;
+    MPI_F_ERRCODES_IGNORE = (int *)e;
+    MPI_F_ARGVS_NULL      = f;
+}
+/* Initialize the Fortran ARGV_NULL to a blank.  Using this routine
+   avoids potential problems with string manipulation routines that
+   exist in the Fortran runtime but not in the C runtime libraries */
+FORTRAN_API void FORT_CALL mpirinitc2_( char *a FORT_MIXED_LEN(d1) 
+                                          FORT_END_LEN(d1) )
+{
+    *a = ' ';
+}
+";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    
+    $OUTFD = "PCONTROLFFD";
+    $filename = "pcontrolf.c";
+    open( $OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    $args = "int";
+    &print_header( "MPI_Pcontrol", "pcontrol", $args );
+    &print_routine_type_decl( $OUTFD, "pcontrol" );
+    &print_args( $OUTFD, $args, 0, "pcontrol" );
+    #&print_attr;
+    print $OUTFD "{\n";
+    print $OUTFD "    *ierr = MPI_Pcontrol( (int)*v1 );\n";
+    print $OUTFD "}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    &AddPrototype( "pcontrol", $args );
+
+    $OUTFD = "ADDRESSFFD";
+    $filename = "addressf.c";
+    open ($OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    $args = "void *, int *";
+    &print_header( "MPI_Address", "address", $args );
+    # Add the definitions needed for error reporting
+    # (We could use mpiimpl.h, but mpierrs.h should be sufficient)
+    # mpierror.h references FILE *, so needs stdio.h
+    print $OUTFD "#include \"mpierrs.h\"\n"; 
+    print $OUTFD "#include <stdio.h>\n"; 
+    print $OUTFD "#include \"mpierror.h\"\n"; 
+    &print_routine_type_decl( $OUTFD, "address" );
+    &print_args( $OUTFD, $args, 0, "address" );
+    #&print_attr;
+    print $OUTFD "{
+    MPI_Aint a, b;
+    *ierr = MPI_Address( v1, &a );\n";
+    &specialInitStatement( $OUTFD );
+    print $OUTFD "\
+#ifdef USE_POINTER_FOR_BOTTOM
+    b = a;
+#else
+    b = a - (MPIR_Pint) MPIR_F_MPI_BOTTOM;
+#endif
+    *v2 = (MPI_Fint)( b );
+#ifdef HAVE_AINT_LARGER_THAN_FINT
+    /* Check for truncation */
+    if ((MPI_Aint)*v2 - b != 0) {
+        *ierr = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, 
+			  \"MPI_Address\", __LINE__, MPI_ERR_ARG, \"**inttoosmall\", 0 );
+	(void)MPIR_Err_return_comm( 0, \"MPI_Address\",  *ierr );
+    }
+#endif
+}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    &AddPrototype( "address", $args );
+
+    $OUTFD = "GETADDRESSFFD";
+    $filename = "getaddressf.c";
+    open ($OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    $args = "void *, MPI_FAintp";
+    &print_header( "MPI_Get_address", "get_address", $args );
+    # Add the definitions needed for error reporting
+    # (We could use mpiimpl.h, but mpierrs.h should be sufficient)
+    # mpierror.h references FILE *, so needs stdio.h
+    print $OUTFD "#include \"mpierrs.h\"\n"; 
+    print $OUTFD "#include <stdio.h>\n"; 
+    print $OUTFD "#include \"mpierror.h\"\n"; 
+    &print_routine_type_decl( $OUTFD, "get_address" );
+    &print_args( $OUTFD, $args, 0, "get_address" );
+    #&print_attr;
+    print $OUTFD "{
+    MPI_Aint a;
+    *ierr = MPI_Get_address( v1, &a );\n";
+    &specialInitStatement( $OUTFD );
+    print $OUTFD "\
+#ifndef USE_POINTER_FOR_BOTTOM
+    a = a - (MPIR_Pint) MPIR_F_MPI_BOTTOM;
+#endif
+    *v2 =  a;
+}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    &AddPrototype( "get_address", $args );
+
+    $OUTFD = "WTIMEFD";
+    $filename = "wtimef.c";
+    open( $OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    $returnType = "double";
+    &set_weak_decl( "MPI_Wtime", "void", "double" );
+    &set_weak_decl( "PMPI_Wtime", "void", "double" );
+    &print_header( "MPI_Wtime", "wtime", "" );
+    # mpichtimer.h is needed for the timer definitions
+    print $OUTFD "#include \"mpichconf.h\"\n";
+    print $OUTFD "#include \"mpichtimer.h\"\n";
+    &print_routine_type_decl( $OUTFD, "wtime" );
+    print $OUTFD "( void ) ";
+    #&print_attr;
+    print $OUTFD "{\n";
+    print $OUTFD "    double d; MPID_Time_t t;\n
+    MPID_Wtime( &t );
+    MPID_Wtime_todouble( &t, &d );
+    return d;\n";
+    print $OUTFD "}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+
+    if ($build_prototypes) {
+        print PROTOFD "extern ";
+        &print_routine_type_decl( PROTOFD, "wtime" );
+	print PROTOFD "( void )";
+	&print_attr( PROTOFD, "${out_prefix}wtime_" );
+        print PROTOFD ";\n";
+    }
+    $returnType = "void";
+
+    $OUTFD = "WTICKFD";
+    $filename = "wtickf.c";
+    open( $OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    $returnType = "double";
+    &set_weak_decl( "MPI_Wtick", "void", "double" );
+    &set_weak_decl( "PMPI_Wtick", "void", "double" );
+    &print_header( "MPI_Wtick", "wtick", "" );
+    # mpichtimer.h is needed for the timer definitions
+    print $OUTFD "#include \"mpichconf.h\"\n";
+    print $OUTFD "#include \"mpichtimer.h\"\n";
+    &print_routine_type_decl( $OUTFD, "wtick" );
+    print $OUTFD "( void ) ";
+    #&print_attr;
+    print $OUTFD "{\n";
+    print $OUTFD "    double d; 
+    d = MPID_Wtick( );
+    return d;\n";
+    print $OUTFD "}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    
+    if ($build_prototypes) {
+        print PROTOFD "extern ";
+        &print_routine_type_decl( PROTOFD, "wtick" );
+	print PROTOFD "( void )";
+	&print_attr( PROTOFD, "${out_prefix}wtick_" );
+        print PROTOFD ";\n";
+    }
+    $returnType = "void";
+
+    $OUTFD = "KEYVALCREATEF";
+    $filename = "keyval_createf.c";
+    open ($OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    $args = "MPI_Copy_function , MPI_Delete_function , int *, void *";
+    &print_header( "MPI_Keyval_create", "keyval_create", $args );
+    print $OUTFD " 
+#ifndef MPICH_MPI_FROM_PMPI
+#undef MPI_Comm_create_keyval
+#define MPI_Comm_create_keyval PMPI_Comm_create_keyval
+#endif
+";
+
+    print $OUTFD " 
+/* The F77 attr copy function prototype and calling convention */
+typedef void (FORT_CALL F77_CopyFunction) (MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *,MPI_Fint *, MPI_Fint *, MPI_Fint *);
+
+/* Helper proxy function to thunk the attr copy function call into F77 calling convention */
+static
+int
+MPIR_Comm_copy_attr_f77_proxy(
+    MPI_Comm_copy_attr_function* user_function,
+    MPI_Comm comm,
+    int keyval,
+    void* extra_state,
+    MPIR_AttrType value_type,
+    void* value,
+    void** new_value,
+    int* flag
+    )
+{
+    MPI_Fint ierr = 0;
+    MPI_Fint fhandle = (MPI_Fint)comm;
+    MPI_Fint fkeyval = (MPI_Fint)keyval;
+    MPI_Fint fvalue = (MPI_Fint) MPI_VOID_PTR_CAST_TO_MPI_AINT (value);
+    MPI_Fint* fextra  = (MPI_Fint*)extra_state;
+    MPI_Fint fnew = 0;
+    MPI_Fint fflag = 0;
+
+    ((F77_CopyFunction*)user_function)( &fhandle, &fkeyval, fextra, &fvalue, &fnew, &fflag, &ierr );
+
+    *flag = fflag;
+    *new_value = MPI_AINT_CAST_TO_VOID_PTR ((MPI_Aint) fnew);
+    return ierr;
+}
+
+
+/* The F77 attr delete function prototype and calling convention */
+typedef void (FORT_CALL F77_DeleteFunction) (MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *);
+
+/* Helper proxy function to thunk the attr delete function call into F77 calling convention */
+static
+int
+MPIR_Comm_delete_attr_f77_proxy(
+    MPI_Comm_delete_attr_function* user_function,
+    MPI_Comm comm,
+    int keyval,
+    MPIR_AttrType value_type,
+    void* value,
+    void* extra_state
+    )
+{
+    MPI_Fint ierr = 0;
+    MPI_Fint fhandle = (MPI_Fint)comm;
+    MPI_Fint fkeyval = (MPI_Fint)keyval;
+    MPI_Fint fvalue = (MPI_Fint) MPI_VOID_PTR_CAST_TO_MPI_AINT (value);
+    MPI_Fint* fextra  = (MPI_Fint*)extra_state;
+
+    ((F77_DeleteFunction*)user_function)( &fhandle, &fkeyval, &fvalue, fextra, &ierr );
+    return ierr;
+}
+
+
+";
+    &print_routine_type_decl( $OUTFD, "keyval_create" );
+    &print_args( $OUTFD, $args, 0, "keyval_create" );
+    #&print_attr;
+    print $OUTFD "{
+        *ierr = MPI_Comm_create_keyval( v1, v2, v3, v4 );
+        if (!*ierr) {
+            MPIR_Keyval_set_proxy(*v3, MPIR_Comm_copy_attr_f77_proxy, MPIR_Comm_delete_attr_f77_proxy);
+        }
+}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    &AddPrototype( "keyval_create", $args );
+
+    # Default attribute functions.  
+    # We must create separate functions since we cannot rely on
+    # using a preprocessor to alias the names.
+    # OPTION: we could use weak symbols where available to
+    # reduce the number of files.
+    $OUTFD = "DUPFN";
+    $filename = "dup_fnf.c";
+    open ($OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    $args = "MPI_Fint, MPI_Fint *, void *, void **, void **, MPI_Fint *";
+    &print_header( "mpi_dup_fn", "dup_fn", $args );
+    &print_routine_type_decl( $OUTFD, "dup_fn" );
+    &print_args( $OUTFD, $args, 0, "dup_fn" );
+    #&print_attr;
+    print $OUTFD "{
+        *v5 = *v4;
+        *v6 = MPIR_TO_FLOG(1);
+        *ierr = MPI_SUCCESS;
+}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    &AddPrototype( "dup_fn", $args );
+
+    $OUTFD = "NULLDELFN";
+    $filename = "null_del_fnf.c";
+    open ($OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    $args = "MPI_Fint *, MPI_Fint *, void *, void *";
+    &print_header( "mpi_null_delete_fn", "null_delete_fn", $args );
+    &print_routine_type_decl( $OUTFD, "null_delete_fn" );
+    &print_args( $OUTFD, $args, 0, "null_delete_fn" );
+    #&print_attr;
+    print $OUTFD "{
+        *ierr = MPI_SUCCESS;
+}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    &AddPrototype( "null_delete_fn", $args );
+
+    $OUTFD = "NULLCOPYFN";
+    $filename = "null_copy_fnf.c";
+    open ($OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    $args = "MPI_Fint *, MPI_Fint *, void *, void *, void *, int *";
+    &print_header( "mpi_null_copy_fn", "null_copy_fn", $args );
+    &print_routine_type_decl( $OUTFD, "null_copy_fn" );
+    &print_args( $OUTFD, $args, 0, "null_copy_fn" );
+    print $OUTFD "{
+        *ierr = MPI_SUCCESS;
+        *v6 = MPIR_TO_FLOG(0);
+}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    &AddPrototype( "null_copy_fn", $args );
+
+    &WriteAttrDefaults( "comm_" );
+    &WriteAttrDefaults( "win_" );
+    &WriteAttrDefaults( "type_" );
+
+    # Datarep conversion function
+    # This is a special case.  We need to define this function
+    # but it should never be called (we convert a reference to it
+    # to a reference to null, which is how the C version of this
+    # routine is defined.
+#
+# This is now part of the register_datarep function
+#    $OUTFD = "NULLCONVERSIONFN";
+#    $filename = "null_conv_fnf.c";
+#    $returnType = "int";
+#    open ($OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+#    $files[$#files+1] = $filename;
+#    $args = "void *, MPI_Fint *, MPI_Fint *, void *, MPI_Offset *, MPI_Aint *, MPI_Fint *";
+#    &print_header( "mpi_conversion_fn_null", "conversion_fn_null", $args,
+#	   "#ifdef MPI_CONVERSION_FN_NULL\n#undef MPI_CONVERSION_FN_NULL\n#endif\n" );
+#    &print_routine_type_decl( $OUTFD, "conversion_fn_null" );
+#    &print_args( $OUTFD, $args, 0, "conversion_fn_null" );
+#    # This is tricky; we don't want to call this function at all
+#    # FIXME    
+#    print $OUTFD "\n{\n   return MPI_SUCCESS;\n}\n";
+#    close ($OUTFD);
+#    &ReplaceIfDifferent( $filename, $filename . ".new" );
+#    &AddPrototype( "conversion_fn_null", $args );
+
+
+    # The status conversion functions.
+    # These are a little different because they are routines that
+    # are called from C.
+    # Also note that we must exclude them from the routines that
+    # are generated for Fortran.  These are here because they need to
+    # know how Fortran stores a status (e.g., if C and Fortran integers 
+    # are the same size).
+    $OUTFD = "STATUSF2C";
+    $filename = "statusf2c.c";
+    open ($OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    # Status_f2c and c2f will need to have const added before the input
+    # argument for MPI 2.2
+    print $OUTFD "
+/* -*- Mode: C; c-basic-offset:4 ; -*- */
+/*  
+ *  (C) 2003 by Argonne National Laboratory and Northwestern University.
+ *      See COPYRIGHT in top-level directory.
+ *
+ * This file is automatically generated by ./buildiface 
+ * DO NOT EDIT
+ */
+#include \"mpi_fortimpl.h\"
+/* mpierrs.h and mpierror.h for the error code creation */
+#include \"mpierrs.h\"
+#include <stdio.h> 
+#include \"mpierror.h\"
+
+/* -- Begin Profiling Symbol Block for routine MPI_Status_f2c */
+#if defined(USE_WEAK_SYMBOLS) && !defined(USE_ONLY_MPI_NAMES) 
+#if defined(HAVE_PRAGMA_WEAK)
+#pragma weak MPI_Status_f2c = PMPI_Status_f2c
+#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
+#pragma _HP_SECONDARY_DEF PMPI_Status_f2c  MPI_Status_f2c
+#elif defined(HAVE_PRAGMA_CRI_DUP)
+#pragma _CRI duplicate MPI_Status_f2c as PMPI_Status_f2c
+#endif
+#endif
+/* -- End Profiling Symbol Block */
+
+/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
+   the MPI routines */
+#ifndef MPICH_MPI_FROM_PMPI
+#undef MPI_Status_f2c
+#define MPI_Status_f2c PMPI_Status_f2c
+#endif
+
+#undef FUNCNAME
+#define FUNCNAME MPI_Status_f2c
+
+int MPI_Status_f2c( MPI_Fint *f_status, MPI_Status *c_status )
+{
+    int mpi_errno = MPI_SUCCESS;
+    /* This code assumes that the ints are the same size */\n";
+    &specialInitStatement( $OUTFD );
+print $OUTFD "\    
+    if (f_status == MPI_F_STATUS_IGNORE) {
+	/* The call is erroneous (see 4.12.5 in MPI-2) */
+        mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
+		 \"MPI_Status_f2c\", __LINE__, MPI_ERR_OTHER, \"**notfstatignore\", 0 );
+	return MPIR_Err_return_comm( 0, \"MPI_Status_f2c\",  mpi_errno );
+    }
+    *c_status = *(MPI_Status *)	f_status;
+    return MPI_SUCCESS;  
+}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+
+    $OUTFD = "STATUSC2F";
+    $filename = "statusc2f.c";
+    open ($OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    print $OUTFD "
+/* -*- Mode: C; c-basic-offset:4 ; -*- */
+/*  
+ *  (C) 2003 by Argonne National Laboratory and Northwestern University.
+ *      See COPYRIGHT in top-level directory.
+ *
+ * This file is automatically generated by ./buildiface 
+ * DO NOT EDIT
+ */
+#include \"mpi_fortimpl.h\"
+/* mpierrs.h and mpierror.h for the error code creation */
+#include \"mpierrs.h\"
+#include <stdio.h> 
+#include \"mpierror.h\"
+
+/* -- Begin Profiling Symbol Block for routine MPI_Status_c2f */
+#if defined(USE_WEAK_SYMBOLS) && !defined(USE_ONLY_MPI_NAMES) 
+#if defined(HAVE_PRAGMA_WEAK)
+#pragma weak MPI_Status_c2f = PMPI_Status_c2f
+#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
+#pragma _HP_SECONDARY_DEF PMPI_Status_c2f MPI_Status_c2f
+#elif defined(HAVE_PRAGMA_CRI_DUP)
+#pragma _CRI duplicate MPI_Status_c2f as PMPI_Status_c2f
+#endif
+#endif
+/* -- End Profiling Symbol Block */
+
+/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
+   the MPI routines */
+#ifndef MPICH_MPI_FROM_PMPI
+#undef MPI_Status_c2f
+#define MPI_Status_c2f PMPI_Status_c2f
+#endif
+
+#undef FUNCNAME
+#define FUNCNAME MPI_Status_c2f
+
+int MPI_Status_c2f( MPI_Status *c_status, MPI_Fint *f_status )
+{
+    int mpi_errno = MPI_SUCCESS;
+    /* This code assumes that the ints are the same size */
+    if (c_status == MPI_STATUS_IGNORE ||
+	c_status == MPI_STATUSES_IGNORE) {
+	/* The call is erroneous (see 4.12.5 in MPI-2) */
+        mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
+		 \"MPI_Status_c2f\", __LINE__, MPI_ERR_OTHER, \"**notcstatignore\", 0 );
+	return MPIR_Err_return_comm( 0, \"MPI_Status_c2f\",  mpi_errno );
+    }
+    *(MPI_Status *)f_status = *c_status;
+    return MPI_SUCCESS;
+}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+
+}
+
+sub print_mpif_int {
+    my $key = $_[0];
+    my $value = $mpidef{$key};
+    my $valueOffset = $_[1];
+    my $inttype = $_[2];
+
+    # integertype lets use change the integer type of the 
+    # variable; e.g., to make it integer*8 or integer (kind=MPI_OFFSET_KIND).
+    # This is needed for MPI_DISPLACEMENT_CURRENT.
+    # Because this will need to be set by configure, if set, this 
+    # needs to be a configure variable.
+    my $integertype = "INTEGER";
+
+    if (defined($inttype)) {
+	$integertype = $inttype;
+    }
+    
+    if (!defined($value) || $value eq "") {
+	print STDERR "No value found for \"$key\"\n";
+	return 0;
+    }
+    # Remove any casts
+    print "Input value for $key = $value\n" if $debug;
+    if ($value =~ /\(MPI/) {
+	$value =~ s/\(MPI_[A-Za-z0-9]*\s*\)//;
+	print "cast removal: $value\n" if $debug;
+    }
+    # Remove any surrounding ()
+    if ($value =~ /\(\s*[-a-fx0-9]*\)/) {
+	$value =~ s/\(\s*([-a-fx0-9]*)\s*\)/$1/;
+	print "paren removal: $value\n" if $debug;
+    }
+    # Convert hex to decimal
+    if ($value =~ /^0x[a-f\d]*/) {
+	$value = hex $value;
+	print "hex conversion: $value\n" if $debug;
+    }
+    if (defined($valueOffset) && $valueOffset ne "0") { 
+	if ($value =~ /^-?\d+/) {
+	    $value += $valueOffset;
+	}
+	else {
+	    $value .= "$valueOffset";
+	}
+    }
+    print MPIFFD "       $integertype $key\n";
+    print MPIFFD "       PARAMETER ($key=$value)\n";
+}
+
+
+sub ReadAndProcessInterface {
+    my $prototype_file = $_[0];
+    my $protectMPIO = $_[1];      # Wrap MPI-IO routines in ifdefs MPI_MODE_RDONLY
+    my $linecount = 0;
+    my $newfilename = "";
+    my $filename = "";
+    open( FD, "<$prototype_file" ) || die "Cannot open $prototype_file\n";
+
+    # Skip to prototypes
+    while (<FD>) {
+	$linecount ++;
+	if ( /\/\*\s*Begin Prototypes/ ) { last; }
+    }
+
+    # Read each one
+    while (<FD>) {
+	$linecount ++;
+	print $_ if $debug;
+	# In some packages (not MPI but in Parallel netCDF) not all prototypes
+	# have Fortran equivalents.  The following lets us skip over them
+	if (/\/\*\s*Begin Skip Prototypes/) {
+	    while (<FD>) {
+		if (/\/\*\s*End Skip Prototypes/) { last; }
+	    }
+	}
+	if (/\/\*\s*End Prototypes/) { last; }
+
+	# We should also skip #ifndef xxx, for some xxx.  
+	if (/^#\s*ifndef\s+(\w*)/) {
+	    $ndefname = $1;
+	    if (defined($skipBlocks{$ndefname})) {
+		&SkipCPPIfdef( FD );
+	    }
+	}
+	# Remove any comments; check for problems
+	$origline = $_;
+	while (/(.*)\/\*(.*?)\*\/(.*)/) {
+	    my $removed = $2;
+	    $_ = $1.$3;
+	    if ($2 =~ /\/\*/) {
+		print STDERR "Error in processing comment within interface file $prototype_file in line $origline";
+	    }
+	}
+
+	if (/^int\s+$routine_prefix($routine_pattern)\s*\((.*)/) {
+	    $routine_name = $1;
+	    $args = $2;
+	    while (! ($args =~ /;/)) {
+		$args .= <FD>;
+		$linecount++;
+	    }
+	    $args =~ s/\)\s*;//g;
+	    $args =~ s/[\r\n]*//g;
+	    # remove qualifiers from args
+### TEMP - REMEMBER const because we may need it later	    
+	    #$args =~ s/\s*const\s+//g;
+	    # Convert MPIO_Request to MPI_Request (temporary)
+#	    $args =~ s/MPIO_Request/MPI_Request/g;
+
+	    # Get the name of the Fortran routine (without the prefix).  
+	    # Normally, the name is just the lower-case version, but
+	    # some libraries (such as NetCDF) use "real" in Fortran
+	    # where C uses "float".
+	    $lcname = lc($routine_name);
+	    if (defined($CtoFName{$lcname})) {
+		$lcname = $CtoFName{$lcname};
+	    }
+	    # Eventually, we'll create a new file here.  
+	    # For C++, we may create similar files by looking up 
+	    # the corresponding routines.
+	    if (defined($special_routines{$routine_name})) {
+		print "Skipping $routine_name\n" if $debug;
+	    }
+	    else {
+		# Check for duplicates in the list of routines
+		if (defined($mpi_routines{$routine_name})) {
+		    my $found = "";
+		    if (defined($mpiRoutinesFile{$routine_name})) {
+			my $location = $mpiRoutinesFile{$routine_name};
+			$found = "previous prototoype found in $location\n";
+		    }
+		    print STDERR "Duplicate prototypes for $routine_name in $prototype_file:$linecount\n$found";
+		    next;
+		}
+		# Clear variables
+		&clean_args;
+		$mpi_routines{$routine_name} = $args;
+		$mpiRoutinesFile{$routine_name} = "$prototype_file:$linecount";
+
+		$clean_up = "";
+		if ($buildfiles) {
+		    if (defined($name_map{$lcname})) {
+			$filename = $name_map{$lcname} . "f.c";
+		    }
+		    else {
+			$filename = $lcname . "f.c";
+		    }
+		    $OUTFD = OUTPUTFILED;   # Needed for pre 5.6 versions of perl
+		    $newfilename = $filename . ".new";
+		    open ($OUTFD, ">$newfilename" ) || die "Cannot open $newfilename\n";
+		    # Add the name to the list of files"
+		    $files[$#files+1] = $filename;
+		}
+		else {
+		    $OUTFD = STDOUT;
+		}
+		&print_header( $routine_name, $lcname, $args );
+		if ($do_subdecls) {
+		    print $OUTFD "FORTRAN_API $returnType FORT_CALL ";
+		}
+		else {
+		    print $OUTFD "$returnType ";
+		}
+		print $OUTFD "${out_prefix}${lcname}_ ";
+		# Print args not only prints the arguments but fills the
+		# array @arg_addresses to indicate the number of dereference
+		# operations are needed to recover the original value (since
+		# all Fortran parameters are passed either by value-result or
+		# by reference, many value parameters in the C calls are 
+		# replaced by reference parameters in the Fortran interface.
+		print "Printing arguments for $routine_prefix${lcname}_\n" if $debug;
+		&print_args( $OUTFD, $args, 0, $lcname );
+
+		#&print_attr;
+		print $OUTFD "{\n";
+		&specialInitClear;
+		if ($protectMPIO) {
+		    print $OUTFD "#ifdef MPI_MODE_RDONLY\n";
+ 		}
+		&print_special_decls( $routine_name );
+		if (defined($ChangeCall{$routine_name})) {
+		    my ($newName,$extraArgs) = 
+			split(/:/,$ChangeCall{$routine_name} );
+		    print $OUTFD "   $errparmlval = $newName";
+		    my $largs = $args . "," . $extraArgs;
+		    &print_call_args( $largs );
+		}
+		else {
+		    print $OUTFD "    $errparmlval = $routine_prefix$routine_name";
+		    print "Printing call arguments for mpi_${lcname}_\n" if $debug;
+		    &print_call_args( $args );
+		}
+		# Print any post call processing
+		&print_post_call( $routine_name, $args );
+		if ($protectMPIO) {
+		    print $OUTFD "#else\n$errparmlval = MPI_ERR_INTERN;\n#endif\n";
+ 		}
+		if ($returnErrval) {
+		    print $OUTFD "    return $errparmrval;\n";
+		}
+		print $OUTFD "}\n";
+		if ($buildfiles) {
+		    close ($OUTFD);
+		    &ReplaceIfDifferent( $filename, $newfilename );
+		}
+		if ($build_prototypes) {
+		    if ($do_subdecls) {
+			print PROTOFD "extern FORTRAN_API $returnType FORT_CALL ${out_prefix}${lcname}_ ";
+		    }
+		    else {
+			print PROTOFD "extern $returnType ${out_prefix}${lcname}_ ";
+		    }
+		    &print_args( PROTOFD, $args, 0, $lcname );
+		    &print_attr( PROTOFD, "${out_prefix}${lcname}_" );
+		    print PROTOFD ";\n";
+		}
+	    }
+	}
+    }
+}
+
+sub ReadInterfaceForDefinitions {
+    my $prototype_file = $_[0];
+    my $linecount = 0;
+
+    open ( MPIFD, "<$prototype_file" ) || die "Could not open $prototype_file\n";
+    #
+    # First, find the values that we need
+    while (<MPIFD>) {
+	$linecount++;
+	# Remove any comments; check for problems
+	$origline = $_;
+	while (/(.*)\/\*(.*?)\*\/(.*)/) {
+	    my $removed = $2;
+	    $_ = $1.$3;
+	    if ($2 =~ /\/\*/) {
+		print STDERR "Error in processing comment within interface file $prototype_file in line $origline";
+	    }
+	}
+
+	# We should also skip #ifndef xxx, for some xxx.  
+	if (/^#\s*ifndef\s+(\w*)/) {
+	    $ndefname = $1;
+	    if (defined($skipBlocks{$ndefname})) {
+		&SkipCPPIfdef( MPIFD );
+	    }
+	}
+
+	# Use \S instead of [^\s].  See the comment above
+	if (/^\s*#\s*define\s+(MPI_[A-Za-z_0-9]*)\s+(\S+)(.*)/) {
+	    my $name      = $1;
+	    my $val       = $2;
+	    my $remainder = $3;
+	    print "Found definition of $name as $val\n" if $debug;
+	    # If the name has some lower case letters in it, we
+	    # need to skip it (e.g., for a define MPI_Comm_c2f...)
+	    if ($name =~ /[a-z]/) { next; }
+	    if (defined($mpidef{$name})) {
+		# We want to catch the case ((cast) value).  In
+		# The above definition, the space will break the
+		# value into the cast (actually, "((cast)").
+		$fullval = "$val $remainder";
+		if ($fullval =~ /\(\(([^\(\)]*)\)\s*([^\(\)]*)\s*\)/) {
+		    $val = "(($1)$2)";
+		}
+		if ($mpidef{$name} ne $val) {
+		    my $found = "";
+		    if (defined($mpidefFile{$name})) {
+			my $location = $mpidefFile{$name};
+			$found = " found in $location";
+		    }
+		    print STDERR "Attempting to redefine $name with a new value $val found in $prototype_file:$linecount,\nusing original value of $mpidef{$name}$found\n";
+		}
+	    }
+	    else {
+		$mpidef{$name} = $val;
+		$mpidefFile{$name} = "$prototype_file:$linecount";
+	    }
+	}
+	elsif (/typedef\s+enum\s+[A-Za-z0-9_]*\s*{\s*(.*)/) {
+	    # Allow a named type
+	    # Eat until we find the closing right brace
+	    $enum_line = $1;
+	    while (! ($enum_line =~ /}/)) { 
+	        $enum_line .= <MPIFD>; 
+                $linecount++;
+            }
+	    # Now process for names and values
+	    while ( ($enum_line =~ /\s*(MPI_[A-Z_0-9]*)\s*=\s*([a-fx0-9]*)(.*)/ ) ){
+		$mpidef{$1} = $2;
+		$mpidefFile{$1} = "$prototype_file:$linecount";
+		$enum_line = $3;
+		print "Defining $1 as $2\n" if $debug;
+	       }
+	       
+	   } 
+	elsif (/enum\s+([A-Za-z0-9_]*)\s*{\s*(.*)/) {
+	    # Allow a named type
+	    # Eat until we find the closing right brace
+	    my $enum_name = $1;
+	    my $enum_line = $2;
+	    while (! ($enum_line =~ /}/)) { 
+	        print "reading for $enum_name...\n" if $debug;
+	        my $newline = <MPIFD>;
+	        $newline =~ s/\r*\n//;
+	        $enum_line .= $newline;
+                $linecount++;
+            }
+	    # Now process for names and values
+	    while ( ($enum_line =~ /\s*(MPI_[A-Z_0-9]*)\s*=\s*([a-fx0-9]*)(.*)/ ) ){
+		my $name = $1;
+		my $val = $2;
+		my $remainder = $3;
+		$mpidef{$name} = $val;
+		$mpidefFile{$name} = "$prototype_file:$linecount";
+		$enum_line = $remainder;
+		print "Defining $name as $val\n" if $debug;
+	       }
+	       
+	   } 
+    }
+    close (MPIFD);
+}
+
+# ----------------------------------------------------------------------------
+# Check for a working autoconf
+#
+# Try the following first
+# in a new directory, create configure.in containing:
+# AC_INIT(configure.in)
+# AC_LANG_FORTRAN77
+# AC_TRY_COMPILE(,[integer a],a=1,a=0)
+# Then run autoconf
+# Then grep endEOF configure.  If found (status 0), then autoconf is
+# broken.
+#
+# CheckAutoconf - returns 0 if autoconf works, 1 if broken.
+sub CheckAutoconf {
+    if (! -d "tmp") {
+        mkdir "tmp", 0777 || die "Cannot create temporary directory\n";
+    }
+    open (ACFD, ">tmp/configure.in" ) || die "Cannot create test configure.in\n";
+    print ACFD "AC_INIT(configure.in)\nAC_LANG_FORTRAN77\n";
+    print ACFD "AC_TRY_COMPILE(,[integer a],a=1,a=0)\n";
+    close ACFD;
+
+    chdir 'tmp';
+    $rc = system "autoconf >/dev/null 2>&1 ";
+    $rc = system "grep endEOF configure >/dev/null 2>&1";
+    $rc = !$rc;
+    chdir "..";
+
+    system "rm -rf tmp";
+    return $rc;
+}
+#
+# ISSUES NOT YET HANDLED
+# ----------------------------------------------------------------------------
+# Fortran Integer conversion.
+# If C ints and Fortran integers are not the same size, we have to do
+# more.  In the case of arrays, we must make temporary copies.
+# In MPICH1, there is also code for the case where the sizes of 
+# the C and Fortran integers are not known.  Roughly, the code could look 
+# like
+# #ifdef SIZEOF_F77_INTEGER = SIZEOF_INT
+#   straight-forward code
+# #else
+# {
+#   code that converts arrays, calls routine, frees arrays
+# }
+# #endif
+#
+# There are several options for allocating the temporary arrays
+# For some, like cartesian dimension arrays, it is reasonable to 
+# use a predeclared array (and signal an error if too large)
+# For the others, use a predeclared array with a special case
+# for extra-large
+#
+# Scalars:
+# FintToint_in_decl: int *vi$count;
+# FintToint_in_arg: vi$count
+# FintToint_ftoc: vi$count = (int)v$count
+# similar for intToFint_out
+# For arrays,
+# FintTointArray_in_decl ...
+#
+# ----------------------------------------------------------------------------
+# Character buffer handling for choice arguments
+#  If Fortran passes character arrays as a pair of arguments (rather than
+# putting the second argument at the end of the arg list), then all of the
+# choice arg routines must check the *count* of the number of arguments, 
+# and then, if there are too many args, assume that the choice buffer
+# is a character.  Note that for Sendrecv, there is no unique
+# solution unless you know more about the MPI datatypes.
+# 
+# ----------------------------------------------------------------------------
+sub SkipCPPIfdef {
+    my $FD = $_[0];
+    my $depth = 1;
+
+    while (<$FD>) {
+	if (/^#\s*endif/) { 
+	    $depth--; 
+	    #print "Depth is now $depth\n";
+	}
+        elsif (/^#\s*if/) { 
+	    $depth++; 
+	    #print "Depth is now $depth\n";   
+	}
+	#print "Skipping $_";
+	if ($depth <= 0) { last; }
+    }
+    return 0;
+}
+# ---------------------------------------------------------------------------
+# Add a prototype for (functionname, arguments)
+sub AddPrototype {
+    my ($funcname,$args) = @_;
+    if ($build_prototypes) {
+        print PROTOFD "extern ";
+	&print_routine_type_decl( PROTOFD, "$funcname" );
+	&print_args( PROTOFD, $args, 1, "$funcname" );
+	&print_attr( PROTOFD, "${out_prefix}${funcname}_" );
+	print PROTOFD ";\n";
+    }
+}
+# ---------------------------------------------------------------------------
+# This function writes the attribute copy/delete/dup functions
+# with a particular prefix (and a null prefix is allowed)
+# WriteAttrDefaults( prefix )
+sub WriteAttrDefaults {
+    my $prefix =$_[0];
+    my $ucprefix = uc($prefix);
+    
+    my $filename = "dup_${prefix}fnf.c";
+    open ($OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    # The dup functions with a prefix in Fortran take an MPI_Aint * as
+    # the argument, not a void *.  When sizeof(MPI_Aint) > sizeof(void *),
+    # its important to use an MPI_Aint * instead of a void **
+#    $args = "MPI_Fint, MPI_Fint *, void *, void **, void **, MPI_Fint *";
+    $args = "MPI_Fint, MPI_Fint *, void *, MPI_FAintp, MPI_FAintp, MPI_Fint *";
+    &print_header( "mpi_${prefix}dup_fn", "${prefix}dup_fn", $args,
+	   "#ifdef MPI_${ucprefix}DUP_FN\n#undef MPI_${ucprefix}DUP_FN\n#endif\n" );
+    &print_routine_type_decl( $OUTFD, "${prefix}dup_fn" );
+    &print_args( $OUTFD, $args, 0, "${prefix}dup_fn" );
+    #&print_attr;
+    print $OUTFD "{
+        *v5 = *v4;
+        *v6 = MPIR_TO_FLOG(1);
+        *ierr = MPI_SUCCESS;
+}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    &AddPrototype( "${prefix}dup_fn", $args );
+
+    $OUTFD = "NULLDELFN";
+    $filename = "null_${prefix}del_fnf.c";
+    open ($OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    $args = "MPI_Fint *, MPI_Fint *, MPI_FAintp, MPI_FAintp";
+    &print_header( "mpi_${prefix}null_delete_fn", "${prefix}null_delete_fn", $args,
+	   "#ifdef MPI_${ucprefix}NULL_DELETE_FN\n#undef MPI_${ucprefix}NULL_DELETE_FN\n#endif\n" );
+    &print_routine_type_decl( $OUTFD, "${prefix}null_delete_fn" );
+    &print_args( $OUTFD, $args, 0, "${prefix}null_delete_fn" );
+    #&print_attr;
+    print $OUTFD "{
+        *ierr = MPI_SUCCESS;
+}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+    &AddPrototype( "${prefix}null_delete_fn", $args );
+
+    $OUTFD = "NULLCOPYFN";
+    $filename = "null_${prefix}copy_fnf.c";
+    open ($OUTFD, ">$filename.new" ) || die "Cannot open $filename.new\n";
+    $files[$#files+1] = $filename;
+    $args = "MPI_Fint *, MPI_Fint *, MPI_FAintp, MPI_FAintp, MPI_FAintp, int *";
+    &print_header( "mpi_${prefix}null_copy_fn", "${prefix}null_copy_fn", $args,
+	   "#ifdef MPI_${ucprefix}NULL_COPY_FN\n#undef MPI_${ucprefix}NULL_COPY_FN\n#endif\n" );
+    &print_routine_type_decl( $OUTFD, "${prefix}null_copy_fn" );
+    &print_args( $OUTFD, $args, 0, "${prefix}null_copy_fn" );
+    print $OUTFD "{
+        *ierr = MPI_SUCCESS;
+        *v6 = MPIR_TO_FLOG(0);
+}\n";
+    close ($OUTFD);
+    &ReplaceIfDifferent( $filename, $filename . ".new" );
+
+    &AddPrototype( "${prefix}null_copy_fn", $args );
+}
+
+#
+# Replace old file with new file only if new file is different
+# Otherwise, remove new filename 
+sub ReplaceIfDifferent {
+    my ($oldfilename,$newfilename) = @_;
+    my $rc = 1;
+    if (-s $oldfilename) { 
+	$rc = system "cmp -s $newfilename $oldfilename";
+	$rc >>= 8;   # Shift right to get exit status
+    }
+    if ($rc != 0) {
+	# The files differ.  Replace the old file 
+	# with the new one
+	if (-s $oldfilename) {
+	    print STDERR "Replacing $oldfilename\n";
+	    unlink $oldfilename;
+	}
+	# else {
+	#     print STDERR "Creating $oldfilename\n";
+	# }
+	rename $newfilename, $oldfilename || 
+	    die "Could not replace $oldfilename";
+    }
+    else {
+	unlink $newfilename;
+    }
+}
+# ------------------------------------------------------------------------
+# We wish to have the option of adding a special init call for some
+# variables.  This lets us ensure that MPI routines that need special
+# symbols (such as MPI_BOTTOM or MPI_IN_PLACE) can initialize them without
+# requiring any Fortran routines be called from the C verison of MPI_Init
+# (this can cause problems if the Fortran object file includes references
+# to compiler-specific symbols, making it difficult and inconvenient at
+# best to link C programs)
+# ------------------------------------------------------------------------
+sub specialInitClear {
+    $specialInitAdded = 0;
+}
+sub specialInitStatement {
+    my $FD = $_[0];
+    
+    if ($specialInitAdded) { return; }
+    if (length($specialInitString) > 0) {
+	print $FD $specialInitString . "\n";
+    }
+    $specialInitAdded = 1;
+}
+# ------------------------------------------------------------------------
+# Helper function entries.  Only one so far
+sub HelperForRegister_datarep {
+    my $OUTFD = $_[0]; 
+
+    print $OUTFD "\
+    /* There is a dummy routine, mpi_conversion_fn_null, that is available 
+       for use as the conversion function for MPI_Register_datarep.  
+       Like the attribute null functions, we provide multiple weak versions
+       of this if possible */
+#if defined(USE_WEAK_SYMBOLS) && defined(HAVE_MULTIPLE_PRAGMA_WEAK)
+extern FORTRAN_API int FORT_CALL mpi_conversion_fn_null_ ( void*v1, MPI_Fint*v2, MPI_Fint*v3, void*v4, MPI_Offset*v5, MPI_Fint *v6, MPI_Fint*v7, MPI_Fint *ierr );
+extern FORTRAN_API int FORT_CALL mpi_conversion_fn_null__ ( void*v1, MPI_Fint*v2, MPI_Fint*v3, void*v4, MPI_Offset*v5, MPI_Fint *v6, MPI_Fint*v7, MPI_Fint *ierr );
+extern FORTRAN_API int FORT_CALL mpi_conversion_fn_null ( void*v1, MPI_Fint*v2, MPI_Fint*v3, void*v4, MPI_Offset*v5, MPI_Fint *v6, MPI_Fint*v7, MPI_Fint *ierr );
+extern FORTRAN_API int FORT_CALL MPI_CONVERSION_FN_NULL ( void*v1, MPI_Fint*v2, MPI_Fint*v3, void*v4, MPI_Offset*v5, MPI_Fint *v6, MPI_Fint*v7, MPI_Fint *ierr );
+/* */
+#ifndef MPICH_MPI_FROM_PMPI
+#pragma weak mpi_conversion_fn_null__ = mpi_conversion_fn_null_
+#pragma weak mpi_conversion_fn_null   = mpi_conversion_fn_null_
+#pragma weak MPI_CONVERSION_FN_NULL   = mpi_conversion_fn_null_
+#endif /* MPICH_MPI_FROM_PMPI */
+
+#else
+   /* No weak symbols, so simply rename the one version to match the 
+      Fortran naming convention */
+#ifdef F77_NAME_UPPER
+#define mpi_conversion_fn_null_ MPI_CONVERSION_FN_NULL
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define mpi_conversion_fn_null_ mpi_conversion_fn_null__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define mpi_conversion_fn_null_ mpi_conversion_fn_null
+/* Else leave name alone */
+#endif /* Test on name mapping */
+
+/* Add the prototype so the routine knows what this is */
+extern FORTRAN_API int FORT_CALL mpi_conversion_fn_null_ ( void*v1, MPI_Fint*v2, MPI_Fint*v3, void*v4, MPI_Offset*v5, MPI_Fint *v6, MPI_Fint*v7, MPI_Fint *ierr );
+
+
+#endif /* Test on use multiple weak symbols */
+#ifndef MPICH_MPI_FROM_PMPI
+
+/* This isn't a callable function */
+FORTRAN_API int FORT_CALL mpi_conversion_fn_null_ ( void*v1, MPI_Fint*v2, MPI_Fint*v3, void*v4, MPI_Offset*v5, MPI_Fint *v6, MPI_Fint*v7, MPI_Fint *ierr ) {
+    return 0;
+}
+#endif
+
+";
+
+}
+
+sub HelperForType_create_keyval {
+    my $OUTFD = $_[0]; 
+
+    print $OUTFD "\
+
+/* The F90 attr copy function prototype and calling convention */
+typedef void (FORT_CALL F90_CopyFunction) (MPI_Fint *, MPI_Fint *, MPI_Aint *, MPI_Aint *,MPI_Aint *, MPI_Fint *, MPI_Fint *);
+
+/* Helper proxy function to thunk the attr copy function call into F90 calling convention */
+static
+int
+MPIR_Type_copy_attr_f90_proxy(
+    MPI_Type_copy_attr_function* user_function,
+    MPI_Datatype datatype,
+    int keyval,
+    void* extra_state,
+    MPIR_AttrType value_type,
+    void* value,
+    void** new_value,
+    int* flag
+    )
+{
+    MPI_Fint ierr = 0;
+    MPI_Fint fhandle = (MPI_Fint)datatype;
+    MPI_Fint fkeyval = (MPI_Fint)keyval;
+    MPI_Aint fvalue = MPI_VOID_PTR_CAST_TO_MPI_AINT (value);
+    MPI_Aint* fextra  = (MPI_Aint*)extra_state;
+    MPI_Aint fnew = 0;
+    MPI_Fint fflag = 0;
+
+    ((F90_CopyFunction*)user_function)( &fhandle, &fkeyval, fextra, &fvalue, &fnew, &fflag, &ierr );
+
+    *flag = fflag;
+    *new_value = MPI_AINT_CAST_TO_VOID_PTR (fnew);
+    return ierr;
+}
+
+
+/* The F90 attr delete function prototype and calling convention */
+typedef void (FORT_CALL F90_DeleteFunction) (MPI_Fint *, MPI_Fint *, MPI_Aint *, MPI_Aint *, MPI_Fint *);
+
+/* Helper proxy function to thunk the attr delete function call into F77 calling convention */
+static
+int
+MPIR_Type_delete_attr_f90_proxy(
+    MPI_Type_delete_attr_function* user_function,
+    MPI_Datatype datatype,
+    int keyval,
+    MPIR_AttrType value_type,
+    void* value,
+    void* extra_state
+    )
+{
+    MPI_Fint ierr = 0;
+    MPI_Fint fhandle = (MPI_Fint)datatype;
+    MPI_Fint fkeyval = (MPI_Fint)keyval;
+    MPI_Aint fvalue = MPI_VOID_PTR_CAST_TO_MPI_AINT (value);
+    MPI_Aint* fextra  = (MPI_Aint*)extra_state;
+
+    ((F90_DeleteFunction*)user_function)( &fhandle, &fkeyval, &fvalue, fextra, &ierr );
+    return ierr;
+}\n";
+}
+
+sub HelperForComm_create_keyval {
+    my $OUTFD = $_[0]; 
+
+    print $OUTFD "\
+
+/* The F90 attr copy function prototype and calling convention */
+typedef void (FORT_CALL F90_CopyFunction) (MPI_Fint *, MPI_Fint *, MPI_Aint *, MPI_Aint *,MPI_Aint *, MPI_Fint *, MPI_Fint *);
+
+/* Helper proxy function to thunk the attr copy function call into F90 calling convention */
+static
+int
+MPIR_Comm_copy_attr_f90_proxy(
+    MPI_Comm_copy_attr_function* user_function,
+    MPI_Comm comm,
+    int keyval,
+    void* extra_state,
+    MPIR_AttrType value_type,
+    void* value,
+    void** new_value,
+    int* flag
+    )
+{
+    MPI_Fint ierr = 0;
+    MPI_Fint fhandle = (MPI_Fint)comm;
+    MPI_Fint fkeyval = (MPI_Fint)keyval;
+    MPI_Aint fvalue = MPI_VOID_PTR_CAST_TO_MPI_AINT (value);
+    MPI_Aint* fextra  = (MPI_Aint*)extra_state;
+    MPI_Aint fnew = 0;
+    MPI_Fint fflag = 0;
+
+    ((F90_CopyFunction*)user_function)( &fhandle, &fkeyval, fextra, &fvalue, &fnew, &fflag, &ierr );
+
+    *flag = fflag;
+    *new_value = MPI_AINT_CAST_TO_VOID_PTR (fnew);
+    return ierr;
+}
+
+
+/* The F90 attr delete function prototype and calling convention */
+typedef void (FORT_CALL F90_DeleteFunction) (MPI_Fint *, MPI_Fint *, MPI_Aint *, MPI_Aint *, MPI_Fint *);
+
+/* Helper proxy function to thunk the attr delete function call into F77 calling convention */
+static
+int
+MPIR_Comm_delete_attr_f90_proxy(
+    MPI_Comm_delete_attr_function* user_function,
+    MPI_Comm comm,
+    int keyval,
+    MPIR_AttrType value_type,
+    void* value,
+    void* extra_state
+    )
+{
+    MPI_Fint ierr = 0;
+    MPI_Fint fhandle = (MPI_Fint)comm;
+    MPI_Fint fkeyval = (MPI_Fint)keyval;
+    MPI_Aint fvalue = MPI_VOID_PTR_CAST_TO_MPI_AINT (value);
+    MPI_Aint* fextra  = (MPI_Aint*)extra_state;
+
+    ((F90_DeleteFunction*)user_function)( &fhandle, &fkeyval, &fvalue, fextra, &ierr );
+    return ierr;
+}\n";
+}
+
+sub HelperForWin_create_keyval {
+    my $OUTFD = $_[0]; 
+
+    print $OUTFD "\
+
+/* The F90 attr copy function prototype and calling convention */
+typedef void (FORT_CALL F90_CopyFunction) (MPI_Fint *, MPI_Fint *, MPI_Aint *, MPI_Aint *,MPI_Aint *, MPI_Fint *, MPI_Fint *);
+
+/* Helper proxy function to thunk the attr copy function call into F90 calling convention */
+static
+int
+MPIR_Win_copy_attr_f90_proxy(
+    MPI_Win_copy_attr_function* user_function,
+    MPI_Win win,
+    int keyval,
+    void* extra_state,
+    MPIR_AttrType value_type,
+    void* value,
+    void** new_value,
+    int* flag
+    )
+{
+    MPI_Fint ierr = 0;
+    MPI_Fint fhandle = (MPI_Fint)win;
+    MPI_Fint fkeyval = (MPI_Fint)keyval;
+    MPI_Aint fvalue = MPI_VOID_PTR_CAST_TO_MPI_AINT (value);
+    MPI_Aint* fextra  = (MPI_Aint*)extra_state;
+    MPI_Aint fnew = 0;
+    MPI_Fint fflag = 0;
+
+    ((F90_CopyFunction*)user_function)( &fhandle, &fkeyval, fextra, &fvalue, &fnew, &fflag, &ierr );
+
+    *flag = fflag;
+    *new_value = MPI_AINT_CAST_TO_VOID_PTR (fnew);
+    return ierr;
+}
+
+
+/* The F90 attr delete function prototype and calling convention */
+typedef void (FORT_CALL F90_DeleteFunction) (MPI_Fint *, MPI_Fint *, MPI_Aint *, MPI_Aint *, MPI_Fint *);
+
+/* Helper proxy function to thunk the attr delete function call into F77 calling convention */
+static
+int
+MPIR_Win_delete_attr_f90_proxy(
+    MPI_Win_delete_attr_function* user_function,
+    MPI_Win win,
+    int keyval,
+    MPIR_AttrType value_type,
+    void* value,
+    void* extra_state
+    )
+{
+    MPI_Fint ierr = 0;
+    MPI_Fint fhandle = (MPI_Fint)win;
+    MPI_Fint fkeyval = (MPI_Fint)keyval;
+    MPI_Aint fvalue = MPI_VOID_PTR_CAST_TO_MPI_AINT (value);
+    MPI_Aint* fextra  = (MPI_Aint*)extra_state;
+
+    ((F90_DeleteFunction*)user_function)( &fhandle, &fkeyval, &fvalue, fextra, &ierr );
+    return ierr;
+}\n";
+}
+#
+# FWRAPLIB is a special case.  We want to compile all of the same files,
+# but with MPICH_MPI_FROM_PMPI defined, even (or especially) if weak symbols 
+# are defined.  
+#
+sub AddFwrapDefs {
+    &print_line(  MAKEFD, "wrap_objs = ", 80, "\\\n\t", 8 );
+    for ($i=0; $i<=$#files; $i++) {
+	$name = $files[$i];
+	# files contains only the "mpi" files, which is what
+	# we want
+	my $basename = $name;
+	$basename =~ s/\.c//;
+	&print_line( MAKEFD, "_w$basename.o ", 80, "\\\n\t", 8 );
+    }
+    &print_endline( MAKEFD );
+    # FWRAPNAME is the name of a library that contains ONLY the 
+    # Fortran wrappers
+    print MAKEFD "FWRAPNAME = \@FWRAPNAME\@\n";
+print MAKEFD "\
+lib\${FWRAPNAME}_a_DIR = ROOTDIR/lib\
+lib\${FWRAPNAME}_a_SOURCES = \${wrap_objs}\n";
+}
+
+sub AddFwrapBuild {
+    for ($i=0; $i<=$#files; $i++) {
+	$name = $files[$i];
+	# files contains only the "mpi" files, which is what
+	# we want
+	my $basename = $name;
+	$basename =~ s/\.c//;
+	# Some versions of make won't figure out the $< in this case,
+	# so we use the explicit version
+	# To conform to the newer format of output produced by simplemake,
+	# we output the same set of commands to shorten the output lines
+	# (it seems wierd to optimize make output which is too long to 
+        # watch manually anyway, but this seems to be the current expected
+        # practice). (Note that CC is the C++ compiler on some systems; 
+	# this use of CC is apparently supposed to be a shorthand for \$(CC), 
+	# which may not be correct either.
+	print MAKEFD "_w$basename.o: $name\n";
+	print MAKEFD "	\@if [ \"x\$(VERBOSE)\" != \"x1\" ] ; then \\
+	  echo \"  CC             -o _w$basename.o -c -D... \$(srcdir)/$basename.c\" ; \\
+	else \\
+	  echo \"\$(C_COMPILE) -o _w$basename.o -c -DMPICH_MPI_FROM_PMPI -DUSE_ONLY_MPI_NAMES \$(srcdir)/$basename.c\" ; \\
+	fi\n";
+	print MAKEFD "\t\@\$(C_COMPILE) -o _w$basename.o -c -DMPICH_MPI_FROM_PMPI -DUSE_ONLY_MPI_NAMES \$(srcdir)/$basename.c\n";
+
+	print MAKEFD "_w$basename.lo: $name\n";
+	print MAKEFD "	\@if [ \"x\$(VERBOSE)\" != \"x1\" ] ; then \\
+	  echo \"  CC             -o _sw$basename.o -c -D... \$(srcdir)/$basename.c\" ; \\
+	else \\
+	  echo \"\$(C_COMPILE_SHL) -o _sw$basename.o -c -DMPICH_MPI_FROM_PMPI -DUSE_ONLY_MPI_NAMES \$(srcdir)/$basename.c\" ; \\
+	fi\n";
+	print MAKEFD "\t\@\$(C_COMPILE_SHL) -o _sw$basename.o -c -DMPICH_MPI_FROM_PMPI -DUSE_ONLY_MPI_NAMES \$(srcdir)/$basename.c\n";
+	print MAKEFD "\t\@mv -f _sw$basename.o _w$basename.lo\n";
+    }
+}
+
+# Allow multiple underscore versions of names
+# but without the PMPI versions (needed for the wrapper library)
+sub AddFwrapWeakName {
+    my ($lcname, $ucname, $args) = @_;
+
+    print $OUTFD "
+/* These definitions are used only for generating the Fortran wrappers */
+#if defined(USE_WEAK_SYMBOLS) && defined(HAVE_MULTIPLE_PRAGMA_WEAK) && \\
+    defined(USE_ONLY_MPI_NAMES)\n";
+    &print_weak_decl( $OUTFD, "MPI_$ucname", $args, $lcname ); 
+    &print_weak_decl( $OUTFD, "mpi_${lcname}__", $args, $lcname );
+    &print_weak_decl( $OUTFD, "mpi_${lcname}", $args, $lcname );
+    &print_weak_decl( $OUTFD, "mpi_${lcname}_", $args, $lcname );
+    print $OUTFD "\
+#if defined(F77_NAME_UPPER)
+#pragma weak mpi_${lcname}__ = MPI_${ucname}
+#pragma weak mpi_${lcname}_ = MPI_${ucname}
+#pragma weak mpi_${lcname} = MPI_${ucname}
+#elif defined(F77_NAME_LOWER_2USCORE)
+#pragma weak MPI_$ucname = mpi_${lcname}__
+#pragma weak mpi_${lcname}_ = mpi_${lcname}__
+#pragma weak mpi_${lcname} = mpi_${lcname}__
+#elif defined(F77_NAME_LOWER_USCORE)
+#pragma weak MPI_$ucname = mpi_${lcname}_
+#pragma weak mpi_${lcname}__ = mpi_${lcname}_
+#pragma weak mpi_${lcname} = mpi_${lcname}_
+#else
+#pragma weak MPI_$ucname = mpi_${lcname}
+#pragma weak mpi_${lcname}__ = mpi_${lcname}
+#pragma weak mpi_${lcname}_ = mpi_${lcname}
+#endif
+
+#endif
+";
+}
diff --git a/src/libf/createffiles b/src/libf/createffiles
new file mode 100755
index 0000000..321055b
--- /dev/null
+++ b/src/libf/createffiles
@@ -0,0 +1,24 @@
+#! /bin/sh
+# -*- Mode: shell-script-mode; -*-
+#
+# $Id: createffiles 1162 2013-02-12 20:04:25Z wkliao $
+
+# This is a simple script that creates the Fortran interface files.
+# Usually, it is MPICH_DISTRIBUTION/src/binding/f77/buildiface
+# It makes use of an interface builder developed for MPICH2 and a set of 
+# NetCDF-specific descriptions in the file "defs".
+
+if [ -z "$BUILDIFACE" ] ; then
+    BUILDIFACE=./buildiface
+fi
+
+# Build the files 
+$BUILDIFACE -infile=../lib/pnetcdf.h -deffile=defs $@
+# Update to the old name
+for file in *f.c mpifnetcdf.h ; do
+    if grep FORT_DLL_SPEC $file >/dev/null 2>&1 ; then 
+	rm -f .tmp
+        sed -e 's/FORT_DLL_SPEC/FORTRAN_API/g' $file > .tmp
+	mv .tmp $file
+    fi
+done
diff --git a/src/libf/defs b/src/libf/defs
new file mode 100644
index 0000000..9a5f8d4
--- /dev/null
+++ b/src/libf/defs
@@ -0,0 +1,2547 @@
+#
+#  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+#  See COPYRIGHT notice in top-level directory.
+#
+# $Id: defs 2071 2015-08-11 04:39:53Z wkliao $
+
+$routine_prefix = "ncmpi_";
+$routine_pattern = "[a-z0-9_]*";
+$out_prefix = "nfmpi_";
+$do_weak = 0;
+$do_profiling = 0;
+
+## Need MPI_Offset / INTEGER(KIND=MPI_OFFSET_KIND) Fortran interface
+# $tof77{"MPI_Offset"} = "int *";
+# $tof77{"MPI_Offset *"} = "int *";
+# $tof77{"MPI_Offset*"} = "int *";
+# $tof77{"MPI_Offset\[\]"} = "int";
+
+$tof77{"int"} = "int *";
+$tof77{"int64_t"} = "int64_t *";
+$tof77{"int64_t *"} = "int64_t *";
+$tof77{"nc_type"} = "int *";
+$tof77{"nc_type *"} = "int *";
+$tof77{"nc_type*"} = "int *";
+$malloc = "malloc";
+$calloc = "calloc";
+$free   = "free";
+$header_file = "mpinetcdf_impl.h";
+
+# $tof77{"NCMPI_Request*"} = "MPI_Fint *";
+# $tof77{"NCMPI_Request*"} = "MPI_Fint *";
+# $tof77{"NCMPI_Request\[\]"} = "int *";
+# $tof77{"MPI_Offset**"} = "MPI_Offset *";
+
+# Error return handling
+$errparmtype = "";
+$errparm = "";
+$errparmlval = "ierr";
+$errparmrval = "ierr";
+$returnErrval = 1;
+$returnType   = "int";
+
+#%
+#% Change the handling of input MPI handles
+%argsneedcast = ( 'MPI_Request *' 	=> '(fixme][)(ARG)',
+		  'MPI_Status *'  	=> '(MPI_Status *)(ARG)',
+		  'MPI_File' 		=> 'MPI_File_f2c(ARG)',
+		  'MPI_Comm' 		=> 'MPI_Comm_f2c(ARG)',
+		  'MPI_Comm *' 		=> '(fixme][)(ARG)',
+		  'MPI_Datatype' 	=> 'MPI_Type_f2c(ARG)',
+		  'MPI_Datatype *' 	=> '(fixme][ *)(ARG)',
+		  'MPI_Info *' 		=> '(fixme][)(ARG)',
+		  'MPI_Info' 		=> 'MPI_Info_f2c(ARG)'
+);
+
+# Map some of the names from C to Fortran to replace float with real,
+# schar with int1, short with int2, longlong with int8
+%CtoFName = (
+	'put_att_schar'		=> 'put_att_int1',
+	'get_att_schar'		=> 'get_att_int1',
+	'put_var1_schar'	=> 'put_var1_int1',
+	'get_var1_schar'	=> 'get_var1_int1',
+	'put_var1_schar_all'	=> 'put_var1_int1_all',
+	'get_var1_schar_all'	=> 'get_var1_int1_all',
+	'put_var_schar'		=> 'put_var_int1',
+	'get_var_schar'		=> 'get_var_int1',
+	'put_var_schar_all'	=> 'put_var_int1_all',
+	'get_var_schar_all'	=> 'get_var_int1_all',
+	'put_vara_schar'	=> 'put_vara_int1',
+	'get_vara_schar'	=> 'get_vara_int1',
+	'put_vara_schar_all'	=> 'put_vara_int1_all',
+	'get_vara_schar_all'	=> 'get_vara_int1_all',
+	'put_vars_schar'	=> 'put_vars_int1',
+	'get_vars_schar'	=> 'get_vars_int1',
+	'put_vars_schar_all'	=> 'put_vars_int1_all',
+	'get_vars_schar_all'	=> 'get_vars_int1_all',
+	'put_varm_schar'	=> 'put_varm_int1',
+	'get_varm_schar'	=> 'get_varm_int1',
+	'put_varm_schar_all'	=> 'put_varm_int1_all',
+	'get_varm_schar_all'	=> 'get_varm_int1_all',
+
+	'put_att_short'		=> 'put_att_int2',
+	'get_att_short'		=> 'get_att_int2',
+	'put_var1_short'	=> 'put_var1_int2',
+	'get_var1_short'	=> 'get_var1_int2',
+	'put_var1_short_all'	=> 'put_var1_int2_all',
+	'get_var1_short_all'	=> 'get_var1_int2_all',
+	'put_var_short'		=> 'put_var_int2',
+	'get_var_short'		=> 'get_var_int2',
+	'put_var_short_all'	=> 'put_var_int2_all',
+	'get_var_short_all'	=> 'get_var_int2_all',
+	'put_vara_short'	=> 'put_vara_int2',
+	'get_vara_short'	=> 'get_vara_int2',
+	'put_vara_short_all'	=> 'put_vara_int2_all',
+	'get_vara_short_all'	=> 'get_vara_int2_all',
+	'put_vars_short'	=> 'put_vars_int2',
+	'get_vars_short'	=> 'get_vars_int2',
+	'put_vars_short_all'	=> 'put_vars_int2_all',
+	'get_vars_short_all'	=> 'get_vars_int2_all',
+	'put_varm_short'	=> 'put_varm_int2',
+	'get_varm_short'	=> 'get_varm_int2',
+	'put_varm_short_all'	=> 'put_varm_int2_all',
+	'get_varm_short_all'	=> 'get_varm_int2_all',
+
+	'put_att_float'		=> 'put_att_real',
+	'get_att_float'		=> 'get_att_real',
+	'put_var1_float'	=> 'put_var1_real',
+	'get_var1_float'	=> 'get_var1_real',
+	'put_var1_float_all'	=> 'put_var1_real_all',
+	'get_var1_float_all'	=> 'get_var1_real_all',
+	'put_var_float'		=> 'put_var_real',
+	'get_var_float'		=> 'get_var_real',
+	'put_var_float_all'	=> 'put_var_real_all',
+	'get_var_float_all'	=> 'get_var_real_all',
+	'put_vara_float'	=> 'put_vara_real',
+	'get_vara_float'	=> 'get_vara_real',
+	'put_vara_float_all'	=> 'put_vara_real_all',
+	'get_vara_float_all'	=> 'get_vara_real_all',
+	'put_vars_float'	=> 'put_vars_real',
+	'get_vars_float'	=> 'get_vars_real',
+	'put_vars_float_all'	=> 'put_vars_real_all',
+	'get_vars_float_all'	=> 'get_vars_real_all',
+	'put_varm_float'	=> 'put_varm_real',
+	'get_varm_float'	=> 'get_varm_real',
+	'put_varm_float_all'	=> 'put_varm_real_all',
+	'get_varm_float_all'	=> 'get_varm_real_all',
+
+	'put_att_longlong'	=> 'put_att_int8',
+	'get_att_longlong'	=> 'get_att_int8',
+	'put_var1_longlong'	=> 'put_var1_int8',
+	'get_var1_longlong'	=> 'get_var1_int8',
+	'put_var1_longlong_all'	=> 'put_var1_int8_all',
+	'get_var1_longlong_all'	=> 'get_var1_int8_all',
+	'put_var_longlong'	=> 'put_var_int8',
+	'get_var_longlong'	=> 'get_var_int8',
+	'put_var_longlong_all'	=> 'put_var_int8_all',
+	'get_var_longlong_all'	=> 'get_var_int8_all',
+	'put_vara_longlong'	=> 'put_vara_int8',
+	'get_vara_longlong'	=> 'get_vara_int8',
+	'put_vara_longlong_all'	=> 'put_vara_int8_all',
+	'get_vara_longlong_all'	=> 'get_vara_int8_all',
+	'put_vars_longlong'	=> 'put_vars_int8',
+	'get_vars_longlong'	=> 'get_vars_int8',
+	'put_vars_longlong_all'	=> 'put_vars_int8_all',
+	'get_vars_longlong_all'	=> 'get_vars_int8_all',
+	'put_varm_longlong'	=> 'put_varm_int8',
+	'get_varm_longlong'	=> 'get_varm_int8',
+	'put_varm_longlong_all'	=> 'put_varm_int8_all',
+	'get_varm_longlong_all'	=> 'get_varm_int8_all',
+
+	'put_varn_schar'	=> 'put_varn_int1',
+	'get_varn_schar'	=> 'get_varn_int1',
+	'put_varn_schar_all'	=> 'put_varn_int1_all',
+	'get_varn_schar_all'	=> 'get_varn_int1_all',
+	'put_varn_short'	=> 'put_varn_int2',
+	'get_varn_short'	=> 'get_varn_int2',
+	'put_varn_short_all'	=> 'put_varn_int2_all',
+	'get_varn_short_all'	=> 'get_varn_int2_all',
+	'put_varn_float'	=> 'put_varn_real',
+	'get_varn_float'	=> 'get_varn_real',
+	'put_varn_float_all'	=> 'put_varn_real_all',
+	'get_varn_float_all'	=> 'get_varn_real_all',
+	'put_varn_longlong'	=> 'put_varn_int8',
+	'get_varn_longlong'	=> 'get_varn_int8',
+	'put_varn_longlong_all'	=> 'put_varn_int8_all',
+	'get_varn_longlong_all'	=> 'get_varn_int8_all',
+
+	'iput_var1_schar'	=> 'iput_var1_int1',
+	'iget_var1_schar'	=> 'iget_var1_int1',
+	'iput_var_schar'	=> 'iput_var_int1',
+	'iget_var_schar'	=> 'iget_var_int1',
+	'iput_vara_schar'	=> 'iput_vara_int1',
+	'iget_vara_schar'	=> 'iget_vara_int1',
+	'iput_vars_schar'	=> 'iput_vars_int1',
+	'iget_vars_schar'	=> 'iget_vars_int1',
+	'iput_varm_schar'	=> 'iput_varm_int1',
+	'iget_varm_schar'	=> 'iget_varm_int1',
+
+	'iput_var1_short'	=> 'iput_var1_int2',
+	'iget_var1_short'	=> 'iget_var1_int2',
+	'iput_var_short'	=> 'iput_var_int2',
+	'iget_var_short'	=> 'iget_var_int2',
+	'iput_vara_short'	=> 'iput_vara_int2',
+	'iget_vara_short'	=> 'iget_vara_int2',
+	'iput_vars_short'	=> 'iput_vars_int2',
+	'iget_vars_short'	=> 'iget_vars_int2',
+	'iput_varm_short'	=> 'iput_varm_int2',
+	'iget_varm_short'	=> 'iget_varm_int2',
+
+	'iput_var1_float'	=> 'iput_var1_real',
+	'iget_var1_float'	=> 'iget_var1_real',
+	'iput_var_float'	=> 'iput_var_real',
+	'iget_var_float'	=> 'iget_var_real',
+	'iput_vara_float'	=> 'iput_vara_real',
+	'iget_vara_float'	=> 'iget_vara_real',
+	'iput_vars_float'	=> 'iput_vars_real',
+	'iget_vars_float'	=> 'iget_vars_real',
+	'iput_varm_float'	=> 'iput_varm_real',
+	'iget_varm_float'	=> 'iget_varm_real',
+
+	'iput_var1_longlong'	=> 'iput_var1_int8',
+	'iget_var1_longlong'	=> 'iget_var1_int8',
+	'iput_var_longlong'	=> 'iput_var_int8',
+	'iget_var_longlong'	=> 'iget_var_int8',
+	'iput_vara_longlong'	=> 'iput_vara_int8',
+	'iget_vara_longlong'	=> 'iget_vara_int8',
+	'iput_vars_longlong'	=> 'iput_vars_int8',
+	'iget_vars_longlong'	=> 'iget_vars_int8',
+	'iput_varm_longlong'	=> 'iput_varm_int8',
+	'iget_varm_longlong'	=> 'iget_varm_int8',
+
+	'iput_varn_schar'	=> 'iput_varn_int1',
+	'iget_varn_schar'	=> 'iget_varn_int1',
+	'iput_varn_short'	=> 'iput_varn_int2',
+	'iget_varn_short'	=> 'iget_varn_int2',
+	'iput_varn_float'	=> 'iput_varn_real',
+	'iget_varn_float'	=> 'iget_varn_real',
+	'iput_varn_longlong'	=> 'iput_varn_int8',
+	'iget_varn_longlong'	=> 'iget_varn_int8',
+
+	'bput_varn_schar'	=> 'bput_varn_int1',
+	'bput_varn_short'	=> 'bput_varn_int2',
+	'bput_varn_float'	=> 'bput_varn_real',
+	'bput_varn_longlong'	=> 'bput_varn_int8',
+
+	'bput_var1_schar'	=> 'bput_var1_int1',
+	'bput_var_schar'	=> 'bput_var_int1',
+	'bput_vara_schar'	=> 'bput_vara_int1',
+	'bput_vars_schar'	=> 'bput_vars_int1',
+	'bput_varm_schar'	=> 'bput_varm_int1',
+
+	'bput_var1_short'	=> 'bput_var1_int2',
+	'bput_var_short'	=> 'bput_var_int2',
+	'bput_vara_short'	=> 'bput_vara_int2',
+	'bput_vars_short'	=> 'bput_vars_int2',
+	'bput_varm_short'	=> 'bput_varm_int2',
+
+	'bput_var1_float'	=> 'bput_var1_real',
+	'bput_var_float'	=> 'bput_var_real',
+	'bput_vara_float'	=> 'bput_vara_real',
+	'bput_vars_float'	=> 'bput_vars_real',
+	'bput_varm_float'	=> 'bput_varm_real',
+
+	'bput_var1_longlong'	=> 'bput_var1_int8',
+	'bput_var_longlong'	=> 'bput_var_int8',
+	'bput_vara_longlong'	=> 'bput_vara_int8',
+	'bput_vars_longlong'	=> 'bput_vars_int8',
+	'bput_varm_longlong'	=> 'bput_varm_int8'
+);
+
+#
+# We really need a easier way to force a default for a particular data type
+# (e.g., so that we can say "use 'in:intToOffset' for MPI_Offset.  For arrays,
+# we still need an argument for the array size
+#
+# Other transformations:
+#   variable ids and dimension ids must be shifted by 1 (0... in C, 1... in
+#   Fortran.  This is done with out:OffsetIndex and in:IntIndexIn or
+#   out:IntIndex and in:IntIndexIn).
+#   Arrays of ids are handled with in:IntIndexInArr:dimension
+
+%special_args = (
+	'copy_att' => '2:3:5',
+		'copy_att-2'	=> 'in:IntIndexIn',
+		'copy_att-3'	=> 'in:addnull',
+		'copy_att-5'	=> 'in:IntIndexIn',
+	'create' => 2,
+		'create-2'	=> 'in:addnull',
+	'def_dim' => '2:4',
+		'def_dim-2'	=> 'in:addnull',
+		'def_dim-4'	=> 'out:IntIndex',
+	'def_var' => '2:5:6',
+		'def_var-2'	=> 'in:addnull',
+		'def_var-5'	=> 'in:IntIndexInArr:*v4',
+		'def_var-6'	=> 'out:IntIndex',
+	'del_att' => '2:3',
+		'del_att-2'	=> 'in:IntIndexIn',
+		'del_att-3'	=> 'in:addnull',
+
+	'get_att_text' => '2:3:4',
+		'get_att_text-2'	=> 'in:IntIndexIn',
+		'get_att_text-3'	=> 'in:addnull',
+		'get_att_text-4'	=> 'out:charBufferOut',
+	'get_att_schar' => '2:3:4',
+		'get_att_schar-2'	=> 'in:IntIndexIn',
+		'get_att_schar-3'	=> 'in:addnull',
+		'get_att_schar-4'	=> 'out:int1toschar',
+	'get_att_short' => '2:3',
+		'get_att_short-2'	=> 'in:IntIndexIn',
+		'get_att_short-3'	=> 'in:addnull',
+	'get_att_int' => '2:3',
+		'get_att_int-2'		=> 'in:IntIndexIn',
+		'get_att_int-3'		=> 'in:addnull',
+## Skip long for fortran binding iface
+#	'get_att_long' => '2:3',
+#		'get_att_long-2'	=> 'in:IntIndexIn',
+#		'get_att_long-3'	=> 'in:addnull',
+	'get_att_float' => '2:3',
+		'get_att_float-2'	=> 'in:IntIndexIn',
+		'get_att_float-3'	=> 'in:addnull',
+	'get_att_double' => '2:3',
+		'get_att_double-2'	=> 'in:IntIndexIn',
+		'get_att_double-3'	=> 'in:addnull',
+	'get_att_longlong' => '2:3',
+		'get_att_longlong-2'	=> 'in:IntIndexIn',
+		'get_att_longlong-3'	=> 'in:addnull',
+
+## Skip uchar for fortran binding iface
+#	'get_att_uchar' => '2:3:4',
+# 		'get_att_uchar-2'	=> 'in:IntIndexIn',
+#		'get_att_uchar-3'	=> 'in:addnull',
+#		'get_att_uchar-4'	=> 'out:charBufferOut',
+
+	'get_var1' => '2:3',
+		'get_var1-2'		=> 'in:IntIndexIn',
+		'get_var1-3'		=> 'in:reorderOffsetArr:true',
+	'get_var1_all' => '2:3',
+		'get_var1_all-2'	=> 'in:IntIndexIn',
+		'get_var1_all-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_text' => '2:3:4',
+		'get_var1_text-2'	=> 'in:IntIndexIn',
+		'get_var1_text-4'	=> 'out:charBufferOut',
+		'get_var1_text-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_text_all' => '2:3:4',
+		'get_var1_text_all-2'	=> 'in:IntIndexIn',
+		'get_var1_text_all-4'	=> 'out:charBufferOut',
+		'get_var1_text_all-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_schar' => '2:3',
+		'get_var1_schar-2'	=> 'in:IntIndexIn',
+		'get_var1_schar-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_schar_all' => '2:3',
+		'get_var1_schar_all-2'	=> 'in:IntIndexIn',
+		'get_var1_schar_all-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_short' => '2:3',
+		'get_var1_short-2'	=> 'in:IntIndexIn',
+		'get_var1_short-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_short_all' => '2:3',
+		'get_var1_short_all-2'	=> 'in:IntIndexIn',
+		'get_var1_short_all-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_int' => '2:3',
+		'get_var1_int-2'	=> 'in:IntIndexIn',
+		'get_var1_int-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_int_all' => '2:3',
+		'get_var1_int_all-2'	=> 'in:IntIndexIn',
+		'get_var1_int_all-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_float' => '2:3',
+		'get_var1_float-2'	=> 'in:IntIndexIn',
+		'get_var1_float-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_float_all' => '2:3',
+		'get_var1_float_all-2'	=> 'in:IntIndexIn',
+		'get_var1_float_all-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_double' => '2:3',
+		'get_var1_double-2'	=> 'in:IntIndexIn',
+		'get_var1_double-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_double_all' => '2:3',
+		'get_var1_double_all-2'	=> 'in:IntIndexIn',
+		'get_var1_double_all-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_longlong' => '2:3',
+		'get_var1_longlong-2'	=> 'in:IntIndexIn',
+		'get_var1_longlong-3'	=> 'in:reorderOffsetArr:true',
+	'get_var1_longlong_all' => '2:3',
+		'get_var1_longlong_all-2'	=> 'in:IntIndexIn',
+		'get_var1_longlong_all-3'	=> 'in:reorderOffsetArr:true',
+
+	'get_var' => '2',
+		'get_var-2'		=> 'in:IntIndexIn',
+	'get_var_all' => '2',
+		'get_var_all-2'		=> 'in:IntIndexIn',
+	'get_var_text' => '2:3',
+		'get_var_text-2'	=> 'in:IntIndexIn',
+		'get_var_text-3'	=> 'out:charBufferOut',
+	'get_var_text_all' => '2:3',
+		'get_var_text_all-2'	=> 'in:IntIndexIn',
+		'get_var_text_all-3'	=> 'out:charBufferOut',
+	'get_var_schar' => '2',
+		'get_var_schar-2'	=> 'in:IntIndexIn',
+	'get_var_schar_all' => '2',
+		'get_var_schar_all-2'	=> 'in:IntIndexIn',
+	'get_var_short' => '2',
+		'get_var_short-2'	=> 'in:IntIndexIn',
+	'get_var_short_all' => '2',
+		'get_var_short_all-2'	=> 'in:IntIndexIn',
+	'get_var_int' => '2',
+		'get_var_int-2'		=> 'in:IntIndexIn',
+	'get_var_int_all' => '2',
+		'get_var_int_all-2'	=> 'in:IntIndexIn',
+	'get_var_float' => '2',
+		'get_var_float-2'	=> 'in:IntIndexIn',
+	'get_var_float_all' => '2',
+		'get_var_float_all-2'	=> 'in:IntIndexIn',
+	'get_var_double' => '2',
+		'get_var_double-2'	=> 'in:IntIndexIn',
+	'get_var_double_all' => '2',
+		'get_var_double_all-2'	=> 'in:IntIndexIn',
+	'get_var_longlong' => '2',
+		'get_var_longlong-2'	=> 'in:IntIndexIn',
+	'get_var_longlong_all' => '2',
+		'get_var_longlong_all-2'	=> 'in:IntIndexIn',
+
+	'get_vara' => '2:3:4',
+		'get_vara-2'		=> 'in:IntIndexIn',
+		'get_vara-3'		=> 'in:reorderOffsetArr:true',
+		'get_vara-4'		=> 'in:reorderOffsetArr',
+	'get_vara_all' => '2:3:4',
+		'get_vara_all-2'	=> 'in:IntIndexIn',
+		'get_vara_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_all-4'	=> 'in:reorderOffsetArr',
+	'get_vara_text' => '2:3:4:5',
+		'get_vara_text-2'	=> 'in:IntIndexIn',
+		'get_vara_text-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_text-4'	=> 'in:reorderOffsetArr',
+		'get_vara_text-5'	=> 'out:charBufferOut',
+	'get_vara_text_all' => '2:3:4:5',
+		'get_vara_text_all-2'	=> 'in:IntIndexIn',
+		'get_vara_text_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_text_all-4'	=> 'in:reorderOffsetArr',
+		'get_vara_text_all-5'	=> 'out:charBufferOut',
+	'get_vara_schar' => '2:3:4',
+		'get_vara_schar-2'	=> 'in:IntIndexIn',
+		'get_vara_schar-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_schar-4'	=> 'in:reorderOffsetArr',
+	'get_vara_schar_all' => '2:3:4',
+		'get_vara_schar_all-2'	=> 'in:IntIndexIn',
+		'get_vara_schar_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_schar_all-4'	=> 'in:reorderOffsetArr',
+	'get_vara_short' => '2:3:4',
+		'get_vara_short-2'	=> 'in:IntIndexIn',
+		'get_vara_short-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_short-4'	=> 'in:reorderOffsetArr',
+	'get_vara_short_all' => '2:3:4',
+		'get_vara_short_all-2'	=> 'in:IntIndexIn',
+		'get_vara_short_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_short_all-4'	=> 'in:reorderOffsetArr',
+	'get_vara_int' => '2:3:4',
+		'get_vara_int-2'	=> 'in:IntIndexIn',
+		'get_vara_int-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_int-4'	=> 'in:reorderOffsetArr',
+	'get_vara_int_all' => '2:3:4',
+		'get_vara_int_all-2'	=> 'in:IntIndexIn',
+		'get_vara_int_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_int_all-4'	=> 'in:reorderOffsetArr',
+	'get_vara_float' => '2:3:4',
+		'get_vara_float-2'	=> 'in:IntIndexIn',
+		'get_vara_float-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_float-4'	=> 'in:reorderOffsetArr',
+	'get_vara_float_all' => '2:3:4',
+		'get_vara_float_all-2'	=> 'in:IntIndexIn',
+		'get_vara_float_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_float_all-4'	=> 'in:reorderOffsetArr',
+	'get_vara_double' => '2:3:4',
+		'get_vara_double-2'	=> 'in:IntIndexIn',
+		'get_vara_double-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_double-4'	=> 'in:reorderOffsetArr',
+	'get_vara_double_all' => '2:3:4',
+		'get_vara_double_all-2'	=> 'in:IntIndexIn',
+		'get_vara_double_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_double_all-4'	=> 'in:reorderOffsetArr',
+	'get_vara_longlong' => '2:3:4',
+		'get_vara_longlong-2'	=> 'in:IntIndexIn',
+		'get_vara_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_longlong-4'	=> 'in:reorderOffsetArr',
+	'get_vara_longlong_all' => '2:3:4',
+		'get_vara_longlong_all-2'	=> 'in:IntIndexIn',
+		'get_vara_longlong_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vara_longlong_all-4'	=> 'in:reorderOffsetArr',
+
+	'get_vars' => '2:3:4:5',
+		'get_vars-2'		=> 'in:IntIndexIn',
+		'get_vars-3'		=> 'in:reorderOffsetArr:true',
+		'get_vars-4'		=> 'in:reorderOffsetArr',
+		'get_vars-5'		=> 'in:reorderOffsetArr',
+	'get_vars_all' => '2:3:4:5',
+		'get_vars_all-2'	=> 'in:IntIndexIn',
+		'get_vars_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_all-4'	=> 'in:reorderOffsetArr',
+		'get_vars_all-5'	=> 'in:reorderOffsetArr',
+	'get_vars_text' => '2:3:4:5:6',
+		'get_vars_text-2'	=> 'in:IntIndexIn',
+		'get_vars_text-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_text-4'	=> 'in:reorderOffsetArr',
+		'get_vars_text-5'	=> 'in:reorderOffsetArr',
+		'get_vars_text-6'	=> 'out:charBufferOut',
+	'get_vars_text_all' => '2:3:4:5:6',
+		'get_vars_text_all-2'	=> 'in:IntIndexIn',
+		'get_vars_text_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_text_all-4'	=> 'in:reorderOffsetArr',
+		'get_vars_text_all-5'	=> 'in:reorderOffsetArr',
+		'get_vars_text_all-6'	=> 'out:charBufferOut',
+	'get_vars_schar' => '2:3:4:5',
+		'get_vars_schar-2'	=> 'in:IntIndexIn',
+		'get_vars_schar-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_schar-4'	=> 'in:reorderOffsetArr',
+		'get_vars_schar-5'	=> 'in:reorderOffsetArr',
+	'get_vars_schar_all' => '2:3:4:5',
+		'get_vars_schar_all-2'	=> 'in:IntIndexIn',
+		'get_vars_schar_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_schar_all-4'	=> 'in:reorderOffsetArr',
+		'get_vars_schar_all-5'	=> 'in:reorderOffsetArr',
+	'get_vars_short' => '2:3:4:5',
+		'get_vars_short-2'	=> 'in:IntIndexIn',
+		'get_vars_short-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_short-4'	=> 'in:reorderOffsetArr',
+		'get_vars_short-5'	=> 'in:reorderOffsetArr',
+	'get_vars_short_all' => '2:3:4:5',
+		'get_vars_short_all-2'	=> 'in:IntIndexIn',
+		'get_vars_short_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_short_all-4'	=> 'in:reorderOffsetArr',
+		'get_vars_short_all-5'	=> 'in:reorderOffsetArr',
+	'get_vars_int' => '2:3:4:5',
+		'get_vars_int-2'	=> 'in:IntIndexIn',
+		'get_vars_int-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_int-4'	=> 'in:reorderOffsetArr',
+		'get_vars_int-5'	=> 'in:reorderOffsetArr',
+	'get_vars_int_all' => '2:3:4:5',
+		'get_vars_int_all-2'	=> 'in:IntIndexIn',
+		'get_vars_int_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_int_all-4'	=> 'in:reorderOffsetArr',
+		'get_vars_int_all-5'	=> 'in:reorderOffsetArr',
+	'get_vars_float' => '2:3:4:5',
+		'get_vars_float-2'	=> 'in:IntIndexIn',
+		'get_vars_float-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_float-4'	=> 'in:reorderOffsetArr',
+		'get_vars_float-5'	=> 'in:reorderOffsetArr',
+	'get_vars_float_all' => '2:3:4:5',
+		'get_vars_float_all-2'	=> 'in:IntIndexIn',
+		'get_vars_float_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_float_all-4'	=> 'in:reorderOffsetArr',
+		'get_vars_float_all-5'	=> 'in:reorderOffsetArr',
+	'get_vars_double' => '2:3:4:5',
+		'get_vars_double-2'	=> 'in:IntIndexIn',
+		'get_vars_double-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_double-4'	=> 'in:reorderOffsetArr',
+		'get_vars_double-5'	=> 'in:reorderOffsetArr',
+	'get_vars_double_all' => '2:3:4:5',
+		'get_vars_double_all-2'	=> 'in:IntIndexIn',
+		'get_vars_double_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_double_all-4'	=> 'in:reorderOffsetArr',
+		'get_vars_double_all-5'	=> 'in:reorderOffsetArr',
+	'get_vars_longlong' => '2:3:4:5',
+		'get_vars_longlong-2'	=> 'in:IntIndexIn',
+		'get_vars_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_longlong-4'	=> 'in:reorderOffsetArr',
+		'get_vars_longlong-5'	=> 'in:reorderOffsetArr',
+	'get_vars_longlong_all' => '2:3:4:5',
+		'get_vars_longlong_all-2'	=> 'in:IntIndexIn',
+		'get_vars_longlong_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_vars_longlong_all-4'	=> 'in:reorderOffsetArr',
+		'get_vars_longlong_all-5'	=> 'in:reorderOffsetArr',
+
+	'get_varm' => '2:3:4:5:6',
+		'get_varm-2'		=> 'in:IntIndexIn',
+		'get_varm-3'		=> 'in:reorderOffsetArr:true',
+		'get_varm-4'		=> 'in:reorderOffsetArr',
+		'get_varm-5'		=> 'in:reorderOffsetArr',
+		'get_varm-6'		=> 'in:reorderOffsetArr',
+	'get_varm_all' => '2:3:4:5:6',
+		'get_varm_all-2'	=> 'in:IntIndexIn',
+		'get_varm_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_all-4'	=> 'in:reorderOffsetArr',
+		'get_varm_all-5'	=> 'in:reorderOffsetArr',
+		'get_varm_all-6'	=> 'in:reorderOffsetArr',
+	'get_varm_text' => '2:3:4:5:6:7',
+		'get_varm_text-2'	=> 'in:IntIndexIn',
+		'get_varm_text-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_text-4'	=> 'in:reorderOffsetArr',
+		'get_varm_text-5'	=> 'in:reorderOffsetArr',
+		'get_varm_text-6'	=> 'in:reorderOffsetArr',
+		'get_varm_text-7'	=> 'out:charBufferOut',
+	'get_varm_text_all' => '2:3:4:5:6:7',
+		'get_varm_text_all-2'	=> 'in:IntIndexIn',
+		'get_varm_text_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_text_all-4'	=> 'in:reorderOffsetArr',
+		'get_varm_text_all-5'	=> 'in:reorderOffsetArr',
+		'get_varm_text_all-6'	=> 'in:reorderOffsetArr',
+		'get_varm_text_all-7'	=> 'out:charBufferOut',
+	'get_varm_schar' => '2:3:4:5:6',
+		'get_varm_schar-2'	=> 'in:IntIndexIn',
+		'get_varm_schar-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_schar-4'	=> 'in:reorderOffsetArr',
+		'get_varm_schar-5'	=> 'in:reorderOffsetArr',
+		'get_varm_schar-6'	=> 'in:reorderOffsetArr',
+	'get_varm_schar_all' => '2:3:4:5:6',
+		'get_varm_schar_all-2'	=> 'in:IntIndexIn',
+		'get_varm_schar_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_schar_all-4'	=> 'in:reorderOffsetArr',
+		'get_varm_schar_all-5'	=> 'in:reorderOffsetArr',
+		'get_varm_schar_all-6'	=> 'in:reorderOffsetArr',
+	'get_varm_short' => '2:3:4:5:6',
+		'get_varm_short-2'	=> 'in:IntIndexIn',
+		'get_varm_short-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_short-4'	=> 'in:reorderOffsetArr',
+		'get_varm_short-5'	=> 'in:reorderOffsetArr',
+		'get_varm_short-6'	=> 'in:reorderOffsetArr',
+	'get_varm_short_all' => '2:3:4:5:6',
+		'get_varm_short_all-2'	=> 'in:IntIndexIn',
+		'get_varm_short_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_short_all-4'	=> 'in:reorderOffsetArr',
+		'get_varm_short_all-5'	=> 'in:reorderOffsetArr',
+		'get_varm_short_all-6'	=> 'in:reorderOffsetArr',
+	'get_varm_int' => '2:3:4:5:6',
+		'get_varm_int-2'	=> 'in:IntIndexIn',
+		'get_varm_int-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_int-4'	=> 'in:reorderOffsetArr',
+		'get_varm_int-5'	=> 'in:reorderOffsetArr',
+		'get_varm_int-6'	=> 'in:reorderOffsetArr',
+	'get_varm_int_all' => '2:3:4:5:6',
+		'get_varm_int_all-2'	=> 'in:IntIndexIn',
+		'get_varm_int_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_int_all-4'	=> 'in:reorderOffsetArr',
+		'get_varm_int_all-5'	=> 'in:reorderOffsetArr',
+		'get_varm_int_all-6'	=> 'in:reorderOffsetArr',
+	'get_varm_float' => '2:3:4:5:6',
+		'get_varm_float-2'	=> 'in:IntIndexIn',
+		'get_varm_float-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_float-4'	=> 'in:reorderOffsetArr',
+		'get_varm_float-5'	=> 'in:reorderOffsetArr',
+		'get_varm_float-6'	=> 'in:reorderOffsetArr',
+	'get_varm_float_all' => '2:3:4:5:6',
+		'get_varm_float_all-2'	=> 'in:IntIndexIn',
+		'get_varm_float_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_float_all-4'	=> 'in:reorderOffsetArr',
+		'get_varm_float_all-5'	=> 'in:reorderOffsetArr',
+		'get_varm_float_all-6'	=> 'in:reorderOffsetArr',
+	'get_varm_double' => '2:3:4:5:6',
+		'get_varm_double-2'	=> 'in:IntIndexIn',
+		'get_varm_double-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_double-4'	=> 'in:reorderOffsetArr',
+		'get_varm_double-5'	=> 'in:reorderOffsetArr',
+		'get_varm_double-6'	=> 'in:reorderOffsetArr',
+	'get_varm_double_all' => '2:3:4:5:6',
+		'get_varm_double_all-2'	=> 'in:IntIndexIn',
+		'get_varm_double_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_double_all-4'	=> 'in:reorderOffsetArr',
+		'get_varm_double_all-5'	=> 'in:reorderOffsetArr',
+		'get_varm_double_all-6'	=> 'in:reorderOffsetArr',
+	'get_varm_longlong' => '2:3:4:5:6',
+		'get_varm_longlong-2'	=> 'in:IntIndexIn',
+		'get_varm_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_longlong-4'	=> 'in:reorderOffsetArr',
+		'get_varm_longlong-5'	=> 'in:reorderOffsetArr',
+		'get_varm_longlong-6'	=> 'in:reorderOffsetArr',
+	'get_varm_longlong_all' => '2:3:4:5:6',
+		'get_varm_longlong_all-2'	=> 'in:IntIndexIn',
+		'get_varm_longlong_all-3'	=> 'in:reorderOffsetArr:true',
+		'get_varm_longlong_all-4'	=> 'in:reorderOffsetArr',
+		'get_varm_longlong_all-5'	=> 'in:reorderOffsetArr',
+		'get_varm_longlong_all-6'	=> 'in:reorderOffsetArr',
+
+	'inq' => '5',
+		'inq-5'			=> 'out:IntDimIndex',
+	'inq_att' => '2:3',
+		'inq_att-2'		=> 'in:IntIndexIn',
+		'inq_att-3'		=> 'in:addnull',
+	'inq_attid' => '2:3:4',
+		'inq_attid-2'		=> 'in:IntIndexIn',
+		'inq_attid-3'		=> 'in:addnull',
+		'inq_attid-4'		=> 'out:IntIndex',
+	'inq_attlen' => '2:3',
+		'inq_attlen-2'		=> 'in:IntIndexIn',
+		'inq_attlen-3'		=> 'in:addnull',
+	'inq_attname' => '2:3:4',
+		'inq_attname-2'		=> 'in:IntIndexIn',
+		'inq_attname-3'		=> 'in:IntIndexIn',
+		'inq_attname-4'		=> 'out:blankpad',
+	'inq_atttype' => '2:3',
+		'inq_atttype-2'		=> 'in:IntIndexIn',
+		'inq_atttype-3'		=> 'in:addnull',
+	'inq_attdim' => 3,
+		'inq_attdim-3'		=> 'in:addnull',
+	'inq_dim' => '2:3',
+		'inq_dim-2'		=> 'in:IntIndexIn',
+		'inq_dim-3'		=> 'out:blankpad',
+	'inq_dimid' => '2:3',
+		'inq_dimid-2'		=> 'in:addnull',
+		'inq_dimid-3'		=> 'out:IntIndex',
+	'inq_dimlen' => '2',
+		'inq_dimlen-2'		=> 'in:IntIndexIn',
+	'inq_dimname' => '2:3',
+		'inq_dimname-2'		=> 'in:IntIndexIn',
+		'inq_dimname-3'		=> 'out:blankpad',
+	'inq_unlimdim' => 2,
+		'inq_unlimdim-2'	=> 'out:IntIndex',
+	'inq_var' => '2:3:6',
+		'inq_var-2'		=> 'in:IntIndexIn',
+		'inq_var-3'		=> 'out:blankpad',
+		'inq_var-6'		=> 'out:reorderIntArrOut',
+	'inq_vardimid' => '2:3',
+		'inq_vardimid-2'	=> 'in:IntIndexIn',
+		'inq_vardimid-3'	=> 'out:reorderIntArrOut',
+	'inq_varid' => '2:3',
+		'inq_varid-2'		=> 'in:addnull',
+		'inq_varid-3'		=> 'out:IntIndex',
+	'inq_varname' => '2:3',
+		'inq_varname-2'		=> 'in:IntIndexIn',
+		'inq_varname-3'		=> 'out:blankpad',
+	'inq_varnatts' => '2',
+		'inq_varnatts-2'	=> 'in:IntIndexIn',
+	'inq_varndims' => '2',
+		'inq_varndims-2'	=> 'in:IntIndexIn',
+	'inq_vartype' => '2',
+		'inq_vartype-2'		=> 'in:IntIndexIn',
+	'inq_varoffset' => '2',
+		'inq_varoffset-2'	=> 'in:IntIndexIn',
+	'open' => 2,
+		'open-2'		=> 'in:addnull',
+	'delete' => 1,
+		'delete-1'		=> 'in:addnull',
+	'def_var_fill' => '2',
+		'def_var_fill-2'	=> 'in:IntIndexIn',
+	'inq_var_fill' => '2',
+		'inq_var_fill-2'	=> 'in:IntIndexIn',
+	'fill_var_rec' => '2:3',
+		'fill_var_rec-2'	=> 'in:IntIndexIn',
+		'fill_var_rec-3'	=> 'in:OffsetIndexIn',
+
+	'put_att_text' => '2:3:5',
+		'put_att_text-2'	=> 'in:IntIndexIn',
+		'put_att_text-3'	=> 'in:addnull',
+		'put_att_text-5'	=> 'in:charBufferIn',
+	'put_att_schar' => '2:3:6',
+		'put_att_schar-2'	=> 'in:IntIndexIn',
+		'put_att_schar-3'	=> 'in:addnull',
+		'put_att_schar-6'	=> 'in:int1toschar',
+	'put_att_short' => '2:3',
+		'put_att_short-2'	=> 'in:IntIndexIn',
+		'put_att_short-3'	=> 'in:addnull',
+	'put_att_int' => '2:3',
+		'put_att_int-2'		=> 'in:IntIndexIn',
+		'put_att_int-3'		=> 'in:addnull',
+	'put_att_float' => '2:3',
+		'put_att_float-2'	=> 'in:IntIndexIn',
+		'put_att_float-3'	=> 'in:addnull',
+	'put_att_double' => '2:3',
+		'put_att_double-2'	=> 'in:IntIndexIn',
+		'put_att_double-3'	=> 'in:addnull',
+	'put_att_longlong' => '2:3',
+		'put_att_longlong-2'	=> 'in:IntIndexIn',
+		'put_att_longlong-3'	=> 'in:addnull',
+## Skip long for fortran binding iface
+# 	'put_att_long' => '2:3',
+# 		'put_att_long-2'	=> 'in:IntIndexIn',
+#		'put_att_long-3'	=> 'in:addnull',
+#		'put_att_long-5'	=> 'in:intToOffset',
+
+## Skip uchar for fortran binding iface
+# 	'put_att_uchar' => '2:3',
+# 		'put_att_uchar-2'	=> 'in:IntIndexIn',
+#		'put_att_uchar-3'	=> 'in:charBufferIn',
+#		'put_att_uchar-5'	=> 'in:intToOffset',
+
+	'put_var1' => '2:3',
+		'put_var1-2'		=> 'in:IntIndexIn',
+		'put_var1-3'		=> 'in:reorderOffsetArr:true',
+	'put_var1_all' => '2:3',
+		'put_var1_all-2'	=> 'in:IntIndexIn',
+		'put_var1_all-3'	=> 'in:reorderOffsetArr:true',
+	'put_var1_text' => '2:3:4',
+		'put_var1_text-2'	=> 'in:IntIndexIn',
+		'put_var1_text-3'	=> 'in:reorderOffsetArr:true',
+		'put_var1_text-4'	=> 'in:charBufferIn',
+	'put_var1_text_all' => '2:3:4',
+		'put_var1_text_all-2'	=> 'in:IntIndexIn',
+		'put_var1_text_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_var1_text_all-4'	=> 'in:charBufferIn',
+	'put_var1_schar' => '2:3',
+		'put_var1_schar-2'	=> 'in:IntIndexIn',
+		'put_var1_schar-3'	=> 'in:reorderOffsetArr:true',
+	'put_var1_schar_all' => '2:3',
+		'put_var1_schar_all-2'	=> 'in:IntIndexIn',
+		'put_var1_schar_all-3'	=> 'in:reorderOffsetArr:true',
+	'put_var1_short' => '2:3',
+		'put_var1_short-2'	=> 'in:IntIndexIn',
+		'put_var1_short-3'	=> 'in:reorderOffsetArr:true',
+	'put_var1_short_all' => '2:3',
+		'put_var1_short_all-2'	=> 'in:IntIndexIn',
+		'put_var1_short_all-3'	=> 'in:reorderOffsetArr:true',
+	'put_var1_int' => '2:3',
+		'put_var1_int-2'	=> 'in:IntIndexIn',
+		'put_var1_int-3'	=> 'in:reorderOffsetArr:true',
+	'put_var1_int_all' => '2:3',
+		'put_var1_int_all-2'	=> 'in:IntIndexIn',
+		'put_var1_int_all-3'	=> 'in:reorderOffsetArr:true',
+	'put_var1_float' => '2:3',
+		'put_var1_float-2'	=> 'in:IntIndexIn',
+		'put_var1_float-3'	=> 'in:reorderOffsetArr:true',
+	'put_var1_float_all' => '2:3',
+		'put_var1_float_all-2'	=> 'in:IntIndexIn',
+		'put_var1_float_all-3'	=> 'in:reorderOffsetArr:true',
+	'put_var1_double' => '2:3',
+		'put_var1_double-2'	=> 'in:IntIndexIn',
+		'put_var1_double-3'	=> 'in:reorderOffsetArr:true',
+	'put_var1_double_all' => '2:3',
+		'put_var1_double_all-2'	=> 'in:IntIndexIn',
+		'put_var1_double_all-3'	=> 'in:reorderOffsetArr:true',
+	'put_var1_longlong' => '2:3',
+		'put_var1_longlong-2'	=> 'in:IntIndexIn',
+		'put_var1_longlong-3'	=> 'in:reorderOffsetArr:true',
+	'put_var1_longlong_all' => '2:3',
+		'put_var1_longlong_all-2'	=> 'in:IntIndexIn',
+		'put_var1_longlong_all-3'	=> 'in:reorderOffsetArr:true',
+
+	'put_var_text' => '2:3',
+		'put_var_text-2'	=> 'in:IntIndexIn',
+		'put_var_text-3'	=> 'in:charBufferIn',
+	'put_var_text_all' => '2:3',
+		'put_var_text_all-2'	=> 'in:IntIndexIn',
+		'put_var_text_all-3'	=> 'in:charBufferIn',
+	'put_var_schar' => '2',
+		'put_var_schar-2'	=> 'in:IntIndexIn',
+	'put_var_schar_all' => '2',
+		'put_var_schar_all-2'	=> 'in:IntIndexIn',
+	'put_var_int' => '2',
+		'put_var_int-2'		=> 'in:IntIndexIn',
+	'put_var_int_all' => '2',
+		'put_var_int_all-2'	=> 'in:IntIndexIn',
+	'put_var_short' => '2',
+		'put_var_short-2'	=> 'in:IntIndexIn',
+	'put_var_short_all' => '2',
+		'put_var_short_all-2'	=> 'in:IntIndexIn',
+	'put_var_float' => '2',
+		'put_var_float-2'	=> 'in:IntIndexIn',
+	'put_var_float_all' => '2',
+		'put_var_float_all-2'	=> 'in:IntIndexIn',
+	'put_var_double' => '2',
+		'put_var_double-2'	=> 'in:IntIndexIn',
+	'put_var_double_all' => '2',
+		'put_var_double_all-2'	=> 'in:IntIndexIn',
+	'put_var_longlong' => '2',
+		'put_var_longlong-2'	=> 'in:IntIndexIn',
+	'put_var_longlong_all' => '2',
+		'put_var_longlong_all-2'	=> 'in:IntIndexIn',
+
+	'put_var' => '2',
+		'put_var-2'		=> 'in:IntIndexIn',
+	'put_vara' => '2:3:4',
+		'put_vara-2'		=> 'in:IntIndexIn',
+		'put_vara-3'		=> 'in:reorderOffsetArr:true',
+		'put_vara-4'		=> 'in:reorderOffsetArr',
+	'put_vara_all' => '2:3:4',
+		'put_vara_all-2'	=> 'in:IntIndexIn',
+		'put_vara_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_all-4'	=> 'in:reorderOffsetArr',
+	'put_vara_text' => '2:3:4:5',
+		'put_vara_text-2'	=> 'in:IntIndexIn',
+		'put_vara_text-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_text-4'	=> 'in:reorderOffsetArr',
+		'put_vara_text-5'	=> 'in:charBufferIn',
+	'put_vara_text_all' => '2:3:4:5',
+		'put_vara_text_all-2'	=> 'in:IntIndexIn',
+		'put_vara_text_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_text_all-4'	=> 'in:reorderOffsetArr',
+		'put_vara_text_all-5'	=> 'in:charBufferIn',
+	'put_vara_schar' => '2:3:4',
+		'put_vara_schar-2'	=> 'in:IntIndexIn',
+		'put_vara_schar-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_schar-4'	=> 'in:reorderOffsetArr',
+	'put_vara_schar_all' => '2:3:4',
+		'put_vara_schar_all-2'	=> 'in:IntIndexIn',
+		'put_vara_schar_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_schar_all-4'	=> 'in:reorderOffsetArr',
+	'put_vara_short' => '2:3:4',
+		'put_vara_short-2'	=> 'in:IntIndexIn',
+		'put_vara_short-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_short-4'	=> 'in:reorderOffsetArr',
+	'put_vara_short_all' => '2:3:4',
+		'put_vara_short_all-2'	=> 'in:IntIndexIn',
+		'put_vara_short_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_short_all-4'	=> 'in:reorderOffsetArr',
+	'put_vara_int' => '2:3:4',
+		'put_vara_int-2'	=> 'in:IntIndexIn',
+		'put_vara_int-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_int-4'	=> 'in:reorderOffsetArr',
+	'put_vara_int_all' => '2:3:4',
+		'put_vara_int_all-2'	=> 'in:IntIndexIn',
+		'put_vara_int_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_int_all-4'	=> 'in:reorderOffsetArr',
+	'put_vara_float' => '2:3:4',
+		'put_vara_float-2'	=> 'in:IntIndexIn',
+		'put_vara_float-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_float-4'	=> 'in:reorderOffsetArr',
+	'put_vara_float_all' => '2:3:4',
+		'put_vara_float_all-2'	=> 'in:IntIndexIn',
+		'put_vara_float_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_float_all-4'	=> 'in:reorderOffsetArr',
+	'put_vara_double' => '2:3:4',
+		'put_vara_double-2'	=> 'in:IntIndexIn',
+		'put_vara_double-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_double-4'	=> 'in:reorderOffsetArr',
+	'put_vara_double_all' => '2:3:4',
+		'put_vara_double_all-2'	=> 'in:IntIndexIn',
+		'put_vara_double_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_double_all-4'	=> 'in:reorderOffsetArr',
+	'put_vara_longlong' => '2:3:4',
+		'put_vara_longlong-2'	=> 'in:IntIndexIn',
+		'put_vara_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_longlong-4'	=> 'in:reorderOffsetArr',
+	'put_vara_longlong_all' => '2:3:4',
+		'put_vara_longlong_all-2'	=> 'in:IntIndexIn',
+		'put_vara_longlong_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vara_longlong_all-4'	=> 'in:reorderOffsetArr',
+
+	'put_vars' => '2:3:4:5',
+		'put_vars-2'		=> 'in:IntIndexIn',
+		'put_vars-3'		=> 'in:reorderOffsetArr:true',
+		'put_vars-4'		=> 'in:reorderOffsetArr',
+		'put_vars-5'		=> 'in:reorderOffsetArr',
+	'put_vars_all' => '2:3:4:5',
+		'put_vars_all-2'	=> 'in:IntIndexIn',
+		'put_vars_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_all-4'	=> 'in:reorderOffsetArr',
+		'put_vars_all-5'	=> 'in:reorderOffsetArr',
+	'put_vars_text' => '2:3:4:5:6',
+		'put_vars_text-2'	=> 'in:IntIndexIn',
+		'put_vars_text-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_text-4'	=> 'in:reorderOffsetArr',
+		'put_vars_text-5'	=> 'in:reorderOffsetArr',
+		'put_vars_text-6'	=> 'in:charBufferIn',
+	'put_vars_text_all' => '2:3:4:5:6',
+		'put_vars_text_all-2'	=> 'in:IntIndexIn',
+		'put_vars_text_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_text_all-4'	=> 'in:reorderOffsetArr',
+		'put_vars_text_all-5'	=> 'in:reorderOffsetArr',
+		'put_vars_text_all-6'	=> 'in:charBufferIn',
+	'put_vars_schar' => '2:3:4:5',
+		'put_vars_schar-2'	=> 'in:IntIndexIn',
+		'put_vars_schar-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_schar-4'	=> 'in:reorderOffsetArr',
+		'put_vars_schar-5'	=> 'in:reorderOffsetArr',
+	'put_vars_schar_all' => '2:3:4:5',
+		'put_vars_schar_all-2'	=> 'in:IntIndexIn',
+		'put_vars_schar_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_schar_all-4'	=> 'in:reorderOffsetArr',
+		'put_vars_schar_all-5'	=> 'in:reorderOffsetArr',
+	'put_vars_short' => '2:3:4:5',
+		'put_vars_short-2'	=> 'in:IntIndexIn',
+		'put_vars_short-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_short-4'	=> 'in:reorderOffsetArr',
+		'put_vars_short-5'	=> 'in:reorderOffsetArr',
+	'put_vars_short_all' => '2:3:4:5',
+		'put_vars_short_all-2'	=> 'in:IntIndexIn',
+		'put_vars_short_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_short_all-4'	=> 'in:reorderOffsetArr',
+		'put_vars_short_all-5'	=> 'in:reorderOffsetArr',
+	'put_vars_int' => '2:3:4:5',
+		'put_vars_int-2'	=> 'in:IntIndexIn',
+		'put_vars_int-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_int-4'	=> 'in:reorderOffsetArr',
+		'put_vars_int-5'	=> 'in:reorderOffsetArr',
+	'put_vars_int_all' => '2:3:4:5',
+		'put_vars_int_all-2'	=> 'in:IntIndexIn',
+		'put_vars_int_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_int_all-4'	=> 'in:reorderOffsetArr',
+		'put_vars_int_all-5'	=> 'in:reorderOffsetArr',
+	'put_vars_float' => '2:3:4:5',
+		'put_vars_float-2'	=> 'in:IntIndexIn',
+		'put_vars_float-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_float-4'	=> 'in:reorderOffsetArr',
+		'put_vars_float-5'	=> 'in:reorderOffsetArr',
+	'put_vars_float_all' => '2:3:4:5',
+		'put_vars_float_all-2'	=> 'in:IntIndexIn',
+		'put_vars_float_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_float_all-4'	=> 'in:reorderOffsetArr',
+		'put_vars_float_all-5'	=> 'in:reorderOffsetArr',
+	'put_vars_double' => '2:3:4:5',
+		'put_vars_double-2'	=> 'in:IntIndexIn',
+		'put_vars_double-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_double-4'	=> 'in:reorderOffsetArr',
+		'put_vars_double-5'	=> 'in:reorderOffsetArr',
+	'put_vars_double_all' => '2:3:4:5',
+		'put_vars_double_all-2'	=> 'in:IntIndexIn',
+		'put_vars_double_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_double_all-4'	=> 'in:reorderOffsetArr',
+		'put_vars_double_all-5'	=> 'in:reorderOffsetArr',
+	'put_vars_longlong' => '2:3:4:5',
+		'put_vars_longlong-2'	=> 'in:IntIndexIn',
+		'put_vars_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_longlong-4'	=> 'in:reorderOffsetArr',
+		'put_vars_longlong-5'	=> 'in:reorderOffsetArr',
+	'put_vars_longlong_all' => '2:3:4:5',
+		'put_vars_longlong_all-2'	=> 'in:IntIndexIn',
+		'put_vars_longlong_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_vars_longlong_all-4'	=> 'in:reorderOffsetArr',
+		'put_vars_longlong_all-5'	=> 'in:reorderOffsetArr',
+
+	'put_varm' => '2:3:4:5:6',
+		'put_varm-2'		=> 'in:IntIndexIn',
+		'put_varm-3'		=> 'in:reorderOffsetArr:true',
+		'put_varm-4'		=> 'in:reorderOffsetArr',
+		'put_varm-5'		=> 'in:reorderOffsetArr',
+		'put_varm-6'		=> 'in:reorderOffsetArr',
+	'put_varm_all' => '2:3:4:5:6',
+		'put_varm_all-2'	=> 'in:IntIndexIn',
+		'put_varm_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_all-4'	=> 'in:reorderOffsetArr',
+		'put_varm_all-5'	=> 'in:reorderOffsetArr',
+		'put_varm_all-6'	=> 'in:reorderOffsetArr',
+	'put_varm_text' => '2:3:4:5:6:7',
+		'put_varm_text-2'	=> 'in:IntIndexIn',
+		'put_varm_text-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_text-4'	=> 'in:reorderOffsetArr',
+		'put_varm_text-5'	=> 'in:reorderOffsetArr',
+		'put_varm_text-6'	=> 'in:reorderOffsetArr',
+		'put_varm_text-7'	=> 'in:charBufferIn',
+	'put_varm_text_all' => '2:3:4:5:6:7',
+		'put_varm_text_all-2'	=> 'in:IntIndexIn',
+		'put_varm_text_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_text_all-4'	=> 'in:reorderOffsetArr',
+		'put_varm_text_all-5'	=> 'in:reorderOffsetArr',
+		'put_varm_text_all-6'	=> 'in:reorderOffsetArr',
+		'put_varm_text_all-7'	=> 'in:charBufferIn',
+	'put_varm_schar' => '2:3:4:5:6',
+		'put_varm_schar-2'	=> 'in:IntIndexIn',
+		'put_varm_schar-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_schar-4'	=> 'in:reorderOffsetArr',
+		'put_varm_schar-5'	=> 'in:reorderOffsetArr',
+		'put_varm_schar-6'	=> 'in:reorderOffsetArr',
+	'put_varm_schar_all' => '2:3:4:5:6',
+		'put_varm_schar_all-2'	=> 'in:IntIndexIn',
+		'put_varm_schar_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_schar_all-4'	=> 'in:reorderOffsetArr',
+		'put_varm_schar_all-5'	=> 'in:reorderOffsetArr',
+		'put_varm_schar_all-6'	=> 'in:reorderOffsetArr',
+	'put_varm_short' => '2:3:4:5:6',
+		'put_varm_short-2'	=> 'in:IntIndexIn',
+		'put_varm_short-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_short-4'	=> 'in:reorderOffsetArr',
+		'put_varm_short-5'	=> 'in:reorderOffsetArr',
+		'put_varm_short-6'	=> 'in:reorderOffsetArr',
+	'put_varm_short_all' => '2:3:4:5:6',
+		'put_varm_short_all-2'	=> 'in:IntIndexIn',
+		'put_varm_short_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_short_all-4'	=> 'in:reorderOffsetArr',
+		'put_varm_short_all-5'	=> 'in:reorderOffsetArr',
+		'put_varm_short_all-6'	=> 'in:reorderOffsetArr',
+	'put_varm_int' => '2:3:4:5:6',
+		'put_varm_int-2'	=> 'in:IntIndexIn',
+		'put_varm_int-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_int-4'	=> 'in:reorderOffsetArr',
+		'put_varm_int-5'	=> 'in:reorderOffsetArr',
+		'put_varm_int-6'	=> 'in:reorderOffsetArr',
+	'put_varm_int_all' => '2:3:4:5:6',
+		'put_varm_int_all-2'	=> 'in:IntIndexIn',
+		'put_varm_int_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_int_all-4'	=> 'in:reorderOffsetArr',
+		'put_varm_int_all-5'	=> 'in:reorderOffsetArr',
+		'put_varm_int_all-6'	=> 'in:reorderOffsetArr',
+	'put_varm_float' => '2:3:4:5:6',
+		'put_varm_float-2'	=> 'in:IntIndexIn',
+		'put_varm_float-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_float-4'	=> 'in:reorderOffsetArr',
+		'put_varm_float-5'	=> 'in:reorderOffsetArr',
+		'put_varm_float-6'	=> 'in:reorderOffsetArr',
+	'put_varm_float_all' => '2:3:4:5:6',
+		'put_varm_float_all-2'	=> 'in:IntIndexIn',
+		'put_varm_float_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_float_all-4'	=> 'in:reorderOffsetArr',
+		'put_varm_float_all-5'	=> 'in:reorderOffsetArr',
+		'put_varm_float_all-6'	=> 'in:reorderOffsetArr',
+	'put_varm_double' => '2:3:4:5:6',
+		'put_varm_double-2'	=> 'in:IntIndexIn',
+		'put_varm_double-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_double-4'	=> 'in:reorderOffsetArr',
+		'put_varm_double-5'	=> 'in:reorderOffsetArr',
+		'put_varm_double-6'	=> 'in:reorderOffsetArr',
+	'put_varm_double_all' => '2:3:4:5:6',
+		'put_varm_double_all-2'	=> 'in:IntIndexIn',
+		'put_varm_double_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_double_all-4'	=> 'in:reorderOffsetArr',
+		'put_varm_double_all-5'	=> 'in:reorderOffsetArr',
+		'put_varm_double_all-6'	=> 'in:reorderOffsetArr',
+	'put_varm_longlong' => '2:3:4:5:6',
+		'put_varm_longlong-2'	=> 'in:IntIndexIn',
+		'put_varm_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_longlong-4'	=> 'in:reorderOffsetArr',
+		'put_varm_longlong-5'	=> 'in:reorderOffsetArr',
+		'put_varm_longlong-6'	=> 'in:reorderOffsetArr',
+	'put_varm_longlong_all' => '2:3:4:5:6',
+		'put_varm_longlong_all-2'	=> 'in:IntIndexIn',
+		'put_varm_longlong_all-3'	=> 'in:reorderOffsetArr:true',
+		'put_varm_longlong_all-4'	=> 'in:reorderOffsetArr',
+		'put_varm_longlong_all-5'	=> 'in:reorderOffsetArr',
+		'put_varm_longlong_all-6'	=> 'in:reorderOffsetArr',
+
+	'get_varn' => '2:4:5',
+		'get_varn-2'		=> 'in:IntIndexIn',
+		'get_varn-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'get_varn_text' => '2:4:5:6',
+		'get_varn_text-2'	=> 'in:IntIndexIn',
+		'get_varn_text-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_text-5'	=> 'in:reorderOffsetArr1DTo2D',
+		'get_varn_text-6'	=> 'out:charBufferOut',
+	'get_varn_schar' => '2:4:5',
+		'get_varn_schar-2'	=> 'in:IntIndexIn',
+		'get_varn_schar-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_schar-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'get_varn_short' => '2:4:5',
+		'get_varn_short-2'	=> 'in:IntIndexIn',
+		'get_varn_short-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_short-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'get_varn_int' => '2:4:5',
+		'get_varn_int-2'	=> 'in:IntIndexIn',
+		'get_varn_int-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_int-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'get_varn_float' => '2:4:5',
+		'get_varn_float-2'	=> 'in:IntIndexIn',
+		'get_varn_float-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_float-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'get_varn_double' => '2:4:5',
+		'get_varn_double-2'	=> 'in:IntIndexIn',
+		'get_varn_double-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_double-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'get_varn_longlong' => '2:4:5',
+		'get_varn_longlong-2'	=> 'in:IntIndexIn',
+		'get_varn_longlong-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_longlong-5'	=> 'in:reorderOffsetArr1DTo2D',
+
+	'get_varn_all' => '2:4:5',
+		'get_varn_all-2'		=> 'in:IntIndexIn',
+		'get_varn_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'get_varn_text_all' => '2:4:5:6',
+		'get_varn_text_all-2'		=> 'in:IntIndexIn',
+		'get_varn_text_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_text_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+		'get_varn_text_all-6'		=> 'out:charBufferOut',
+	'get_varn_schar_all' => '2:4:5',
+		'get_varn_schar_all-2'		=> 'in:IntIndexIn',
+		'get_varn_schar_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_schar_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'get_varn_short_all' => '2:4:5',
+		'get_varn_short_all-2'		=> 'in:IntIndexIn',
+		'get_varn_short_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_short_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'get_varn_int_all' => '2:4:5',
+		'get_varn_int_all-2'		=> 'in:IntIndexIn',
+		'get_varn_int_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_int_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'get_varn_float_all' => '2:4:5',
+		'get_varn_float_all-2'		=> 'in:IntIndexIn',
+		'get_varn_float_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_float_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'get_varn_double_all' => '2:4:5',
+		'get_varn_double_all-2'		=> 'in:IntIndexIn',
+		'get_varn_double_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_double_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'get_varn_longlong_all' => '2:4:5',
+		'get_varn_longlong_all-2'	=> 'in:IntIndexIn',
+		'get_varn_longlong_all-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'get_varn_longlong_all-5'	=> 'in:reorderOffsetArr1DTo2D',
+
+	'put_varn' => '2:4:5',
+		'put_varn-2'		=> 'in:IntIndexIn',
+		'put_varn-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'put_varn_text' => '2:4:5:6',
+		'put_varn_text-2'	=> 'in:IntIndexIn',
+		'put_varn_text-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_text-5'	=> 'in:reorderOffsetArr1DTo2D',
+		'put_varn_text-6'	=> 'in:charBufferIn',
+	'put_varn_schar' => '2:4:5',
+		'put_varn_schar-2'	=> 'in:IntIndexIn',
+		'put_varn_schar-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_schar-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'put_varn_short' => '2:4:5',
+		'put_varn_short-2'	=> 'in:IntIndexIn',
+		'put_varn_short-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_short-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'put_varn_int' => '2:4:5',
+		'put_varn_int-2'	=> 'in:IntIndexIn',
+		'put_varn_int-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_int-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'put_varn_float' => '2:4:5',
+		'put_varn_float-2'	=> 'in:IntIndexIn',
+		'put_varn_float-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_float-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'put_varn_double' => '2:4:5',
+		'put_varn_double-2'	=> 'in:IntIndexIn',
+		'put_varn_double-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_double-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'put_varn_longlong' => '2:4:5',
+		'put_varn_longlong-2'	=> 'in:IntIndexIn',
+		'put_varn_longlong-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_longlong-5'	=> 'in:reorderOffsetArr1DTo2D',
+
+	'put_varn_all' => '2:4:5',
+		'put_varn_all-2'		=> 'in:IntIndexIn',
+		'put_varn_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'put_varn_text_all' => '2:4:5:6',
+		'put_varn_text_all-2'		=> 'in:IntIndexIn',
+		'put_varn_text_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_text_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+		'put_varn_text_all-6'		=> 'in:charBufferIn',
+	'put_varn_schar_all' => '2:4:5',
+		'put_varn_schar_all-2'		=> 'in:IntIndexIn',
+		'put_varn_schar_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_schar_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'put_varn_short_all' => '2:4:5',
+		'put_varn_short_all-2'		=> 'in:IntIndexIn',
+		'put_varn_short_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_short_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'put_varn_int_all' => '2:4:5',
+		'put_varn_int_all-2'		=> 'in:IntIndexIn',
+		'put_varn_int_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_int_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'put_varn_float_all' => '2:4:5',
+		'put_varn_float_all-2'		=> 'in:IntIndexIn',
+		'put_varn_float_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_float_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'put_varn_double_all' => '2:4:5',
+		'put_varn_double_all-2'		=> 'in:IntIndexIn',
+		'put_varn_double_all-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_double_all-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'put_varn_longlong_all' => '2:4:5',
+		'put_varn_longlong_all-2'	=> 'in:IntIndexIn',
+		'put_varn_longlong_all-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'put_varn_longlong_all-5'	=> 'in:reorderOffsetArr1DTo2D',
+
+	'get_vard' => '2',
+		'get_vard-2'		=> 'in:IntIndexIn',
+	'put_vard' => '2',
+		'put_vard-2'		=> 'in:IntIndexIn',
+	'get_vard_all' => '2',
+		'get_vard_all-2'	=> 'in:IntIndexIn',
+	'put_vard_all' => '2',
+		'put_vard_all-2'	=> 'in:IntIndexIn',
+
+	'iget_var1' => '2:3',
+		'iget_var1-2'		=> 'in:IntIndexIn',
+		'iget_var1-3'		=> 'in:reorderOffsetArr:true',
+	'iget_var1_text' => '2:3:4',
+		'iget_var1_text-2'	=> 'in:IntIndexIn',
+		'iget_var1_text-3'	=> 'in:reorderOffsetArr:true',
+		'iget_var1_text-4'	=> 'out:charBufferOut',
+	'iget_var1_schar' => '2:3',
+		'iget_var1_schar-2'	=> 'in:IntIndexIn',
+		'iget_var1_schar-3'	=> 'in:reorderOffsetArr:true',
+	'iget_var1_short' => '2:3',
+		'iget_var1_short-2'	=> 'in:IntIndexIn',
+		'iget_var1_short-3'	=> 'in:reorderOffsetArr:true',
+	'iget_var1_int' => '2:3',
+		'iget_var1_int-2'	=> 'in:IntIndexIn',
+		'iget_var1_int-3'	=> 'in:reorderOffsetArr:true',
+	'iget_var1_float' => '2:3',
+		'iget_var1_float-2'	=> 'in:IntIndexIn',
+		'iget_var1_float-3'	=> 'in:reorderOffsetArr:true',
+	'iget_var1_double' => '2:3',
+		'iget_var1_double-2'	=> 'in:IntIndexIn',
+		'iget_var1_double-3'	=> 'in:reorderOffsetArr:true',
+	'iget_var1_longlong' => '2:3',
+		'iget_var1_longlong-2'	=> 'in:IntIndexIn',
+		'iget_var1_longlong-3'	=> 'in:reorderOffsetArr:true',
+
+	'iget_var' => '2',
+		'iget_var-2'		=> 'in:IntIndexIn',
+	'iget_var_text' => '2:3',
+		'iget_var_text-2'	=> 'in:IntIndexIn',
+		'iget_var_text-3'	=> 'out:charBufferOut',
+	'iget_var_schar' => '2',
+		'iget_var_schar-2'	=> 'in:IntIndexIn',
+	'iget_var_short' => '2',
+		'iget_var_short-2'	=> 'in:IntIndexIn',
+	'iget_var_float' => '2',
+		'iget_var_float-2'	=> 'in:IntIndexIn',
+	'iget_var_double' => '2',
+		'iget_var_double-2'	=> 'in:IntIndexIn',
+	'iget_var_longlong' => '2',
+		'iget_var_longlong-2'	=> 'in:IntIndexIn',
+	'iget_var_int' => '2',
+		'iget_var_int-2'	=> 'in:IntIndexIn',
+
+	'iget_vara' => '2:3:4',
+		'iget_vara-2'		=> 'in:IntIndexIn',
+		'iget_vara-3'		=> 'in:reorderOffsetArr:true',
+		'iget_vara-4'		=> 'in:reorderOffsetArr',
+	'iget_vara_text' => '2:3:4:5',
+		'iget_vara_text-2'	=> 'in:IntIndexIn',
+		'iget_vara_text-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vara_text-4'	=> 'in:reorderOffsetArr',
+		'iget_vara_text-5'	=> 'out:charBufferOut',
+	'iget_vara_schar' => '2:3:4',
+		'iget_vara_schar-2'	=> 'in:IntIndexIn',
+		'iget_vara_schar-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vara_schar-4'	=> 'in:reorderOffsetArr',
+	'iget_vara_short' => '2:3:4',
+		'iget_vara_short-2'	=> 'in:IntIndexIn',
+		'iget_vara_short-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vara_short-4'	=> 'in:reorderOffsetArr',
+	'iget_vara_int' => '2:3:4',
+		'iget_vara_int-2'	=> 'in:IntIndexIn',
+		'iget_vara_int-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vara_int-4'	=> 'in:reorderOffsetArr',
+	'iget_vara_float' => '2:3:4',
+		'iget_vara_float-2'	=> 'in:IntIndexIn',
+		'iget_vara_float-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vara_float-4'	=> 'in:reorderOffsetArr',
+	'iget_vara_double' => '2:3:4',
+		'iget_vara_double-2'	=> 'in:IntIndexIn',
+		'iget_vara_double-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vara_double-4'	=> 'in:reorderOffsetArr',
+	'iget_vara_longlong' => '2:3:4',
+		'iget_vara_longlong-2'	=> 'in:IntIndexIn',
+		'iget_vara_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vara_longlong-4'	=> 'in:reorderOffsetArr',
+
+	'iget_vars' => '2:3:4:5',
+		'iget_vars-2'		=> 'in:IntIndexIn',
+		'iget_vars-3'		=> 'in:reorderOffsetArr:true',
+		'iget_vars-4'		=> 'in:reorderOffsetArr',
+		'iget_vars-5'		=> 'in:reorderOffsetArr',
+	'iget_vars_text' => '2:3:4:5:6',
+		'iget_vars_text-2'	=> 'in:IntIndexIn',
+		'iget_vars_text-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vars_text-4'	=> 'in:reorderOffsetArr',
+		'iget_vars_text-5'	=> 'in:reorderOffsetArr',
+		'iget_vars_text-6'	=> 'out:charBufferOut',
+	'iget_vars_schar' => '2:3:4:5',
+		'iget_vars_schar-2'	=> 'in:IntIndexIn',
+		'iget_vars_schar-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vars_schar-4'	=> 'in:reorderOffsetArr',
+		'iget_vars_schar-5'	=> 'in:reorderOffsetArr',
+	'iget_vars_short' => '2:3:4:5',
+		'iget_vars_short-2'	=> 'in:IntIndexIn',
+		'iget_vars_short-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vars_short-4'	=> 'in:reorderOffsetArr',
+		'iget_vars_short-5'	=> 'in:reorderOffsetArr',
+	'iget_vars_int' => '2:3:4:5',
+		'iget_vars_int-2'	=> 'in:IntIndexIn',
+		'iget_vars_int-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vars_int-4'	=> 'in:reorderOffsetArr',
+		'iget_vars_int-5'	=> 'in:reorderOffsetArr',
+	'iget_vars_float' => '2:3:4:5',
+		'iget_vars_float-2'	=> 'in:IntIndexIn',
+		'iget_vars_float-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vars_float-4'	=> 'in:reorderOffsetArr',
+		'iget_vars_float-5'	=> 'in:reorderOffsetArr',
+	'iget_vars_double' => '2:3:4:5',
+		'iget_vars_double-2'	=> 'in:IntIndexIn',
+		'iget_vars_double-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vars_double-4'	=> 'in:reorderOffsetArr',
+		'iget_vars_double-5'	=> 'in:reorderOffsetArr',
+	'iget_vars_longlong' => '2:3:4:5',
+		'iget_vars_longlong-2'	=> 'in:IntIndexIn',
+		'iget_vars_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'iget_vars_longlong-4'	=> 'in:reorderOffsetArr',
+		'iget_vars_longlong-5'	=> 'in:reorderOffsetArr',
+
+	'iget_varm' => '2:3:4:5:6',
+		'iget_varm-2'		=> 'in:IntIndexIn',
+		'iget_varm-3'		=> 'in:reorderOffsetArr:true',
+		'iget_varm-4'		=> 'in:reorderOffsetArr',
+		'iget_varm-5'		=> 'in:reorderOffsetArr',
+		'iget_varm-6'		=> 'in:reorderOffsetArr',
+	'iget_varm_text' => '2:3:4:5:6:7',
+		'iget_varm_text-2'	=> 'in:IntIndexIn',
+		'iget_varm_text-3'	=> 'in:reorderOffsetArr:true',
+		'iget_varm_text-4'	=> 'in:reorderOffsetArr',
+		'iget_varm_text-5'	=> 'in:reorderOffsetArr',
+		'iget_varm_text-6'	=> 'in:reorderOffsetArr',
+		'iget_varm_text-7'	=> 'out:charBufferOut',
+	'iget_varm_schar' => '2:3:4:5:6',
+		'iget_varm_schar-2'	=> 'in:IntIndexIn',
+		'iget_varm_schar-3'	=> 'in:reorderOffsetArr:true',
+		'iget_varm_schar-4'	=> 'in:reorderOffsetArr',
+		'iget_varm_schar-5'	=> 'in:reorderOffsetArr',
+		'iget_varm_schar-6'	=> 'in:reorderOffsetArr',
+	'iget_varm_short' => '2:3:4:5:6',
+		'iget_varm_short-2'	=> 'in:IntIndexIn',
+		'iget_varm_short-3'	=> 'in:reorderOffsetArr:true',
+		'iget_varm_short-4'	=> 'in:reorderOffsetArr',
+		'iget_varm_short-5'	=> 'in:reorderOffsetArr',
+		'iget_varm_short-6'	=> 'in:reorderOffsetArr',
+	'iget_varm_int' => '2:3:4:5:6',
+		'iget_varm_int-2'	=> 'in:IntIndexIn',
+		'iget_varm_int-3'	=> 'in:reorderOffsetArr:true',
+		'iget_varm_int-4'	=> 'in:reorderOffsetArr',
+		'iget_varm_int-5'	=> 'in:reorderOffsetArr',
+		'iget_varm_int-6'	=> 'in:reorderOffsetArr',
+	'iget_varm_float' => '2:3:4:5:6',
+		'iget_varm_float-2'	=> 'in:IntIndexIn',
+		'iget_varm_float-3'	=> 'in:reorderOffsetArr:true',
+		'iget_varm_float-4'	=> 'in:reorderOffsetArr',
+		'iget_varm_float-5'	=> 'in:reorderOffsetArr',
+		'iget_varm_float-6'	=> 'in:reorderOffsetArr',
+	'iget_varm_double' => '2:3:4:5:6',
+		'iget_varm_double-2'	=> 'in:IntIndexIn',
+		'iget_varm_double-3'	=> 'in:reorderOffsetArr:true',
+		'iget_varm_double-4'	=> 'in:reorderOffsetArr',
+		'iget_varm_double-5'	=> 'in:reorderOffsetArr',
+		'iget_varm_double-6'	=> 'in:reorderOffsetArr',
+	'iget_varm_longlong' => '2:3:4:5:6',
+		'iget_varm_longlong-2'	=> 'in:IntIndexIn',
+		'iget_varm_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'iget_varm_longlong-4'	=> 'in:reorderOffsetArr',
+		'iget_varm_longlong-5'	=> 'in:reorderOffsetArr',
+		'iget_varm_longlong-6'	=> 'in:reorderOffsetArr',
+
+	'iput_var1' => '2:3',
+		'iput_var1-2'		=> 'in:IntIndexIn',
+		'iput_var1-3'		=> 'in:reorderOffsetArr:true',
+	'iput_var1_text' => '2:3:4',
+		'iput_var1_text-2'	=> 'in:IntIndexIn',
+		'iput_var1_text-3'	=> 'in:reorderOffsetArr:true',
+		'iput_var1_text-4'	=> 'in:charBufferIn',
+	'iput_var1_schar' => '2:3',
+		'iput_var1_schar-2'	=> 'in:IntIndexIn',
+		'iput_var1_schar-3'	=> 'in:reorderOffsetArr:true',
+	'iput_var1_short' => '2:3',
+		'iput_var1_short-2'	=> 'in:IntIndexIn',
+		'iput_var1_short-3'	=> 'in:reorderOffsetArr:true',
+	'iput_var1_int' => '2:3',
+		'iput_var1_int-2'	=> 'in:IntIndexIn',
+		'iput_var1_int-3'	=> 'in:reorderOffsetArr:true',
+	'iput_var1_float' => '2:3',
+		'iput_var1_float-2'	=> 'in:IntIndexIn',
+		'iput_var1_float-3'	=> 'in:reorderOffsetArr:true',
+	'iput_var1_double' => '2:3',
+		'iput_var1_double-2'	=> 'in:IntIndexIn',
+		'iput_var1_double-3'	=> 'in:reorderOffsetArr:true',
+	'iput_var1_longlong' => '2:3',
+		'iput_var1_longlong-2'	=> 'in:IntIndexIn',
+		'iput_var1_longlong-3'	=> 'in:reorderOffsetArr:true',
+
+	'iput_var' => '2',
+		'iput_var-2'		=> 'in:IntIndexIn',
+	'iput_var_text' => '2:3',
+		'iput_var_text-2'	=> 'in:IntIndexIn',
+		'iput_var_text-3'	=> 'in:charBufferIn',
+	'iput_var_schar' => '2',
+		'iput_var_schar-2'	=> 'in:IntIndexIn',
+	'iput_var_short' => '2',
+		'iput_var_short-2'	=> 'in:IntIndexIn',
+	'iput_var_int' => '2',
+		'iput_var_int-2'	=> 'in:IntIndexIn',
+	'iput_var_float' => '2',
+		'iput_var_float-2'	=> 'in:IntIndexIn',
+	'iput_var_double' => '2',
+		'iput_var_double-2'	=> 'in:IntIndexIn',
+	'iput_var_longlong' => '2',
+		'iput_var_longlong-2'	=> 'in:IntIndexIn',
+
+	'iput_vara' => '2:3:4',
+		'iput_vara-2'		=> 'in:IntIndexIn',
+		'iput_vara-3'		=> 'in:reorderOffsetArr:true',
+		'iput_vara-4'		=> 'in:reorderOffsetArr',
+	'iput_vara_text' => '2:3:4:5',
+		'iput_vara_text-2'	=> 'in:IntIndexIn',
+		'iput_vara_text-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vara_text-4'	=> 'in:reorderOffsetArr',
+		'iput_vara_text-5'	=> 'in:charBufferIn',
+	'iput_vara_schar' => '2:3:4',
+		'iput_vara_schar-2'	=> 'in:IntIndexIn',
+		'iput_vara_schar-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vara_schar-4'	=> 'in:reorderOffsetArr',
+	'iput_vara_short' => '2:3:4',
+		'iput_vara_short-2'	=> 'in:IntIndexIn',
+		'iput_vara_short-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vara_short-4'	=> 'in:reorderOffsetArr',
+	'iput_vara_int' => '2:3:4',
+		'iput_vara_int-2'	=> 'in:IntIndexIn',
+		'iput_vara_int-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vara_int-4'	=> 'in:reorderOffsetArr',
+	'iput_vara_float' => '2:3:4',
+		'iput_vara_float-2'	=> 'in:IntIndexIn',
+		'iput_vara_float-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vara_float-4'	=> 'in:reorderOffsetArr',
+	'iput_vara_double' => '2:3:4',
+		'iput_vara_double-2'	=> 'in:IntIndexIn',
+		'iput_vara_double-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vara_double-4'	=> 'in:reorderOffsetArr',
+	'iput_vara_longlong' => '2:3:4',
+		'iput_vara_longlong-2'	=> 'in:IntIndexIn',
+		'iput_vara_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vara_longlong-4'	=> 'in:reorderOffsetArr',
+
+	'iput_vars' => '2:3:4:5',
+		'iput_vars-2'		=> 'in:IntIndexIn',
+		'iput_vars-3'		=> 'in:reorderOffsetArr:true',
+		'iput_vars-4'		=> 'in:reorderOffsetArr',
+		'iput_vars-5'		=> 'in:reorderOffsetArr',
+	'iput_vars_text' => '2:3:4:5:6',
+		'iput_vars_text-2'	=> 'in:IntIndexIn',
+		'iput_vars_text-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vars_text-4'	=> 'in:reorderOffsetArr',
+		'iput_vars_text-5'	=> 'in:reorderOffsetArr',
+		'iput_vars_text-6'	=> 'in:charBufferIn',
+	'iput_vars_schar' => '2:3:4:5',
+		'iput_vars_schar-2'	=> 'in:IntIndexIn',
+		'iput_vars_schar-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vars_schar-4'	=> 'in:reorderOffsetArr',
+		'iput_vars_schar-5'	=> 'in:reorderOffsetArr',
+	'iput_vars_short' => '2:3:4:5',
+		'iput_vars_short-2'	=> 'in:IntIndexIn',
+		'iput_vars_short-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vars_short-4'	=> 'in:reorderOffsetArr',
+		'iput_vars_short-5'	=> 'in:reorderOffsetArr',
+	'iput_vars_int' => '2:3:4:5',
+		'iput_vars_int-2'	=> 'in:IntIndexIn',
+		'iput_vars_int-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vars_int-4'	=> 'in:reorderOffsetArr',
+		'iput_vars_int-5'	=> 'in:reorderOffsetArr',
+	'iput_vars_float' => '2:3:4:5',
+		'iput_vars_float-2'	=> 'in:IntIndexIn',
+		'iput_vars_float-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vars_float-4'	=> 'in:reorderOffsetArr',
+		'iput_vars_float-5'	=> 'in:reorderOffsetArr',
+	'iput_vars_double' => '2:3:4:5',
+		'iput_vars_double-2'	=> 'in:IntIndexIn',
+		'iput_vars_double-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vars_double-4'	=> 'in:reorderOffsetArr',
+		'iput_vars_double-5'	=> 'in:reorderOffsetArr',
+	'iput_vars_longlong' => '2:3:4:5',
+		'iput_vars_longlong-2'	=> 'in:IntIndexIn',
+		'iput_vars_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'iput_vars_longlong-4'	=> 'in:reorderOffsetArr',
+		'iput_vars_longlong-5'	=> 'in:reorderOffsetArr',
+
+	'iput_varm' => '2:3:4:5:6',
+		'iput_varm-2'		=> 'in:IntIndexIn',
+		'iput_varm-3'		=> 'in:reorderOffsetArr:true',
+		'iput_varm-4'		=> 'in:reorderOffsetArr',
+		'iput_varm-5'		=> 'in:reorderOffsetArr',
+		'iput_varm-6'		=> 'in:reorderOffsetArr',
+	'iput_varm_text' => '2:3:4:5:6:7',
+		'iput_varm_text-2'	=> 'in:IntIndexIn',
+		'iput_varm_text-3'	=> 'in:reorderOffsetArr:true',
+		'iput_varm_text-4'	=> 'in:reorderOffsetArr',
+		'iput_varm_text-5'	=> 'in:reorderOffsetArr',
+		'iput_varm_text-6'	=> 'in:reorderOffsetArr',
+		'iput_varm_text-7'	=> 'in:charBufferIn',
+	'iput_varm_schar' => '2:3:4:5:6',
+		'iput_varm_schar-2'	=> 'in:IntIndexIn',
+		'iput_varm_schar-3'	=> 'in:reorderOffsetArr:true',
+		'iput_varm_schar-4'	=> 'in:reorderOffsetArr',
+		'iput_varm_schar-5'	=> 'in:reorderOffsetArr',
+		'iput_varm_schar-6'	=> 'in:reorderOffsetArr',
+	'iput_varm_short' => '2:3:4:5:6',
+		'iput_varm_short-2'	=> 'in:IntIndexIn',
+		'iput_varm_short-3'	=> 'in:reorderOffsetArr:true',
+		'iput_varm_short-4'	=> 'in:reorderOffsetArr',
+		'iput_varm_short-5'	=> 'in:reorderOffsetArr',
+		'iput_varm_short-6'	=> 'in:reorderOffsetArr',
+	'iput_varm_int' => '2:3:4:5:6',
+		'iput_varm_int-2'	=> 'in:IntIndexIn',
+		'iput_varm_int-3'	=> 'in:reorderOffsetArr:true',
+		'iput_varm_int-4'	=> 'in:reorderOffsetArr',
+		'iput_varm_int-5'	=> 'in:reorderOffsetArr',
+		'iput_varm_int-6'	=> 'in:reorderOffsetArr',
+	'iput_varm_float' => '2:3:4:5:6',
+		'iput_varm_float-2'	=> 'in:IntIndexIn',
+		'iput_varm_float-3'	=> 'in:reorderOffsetArr:true',
+		'iput_varm_float-4'	=> 'in:reorderOffsetArr',
+		'iput_varm_float-5'	=> 'in:reorderOffsetArr',
+		'iput_varm_float-6'	=> 'in:reorderOffsetArr',
+	'iput_varm_double' => '2:3:4:5:6',
+		'iput_varm_double-2'	=> 'in:IntIndexIn',
+		'iput_varm_double-3'	=> 'in:reorderOffsetArr:true',
+		'iput_varm_double-4'	=> 'in:reorderOffsetArr',
+		'iput_varm_double-5'	=> 'in:reorderOffsetArr',
+		'iput_varm_double-6'	=> 'in:reorderOffsetArr',
+	'iput_varm_longlong' => '2:3:4:5:6',
+		'iput_varm_longlong-2'	=> 'in:IntIndexIn',
+		'iput_varm_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'iput_varm_longlong-4'	=> 'in:reorderOffsetArr',
+		'iput_varm_longlong-5'	=> 'in:reorderOffsetArr',
+		'iput_varm_longlong-6'	=> 'in:reorderOffsetArr',
+
+	'iget_varn' => '2:4:5',
+		'iget_varn-2'		=> 'in:IntIndexIn',
+		'iget_varn-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'iget_varn-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'iget_varn_text' => '2:4:5:6',
+		'iget_varn_text-2'	=> 'in:IntIndexIn',
+		'iget_varn_text-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iget_varn_text-5'	=> 'in:reorderOffsetArr1DTo2D',
+		'iget_varn_text-6'	=> 'out:charBufferOut',
+	'iget_varn_schar' => '2:4:5',
+		'iget_varn_schar-2'	=> 'in:IntIndexIn',
+		'iget_varn_schar-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iget_varn_schar-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'iget_varn_short' => '2:4:5',
+		'iget_varn_short-2'	=> 'in:IntIndexIn',
+		'iget_varn_short-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iget_varn_short-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'iget_varn_int' => '2:4:5',
+		'iget_varn_int-2'	=> 'in:IntIndexIn',
+		'iget_varn_int-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iget_varn_int-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'iget_varn_float' => '2:4:5',
+		'iget_varn_float-2'	=> 'in:IntIndexIn',
+		'iget_varn_float-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iget_varn_float-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'iget_varn_double' => '2:4:5',
+		'iget_varn_double-2'	=> 'in:IntIndexIn',
+		'iget_varn_double-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iget_varn_double-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'iget_varn_longlong' => '2:4:5',
+		'iget_varn_longlong-2'	=> 'in:IntIndexIn',
+		'iget_varn_longlong-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iget_varn_longlong-5'	=> 'in:reorderOffsetArr1DTo2D',
+
+	'iput_varn' => '2:4:5',
+		'iput_varn-2'		=> 'in:IntIndexIn',
+		'iput_varn-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'iput_varn-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'iput_varn_text' => '2:4:5:6',
+		'iput_varn_text-2'	=> 'in:IntIndexIn',
+		'iput_varn_text-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iput_varn_text-5'	=> 'in:reorderOffsetArr1DTo2D',
+		'iput_varn_text-6'	=> 'in:charBufferIn',
+	'iput_varn_schar' => '2:4:5',
+		'iput_varn_schar-2'	=> 'in:IntIndexIn',
+		'iput_varn_schar-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iput_varn_schar-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'iput_varn_short' => '2:4:5',
+		'iput_varn_short-2'	=> 'in:IntIndexIn',
+		'iput_varn_short-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iput_varn_short-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'iput_varn_int' => '2:4:5',
+		'iput_varn_int-2'	=> 'in:IntIndexIn',
+		'iput_varn_int-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iput_varn_int-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'iput_varn_float' => '2:4:5',
+		'iput_varn_float-2'	=> 'in:IntIndexIn',
+		'iput_varn_float-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iput_varn_float-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'iput_varn_double' => '2:4:5',
+		'iput_varn_double-2'	=> 'in:IntIndexIn',
+		'iput_varn_double-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iput_varn_double-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'iput_varn_longlong' => '2:4:5',
+		'iput_varn_longlong-2'	=> 'in:IntIndexIn',
+		'iput_varn_longlong-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'iput_varn_longlong-5'	=> 'in:reorderOffsetArr1DTo2D',
+
+	'bput_varn' => '2:4:5',
+		'bput_varn-2'		=> 'in:IntIndexIn',
+		'bput_varn-4'		=> 'in:reorderOffsetArr1DTo2D:true',
+		'bput_varn-5'		=> 'in:reorderOffsetArr1DTo2D',
+	'bput_varn_text' => '2:4:5:6',
+		'bput_varn_text-2'	=> 'in:IntIndexIn',
+		'bput_varn_text-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'bput_varn_text-5'	=> 'in:reorderOffsetArr1DTo2D',
+		'bput_varn_text-6'	=> 'in:charBufferIn',
+	'bput_varn_schar' => '2:4:5',
+		'bput_varn_schar-2'	=> 'in:IntIndexIn',
+		'bput_varn_schar-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'bput_varn_schar-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'bput_varn_short' => '2:4:5',
+		'bput_varn_short-2'	=> 'in:IntIndexIn',
+		'bput_varn_short-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'bput_varn_short-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'bput_varn_int' => '2:4:5',
+		'bput_varn_int-2'	=> 'in:IntIndexIn',
+		'bput_varn_int-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'bput_varn_int-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'bput_varn_float' => '2:4:5',
+		'bput_varn_float-2'	=> 'in:IntIndexIn',
+		'bput_varn_float-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'bput_varn_float-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'bput_varn_double' => '2:4:5',
+		'bput_varn_double-2'	=> 'in:IntIndexIn',
+		'bput_varn_double-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'bput_varn_double-5'	=> 'in:reorderOffsetArr1DTo2D',
+	'bput_varn_longlong' => '2:4:5',
+		'bput_varn_longlong-2'	=> 'in:IntIndexIn',
+		'bput_varn_longlong-4'	=> 'in:reorderOffsetArr1DTo2D:true',
+		'bput_varn_longlong-5'	=> 'in:reorderOffsetArr1DTo2D',
+
+	'bput_var1' => '2:3',
+		'bput_var1-2'		=> 'in:IntIndexIn',
+		'bput_var1-3'		=> 'in:reorderOffsetArr:true',
+	'bput_var1_text' => '2:3:4',
+		'bput_var1_text-2'	=> 'in:IntIndexIn',
+		'bput_var1_text-3'	=> 'in:reorderOffsetArr:true',
+		'bput_var1_text-4'	=> 'in:charBufferIn',
+	'bput_var1_schar' => '2:3',
+		'bput_var1_schar-2'	=> 'in:IntIndexIn',
+		'bput_var1_schar-3'	=> 'in:reorderOffsetArr:true',
+	'bput_var1_short' => '2:3',
+		'bput_var1_short-2'	=> 'in:IntIndexIn',
+		'bput_var1_short-3'	=> 'in:reorderOffsetArr:true',
+	'bput_var1_int' => '2:3',
+		'bput_var1_int-2'	=> 'in:IntIndexIn',
+		'bput_var1_int-3'	=> 'in:reorderOffsetArr:true',
+	'bput_var1_float' => '2:3',
+		'bput_var1_float-2'	=> 'in:IntIndexIn',
+		'bput_var1_float-3'	=> 'in:reorderOffsetArr:true',
+	'bput_var1_double' => '2:3',
+		'bput_var1_double-2'	=> 'in:IntIndexIn',
+		'bput_var1_double-3'	=> 'in:reorderOffsetArr:true',
+	'bput_var1_longlong' => '2:3',
+		'bput_var1_longlong-2'	=> 'in:IntIndexIn',
+		'bput_var1_longlong-3'	=> 'in:reorderOffsetArr:true',
+
+	'bput_var' => '2',
+		'bput_var-2'		=> 'in:IntIndexIn',
+	'bput_var_text' => '2:3',
+		'bput_var_text-2'	=> 'in:IntIndexIn',
+		'bput_var_text-3'	=> 'in:charBufferIn',
+	'bput_var_schar' => '2',
+		'bput_var_schar-2'	=> 'in:IntIndexIn',
+	'bput_var_short' => '2',
+		'bput_var_short-2'	=> 'in:IntIndexIn',
+	'bput_var_int' => '2',
+		'bput_var_int-2'	=> 'in:IntIndexIn',
+	'bput_var_float' => '2',
+		'bput_var_float-2'	=> 'in:IntIndexIn',
+	'bput_var_double' => '2',
+		'bput_var_double-2'	=> 'in:IntIndexIn',
+	'bput_var_longlong' => '2',
+		'bput_var_longlong-2'	=> 'in:IntIndexIn',
+
+	'bput_vara' => '2:3:4',
+		'bput_vara-2'		=> 'in:IntIndexIn',
+		'bput_vara-3'		=> 'in:reorderOffsetArr:true',
+		'bput_vara-4'		=> 'in:reorderOffsetArr',
+	'bput_vara_text' => '2:3:4:5',
+		'bput_vara_text-2'	=> 'in:IntIndexIn',
+		'bput_vara_text-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vara_text-4'	=> 'in:reorderOffsetArr',
+		'bput_vara_text-5'	=> 'in:charBufferIn',
+	'bput_vara_schar' => '2:3:4',
+		'bput_vara_schar-2'	=> 'in:IntIndexIn',
+		'bput_vara_schar-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vara_schar-4'	=> 'in:reorderOffsetArr',
+	'bput_vara_short' => '2:3:4',
+		'bput_vara_short-2'	=> 'in:IntIndexIn',
+		'bput_vara_short-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vara_short-4'	=> 'in:reorderOffsetArr',
+	'bput_vara_int' => '2:3:4',
+		'bput_vara_int-2'	=> 'in:IntIndexIn',
+		'bput_vara_int-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vara_int-4'	=> 'in:reorderOffsetArr',
+	'bput_vara_float' => '2:3:4',
+		'bput_vara_float-2'	=> 'in:IntIndexIn',
+		'bput_vara_float-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vara_float-4'	=> 'in:reorderOffsetArr',
+	'bput_vara_double' => '2:3:4',
+		'bput_vara_double-2'	=> 'in:IntIndexIn',
+		'bput_vara_double-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vara_double-4'	=> 'in:reorderOffsetArr',
+	'bput_vara_longlong' => '2:3:4',
+		'bput_vara_longlong-2'	=> 'in:IntIndexIn',
+		'bput_vara_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vara_longlong-4'	=> 'in:reorderOffsetArr',
+
+	'bput_vars' => '2:3:4:5',
+		'bput_vars-2'		=> 'in:IntIndexIn',
+		'bput_vars-3'		=> 'in:reorderOffsetArr:true',
+		'bput_vars-4'		=> 'in:reorderOffsetArr',
+		'bput_vars-5'		=> 'in:reorderOffsetArr',
+	'bput_vars_text' => '2:3:4:5:6',
+		'bput_vars_text-2'	=> 'in:IntIndexIn',
+		'bput_vars_text-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vars_text-4'	=> 'in:reorderOffsetArr',
+		'bput_vars_text-5'	=> 'in:reorderOffsetArr',
+		'bput_vars_text-6'	=> 'in:charBufferIn',
+	'bput_vars_schar' => '2:3:4:5',
+		'bput_vars_schar-2'	=> 'in:IntIndexIn',
+		'bput_vars_schar-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vars_schar-4'	=> 'in:reorderOffsetArr',
+		'bput_vars_schar-5'	=> 'in:reorderOffsetArr',
+	'bput_vars_short' => '2:3:4:5',
+		'bput_vars_short-2'	=> 'in:IntIndexIn',
+		'bput_vars_short-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vars_short-4'	=> 'in:reorderOffsetArr',
+		'bput_vars_short-5'	=> 'in:reorderOffsetArr',
+	'bput_vars_int' => '2:3:4:5',
+		'bput_vars_int-2'	=> 'in:IntIndexIn',
+		'bput_vars_int-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vars_int-4'	=> 'in:reorderOffsetArr',
+		'bput_vars_int-5'	=> 'in:reorderOffsetArr',
+	'bput_vars_float' => '2:3:4:5',
+		'bput_vars_float-2'	=> 'in:IntIndexIn',
+		'bput_vars_float-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vars_float-4'	=> 'in:reorderOffsetArr',
+		'bput_vars_float-5'	=> 'in:reorderOffsetArr',
+	'bput_vars_double' => '2:3:4:5',
+		'bput_vars_double-2'	=> 'in:IntIndexIn',
+		'bput_vars_double-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vars_double-4'	=> 'in:reorderOffsetArr',
+		'bput_vars_double-5'	=> 'in:reorderOffsetArr',
+	'bput_vars_longlong' => '2:3:4:5',
+		'bput_vars_longlong-2'	=> 'in:IntIndexIn',
+		'bput_vars_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'bput_vars_longlong-4'	=> 'in:reorderOffsetArr',
+		'bput_vars_longlong-5'	=> 'in:reorderOffsetArr',
+
+	'bput_varm' => '2:3:4:5:6',
+		'bput_varm-2'		=> 'in:IntIndexIn',
+		'bput_varm-3'		=> 'in:reorderOffsetArr:true',
+		'bput_varm-4'		=> 'in:reorderOffsetArr',
+		'bput_varm-5'		=> 'in:reorderOffsetArr',
+		'bput_varm-6'		=> 'in:reorderOffsetArr',
+	'bput_varm_text' => '2:3:4:5:6:7',
+		'bput_varm_text-2'	=> 'in:IntIndexIn',
+		'bput_varm_text-3'	=> 'in:reorderOffsetArr:true',
+		'bput_varm_text-4'	=> 'in:reorderOffsetArr',
+		'bput_varm_text-5'	=> 'in:reorderOffsetArr',
+		'bput_varm_text-6'	=> 'in:reorderOffsetArr',
+		'bput_varm_text-7'	=> 'in:charBufferIn',
+	'bput_varm_schar' => '2:3:4:5:6',
+		'bput_varm_schar-2'	=> 'in:IntIndexIn',
+		'bput_varm_schar-3'	=> 'in:reorderOffsetArr:true',
+		'bput_varm_schar-4'	=> 'in:reorderOffsetArr',
+		'bput_varm_schar-5'	=> 'in:reorderOffsetArr',
+		'bput_varm_schar-6'	=> 'in:reorderOffsetArr',
+	'bput_varm_short' => '2:3:4:5:6',
+		'bput_varm_short-2'	=> 'in:IntIndexIn',
+		'bput_varm_short-3'	=> 'in:reorderOffsetArr:true',
+		'bput_varm_short-4'	=> 'in:reorderOffsetArr',
+		'bput_varm_short-5'	=> 'in:reorderOffsetArr',
+		'bput_varm_short-6'	=> 'in:reorderOffsetArr',
+	'bput_varm_int' => '2:3:4:5:6',
+		'bput_varm_int-2'	=> 'in:IntIndexIn',
+		'bput_varm_int-3'	=> 'in:reorderOffsetArr:true',
+		'bput_varm_int-4'	=> 'in:reorderOffsetArr',
+		'bput_varm_int-5'	=> 'in:reorderOffsetArr',
+		'bput_varm_int-6'	=> 'in:reorderOffsetArr',
+	'bput_varm_float' => '2:3:4:5:6',
+		'bput_varm_float-2'	=> 'in:IntIndexIn',
+		'bput_varm_float-3'	=> 'in:reorderOffsetArr:true',
+		'bput_varm_float-4'	=> 'in:reorderOffsetArr',
+		'bput_varm_float-5'	=> 'in:reorderOffsetArr',
+		'bput_varm_float-6'	=> 'in:reorderOffsetArr',
+	'bput_varm_double' => '2:3:4:5:6',
+		'bput_varm_double-2'	=> 'in:IntIndexIn',
+		'bput_varm_double-3'	=> 'in:reorderOffsetArr:true',
+		'bput_varm_double-4'	=> 'in:reorderOffsetArr',
+		'bput_varm_double-5'	=> 'in:reorderOffsetArr',
+		'bput_varm_double-6'	=> 'in:reorderOffsetArr',
+	'bput_varm_longlong' => '2:3:4:5:6',
+		'bput_varm_longlong-2'	=> 'in:IntIndexIn',
+		'bput_varm_longlong-3'	=> 'in:reorderOffsetArr:true',
+		'bput_varm_longlong-4'	=> 'in:reorderOffsetArr',
+		'bput_varm_longlong-5'	=> 'in:reorderOffsetArr',
+		'bput_varm_longlong-6'	=> 'in:reorderOffsetArr',
+
+
+	'rename_att' => '2:3:4',
+		'rename_att-2'		=> 'in:IntIndexIn',
+		'rename_att-3'		=> 'in:addnull',
+		'rename_att-4'		=> 'in:addnull',
+	'rename_dim' => '2:3',
+		'rename_dim-2'		=> 'in:IntIndexIn',
+		'rename_dim-3'		=> 'in:addnull',
+	'rename_var' => '2:3',
+		'rename_var-2'		=> 'in:IntIndexIn',
+		'rename_var-3'		=> 'in:addnull'
+);
+
+$build_prototypes = 1;
+$buildMakefile = 0;
+$prototype_header_file = "mpifnetcdf.h";
+$argsneedcast{'const MPI_Offset []'} = '(const MPI_Offset *)(ARG)';
+$argsneedcast{'nc_type *'} = '(nc_type *)(ARG)';
+$argsneedcast{'nc_type'} = '(nc_type)(ARG)';
+
+# Special handling for integer*1 routines
+$declarg{'get_att_int1-4'}		=       'signed char *';
+$declarg{'put_att_int1-6'}		= 'const signed char *';
+$declarg{'get_var1_int1-4'}		=       'signed char *';
+$declarg{'put_var1_int1-4'}		= 'const signed char *';
+$declarg{'get_var1_int1_all-4'}		=       'signed char *';
+$declarg{'put_var1_int1_all-4'}		= 'const signed char *';
+$declarg{'get_var_int1-3'}		=       'signed char *';
+$declarg{'put_var_int1-3'}		= 'const signed char *';
+$declarg{'get_var_int1_all-3'}		=       'signed char *';
+$declarg{'put_var_int1_all-3'}		= 'const signed char *';
+$declarg{'get_vara_int1-5'}		=       'signed char *';
+$declarg{'put_vara_int1-5'}		= 'const signed char *';
+$declarg{'get_vara_int1_all-5'}		=       'signed char *';
+$declarg{'put_vara_int1_all-5'}		= 'const signed char *';
+$declarg{'get_vars_int1-6'}		=       'signed char *';
+$declarg{'put_vars_int1-6'}		= 'const signed char *';
+$declarg{'get_vars_int1_all-6'}		=       'signed char *';
+$declarg{'put_vars_int1_all-6'}		= 'const signed char *';
+$declarg{'get_varm_int1-7'}		=       'signed char *';
+$declarg{'put_varm_int1-7'}		= 'const signed char *';
+$declarg{'get_varm_int1_all-7'}		=       'signed char *';
+$declarg{'put_varm_int1_all-7'}		= 'const signed char *';
+
+$declarg{'get_varn_int1-6'}		=       'signed char *';
+$declarg{'put_varn_int1-6'}		= 'const signed char *';
+$declarg{'get_varn_int1_all-6'}		=       'signed char *';
+$declarg{'put_varn_int1_all-6'}		= 'const signed char *';
+
+$declarg{'iget_varn_int1-6'}		=       'signed char *';
+$declarg{'iput_varn_int1-6'}		= 'const signed char *';
+$declarg{'iget_varn_int1_all-6'}	=       'signed char *';
+$declarg{'iput_varn_int1_all-6'}	= 'const signed char *';
+
+$declarg{'bput_varn_int1-6'}		= 'const signed char *';
+$declarg{'bput_varn_int1_all-6'}	= 'const signed char *';
+
+$declarg{'iget_var1_int1-4'}		=       'signed char *';
+$declarg{'iput_var1_int1-4'}		= 'const signed char *';
+$declarg{'iget_var1_int1-4'}		=       'signed char *';
+$declarg{'iput_var1_int1-4'}		= 'const signed char *';
+$declarg{'iget_var_int1-3'}		=       'signed char *';
+$declarg{'iput_var_int1-3'}		= 'const signed char *';
+$declarg{'iget_vara_int1-5'}		=       'signed char *';
+$declarg{'iput_vara_int1-5'}		= 'const signed char *';
+$declarg{'iget_vars_int1-6'}		=       'signed char *';
+$declarg{'iput_vars_int1-6'}		= 'const signed char *';
+$declarg{'iget_varm_int1-7'}		=       'signed char *';
+$declarg{'iput_varm_int1-7'}		= 'const signed char *';
+
+$declarg{'bput_var1_int1-4'}		= 'const signed char *';
+$declarg{'bput_var_int1-3'}		= 'const signed char *';
+$declarg{'bput_vara_int1-5'}		= 'const signed char *';
+$declarg{'bput_vars_int1-6'}		= 'const signed char *';
+$declarg{'bput_varm_int1-7'}		= 'const signed char *';
+
+# Special handling for int8 routines
+$declarg{'put_att_int8-6'}		= 'const long long *';
+$declarg{'get_att_int8-4'}		= 'long long *';
+
+$declarg{'get_var1_int8-4'}		=       'long long *';
+$declarg{'put_var1_int8-4'}		= 'const long long *';
+$declarg{'get_var1_int8_all-4'}		=       'long long *';
+$declarg{'put_var1_int8_all-4'}		= 'const long long *';
+$declarg{'get_var_int8-3'}		=       'long long *';
+$declarg{'put_var_int8-3'}		= 'const long long *';
+$declarg{'get_var_int8_all-3'}		=       'long long *';
+$declarg{'put_var_int8_all-3'}		= 'const long long *';
+$declarg{'get_vara_int8-5'}		=       'long long *';
+$declarg{'put_vara_int8-5'}		= 'const long long *';
+$declarg{'get_vara_int8_all-5'}		=       'long long *';
+$declarg{'put_vara_int8_all-5'}		= 'const long long *';
+$declarg{'get_vars_int8-6'}		=       'long long *';
+$declarg{'put_vars_int8-6'}		= 'const long long *';
+$declarg{'get_vars_int8_all-6'}		=       'long long *';
+$declarg{'put_vars_int8_all-6'}		= 'const long long *';
+$declarg{'get_varm_int8-7'}		=       'long long *';
+$declarg{'put_varm_int8-7'}		= 'const long long *';
+$declarg{'get_varm_int8_all-7'}		=       'long long *';
+$declarg{'put_varm_int8_all-7'}		= 'const long long *';
+
+$declarg{'get_varn_int8-6'}		=       'long long *';
+$declarg{'put_varn_int8-6'}		= 'const long long *';
+$declarg{'get_varn_int8_all-6'}		=       'long long *';
+$declarg{'put_varn_int8_all-6'}		= 'const long long *';
+
+$declarg{'iget_varn_int8-6'}		=       'long long *';
+$declarg{'iput_varn_int8-6'}		= 'const long long *';
+$declarg{'iget_varn_int8_all-6'}	=       'long long *';
+$declarg{'iput_varn_int8_all-6'}	= 'const long long *';
+
+$declarg{'bput_varn_int8-6'}		= 'const long long *';
+$declarg{'bput_varn_int8_all-6'}	= 'const long long *';
+
+$declarg{'iget_var1_int8-4'}		=       'long long *';
+$declarg{'iput_var1_int8-4'}		= 'const long long *';
+$declarg{'iget_var_int8-3'}		=       'long long *';
+$declarg{'iput_var_int8-3'}		= 'const long long *';
+$declarg{'iget_vara_int8-5'}		=       'long long *';
+$declarg{'iput_vara_int8-5'}		= 'const long long *';
+$declarg{'iget_vars_int8-6'}		=       'long long *';
+$declarg{'iput_vars_int8-6'}		= 'const long long *';
+$declarg{'iget_varm_int8-7'}		=       'long long *';
+$declarg{'iput_varm_int8-7'}		= 'const long long *';
+
+$declarg{'bput_var1_int8-4'}		= 'const long long *';
+$declarg{'bput_var_int8-3'}		= 'const long long *';
+$declarg{'bput_vara_int8-5'}		= 'const long long *';
+$declarg{'bput_vars_int8-6'}		= 'const long long *';
+$declarg{'bput_varm_int8-7'}		= 'const long long *';
+
+# Special argument handling
+# Special routines are used whose names are created from the name
+# used in the hashes above (routinename-position) and these special routine
+# names.
+# void foo( MPI_Fint *v1, etc )
+# {
+# /* Special declarations needed for the variables */
+# <name>_<direction>_decl( <argnum> )
+# /* Special processing need for in variables */
+# <name>_ftoc( <argnum> )
+# /* Call the function.  Replace special arguments with the output from */
+# <name>_<direction>_arg( <argnum> )
+# /* Special post call processing (for out variables) */
+# <name>_ctof( l$count, v$count ) /* local (C) variable name, fortran var name */
+# Not all routines must be provided
+#    use $declarg{routine-position} to replace the handling of input
+#    arguments (in the definition)
+#    E.g., $declarg{'put_att_schar-6'} = 'const signed char *';
+#
+# Routines needed for special argument handling for MPI_Offset
+
+# ---------------------------------------------------------------------------
+# F2C dimension reorder from a Fortran 1D array of type MPI_Offset to a C
+# 1D array of type MPI_Offset.
+# usage is
+#    'Type_struct' => '3', 'Type_struct-3' => 'in:reorderOffsetArr:true',
+# or
+#    'Type_struct' => '3', 'Type_struct-3' => 'in:reorderOffsetArr',
+# where true indicates the array values of the array will be converted
+# from 1-based to 0-based.  Without it, no conversion is done.
+#
+sub reorderOffsetArr_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    MPI_Offset *l$count = NULL;\n";
+}
+sub reorderOffsetArr_ftoc {
+    my $count = $_[0];
+    # We use a local variable for the array size because we may need to
+    # call a function of some of the other arguments to get the array size
+    if ($Array_size) {
+        print $OUTFD "
+    int ndims;
+    ierr = ncmpi_inq_varndims(*v1, l2, &ndims); /* get number of dimensions */
+    if (ierr != NC_NOERR) return ierr;
+
+    if (ndims > 0) {
+        int li;
+        l$count = (MPI_Offset*) $malloc((size_t)ndims * sizeof(MPI_Offset));
+        for (li=0; li<ndims; li++) /* convert Fortran order to C order */
+            l$count\[li\] = v$count\[ndims-1-li\] - 1; /* convert 1-based to 0-based */
+    }\n";
+    } else {
+        print $OUTFD "
+    if (ndims > 0) {
+        int li;
+        l$count = (MPI_Offset*) $malloc((size_t)ndims * sizeof(MPI_Offset));
+        for (li=0; li<ndims; li++) /* convert Fortran order to C order */
+            l$count\[li\] = v$count\[ndims-1-li\];
+    }\n";
+    }
+}
+sub reorderOffsetArr_in_arg {
+    my $count = $_[0];
+    print $OUTFD "l$count";
+}
+# This routine is invoked even for the in case (to free the result)
+sub reorderOffsetArr_in_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+    print $OUTFD "
+    if ($lname) { $free($lname); }
+";
+}
+
+# ---------------------------------------------------------------------------
+# F2C dimension reorder from a Fortran MPI_Offset 1D array to a C MPI_Offset
+# 2D array.
+#    'Type_struct' => '3', 'Type_struct-3' => 'in:reorderOffsetArr1DTo2D:true',
+# or
+#    'Type_struct' => '3', 'Type_struct-3' => 'in:reorderOffsetArr1DTo2D',
+# where true indicates the array values of the array will be converted
+# from 1-based to 0-based.  Without it, no conversion is done.
+#
+sub reorderOffsetArr1DTo2D_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    MPI_Offset **l$count = NULL;\n";
+}
+sub reorderOffsetArr1DTo2D_ftoc {
+    my $count = $_[0];
+    if ($Array_size) {
+        print $OUTFD "
+    int ndims;
+    ierr = ncmpi_inq_varndims(*v1, l2, &ndims); /* get number of dimensions */
+    if (ierr != NC_NOERR) return ierr;\n"
+    }
+    print $OUTFD "
+    if (ndims > 0) {
+        int li, lj;
+        size_t len = (size_t)*v3;
+        l$count    = (MPI_Offset**) $malloc(len * sizeof(MPI_Offset*));
+        l$count\[0\] = (MPI_Offset*)  $malloc(len * (size_t)ndims * sizeof(MPI_Offset));
+        for (lj=1; lj<*v3; lj++)
+            l$count\[lj\] = l$count\[lj-1\] + ndims;
+        for (lj=0; lj<*v3; lj++)
+            for (li=0; li<ndims; li++) /* convert Fortran order to C order */";
+    if ($Array_size) {
+        print $OUTFD "
+                l$count\[lj\]\[li\] = v$count\[lj*ndims + ndims-1-li\] - 1; /* convert 1-based to 0-based */
+    }\n";
+    } else {
+        print $OUTFD "
+                l$count\[lj\]\[li\] = v$count\[lj*ndims + ndims-1-li\];
+    }\n";
+    }
+}
+sub reorderOffsetArr1DTo2D_in_arg {
+    my $count = $_[0];
+    print $OUTFD "l$count";
+}
+# This routine is invoked even for the in case (to free the result)
+sub reorderOffsetArr1DTo2D_in_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+    print $OUTFD "
+    if ($lname) { $free($lname\[0\]); $free($lname); }
+";
+}
+
+# -------------------------------------------------------------------------
+# F2C dimension reorder from a Fortran int array to a C int array.
+# usage is
+#    'Type_struct' => '3', 'Type_struct-3' => 'in:reorderIntArr:true',
+# or
+#    'Type_struct' => '3', 'Type_struct-3' => 'in:reorderIntArr",
+# where true indicates the array values of the array will be converted
+# from 1-based to 0-based.  Without it, no conversion is done.
+#
+sub reorderIntArr_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    int *l$count=NULL;\n";
+}
+sub reorderIntArr_ftoc {
+    my $count = $_[0];
+    # We use a local variable for the array size because we may need to
+    # call a function of some of the other arguments to get the array size
+    # Always copy and invert order
+    if ($Array_size) {
+        print $OUTFD "
+    int ndims;
+    ierr = ncmpi_inq_varndims(*v1, l2, &ndims); /* get number of dimensions */
+    if (ierr != NC_NOERR) return ierr;\n"
+    }
+    print $OUTFD "
+    if (ndims > 0) {
+        int li;
+        l$count = (int*) $malloc((size_t)ndims * sizeof(int));
+        for (li=0; li<ndims; li++) /* convert Fortran order to C order */
+            l$count\[li\] = v$count\[ndims-1-li\];
+    }\n";
+    $clean_up .= "    $free(l$count);\n";
+}
+sub reorderIntArr_in_arg {
+    my $count = $_[0];
+    print $OUTFD "l$count";
+}
+# This routine is invoked even for the in case (to free the result)
+sub reorderIntArr_in_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+    print $OUTFD "
+    if ($lname) { $free($lname); }
+";
+}
+
+# -------------------------------------------------------------------------
+# Convert from a C int array to a Fortran int array with the values reordered
+# for an OUTPUT array
+# usage is
+#    'Type_struct' => '3', 'Type_struct-3' => 'out:reorderIntArrOut',
+# the array values will be converted from C 0-based to Fortran 1-based.
+#
+sub reorderIntArrOut_out_decl {
+    my $count = $_[0];
+    print $OUTFD "    int *l$count=NULL;\n";
+}
+sub reorderIntArrOut_out_ftoc {
+    my $count = $_[0];
+    # We use a local variable for the array size because we may need to
+    # call a function of some of the other arguments to get the array size
+    # Always copy and invert order
+    print $OUTFD "
+    int ndims;
+    ierr = ncmpi_inq_varndims(*v1, l2, &ndims); /* get number of dimensions */
+    if (ierr != NC_NOERR) return ierr;
+
+    if (ndims > 0) {
+        l$count = (int*) $malloc((size_t)ndims * sizeof(int));
+    }\n";
+}
+sub reorderIntArrOut_out_arg {
+    my $count = $_[0];
+    print $OUTFD "l$count";
+}
+# This routine is invoked even for the in case (to free the result)
+sub reorderIntArrOut_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+    print $OUTFD "
+    if (ndims > 0) {
+        int li;
+        for (li=0; li<ndims; li++) /* convert C order to Fortran order */
+            v$count\[li\] = l$count\[ndims-1-li\] + 1; /* convert from 0-based to 1-based */
+        $free($lname);
+    }\n";
+}
+
+# -------------------------------------------------------------------------
+sub intToOffset_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    MPI_Offset l$count = (MPI_Offset)*v$count;\n";
+}
+sub intToOffset_ftoc {
+    my $count = $_[0];
+}
+sub intToOffset_in_arg {
+    my $count = $_[0];
+    print $OUTFD "l$count";
+}
+# This routine is invoked even for the in case (to free the result)
+sub intToOffset_in_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+}
+
+# -------------------------------------------------------------------------
+# For output of int indices, add one to the result
+# usage is
+#    'inq_varid' => '3', 'inq_varid-3' => 'out:IntIndex',
+#
+sub IntIndex_out_decl {
+    my $count = $_[0];
+}
+sub IntIndex_out_ftoc {
+    my $count = $_[0];
+}
+sub IntIndex_out_arg {
+    my $count = $_[0];
+    print $OUTFD "v$count";
+}
+sub IntIndex_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+    print $OUTFD "
+    if (!$errparmrval) *v$count = *v$count + 1;\n";
+}
+
+# -------------------------------------------------------------------------
+# For output of MPI_Offset indices, add one to the result
+# usage is
+#    'inq_varid' => '3', 'inq_varid-3' => 'out:OffsetIndex',
+#
+sub OffsetIndex_out_decl {
+    my $count = $_[0];
+}
+sub OffsetIndex_out_ftoc {
+    my $count = $_[0];
+}
+sub OffsetIndex_out_arg {
+    my $count = $_[0];
+    print $OUTFD "v$count";
+}
+sub OffsetIndex_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+    print $OUTFD "
+    if (!$errparmrval) *v$count = *v$count + 1;\n";
+}
+
+# -------------------------------------------------------------------------
+# For output of dimension indices, add one to the result
+# If no unlimited length dimension has been defined, -1 is returned.
+# usage is
+#    'inq_varid' => '3', 'inq_varid-3' => 'out:IntDimIndex',
+#
+sub IntDimIndex_out_decl {
+    my $count = $_[0];
+}
+sub IntDimIndex_out_ftoc {
+    my $count = $_[0];
+}
+sub IntDimIndex_out_arg {
+    my $count = $_[0];
+    print $OUTFD "v$count";
+}
+sub IntDimIndex_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+    print $OUTFD "
+    if (!$errparmrval && *v$count != -1) *v$count = *v$count + 1;\n";
+}
+
+# -------------------------------------------------------------------------
+# For input of int indices, subtract one to the result
+# usage is
+#    'inq_dim' => '3', 'inq_dim-3' => 'in:IntIndexIn',
+#
+sub IntIndexIn_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    int l$count = *v$count - 1;\n";
+}
+sub IntIndexIn_ftoc {
+    my $count = $_[0];
+}
+sub IntIndexIn_in_arg {
+    my $count = $_[0];
+    print $OUTFD "l$count";
+}
+sub IntIndexIn_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+}
+
+# -------------------------------------------------------------------------
+# For input of MPI_Offset indices, subtract one to the result
+# usage is
+#    'inq_dim' => '3', 'inq_dim-3' => 'in:OffsetIndexIn',
+#
+sub OffsetIndexIn_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    MPI_Offset l$count = *v$count - 1;\n";
+}
+sub OffsetIndexIn_ftoc {
+    my $count = $_[0];
+}
+sub OffsetIndexIn_in_arg {
+    my $count = $_[0];
+    print $OUTFD "l$count";
+}
+sub OffsetIndexIn_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+}
+
+# -------------------------------------------------------------------------
+# For input of an array of int indices, subtract one from the result.
+# Also, reverse the order of the array indices
+# usage is
+#    'def_var' => '3', 'def_var-3' => 'in:IntIndexInArr',
+# Note:
+#   This did not match the one use of this routine, in defA-var
+#
+sub IntIndexInArr_in_decl {
+    my $count = $_[0];
+    print $OUTFD "    int *l$count=NULL;\n    int ln$count;\n";
+}
+sub IntIndexInArr_ftoc {
+    my $count = $_[0];
+    print $OUTFD "
+    { ln$count = $Array_size;
+    if (ln$count > 0) {
+        int li;
+        l$count = (int*) $malloc( (size_t)ln$count * sizeof(int));
+        for (li=0; li<ln$count; li++) /* convert Fortran order to C order */
+            l$count\[li\] = v$count\[ln$count-li-1\]-1; /* convert 1-based to 0-based */
+      }}\n";
+      $clean_up .= "    $free(l$count);\n";
+}
+sub IntIndexInArr_in_arg {
+    my $count = $_[0];
+    print $OUTFD "l$count";
+}
+sub IntIndexInArr_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+    print $OUTFD "
+    if ($lname) { $free($lname); }
+";
+}
+
+# ---------------------------------------------------------------------------
+# charBufferIn and charBufferOut are basically no-ops.  They are provided
+# in case special processing is required for the character buffers.
+#
+sub charBufferIn_in_decl {
+}
+sub charBufferIn_in_arg {
+    my $count = $_[0];
+    print $OUTFD "v$count";
+}
+sub charBufferIn_ftoc {
+}
+# Output text buffers
+sub charBufferOut_out_decl {
+}
+sub charBufferOut_out_arg {
+    my $count = $_[0];
+    print $OUTFD "v$count";
+}
+sub charBufferOut_ctof {
+}
+
+# -----------------------------------------------------------------------------
+# integer*1 in Fortran to signed char in C
+# FIXME: Not done yet
+#
+sub int1toschar_out_arg {
+    my $count = $_[0];
+    print $OUTFD "v$count";
+}
+sub int1toschar_in_decl {
+    my $count = $_[0];
+}
+sub int1toschar_out_decl {
+    my $count = $_[0];
+}
+sub int1toschar_ftoc {
+    my $count = $_[0];
+}
+sub int1toschar_in_arg {
+    my $count = $_[0];
+    print $OUTFD "v$count";
+}
+sub int1toschar_ctof {
+    my $lname = $_[0];
+    my $vname = $_[1];
+}
+
+# will this overrride buildiface?
+sub blankpad_out_ftoc {
+    my $count = $_[0];
+
+    # Allocate space to hold the C version of the output
+    $strlen = "d$count";
+    print $OUTFD "    p$count = (char*) $calloc((size_t)$strlen + 1, 1);\n";
+}
+
+# ---------------------------------------------------------------------------
+# Functions to add routines that need special handling
+$ExtraRoutines[$#ExtraRoutines+1] = "ncfxstrerror";
+$ExtraRoutines[$#ExtraRoutines+1] = "ncfxutil";
+$ExtraRoutines[$#ExtraRoutines+1] = "ncfxinqlibvers";
+$ExtraRoutines[$#ExtraRoutines+1] = "ncfissyserr";
+$ExtraRoutines[$#ExtraRoutines+1] = "get_file_info";
+$ExtraRoutines[$#ExtraRoutines+1] = "inq_file_info";
+
+sub ncfxstrerror {
+    $OUTFD = "NCFXSTRERRORFD";
+    open( $OUTFD, ">xstrerrorf.c" ) || die "Cannot open xstrerrorf.c\n";
+    $out_prefix = "nfmpi_";
+    $files[$#files+1] = "xstrerrorf.c";
+    $args = "int *, char *";
+    &print_header( "ncfmpi_xstrerror", "xstrerror", $args );
+    &print_routine_type_decl( $OUTFD, "xstrerror" );
+    &print_args( $OUTFD, $args, 0, "xstrerror" );
+    print $OUTFD "{
+    const char *p = ncmpi_strerror( *v1 );
+    int i;
+    /* d2 is the length of the string passed into the routine */
+    for (i=0; i<d2 && *p; i++) {
+        v2[i] = *p++;
+    }
+    /* Blank pad */
+    for (; i<d2; i++) v2[i] = ' ';
+    return 0;
+}\n";
+    close ($OUTFD);
+}
+
+# Note that this works for errors because the Netcdf errors are negative
+sub ncfxutil {
+    $OUTFD = "NCFXUTIL";
+    open( $OUTFD, ">nfxutil.c" ) || die "Cannot open nfxutil.c\n";
+    $files[$#files+1] = "nfxutil.c";
+    &print_copyright( );
+    print $OUTFD "
+int ncmpixVardim( int ncid, int varid )
+{
+    int ndims, status;
+    status = ncmpi_inq_varndims(ncid, varid, &ndims); /* get number of dimensions */
+    if (status != NC_NOERR) return status;
+    return ndims;
+}\n";
+    close ($OUTFD);
+}
+
+sub ncfxinqlibvers {
+    $OUTFD = "NCFXINQLIBVERSFD";
+    open( $OUTFD, ">xinq_libversf.c" ) || die "Cannot open xinq_libversf.c\n";
+    $out_prefix = "nfmpi_";
+    $args = "char *";
+    $files[$#files+1] = "xinq_libversf.c";
+    &print_header( "ncfmpi_xinq_libvers", "xinq_libvers", $args );
+    &print_routine_type_decl( $OUTFD, "xinq_libvers" );
+    &print_args( $OUTFD, $args, 0, "xinq_libvers" );
+    print $OUTFD "{
+    const char *p = ncmpi_inq_libvers();
+    int i;
+    /* d1 is the length of the string passed into the routine */
+    for (i=0; i<d1 && *p; i++) {
+        v1[i] = *p++;
+    }
+    /* Blank pad */
+    for (; i<d1; i++) v1[i] = ' ';
+    return 0;
+}\n";
+    close ($OUTFD);
+}
+
+sub ncfissyserr {
+    $OUTFD = "NCFISSYSERRFD";
+    open( $OUTFD, ">issyserrf.c" ) || die "Cannot open issyserrf.c\n";
+    $out_prefix = "nfmpi_";
+    $args = "int *";
+    $files[$#files+1] = "issyserrf.c";
+    &print_header( "ncfmpi_issyserr", "issyserr", $args );
+    &print_routine_type_decl( $OUTFD, "issyserr" );
+    &print_args( $OUTFD, $args, 0, "issyserr" );
+    print $OUTFD "{
+    if (*v1 > 0)
+      return 1;
+    else
+      return 0;
+}\n";
+    close ($OUTFD);
+
+}
+
+sub inq_file_info {
+    $OUTFD = "GETFILEINFOFD";
+    open( $OUTFD, ">inq_file_infof.c" ) || die "Cannot open inq_file_infof.c\n";
+    $out_prefix = "nfmpi_";
+    $files[$#files+1] = "inq_file_infof.c";
+    $args = "int *, int *";
+    &print_header( "ncfmpi_inq_file_info", "inq_file_info", $args );
+    &print_routine_type_decl( $OUTFD, "inq_file_info" );
+    &print_args( $OUTFD, $args, 0, "inq_file_info" );
+    print $OUTFD "{
+    int ierr;
+    MPI_Info info;
+
+    ierr = ncmpi_inq_file_info( *v1, &info );
+    *v2 = MPI_Info_c2f(info);
+    return ierr;
+}\n";
+    close ($OUTFD);
+}
+
+sub get_file_info {
+    $OUTFD = "GETFILEINFOFD";
+    open( $OUTFD, ">get_file_infof.c" ) || die "Cannot open get_file_infof.c\n";
+    $out_prefix = "nfmpi_";
+    $files[$#files+1] = "get_file_infof.c";
+    $args = "int *, int *";
+    &print_header( "ncfmpi_get_file_info", "get_file_info", $args );
+    &print_routine_type_decl( $OUTFD, "get_file_info" );
+    &print_args( $OUTFD, $args, 0, "get_file_info" );
+    print $OUTFD "{
+    int ierr;
+    MPI_Info info;
+
+    ierr = ncmpi_get_file_info( *v1, &info );
+    *v2 = MPI_Info_c2f(info);
+    return ierr;
+}\n";
+    close ($OUTFD);
+}
+
+
+return 1;
+
+# Local variables:
+#  mode: perl
+# End:
+#
+# vim:ft=perl
diff --git a/src/libf/inq_libversf.f b/src/libf/inq_libversf.f
new file mode 100644
index 0000000..ce91f54
--- /dev/null
+++ b/src/libf/inq_libversf.f
@@ -0,0 +1,10 @@
+      character *80 function nfmpi_inq_libvers()
+      integer ierr
+      character *(80) tmpstr
+
+      integer nfmpi_xinq_libvers
+      external nfmpi_xinq_libvers
+      
+      ierr = nfmpi_xinq_libvers(tmpstr)
+      nfmpi_inq_libvers = tmpstr
+      end
diff --git a/src/libf/mpinetcdf_impl.h b/src/libf/mpinetcdf_impl.h
new file mode 100644
index 0000000..d9ffa98
--- /dev/null
+++ b/src/libf/mpinetcdf_impl.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C; c-basic-offset:4 ; -*- */
+/*  
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *      See COPYRIGHT in top-level directory.
+ */
+/* $Id: mpinetcdf_impl.h 2104 2015-09-18 23:36:19Z wkliao $ */
+
+#ifndef MPINETCDF_IMPL_H
+#define MPINETCDF_IMPL_H
+
+#if HAVE_CONFIG_H
+# include <ncconfig.h>
+#endif
+
+#include <stdlib.h>
+#include <pnetcdf.h>
+
+/* Support Windows extension to specify calling convention */
+#ifdef USE_FORT_STDCALL
+#define FORT_CALL __stdcall
+#elif defined (USE_FORT_CDECL)
+#define FORT_CALL __cdecl
+#else
+#define FORT_CALL
+#endif
+
+/* Handle different mechanisms for passing Fortran CHARACTER to routines */
+#ifdef USE_FORT_MIXED_STR_LEN
+#define FORT_MIXED_LEN_DECL   , MPI_Fint
+#define FORT_END_LEN_DECL
+#define FORT_MIXED_LEN(a)     , MPI_Fint a
+#define FORT_END_LEN(a)
+#else
+#define FORT_MIXED_LEN_DECL
+#define FORT_END_LEN_DECL     , MPI_Fint
+#define FORT_MIXED_LEN(a)
+#define FORT_END_LEN(a)       , MPI_Fint a
+#endif
+
+/* Support Windows extension to specify which functions are exported from
+   shared (DLL) libraries */
+#ifdef HAVE_FORTRAN_API
+# ifdef FORTRAN_EXPORTS
+#  define FORTRAN_API __declspec(dllexport)
+# else
+#  define FORTRAN_API __declspec(dllimport)
+# endif
+#else
+# define FORTRAN_API
+#endif
+
+/* Support an alternate approach for declaring a weak symbol supported by
+   some versions of gcc */
+#ifdef USE_WEAK_ATTRIBUTE
+#define FUNC_ATTRIBUTES(name) __attribute__ ((weak,alias(#name)))
+#else
+#define FUNC_ATTRIBUTES(name)
+#endif
+
+/* Utility functions */
+int ncmpixVardim( int, int );
+
+extern FORTRAN_API int FORT_CALL nfmpi_xstrerror_ ( MPI_Fint *v1, char *v2 FORT_MIXED_LEN(d2) FORT_END_LEN(d2) );
+extern FORTRAN_API int FORT_CALL nfmpi_xinq_libvers_ ( char *v1 FORT_MIXED_LEN(d1) FORT_END_LEN(d1) );
+extern FORTRAN_API int FORT_CALL nfmpi_issyserr_ ( MPI_Fint *v1 );
+/* Define the internal values needed for Fortran support */
+
+/* Fortran logicals */
+
+/* Fortran logical values */
+
+
+#endif
+
+
+
+
diff --git a/src/libf/nfconfig_inc.in b/src/libf/nfconfig_inc.in
new file mode 100644
index 0000000..6a2bb2e
--- /dev/null
+++ b/src/libf/nfconfig_inc.in
@@ -0,0 +1,91 @@
+#if 0
+    Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+    See COPYRIGHT notice in top-level directory.
+
+    $Id: nfconfig_inc.in 1468 2013-10-26 16:53:18Z wkliao $ 
+#endif
+
+
+#ifndef UD_NETCDF_CPP_INC
+#define UD_NETCDF_CPP_INC
+
+
+#if 0
+    Do not have C-style comments in here because this file is processed
+    by both the FORTRAN compiler (for the nf_test/ stuff) and the C
+    compiler (for the FORTRAN-callable interface routines) and some 
+    FORTRAN preprocessors do not understand the /*...*/ syntax.
+#endif
+
+
+#if 0
+    The following macros define the supplementary FORTRAN arithmetic
+    datatypes beyond the standard INTEGER, REAL, and DOUBLEPRECISION --
+    ostensibly corresponding to 8-bit and 16-bit integers, respectively.
+    For example:
+
+	#define NF_INT1_T        integer*1
+	#define NF_INT2_T        integer*2
+	#define NF_INT8_T        integer*8
+
+    These are the types of the relevant arguments in the NF_*_INT1() and
+    NF_*_INT2() netCDF FORTRAN function calls.  The word "ostensibly"
+    is used advisedly: on some systems an "integer*2" datatype,
+    nevertheless, occupies 64 bits (we are not making this up).
+
+    If your FORTRAN system does not have the respective supplementary
+    datatype, then do not define the corresponding macro.
+#endif
+#undef NF_INT1_T
+#undef NF_INT2_T
+#undef NF_INT8_T
+
+
+#if 0
+   Define the following NF_*_IS_C_* macros appropriatly for your system.
+   The "INT1", "INT2", "INT", and "INT8" after the "NF_" refer to the
+   NF_INT1_T FORTRAN datatype, the NF_INT2_T FORTRAN datatype, the INTEGER
+   FORTRAN datatype, and the NF_INT8_T FORTRAN datatype, respectively.
+   If the respective FORTRAN datatype
+   does not exist, then do not define the corresponding macro.
+#endif
+#undef NF_INT1_IS_C_SIGNED_CHAR
+#undef NF_INT1_IS_C_SHORT
+#undef NF_INT1_IS_C_INT
+#undef NF_INT1_IS_C_LONG
+#undef NF_INT2_IS_C_SHORT
+#undef NF_INT2_IS_C_INT
+#undef NF_INT2_IS_C_LONG
+#undef NF_INT_IS_C_INT
+#undef NF_INT_IS_C_LONG
+#undef NF_INT8_IS_C_LONG
+#undef NF_INT8_IS_C_LONG_LONG
+#undef NF_REAL_IS_C_FLOAT
+#undef NF_REAL_IS_C_DOUBLE
+#undef NF_DOUBLEPRECISION_IS_C_DOUBLE
+#undef NF_DOUBLEPRECISION_IS_C_FLOAT
+
+
+#if 0
+   Whether the system uses something besides the IEEE floating-point
+   format to represent floating-point values.
+#endif
+#undef NO_IEEE_FLOAT
+
+
+#if 0
+   END OF CUSTOMIZATION
+#endif
+
+
+#if 0
+    FORTRAN data types corresponding to netCDF version 2 "byte" and "short"
+    data types (e.g. INTEGER*1, INTEGER*2).  See file "ftest.F" for usage.
+#endif
+#if !defined(NO_NETCDF_2)
+#   undef NCBYTE_T
+#   undef NCSHORT_T
+#endif
+
+
+#endif
diff --git a/src/libf/pnetcdf.inc.in b/src/libf/pnetcdf.inc.in
new file mode 100644
index 0000000..09820d0
--- /dev/null
+++ b/src/libf/pnetcdf.inc.in
@@ -0,0 +1,1512 @@
+!
+! pnetcdf fortran defines
+!
+
+!
+! PnetCDF library version numbers
+!
+      integer PNETCDF_VERSION_MAJOR
+      integer PNETCDF_VERSION_MINOR
+      integer PNETCDF_VERSION_SUB
+
+      parameter (PNETCDF_VERSION_MAJOR = @PNETCDF_VERSION_MAJOR@)
+      parameter (PNETCDF_VERSION_MINOR = @PNETCDF_VERSION_MINOR@)
+      parameter (PNETCDF_VERSION_SUB   = @PNETCDF_VERSION_SUB@)
+
+!
+! external netcdf data types: (must conform with netCDF release)
+!
+      integer nf_byte
+      integer nf_int1
+      integer nf_char
+      integer nf_short
+      integer nf_int2
+      integer nf_int
+      integer nf_float
+      integer nf_real
+      integer nf_double
+      integer nf_ubyte
+      integer nf_ushort
+      integer nf_uint
+      integer nf_int64
+      integer nf_uint64
+
+      parameter (nf_byte = 1)
+      parameter (nf_int1 = nf_byte)
+      parameter (nf_char = 2)
+      parameter (nf_short = 3)
+      parameter (nf_int2 = nf_short)
+      parameter (nf_int = 4)
+      parameter (nf_float = 5)
+      parameter (nf_real = nf_float)
+      parameter (nf_double = 6)
+      parameter (nf_ubyte = 7)
+      parameter (nf_ushort = 8)
+      parameter (nf_uint = 9)
+      parameter (nf_int64 = 10)
+      parameter (nf_uint64 = 11)
+
+!
+! default fill values:
+!
+      integer           nf_fill_byte
+      integer           nf_fill_int1
+      integer           nf_fill_char
+      integer           nf_fill_short
+      integer           nf_fill_int2
+      integer           nf_fill_int
+      real              nf_fill_float
+      real              nf_fill_real
+      doubleprecision   nf_fill_double
+      integer           nf_fill_ubyte
+      integer           nf_fill_ushort
+      integer*8         nf_fill_uint
+      integer*8         nf_fill_int64
+      ! integer*8         nf_fill_uint64    ! no unsigned int*8 in Fortran
+      doubleprecision   nf_fill_uint64
+
+      parameter (nf_fill_byte = -127)
+      parameter (nf_fill_int1 = nf_fill_byte)
+      parameter (nf_fill_char = 0)
+      parameter (nf_fill_short = -32767)
+      parameter (nf_fill_int2 = nf_fill_short)
+      parameter (nf_fill_int = -2147483647)
+      parameter (nf_fill_float = 9.9692099683868690e+36)
+      parameter (nf_fill_real = nf_fill_float)
+      parameter (nf_fill_double = 9.9692099683868690e+36)
+      parameter (nf_fill_ubyte = 255)
+      parameter (nf_fill_ushort = 65535)
+
+ at PNF_INT8_MODIFIER@
+      parameter (nf_fill_uint = @PNF_FILL_UINT@)
+      parameter (nf_fill_int64 = @PNF_FILL_INT64@)
+      ! parameter (nf_fill_uint64 = @PNF_FILL_UINT64@)  ! currently not supported
+      parameter (nf_fill_uint64 = 1.8446744073709551614e+19)
+
+!
+! mode flags for opening and creating a netcdf dataset:
+!
+      integer nf_nowrite
+      integer nf_write
+      integer nf_clobber
+      integer nf_noclobber
+      integer nf_fill
+      integer nf_nofill
+      integer nf_lock
+      integer nf_share
+      integer nf_64bit_offset
+      integer nf_32bit
+      integer nf_64bit_data
+      integer nf_sizehint_default
+      integer nf_align_chunk
+      integer nf_format_classic
+      integer nf_format_64bit
+      integer nf_format_64bit_data
+      integer nf_format_64bit_offset
+      integer nf_format_cdf2
+      integer nf_format_cdf5
+
+      parameter (nf_nowrite = 0)
+      parameter (nf_write = 1)
+      parameter (nf_clobber = 0)
+      parameter (nf_noclobber = 4)
+      parameter (nf_fill = 0)
+      parameter (nf_nofill = 256)
+      parameter (nf_lock = 1024)
+      parameter (nf_share = 2048)
+      parameter (nf_64bit_offset = 512)
+      parameter (nf_64bit_data = 32)
+      parameter (nf_32bit = 16777216)
+      parameter (nf_sizehint_default = 0)
+      parameter (nf_align_chunk = -1)
+      parameter (nf_format_classic = 1)
+      parameter (nf_format_cdf2 = 2)
+      parameter (nf_format_cdf5 = 5)
+      parameter (nf_format_64bit = nf_format_cdf2)
+      parameter (nf_format_64bit_offset = nf_format_cdf2)
+      parameter (nf_format_64bit_data = nf_format_cdf5)
+
+!
+! size argument for defining an unlimited dimension:
+!
+      integer nf_unlimited
+      parameter (nf_unlimited = 0)
+
+      integer*@SIZEOF_MPI_OFFSET@ nfmpi_unlimited
+      parameter (nfmpi_unlimited = 0)
+
+!
+! global attribute id:
+!
+      integer nf_global
+      parameter (nf_global = 0)
+
+!
+! implementation limits:
+!
+      integer nf_max_dims
+      integer nf_max_attrs
+      integer nf_max_vars
+      integer nf_max_name
+      integer nf_max_var_dims
+
+      parameter (nf_max_dims = 512)
+      parameter (nf_max_attrs = 4092)
+      parameter (nf_max_vars = 4096)
+      parameter (nf_max_name = 128)
+      parameter (nf_max_var_dims = nf_max_dims)
+
+!
+! error codes: (conform with netCDF release)
+!
+      integer NF_NOERR
+      integer NF2_ERR
+      integer NF_EBADID
+      integer NF_ENFILE
+      integer NF_EEXIST
+      integer NF_EINVAL
+      integer NF_EPERM
+      integer NF_ENOTINDEFINE
+      integer NF_EINDEFINE
+      integer NF_EINVALCOORDS
+      integer NF_EMAXDIMS
+      integer NF_ENAMEINUSE
+      integer NF_ENOTATT
+      integer NF_EMAXATTS
+      integer NF_EBADTYPE
+      integer NF_EBADDIM
+      integer NF_EUNLIMPOS
+      integer NF_EMAXVARS
+      integer NF_ENOTVAR
+      integer NF_EGLOBAL
+      integer NF_ENOTNC
+      integer NF_ESTS
+      integer NF_EMAXNAME
+      integer NF_EUNLIMIT
+      integer NF_ENORECVARS
+      integer NF_ECHAR
+      integer NF_EEDGE
+      integer NF_ESTRIDE
+      integer NF_EBADNAME
+      integer NF_ERANGE
+      integer NF_ENOMEM
+      integer NF_EVARSIZE
+      integer NF_EDIMSIZE
+      integer NF_ETRUNC
+      integer NF_EAXISTYPE
+      integer NF_EDAP
+      integer NF_ECURL
+      integer NF_EIO
+      integer NF_ENODATA
+      integer NF_EDAPSVC
+      integer NF_EDAS
+      integer NF_EDDS
+      integer NF_EDATADDS
+      integer NF_EDAPURL
+      integer NF_EDAPCONSTRAINT
+      integer NF_ETRANSLATION
+      integer NF_EACCESS
+      integer NF_EAUTH
+      integer NF_ENOTFOUND
+      integer NF_ECANTREMOVE
+
+      PARAMETER (NF_NOERR        = 0)     ! No Error
+      PARAMETER (NF2_ERR         = -1)    ! Returned for all errors in the v2 API
+      PARAMETER (NF_EBADID       = -33)   ! Not a netcdf id
+      PARAMETER (NF_ENFILE       = -34)   ! Too many netcdfs open
+      PARAMETER (NF_EEXIST       = -35)   ! netcdf file exists and NF_NOCLOBBER
+      PARAMETER (NF_EINVAL       = -36)   ! Invalid Argument
+      PARAMETER (NF_EPERM        = -37)   ! Write to read only
+      PARAMETER (NF_ENOTINDEFINE = -38)   ! Operation not allowed in data mode
+      PARAMETER (NF_EINDEFINE    = -39)   ! Operation not allowed in define mode
+      PARAMETER (NF_EINVALCOORDS = -40)   ! Index exceeds dimension bound
+      PARAMETER (NF_EMAXDIMS     = -41)   ! NF_MAX_DIMS exceeded
+      PARAMETER (NF_ENAMEINUSE   = -42)   ! String match to name in use
+      PARAMETER (NF_ENOTATT      = -43)   ! Attribute not found
+      PARAMETER (NF_EMAXATTS     = -44)   ! NF_MAX_ATTRS exceeded
+      PARAMETER (NF_EBADTYPE     = -45)   ! Not a netcdf data type
+      PARAMETER (NF_EBADDIM      = -46)   ! Invalid dimension id or name
+      PARAMETER (NF_EUNLIMPOS    = -47)   ! NFMPI_UNLIMITED in the wrong index
+      PARAMETER (NF_EMAXVARS     = -48)   ! NF_MAX_VARS exceeded
+      PARAMETER (NF_ENOTVAR      = -49)   ! Variable not found
+      PARAMETER (NF_EGLOBAL      = -50)   ! Action prohibited on NF_GLOBAL varid
+      PARAMETER (NF_ENOTNC       = -51)   ! Not a netcdf file
+      PARAMETER (NF_ESTS         = -52)   ! In Fortran, string too short
+      PARAMETER (NF_EMAXNAME     = -53)   ! NF_MAX_NAME exceeded
+      PARAMETER (NF_EUNLIMIT     = -54)   ! NFMPI_UNLIMITED size already in use
+      PARAMETER (NF_ENORECVARS   = -55)   ! nc_rec op when there are no record vars
+      PARAMETER (NF_ECHAR        = -56)   ! Attempt to convert between text & numbers
+      PARAMETER (NF_EEDGE        = -57)   ! Edge+start exceeds dimension bound
+      PARAMETER (NF_ESTRIDE      = -58)   ! Illegal stride
+      PARAMETER (NF_EBADNAME     = -59)   ! Attribute or variable name contains illegal characters
+      PARAMETER (NF_ERANGE       = -60)   ! Math result not representable
+      PARAMETER (NF_ENOMEM       = -61)   ! Memory allocation (malloc) failure
+      PARAMETER (NF_EVARSIZE     = -62)   ! One or more variable sizes violate format constraints
+      PARAMETER (NF_EDIMSIZE     = -63)   ! Invalid dimension size
+      PARAMETER (NF_ETRUNC       = -64)   ! File likely truncated or possibly corrupted
+      PARAMETER (NF_EAXISTYPE    = -65)   ! Unknown axis type
+
+! Following errors are added for DAP
+      PARAMETER (NF_EDAP         = -66)   ! Generic DAP error
+      PARAMETER (NF_ECURL        = -67)   ! Generic libcurl error
+      PARAMETER (NF_EIO          = -68)   ! Generic IO error
+      PARAMETER (NF_ENODATA      = -69)   ! Attempt to access variable with no data
+      PARAMETER (NF_EDAPSVC      = -70)   ! DAP server error
+      PARAMETER (NF_EDAS         = -71)   ! Malformed or inaccessible DAS
+      PARAMETER (NF_EDDS         = -72)   ! Malformed or inaccessible DDS
+      PARAMETER (NF_EDATADDS     = -73)   ! Malformed or inaccessible DATADDS
+      PARAMETER (NF_EDAPURL      = -74)   ! Malformed DAP URL
+      PARAMETER (NF_EDAPCONSTRAINT = -75) ! Malformed DAP Constraint
+      PARAMETER (NF_ETRANSLATION = -76)   ! Untranslatable construct
+      PARAMETER (NF_EACCESS      = -77)   ! Access Failure
+      PARAMETER (NF_EAUTH        = -78)   ! Authorization Failure
+
+! Misc. additional errors
+      PARAMETER (NF_ENOTFOUND    = -90)   ! No such file
+      PARAMETER (NF_ECANTREMOVE  = -91)   ! Can't remove file
+
+!
+! netCDF-4 error codes (copied from netCDF release)
+!
+      integer NF_EHDFERR
+      integer NF_ECANTREAD
+      integer NF_ECANTWRITE
+      integer NF_ECANTCREATE
+      integer NF_EFILEMETA
+      integer NF_EDIMMETA
+      integer NF_EATTMETA
+      integer NF_EVARMETA
+      integer NF_ENOCOMPOUND
+      integer NF_EATTEXISTS
+      integer NF_ENOTNC4
+      integer NF_ESTRICTNC3
+      integer NF_ENOTNC3
+      integer NF_ENOPAR
+      integer NF_EPARINIT
+      integer NF_EBADGRPID
+      integer NF_EBADTYPID
+      integer NF_ETYPDEFINED
+      integer NF_EBADFIELD
+      integer NF_EBADCLASS
+      integer NF_EMAPTYPE
+      integer NF_ELATEFILL
+      integer NF_ELATEDEF
+      integer NF_EDIMSCALE
+      integer NF_ENOGRP
+      integer NF_ESTORAGE
+      integer NF_EBADCHUNK
+      integer NF_ENOTBUILT
+      integer NF_EDISKLESS
+      integer NF_ECANTEXTEND
+      integer NF_EMPI
+
+      PARAMETER (NF_EHDFERR      = -101)  ! Error at HDF5 layer. 
+      PARAMETER (NF_ECANTREAD    = -102)  ! Can't read. 
+      PARAMETER (NF_ECANTWRITE   = -103)  ! Can't write. 
+      PARAMETER (NF_ECANTCREATE  = -104)  ! Can't create. 
+      PARAMETER (NF_EFILEMETA    = -105)  ! Problem with file metadata. 
+      PARAMETER (NF_EDIMMETA     = -106)  ! Problem with dimension metadata. 
+      PARAMETER (NF_EATTMETA     = -107)  ! Problem with attribute metadata. 
+      PARAMETER (NF_EVARMETA     = -108)  ! Problem with variable metadata. 
+      PARAMETER (NF_ENOCOMPOUND  = -109)  ! Not a compound type. 
+      PARAMETER (NF_EATTEXISTS   = -110)  ! Attribute already exists. 
+      PARAMETER (NF_ENOTNC4      = -111)  ! Attempting netcdf-4 operation on netcdf-3 file.   
+      PARAMETER (NF_ESTRICTNC3   = -112)  ! Attempting netcdf-4 operation on strict nc3 netcdf-4 file.   
+      PARAMETER (NF_ENOTNC3      = -113)  ! Attempting netcdf-3 operation on netcdf-4 file.   
+      PARAMETER (NF_ENOPAR       = -114)  ! Parallel operation on file opened for non-parallel access.   
+      PARAMETER (NF_EPARINIT     = -115)  ! Error initializing for parallel access.   
+      PARAMETER (NF_EBADGRPID    = -116)  ! Bad group ID.   
+      PARAMETER (NF_EBADTYPID    = -117)  ! Bad type ID.   
+      PARAMETER (NF_ETYPDEFINED  = -118)  ! Type has already been defined and may not be edited. 
+      PARAMETER (NF_EBADFIELD    = -119)  ! Bad field ID.   
+      PARAMETER (NF_EBADCLASS    = -120)  ! Bad class.   
+      PARAMETER (NF_EMAPTYPE     = -121)  ! Mapped access for atomic types only.   
+      PARAMETER (NF_ELATEFILL    = -122)  ! Attempt to define fill value when data already exists. 
+      PARAMETER (NF_ELATEDEF     = -123)  ! Attempt to define var properties, like deflate, after enddef.
+      PARAMETER (NF_EDIMSCALE    = -124)  ! Problem with HDF5 dimscales.
+      PARAMETER (NF_ENOGRP       = -125)  ! No group found.
+      PARAMETER (NF_ESTORAGE     = -126)  ! Can't specify both contiguous and chunking.
+      PARAMETER (NF_EBADCHUNK    = -127)  ! Bad chunksize.
+      PARAMETER (NF_ENOTBUILT    = -128)  ! Attempt to use feature that was not turned on when netCDF was built.
+      PARAMETER (NF_EDISKLESS    = -129)  ! Error in using diskless  access.
+      PARAMETER (NF_ECANTEXTEND  = -130)  ! Attempt to extend dataset during ind. I/O operation.
+      PARAMETER (NF_EMPI         = -131)  ! MPI operation failed.
+
+!
+! PnetCDF error codes start here
+!
+      integer NF_ESMALL
+      integer NF_ENOTINDEP
+      integer NF_EINDEP
+      integer NF_EFILE
+      integer NF_EREAD
+      integer NF_EWRITE
+      integer NF_EOFILE
+      integer NF_EMULTITYPES
+      integer NF_EIOMISMATCH
+      integer NF_ENEGATIVECNT
+      integer NF_EUNSPTETYPE
+      integer NF_EINVAL_REQUEST
+      integer NF_EAINT_TOO_SMALL
+      integer NF_ENOTSUPPORT
+      integer NF_ENULLBUF
+      integer NF_EPREVATTACHBUF
+      integer NF_ENULLABUF
+      integer NF_EPENDINGBPUT
+      integer NF_EINSUFFBUF
+      integer NF_ENOENT
+      integer NF_EINTOVERFLOW
+      integer NF_ENOTENABLED
+      integer NF_EBAD_FILE
+      integer NF_ENO_SPACE
+      integer NF_EQUOTA
+      integer NF_ENULLSTART
+      integer NF_ENULLCOUNT
+      integer NF_EINVAL_CMODE
+      integer NF_ETYPESIZE
+      integer NF_ETYPE_MISMATCH
+      integer NF_ETYPESIZE_MISMATCH
+      integer NF_ESTRICTCDF2
+      integer NF_ENOTRECVAR
+      integer NF_ENOTFILL
+
+      integer NF_EMULTIDEFINE
+      integer NF_EMULTIDEFINE_OMODE,      NF_ECMODE
+      integer NF_EMULTIDEFINE_DIM_NUM,    NF_EDIMS_NELEMS_MULTIDEFINE
+      integer NF_EMULTIDEFINE_DIM_SIZE,   NF_EDIMS_SIZE_MULTIDEFINE
+      integer NF_EMULTIDEFINE_DIM_NAME,   NF_EDIMS_NAME_MULTIDEFINE
+      integer NF_EMULTIDEFINE_VAR_NUM,    NF_EVARS_NELEMS_MULTIDEFINE
+      integer NF_EMULTIDEFINE_VAR_NAME,   NF_EVARS_NAME_MULTIDEFINE
+      integer NF_EMULTIDEFINE_VAR_NDIMS,  NF_EVARS_NDIMS_MULTIDEFINE
+      integer NF_EMULTIDEFINE_VAR_DIMIDS, NF_EVARS_DIMIDS_MULTIDEFINE
+      integer NF_EMULTIDEFINE_VAR_TYPE,   NF_EVARS_TYPE_MULTIDEFINE
+      integer NF_EMULTIDEFINE_VAR_LEN,    NF_EVARS_LEN_MULTIDEFINE
+      integer NF_EMULTIDEFINE_VAR_BEGIN,  NF_EVARS_BEGIN_MULTIDEFINE
+      integer NF_EMULTIDEFINE_NUMRECS,    NF_ENUMRECS_MULTIDEFINE
+      integer NF_EMULTIDEFINE_ATTR_NUM
+      integer NF_EMULTIDEFINE_ATTR_SIZE
+      integer NF_EMULTIDEFINE_ATTR_NAME
+      integer NF_EMULTIDEFINE_ATTR_TYPE
+      integer NF_EMULTIDEFINE_ATTR_LEN
+      integer NF_EMULTIDEFINE_ATTR_VAL
+      integer NF_EMULTIDEFINE_FNC_ARGS
+      integer NF_EMULTIDEFINE_FILL_MODE
+      integer NF_EMULTIDEFINE_VAR_FILL_MODE
+      integer NF_EMULTIDEFINE_VAR_FILL_VALUE
+
+!
+! PnetCDF error codes start from -201
+!
+      PARAMETER (NF_ESMALL                  = -201)   ! size of off_t too small for format
+      PARAMETER (NF_ENOTINDEP               = -202)   ! Operation not allowed in collective data mode
+      PARAMETER (NF_EINDEP                  = -203)   ! Operation not allowed in independent data mode
+      PARAMETER (NF_EFILE                   = -204)   ! Unknown error in file operation
+      PARAMETER (NF_EREAD                   = -205)   ! Unknown error in reading file
+      PARAMETER (NF_EWRITE                  = -206)   ! Unknown error in writing to file
+      PARAMETER (NF_EOFILE                  = -207)   ! file open/creation failed
+      PARAMETER (NF_EMULTITYPES             = -208)   ! Multiple types used in memory data
+      PARAMETER (NF_EIOMISMATCH             = -209)   ! Input/Output data amount mismatch
+      PARAMETER (NF_ENEGATIVECNT            = -210)   ! Negative count is specified
+      PARAMETER (NF_EUNSPTETYPE             = -211)   ! Unsupported etype in memory MPI datatype
+      PARAMETER (NF_EINVAL_REQUEST          = -212)   ! invalid nonblocking request ID
+      PARAMETER (NF_EAINT_TOO_SMALL         = -213)   ! MPI_Aint not large enough to hold requested value
+      PARAMETER (NF_ENOTSUPPORT             = -214)   ! feature is not yet supported
+      PARAMETER (NF_ENULLBUF                = -215)   ! trying to attach a NULL buffer
+      PARAMETER (NF_EPREVATTACHBUF          = -216)   ! previous attached buffer is found
+      PARAMETER (NF_ENULLABUF               = -217)   ! no attached buffer is found
+      PARAMETER (NF_EPENDINGBPUT            = -218)   ! pending bput is found, cannot detach buffer
+      PARAMETER (NF_EINSUFFBUF              = -219)   ! attached buffer is too small
+      PARAMETER (NF_ENOENT                  = -220)   ! File does not exist when calling nfmpi_open()
+      PARAMETER (NF_EINTOVERFLOW            = -221)   ! Overflow when type cast to 4-byte integer
+      PARAMETER (NF_ENOTENABLED             = -222)   ! feature is not enabled
+      PARAMETER (NF_EBAD_FILE               = -223)   ! Invalid file name (e.g., path name too long)
+      PARAMETER (NF_ENO_SPACE               = -224)   ! Not enough space
+      PARAMETER (NF_EQUOTA                  = -225)   ! Quota exceeded
+      PARAMETER (NF_ENULLSTART              = -226)   ! argument start is a NULL pointer
+      PARAMETER (NF_ENULLCOUNT              = -227)   ! argument count is a NULL pointer
+      PARAMETER (NF_EINVAL_CMODE            = -228)   ! Invalid file create mode, cannot have both NC_64BIT_OFFSET & NC_64BIT_DATA
+      PARAMETER (NF_ETYPESIZE               = -229)   ! MPI derived data type size error (bigger than the variable size)
+      PARAMETER (NF_ETYPE_MISMATCH          = -230)   ! element type of the MPI derived data type mismatches the variable type
+      PARAMETER (NF_ETYPESIZE_MISMATCH      = -231)   ! file type size mismatches buffer type size
+      PARAMETER (NF_ESTRICTCDF2             = -232)   ! Attempting CDF-5 operation on CDF-2 file
+      PARAMETER (NF_ENOTRECVAR              = -233)   ! Attempting operation only for record variables
+      PARAMETER (NF_ENOTFILL                = -234)   ! Attempting to fill a variable when its fill mode is off
+
+!
+! PnetCDF header inconsistency errors start from -250
+!
+      PARAMETER (NF_EMULTIDEFINE            = -250)   ! NC definitions on multiprocesses conflict
+      PARAMETER (NF_EMULTIDEFINE_OMODE      = -251)   ! file create/open modes are inconsistent
+      PARAMETER (NF_EMULTIDEFINE_DIM_NUM    = -252)   ! inconsistent number of dimensions
+      PARAMETER (NF_EMULTIDEFINE_DIM_SIZE   = -253)   ! inconsistent size of dimension
+      PARAMETER (NF_EMULTIDEFINE_DIM_NAME   = -254)   ! inconsistent dimension names
+      PARAMETER (NF_EMULTIDEFINE_VAR_NUM    = -255)   ! inconsistent number of variables
+      PARAMETER (NF_EMULTIDEFINE_VAR_NAME   = -256)   ! inconsistent variable name
+      PARAMETER (NF_EMULTIDEFINE_VAR_NDIMS  = -257)   ! inconsistent variable's number of dimensions
+      PARAMETER (NF_EMULTIDEFINE_VAR_DIMIDS = -258)   ! inconsistent variable's dimid
+      PARAMETER (NF_EMULTIDEFINE_VAR_TYPE   = -259)   ! inconsistent variable's data type
+      PARAMETER (NF_EMULTIDEFINE_VAR_LEN    = -260)   ! inconsistent variable's size
+      PARAMETER (NF_EMULTIDEFINE_NUMRECS    = -261)   ! inconsistent number of records
+      PARAMETER (NF_EMULTIDEFINE_VAR_BEGIN  = -262)   ! inconsistent variable file begin offset (internal use)
+      PARAMETER (NF_EMULTIDEFINE_ATTR_NUM   = -263)   ! inconsistent number of attributes
+      PARAMETER (NF_EMULTIDEFINE_ATTR_SIZE  = -264)   ! inconsistent memory space used by attribute (internal use)
+      PARAMETER (NF_EMULTIDEFINE_ATTR_NAME  = -265)   ! inconsistent attribute name
+      PARAMETER (NF_EMULTIDEFINE_ATTR_TYPE  = -266)   ! inconsistent attribute type
+      PARAMETER (NF_EMULTIDEFINE_ATTR_LEN   = -267)   ! inconsistent attribute length
+      PARAMETER (NF_EMULTIDEFINE_ATTR_VAL   = -268)   ! inconsistent attribute value
+      PARAMETER (NF_EMULTIDEFINE_FNC_ARGS   = -269)   ! inconsistent function arguments used in collective API
+      PARAMETER (NF_EMULTIDEFINE_FILL_MODE  = -270)   !  inconsistent dataset fill mode
+      PARAMETER (NF_EMULTIDEFINE_VAR_FILL_MODE  = -271) ! inconsistent variable fill mode
+      PARAMETER (NF_EMULTIDEFINE_VAR_FILL_VALUE = -272) ! inconsistent variable fill value
+
+      PARAMETER(NF_ECMODE                  =NF_EMULTIDEFINE_OMODE)
+      PARAMETER(NF_EDIMS_NELEMS_MULTIDEFINE=NF_EMULTIDEFINE_DIM_NUM)
+      PARAMETER(NF_EDIMS_SIZE_MULTIDEFINE  =NF_EMULTIDEFINE_DIM_SIZE)
+      PARAMETER(NF_EDIMS_NAME_MULTIDEFINE  =NF_EMULTIDEFINE_DIM_NAME)
+      PARAMETER(NF_EVARS_NELEMS_MULTIDEFINE=NF_EMULTIDEFINE_VAR_NUM)
+      PARAMETER(NF_EVARS_NAME_MULTIDEFINE  =NF_EMULTIDEFINE_VAR_NAME)
+      PARAMETER(NF_EVARS_NDIMS_MULTIDEFINE =NF_EMULTIDEFINE_VAR_NDIMS)
+      PARAMETER(NF_EVARS_DIMIDS_MULTIDEFINE=NF_EMULTIDEFINE_VAR_DIMIDS)
+      PARAMETER(NF_EVARS_TYPE_MULTIDEFINE  =NF_EMULTIDEFINE_VAR_TYPE)
+      PARAMETER(NF_EVARS_LEN_MULTIDEFINE   =NF_EMULTIDEFINE_VAR_LEN)
+      PARAMETER(NF_ENUMRECS_MULTIDEFINE    =NF_EMULTIDEFINE_NUMRECS)
+      PARAMETER(NF_EVARS_BEGIN_MULTIDEFINE =NF_EMULTIDEFINE_VAR_BEGIN)
+
+! error handling modes:
+!
+      integer nf_fatal
+      integer nf_verbose
+
+      parameter (nf_fatal = 1)
+      parameter (nf_verbose = 2)
+
+
+!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+! begin netcdf 2.4 backward compatibility:
+!
+
+!
+! functions in the fortran interface
+!
+
+      integer ncrdwr
+      integer nccreat
+      integer ncexcl
+      integer ncindef
+      integer ncnsync
+      integer nchsync
+      integer ncndirty
+      integer nchdirty
+      integer nclink
+      integer ncnowrit
+      integer ncwrite
+      integer ncclob
+      integer ncnoclob
+      integer ncglobal
+      integer ncfill
+      integer ncnofill
+      integer maxncop
+      integer maxncdim
+      integer maxncatt
+      integer maxncvar
+      integer maxncnam
+      integer maxvdims
+      integer ncnoerr
+      integer ncebadid
+      integer ncenfile
+      integer nceexist
+      integer nceinval
+      integer nceperm
+      integer ncenotin
+      integer nceindef
+      integer ncecoord
+      integer ncemaxds
+      integer ncename
+      integer ncenoatt
+      integer ncemaxat
+      integer ncebadty
+      integer ncebadd
+      integer ncests
+      integer nceunlim
+      integer ncemaxvs
+      integer ncenotvr
+      integer nceglob
+      integer ncenotnc
+      integer ncfoobar
+      integer ncsyserr
+      integer ncfatal
+      integer ncverbos
+      integer ncentool
+
+
+!
+! netcdf data types:
+!
+      integer ncbyte
+      integer ncchar
+      integer ncshort
+      integer nclong
+      integer ncfloat
+      integer ncdouble
+
+      parameter(ncbyte = 1)
+      parameter(ncchar = 2)
+      parameter(ncshort = 3)
+      parameter(nclong = 4)
+      parameter(ncfloat = 5)
+      parameter(ncdouble = 6)
+
+!
+!     masks for the struct nc flag field; passed in as 'mode' arg to
+!     nccreate and ncopen.
+!
+
+!     read/write, 0 => readonly
+      parameter(ncrdwr = 1)
+!     in create phase, cleared by ncendef
+      parameter(nccreat = 2)
+!     on create destroy existing file
+      parameter(ncexcl = 4)
+!     in define mode, cleared by ncendef
+      parameter(ncindef = 8)
+!     synchronise numrecs on change (x'10')
+      parameter(ncnsync = 16)
+!     synchronise whole header on change (x'20')
+      parameter(nchsync = 32)
+!     numrecs has changed (x'40')
+      parameter(ncndirty = 64)
+!     header info has changed (x'80')
+      parameter(nchdirty = 128)
+!     prefill vars on endef and increase of record, the default behavior
+      parameter(ncfill = 0)
+!     do not fill vars on endef and increase of record (x'100')
+      parameter(ncnofill = 256)
+!     isa link (x'8000')
+      parameter(nclink = 32768)
+
+!
+!     'mode' arguments for nccreate and ncopen
+!
+      parameter(ncnowrit = 0)
+      parameter(ncwrite = ncrdwr)
+      parameter(ncclob = nf_clobber)
+      parameter(ncnoclob = nf_noclobber)
+
+!
+!     'size' argument to ncdimdef for an unlimited dimension
+!
+      integer ncunlim
+      parameter(ncunlim = 0)
+
+!
+!     attribute id to put/get a global attribute
+!
+      parameter(ncglobal  = 0)
+
+!
+!     advisory maximums:
+!
+      parameter(maxncop = 32)
+      parameter(maxncdim = 100)
+      parameter(maxncatt = 2000)
+      parameter(maxncvar = 2000)
+!     not enforced
+      parameter(maxncnam = 128)
+      parameter(maxvdims = maxncdim)
+
+!
+!     global netcdf error status variable
+!     initialized in error.c
+!
+
+!     no error
+      parameter(ncnoerr = nf_noerr)
+!     not a netcdf id
+      parameter(ncebadid = nf_ebadid)
+!     too many netcdfs open
+      parameter(ncenfile = -31)   ! nc_syserr
+!     netcdf file exists && ncnoclob
+      parameter(nceexist = nf_eexist)
+!     invalid argument
+      parameter(nceinval = nf_einval)
+!     write to read only
+      parameter(nceperm = nf_eperm)
+!     operation not allowed in data mode
+      parameter(ncenotin = nf_enotindefine)
+!     operation not allowed in define mode
+      parameter(nceindef = nf_eindefine)
+!     coordinates out of domain
+      parameter(ncecoord = nf_einvalcoords)
+!     maxncdims exceeded
+      parameter(ncemaxds = nf_emaxdims)
+!     string match to name in use
+      parameter(ncename = nf_enameinuse)
+!     attribute not found
+      parameter(ncenoatt = nf_enotatt)
+!     maxncattrs exceeded
+      parameter(ncemaxat = nf_emaxatts)
+!     not a netcdf data type
+      parameter(ncebadty = nf_ebadtype)
+!     invalid dimension id
+      parameter(ncebadd = nf_ebaddim)
+!     ncunlimited in the wrong index
+      parameter(nceunlim = nf_eunlimpos)
+!     maxncvars exceeded
+      parameter(ncemaxvs = nf_emaxvars)
+!     variable not found
+      parameter(ncenotvr = nf_enotvar)
+!     action prohibited on ncglobal varid
+      parameter(nceglob = nf_eglobal)
+!     not a netcdf file
+      parameter(ncenotnc = nf_enotnc)
+      parameter(ncests = nf_ests)
+      parameter (ncentool = nf_emaxname)
+      parameter(ncfoobar = 32)
+      parameter(ncsyserr = -31)
+
+!
+!     global options variable. used to determine behavior of error handler.
+!     initialized in lerror.c
+!
+      parameter(ncfatal = 1)
+      parameter(ncverbos = 2)
+
+!
+!     default fill values.  these must be the same as in the c interface.
+!
+      integer filbyte
+      integer filchar
+      integer filshort
+      integer fillong
+      real filfloat
+      doubleprecision fildoub
+
+      parameter (filbyte = -127)
+      parameter (filchar = 0)
+      parameter (filshort = -32767)
+      parameter (fillong = -2147483647)
+      parameter (filfloat = 9.9692099683868690e+36)
+      parameter (fildoub = 9.9692099683868690e+36)
+
+! NULL request for non-blocking I/O APIs
+      integer NF_REQ_NULL
+      PARAMETER (NF_REQ_NULL = -1)
+
+! indicate to flush all pending non-blocking requests
+      integer NF_REQ_ALL
+      PARAMETER (NF_REQ_ALL = -1)
+
+!
+! PnetCDF APIs
+!
+
+!
+! miscellaneous routines:
+!
+      character*80  nfmpi_inq_libvers
+      character*80  nfmpi_strerror
+
+      external      nfmpi_inq_libvers
+      external      nfmpi_strerror
+
+      logical       nfmpi_issyserr
+      external      nfmpi_issyserr
+
+!
+! control routines:
+!
+      integer  nfmpi_create
+      integer  nfmpi_open
+      integer  nfmpi_inq_format
+      integer  nfmpi_inq_file_format
+      integer  nfmpi_inq_file_info
+      integer  nfmpi_get_file_info
+      integer  nfmpi_delete
+      integer  nfmpi_enddef
+      integer  nfmpi__enddef
+      integer  nfmpi_redef
+      integer  nfmpi_set_default_format
+      integer  nfmpi_inq_default_format
+      integer  nfmpi_sync
+      integer  nfmpi_abort
+      integer  nfmpi_close
+      integer  nfmpi_set_fill
+      integer  nfmpi_def_var_fill
+      integer  nfmpi_inq_var_fill
+      integer  nfmpi_fill_var_rec
+
+      external nfmpi_create
+      external nfmpi_open
+      external nfmpi_inq_format
+      external nfmpi_inq_file_format
+      external nfmpi_inq_file_info
+      external nfmpi_get_file_info
+      external nfmpi_delete
+      external nfmpi_enddef
+      external nfmpi__enddef
+      external nfmpi_redef
+      external nfmpi_set_default_format
+      external nfmpi_inq_default_format
+      external nfmpi_sync
+      external nfmpi_abort
+      external nfmpi_close
+      external nfmpi_set_fill
+      external nfmpi_def_var_fill
+      external nfmpi_inq_var_fill
+      external nfmpi_fill_var_rec
+
+!
+! general inquiry routines:
+!
+      integer  nfmpi_inq
+      integer  nfmpi_inq_ndims
+      integer  nfmpi_inq_nvars
+      integer  nfmpi_inq_num_rec_vars
+      integer  nfmpi_inq_num_fix_vars
+      integer  nfmpi_inq_natts
+      integer  nfmpi_inq_unlimdim
+      integer  nfmpi_inq_striping
+      integer  nfmpi_inq_malloc_size
+      integer  nfmpi_inq_malloc_max_size
+      integer  nfmpi_inq_malloc_list
+      integer  nfmpi_inq_files_opened
+      integer  nfmpi_inq_recsize
+
+      external nfmpi_inq
+      external nfmpi_inq_ndims
+      external nfmpi_inq_nvars
+      external nfmpi_inq_num_rec_vars
+      external nfmpi_inq_num_fix_vars
+      external nfmpi_inq_natts
+      external nfmpi_inq_unlimdim
+      external nfmpi_inq_striping
+      external nfmpi_inq_malloc_size
+      external nfmpi_inq_malloc_max_size
+      external nfmpi_inq_malloc_list
+      external nfmpi_inq_files_opened
+      external nfmpi_inq_recsize
+!
+! dimension routines:
+!
+      integer  nfmpi_def_dim
+      integer  nfmpi_inq_dimid
+      integer  nfmpi_inq_dim
+      integer  nfmpi_inq_dimname
+      integer  nfmpi_inq_dimlen
+      integer  nfmpi_rename_dim
+
+      external nfmpi_def_dim
+      external nfmpi_inq_dimid
+      external nfmpi_inq_dim
+      external nfmpi_inq_dimname
+      external nfmpi_inq_dimlen
+      external nfmpi_rename_dim
+!
+! general attribute routines:
+!
+      integer  nfmpi_inq_att
+      integer  nfmpi_inq_attid
+      integer  nfmpi_inq_atttype
+      integer  nfmpi_inq_attlen
+      integer  nfmpi_inq_attname
+      integer  nfmpi_copy_att
+      integer  nfmpi_rename_att
+      integer  nfmpi_del_att
+
+      external nfmpi_inq_att
+      external nfmpi_inq_attid
+      external nfmpi_inq_atttype
+      external nfmpi_inq_attlen
+      external nfmpi_inq_attname
+      external nfmpi_copy_att
+      external nfmpi_rename_att
+      external nfmpi_del_att
+
+!
+! attribute put/get routines:
+!
+      integer  nfmpi_put_att,        nfmpi_get_att
+      integer  nfmpi_put_att_text,   nfmpi_get_att_text
+      integer  nfmpi_put_att_int1,   nfmpi_get_att_int1
+      integer  nfmpi_put_att_int2,   nfmpi_get_att_int2
+      integer  nfmpi_put_att_int,    nfmpi_get_att_int
+      integer  nfmpi_put_att_real,   nfmpi_get_att_real
+      integer  nfmpi_put_att_double, nfmpi_get_att_double
+      integer  nfmpi_put_att_int8,   nfmpi_get_att_int8
+
+      external nfmpi_put_att,        nfmpi_get_att
+      external nfmpi_put_att_text,   nfmpi_get_att_text
+      external nfmpi_put_att_int1,   nfmpi_get_att_int1
+      external nfmpi_put_att_int2,   nfmpi_get_att_int2
+      external nfmpi_put_att_int,    nfmpi_get_att_int
+      external nfmpi_put_att_real,   nfmpi_get_att_real
+      external nfmpi_put_att_double, nfmpi_get_att_double
+      external nfmpi_put_att_int8,   nfmpi_get_att_int8
+
+!
+! independent data mode routines:
+!
+      integer  nfmpi_begin_indep_data
+      integer  nfmpi_end_indep_data
+
+      external nfmpi_begin_indep_data
+      external nfmpi_end_indep_data
+
+!
+! general variable routines:
+!
+      integer  nfmpi_def_var
+      integer  nfmpi_inq_var
+      integer  nfmpi_inq_varid
+      integer  nfmpi_inq_varname
+      integer  nfmpi_inq_vartype
+      integer  nfmpi_inq_varndims
+      integer  nfmpi_inq_vardimid
+      integer  nfmpi_inq_varnatts
+      integer  nfmpi_rename_var
+
+      external nfmpi_def_var
+      external nfmpi_inq_var
+      external nfmpi_inq_varid
+      external nfmpi_inq_varname
+      external nfmpi_inq_vartype
+      external nfmpi_inq_varndims
+      external nfmpi_inq_vardimid
+      external nfmpi_inq_varnatts
+      external nfmpi_rename_var
+
+!
+! entire variable put/get routines:
+!
+      integer  nfmpi_put_var
+      integer  nfmpi_put_var_text
+      integer  nfmpi_put_var_int1
+      integer  nfmpi_put_var_int2
+      integer  nfmpi_put_var_int
+      integer  nfmpi_put_var_real
+      integer  nfmpi_put_var_double
+      integer  nfmpi_put_var_int8
+
+      external nfmpi_put_var
+      external nfmpi_put_var_text
+      external nfmpi_put_var_int1
+      external nfmpi_put_var_int2
+      external nfmpi_put_var_int
+      external nfmpi_put_var_real
+      external nfmpi_put_var_double
+      external nfmpi_put_var_int8
+
+      integer  nfmpi_get_var,        nfmpi_get_var_all
+      integer  nfmpi_get_var_text,   nfmpi_get_var_text_all
+      integer  nfmpi_get_var_int1,   nfmpi_get_var_int1_all
+      integer  nfmpi_get_var_int2,   nfmpi_get_var_int2_all
+      integer  nfmpi_get_var_int,    nfmpi_get_var_int_all
+      integer  nfmpi_get_var_real,   nfmpi_get_var_real_all
+      integer  nfmpi_get_var_double, nfmpi_get_var_double_all
+      integer  nfmpi_get_var_int8,   nfmpi_get_var_int8_all
+
+      external nfmpi_get_var,        nfmpi_get_var_all
+      external nfmpi_get_var_text,   nfmpi_get_var_text_all
+      external nfmpi_get_var_int1,   nfmpi_get_var_int1_all
+      external nfmpi_get_var_int2,   nfmpi_get_var_int2_all
+      external nfmpi_get_var_int,    nfmpi_get_var_int_all
+      external nfmpi_get_var_real,   nfmpi_get_var_real_all
+      external nfmpi_get_var_double, nfmpi_get_var_double_all
+      external nfmpi_get_var_int8,   nfmpi_get_var_int8_all
+
+!
+! single element variable put/get routines:
+!
+      integer  nfmpi_put_var1,        nfmpi_put_var1_all
+      integer  nfmpi_put_var1_text,   nfmpi_put_var1_text_all
+      integer  nfmpi_put_var1_int1,   nfmpi_put_var1_int1_all
+      integer  nfmpi_put_var1_int2,   nfmpi_put_var1_int2_all
+      integer  nfmpi_put_var1_int,    nfmpi_put_var1_int_all
+      integer  nfmpi_put_var1_real,   nfmpi_put_var1_real_all
+      integer  nfmpi_put_var1_double, nfmpi_put_var1_double_all
+      integer  nfmpi_put_var1_int8,   nfmpi_put_var1_int8_all
+
+      external nfmpi_put_var1,        nfmpi_put_var1_all
+      external nfmpi_put_var1_text,   nfmpi_put_var1_text_all
+      external nfmpi_put_var1_int1,   nfmpi_put_var1_int1_all
+      external nfmpi_put_var1_int2,   nfmpi_put_var1_int2_all
+      external nfmpi_put_var1_int,    nfmpi_put_var1_int_all
+      external nfmpi_put_var1_real,   nfmpi_put_var1_real_all
+      external nfmpi_put_var1_double, nfmpi_put_var1_double_all
+      external nfmpi_put_var1_int8,   nfmpi_put_var1_int8_all
+
+      integer  nfmpi_get_var1,        nfmpi_get_var1_all
+      integer  nfmpi_get_var1_text,   nfmpi_get_var1_text_all
+      integer  nfmpi_get_var1_int1,   nfmpi_get_var1_int1_all
+      integer  nfmpi_get_var1_int2,   nfmpi_get_var1_int2_all
+      integer  nfmpi_get_var1_int,    nfmpi_get_var1_int_all
+      integer  nfmpi_get_var1_real,   nfmpi_get_var1_real_all
+      integer  nfmpi_get_var1_double, nfmpi_get_var1_double_all
+      integer  nfmpi_get_var1_int8,   nfmpi_get_var1_int8_all
+
+      external nfmpi_get_var1,        nfmpi_get_var1_all
+      external nfmpi_get_var1_text,   nfmpi_get_var1_text_all
+      external nfmpi_get_var1_int1,   nfmpi_get_var1_int1_all
+      external nfmpi_get_var1_int2,   nfmpi_get_var1_int2_all
+      external nfmpi_get_var1_int,    nfmpi_get_var1_int_all
+      external nfmpi_get_var1_real,   nfmpi_get_var1_real_all
+      external nfmpi_get_var1_double, nfmpi_get_var1_double_all
+      external nfmpi_get_var1_int8,   nfmpi_get_var1_int8_all
+
+!
+! variable sub-array put/get routines:
+!
+      integer  nfmpi_put_vara,        nfmpi_put_vara_all
+      integer  nfmpi_put_vara_text,   nfmpi_put_vara_text_all
+      integer  nfmpi_put_vara_int1,   nfmpi_put_vara_int1_all
+      integer  nfmpi_put_vara_int2,   nfmpi_put_vara_int2_all
+      integer  nfmpi_put_vara_int,    nfmpi_put_vara_int_all
+      integer  nfmpi_put_vara_real,   nfmpi_put_vara_real_all
+      integer  nfmpi_put_vara_double, nfmpi_put_vara_double_all
+      integer  nfmpi_put_vara_int8,   nfmpi_put_vara_int8_all
+
+      external nfmpi_put_vara,        nfmpi_put_vara_all
+      external nfmpi_put_vara_text,   nfmpi_put_vara_text_all
+      external nfmpi_put_vara_int1,   nfmpi_put_vara_int1_all
+      external nfmpi_put_vara_int2,   nfmpi_put_vara_int2_all
+      external nfmpi_put_vara_int,    nfmpi_put_vara_int_all
+      external nfmpi_put_vara_real,   nfmpi_put_vara_real_all
+      external nfmpi_put_vara_double, nfmpi_put_vara_double_all
+      external nfmpi_put_vara_int8,   nfmpi_put_vara_int8_all
+
+      integer  nfmpi_get_vara,        nfmpi_get_vara_all
+      integer  nfmpi_get_vara_text,   nfmpi_get_vara_text_all
+      integer  nfmpi_get_vara_int1,   nfmpi_get_vara_int1_all
+      integer  nfmpi_get_vara_int2,   nfmpi_get_vara_int2_all
+      integer  nfmpi_get_vara_int,    nfmpi_get_vara_int_all
+      integer  nfmpi_get_vara_real,   nfmpi_get_vara_real_all
+      integer  nfmpi_get_vara_double, nfmpi_get_vara_double_all
+      integer  nfmpi_get_vara_int8,   nfmpi_get_vara_int8_all
+
+      external nfmpi_get_vara,        nfmpi_get_vara_all
+      external nfmpi_get_vara_text,   nfmpi_get_vara_text_all
+      external nfmpi_get_vara_int1,   nfmpi_get_vara_int1_all
+      external nfmpi_get_vara_int2,   nfmpi_get_vara_int2_all
+      external nfmpi_get_vara_int,    nfmpi_get_vara_int_all
+      external nfmpi_get_vara_real,   nfmpi_get_vara_real_all
+      external nfmpi_get_vara_double, nfmpi_get_vara_double_all
+      external nfmpi_get_vara_int8,   nfmpi_get_vara_int8_all
+
+!
+! strided variable put/get routines:
+!
+      integer  nfmpi_put_vars,        nfmpi_put_vars_all
+      integer  nfmpi_put_vars_text,   nfmpi_put_vars_text_all
+      integer  nfmpi_put_vars_int1,   nfmpi_put_vars_int1_all
+      integer  nfmpi_put_vars_int2,   nfmpi_put_vars_int2_all
+      integer  nfmpi_put_vars_int,    nfmpi_put_vars_int_all
+      integer  nfmpi_put_vars_real,   nfmpi_put_vars_real_all
+      integer  nfmpi_put_vars_double, nfmpi_put_vars_double_all
+      integer  nfmpi_put_vars_int8,   nfmpi_put_vars_int8_all
+
+      external nfmpi_put_vars,        nfmpi_put_vars_all
+      external nfmpi_put_vars_text,   nfmpi_put_vars_text_all
+      external nfmpi_put_vars_int1,   nfmpi_put_vars_int1_all
+      external nfmpi_put_vars_int2,   nfmpi_put_vars_int2_all
+      external nfmpi_put_vars_int,    nfmpi_put_vars_int_all
+      external nfmpi_put_vars_real,   nfmpi_put_vars_real_all
+      external nfmpi_put_vars_double, nfmpi_put_vars_double_all
+      external nfmpi_put_vars_int8,   nfmpi_put_vars_int8_all
+
+      integer  nfmpi_get_vars,        nfmpi_get_vars_all
+      integer  nfmpi_get_vars_text,   nfmpi_get_vars_text_all
+      integer  nfmpi_get_vars_int1,   nfmpi_get_vars_int1_all
+      integer  nfmpi_get_vars_int2,   nfmpi_get_vars_int2_all
+      integer  nfmpi_get_vars_int,    nfmpi_get_vars_int_all
+      integer  nfmpi_get_vars_real,   nfmpi_get_vars_real_all
+      integer  nfmpi_get_vars_double, nfmpi_get_vars_double_all
+      integer  nfmpi_get_vars_int8,   nfmpi_get_vars_int8_all
+
+      external nfmpi_get_vars,        nfmpi_get_vars_all
+      external nfmpi_get_vars_text,   nfmpi_get_vars_text_all
+      external nfmpi_get_vars_int1,   nfmpi_get_vars_int1_all
+      external nfmpi_get_vars_int2,   nfmpi_get_vars_int2_all
+      external nfmpi_get_vars_int,    nfmpi_get_vars_int_all
+      external nfmpi_get_vars_real,   nfmpi_get_vars_real_all
+      external nfmpi_get_vars_double, nfmpi_get_vars_double_all
+      external nfmpi_get_vars_int8,   nfmpi_get_vars_int8_all
+
+!
+! mapped variable put/get routines:
+!
+      integer  nfmpi_put_varm,        nfmpi_put_varm_all
+      integer  nfmpi_put_varm_text,   nfmpi_put_varm_text_all
+      integer  nfmpi_put_varm_int1,   nfmpi_put_varm_int1_all
+      integer  nfmpi_put_varm_int2,   nfmpi_put_varm_int2_all
+      integer  nfmpi_put_varm_int,    nfmpi_put_varm_int_all
+      integer  nfmpi_put_varm_real,   nfmpi_put_varm_real_all
+      integer  nfmpi_put_varm_double, nfmpi_put_varm_double_all
+      integer  nfmpi_put_varm_int8,   nfmpi_put_varm_int8_all
+
+      external nfmpi_put_varm,        nfmpi_put_varm_all
+      external nfmpi_put_varm_text,   nfmpi_put_varm_text_all
+      external nfmpi_put_varm_int1,   nfmpi_put_varm_int1_all
+      external nfmpi_put_varm_int2,   nfmpi_put_varm_int2_all
+      external nfmpi_put_varm_int,    nfmpi_put_varm_int_all
+      external nfmpi_put_varm_real,   nfmpi_put_varm_real_all
+      external nfmpi_put_varm_double, nfmpi_put_varm_double_all
+      external nfmpi_put_varm_int8,   nfmpi_put_varm_int8_all
+
+      integer  nfmpi_get_varm,        nfmpi_get_varm_all
+      integer  nfmpi_get_varm_text,   nfmpi_get_varm_text_all
+      integer  nfmpi_get_varm_int1,   nfmpi_get_varm_int1_all
+      integer  nfmpi_get_varm_int2,   nfmpi_get_varm_int2_all
+      integer  nfmpi_get_varm_int,    nfmpi_get_varm_int_all
+      integer  nfmpi_get_varm_real,   nfmpi_get_varm_real_all
+      integer  nfmpi_get_varm_double, nfmpi_get_varm_double_all
+      integer  nfmpi_get_varm_int8,   nfmpi_get_varm_int8_all
+
+      external nfmpi_get_varm,        nfmpi_get_varm_all
+      external nfmpi_get_varm_text,   nfmpi_get_varm_text_all
+      external nfmpi_get_varm_int1,   nfmpi_get_varm_int1_all
+      external nfmpi_get_varm_int2,   nfmpi_get_varm_int2_all
+      external nfmpi_get_varm_int,    nfmpi_get_varm_int_all
+      external nfmpi_get_varm_real,   nfmpi_get_varm_real_all
+      external nfmpi_get_varm_double, nfmpi_get_varm_double_all
+      external nfmpi_get_varm_int8,   nfmpi_get_varm_int8_all
+
+!
+! Non-blocking APIs
+!
+! entire variable iput/iget routines:
+!
+      integer  nfmpi_iput_var
+      integer  nfmpi_iput_var_text
+      integer  nfmpi_iput_var_int1
+      integer  nfmpi_iput_var_int2
+      integer  nfmpi_iput_var_int
+      integer  nfmpi_iput_var_real
+      integer  nfmpi_iput_var_double
+      integer  nfmpi_iput_var_int8
+
+      external nfmpi_iput_var
+      external nfmpi_iput_var_text
+      external nfmpi_iput_var_int1
+      external nfmpi_iput_var_int2
+      external nfmpi_iput_var_int
+      external nfmpi_iput_var_real
+      external nfmpi_iput_var_double
+      external nfmpi_iput_var_int8
+
+      integer  nfmpi_iget_var
+      integer  nfmpi_iget_var_text
+      integer  nfmpi_iget_var_int1
+      integer  nfmpi_iget_var_int2
+      integer  nfmpi_iget_var_int
+      integer  nfmpi_iget_var_real
+      integer  nfmpi_iget_var_double
+      integer  nfmpi_iget_var_int8
+
+      external nfmpi_iget_var
+      external nfmpi_iget_var_text
+      external nfmpi_iget_var_int1
+      external nfmpi_iget_var_int2
+      external nfmpi_iget_var_int
+      external nfmpi_iget_var_real
+      external nfmpi_iget_var_double
+      external nfmpi_iget_var_int8
+
+!
+! Nonblocking single-element variable iput/iget routines:
+!
+      integer  nfmpi_iput_var1
+      integer  nfmpi_iput_var1_text
+      integer  nfmpi_iput_var1_int1
+      integer  nfmpi_iput_var1_int2
+      integer  nfmpi_iput_var1_int
+      integer  nfmpi_iput_var1_real
+      integer  nfmpi_iput_var1_double
+      integer  nfmpi_iput_var1_int8
+
+      external nfmpi_iput_var1
+      external nfmpi_iput_var1_text
+      external nfmpi_iput_var1_int1
+      external nfmpi_iput_var1_int2
+      external nfmpi_iput_var1_int
+      external nfmpi_iput_var1_real
+      external nfmpi_iput_var1_double
+      external nfmpi_iput_var1_int8
+
+      integer  nfmpi_iget_var1
+      integer  nfmpi_iget_var1_text
+      integer  nfmpi_iget_var1_int1
+      integer  nfmpi_iget_var1_int2
+      integer  nfmpi_iget_var1_int
+      integer  nfmpi_iget_var1_real
+      integer  nfmpi_iget_var1_double
+      integer  nfmpi_iget_var1_int8
+
+      external nfmpi_iget_var1
+      external nfmpi_iget_var1_text
+      external nfmpi_iget_var1_int1
+      external nfmpi_iget_var1_int2
+      external nfmpi_iget_var1_int
+      external nfmpi_iget_var1_real
+      external nfmpi_iget_var1_double
+      external nfmpi_iget_var1_int8
+
+!
+! Nonblocking subarray variable iput/iget routines:
+!
+      integer  nfmpi_iput_vara
+      integer  nfmpi_iput_vara_text
+      integer  nfmpi_iput_vara_int1
+      integer  nfmpi_iput_vara_int2
+      integer  nfmpi_iput_vara_int
+      integer  nfmpi_iput_vara_real
+      integer  nfmpi_iput_vara_double
+      integer  nfmpi_iput_vara_int8
+
+      external nfmpi_iput_vara
+      external nfmpi_iput_vara_text
+      external nfmpi_iput_vara_int1
+      external nfmpi_iput_vara_int2
+      external nfmpi_iput_vara_int
+      external nfmpi_iput_vara_real
+      external nfmpi_iput_vara_double
+      external nfmpi_iput_vara_int8
+
+      integer  nfmpi_iget_vara
+      integer  nfmpi_iget_vara_text
+      integer  nfmpi_iget_vara_int1
+      integer  nfmpi_iget_vara_int2
+      integer  nfmpi_iget_vara_int
+      integer  nfmpi_iget_vara_real
+      integer  nfmpi_iget_vara_double
+      integer  nfmpi_iget_vara_int8
+
+      external nfmpi_iget_vara
+      external nfmpi_iget_vara_text
+      external nfmpi_iget_vara_int1
+      external nfmpi_iget_vara_int2
+      external nfmpi_iget_vara_int
+      external nfmpi_iget_vara_real
+      external nfmpi_iget_vara_double
+      external nfmpi_iget_vara_int8
+
+!
+! Nonblocking strided variable iput/iget routines:
+!
+      integer  nfmpi_iput_vars
+      integer  nfmpi_iput_vars_text
+      integer  nfmpi_iput_vars_int1
+      integer  nfmpi_iput_vars_int2
+      integer  nfmpi_iput_vars_int
+      integer  nfmpi_iput_vars_real
+      integer  nfmpi_iput_vars_double
+      integer  nfmpi_iput_vars_int8
+
+      external nfmpi_iput_vars
+      external nfmpi_iput_vars_text
+      external nfmpi_iput_vars_int1
+      external nfmpi_iput_vars_int2
+      external nfmpi_iput_vars_int
+      external nfmpi_iput_vars_real
+      external nfmpi_iput_vars_double
+      external nfmpi_iput_vars_int8
+
+      integer  nfmpi_iget_vars
+      integer  nfmpi_iget_vars_text
+      integer  nfmpi_iget_vars_int1
+      integer  nfmpi_iget_vars_int2
+      integer  nfmpi_iget_vars_int
+      integer  nfmpi_iget_vars_real
+      integer  nfmpi_iget_vars_double
+      integer  nfmpi_iget_vars_int8
+
+      external nfmpi_iget_vars
+      external nfmpi_iget_vars_text
+      external nfmpi_iget_vars_int1
+      external nfmpi_iget_vars_int2
+      external nfmpi_iget_vars_int
+      external nfmpi_iget_vars_real
+      external nfmpi_iget_vars_double
+      external nfmpi_iget_vars_int8
+
+!
+! Nonblocking mapped variable iput/iget routines:
+!
+      integer  nfmpi_iput_varm
+      integer  nfmpi_iput_varm_text
+      integer  nfmpi_iput_varm_int1
+      integer  nfmpi_iput_varm_int2
+      integer  nfmpi_iput_varm_int
+      integer  nfmpi_iput_varm_real
+      integer  nfmpi_iput_varm_double
+      integer  nfmpi_iput_varm_int8
+
+      external nfmpi_iput_varm
+      external nfmpi_iput_varm_text
+      external nfmpi_iput_varm_int1
+      external nfmpi_iput_varm_int2
+      external nfmpi_iput_varm_int
+      external nfmpi_iput_varm_real
+      external nfmpi_iput_varm_double
+      external nfmpi_iput_varm_int8
+
+      integer  nfmpi_iget_varm
+      integer  nfmpi_iget_varm_text
+      integer  nfmpi_iget_varm_int1
+      integer  nfmpi_iget_varm_int2
+      integer  nfmpi_iget_varm_int
+      integer  nfmpi_iget_varm_real
+      integer  nfmpi_iget_varm_double
+      integer  nfmpi_iget_varm_int8
+
+      external nfmpi_iget_varm
+      external nfmpi_iget_varm_text
+      external nfmpi_iget_varm_int1
+      external nfmpi_iget_varm_int2
+      external nfmpi_iget_varm_int
+      external nfmpi_iget_varm_real
+      external nfmpi_iget_varm_double
+      external nfmpi_iget_varm_int8
+
+!
+! Nonblocking entire variable bput routines:
+!
+      integer  nfmpi_bput_var
+      integer  nfmpi_bput_var_text
+      integer  nfmpi_bput_var_int1
+      integer  nfmpi_bput_var_int2
+      integer  nfmpi_bput_var_int
+      integer  nfmpi_bput_var_real
+      integer  nfmpi_bput_var_double
+      integer  nfmpi_bput_var_int8
+
+      external nfmpi_bput_var
+      external nfmpi_bput_var_text
+      external nfmpi_bput_var_int1
+      external nfmpi_bput_var_int2
+      external nfmpi_bput_var_int
+      external nfmpi_bput_var_real
+      external nfmpi_bput_var_double
+      external nfmpi_bput_var_int8
+
+!
+! Nonblocking single element variable bput routines:
+!
+      integer  nfmpi_bput_var1
+      integer  nfmpi_bput_var1_text
+      integer  nfmpi_bput_var1_int1
+      integer  nfmpi_bput_var1_int2
+      integer  nfmpi_bput_var1_int
+      integer  nfmpi_bput_var1_real
+      integer  nfmpi_bput_var1_double
+      integer  nfmpi_bput_var1_int8
+
+      external nfmpi_bput_var1
+      external nfmpi_bput_var1_text
+      external nfmpi_bput_var1_int1
+      external nfmpi_bput_var1_int2
+      external nfmpi_bput_var1_int
+      external nfmpi_bput_var1_real
+      external nfmpi_bput_var1_double
+      external nfmpi_bput_var1_int8
+
+!
+! Nonblocking subarray variable bput routines:
+!
+      integer  nfmpi_bput_vara
+      integer  nfmpi_bput_vara_text
+      integer  nfmpi_bput_vara_int1
+      integer  nfmpi_bput_vara_int2
+      integer  nfmpi_bput_vara_int
+      integer  nfmpi_bput_vara_real
+      integer  nfmpi_bput_vara_double
+      integer  nfmpi_bput_vara_int8
+
+      external nfmpi_bput_vara
+      external nfmpi_bput_vara_text
+      external nfmpi_bput_vara_int1
+      external nfmpi_bput_vara_int2
+      external nfmpi_bput_vara_int
+      external nfmpi_bput_vara_real
+      external nfmpi_bput_vara_double
+      external nfmpi_bput_vara_int8
+
+!
+! Nonblocking strided variable bput routines:
+!
+      integer  nfmpi_bput_vars
+      integer  nfmpi_bput_vars_text
+      integer  nfmpi_bput_vars_int1
+      integer  nfmpi_bput_vars_int2
+      integer  nfmpi_bput_vars_int
+      integer  nfmpi_bput_vars_real
+      integer  nfmpi_bput_vars_double
+      integer  nfmpi_bput_vars_int8
+
+      external nfmpi_bput_vars
+      external nfmpi_bput_vars_text
+      external nfmpi_bput_vars_int1
+      external nfmpi_bput_vars_int2
+      external nfmpi_bput_vars_int
+      external nfmpi_bput_vars_real
+      external nfmpi_bput_vars_double
+      external nfmpi_bput_vars_int8
+
+!
+! Nonblocking mapped variable bput routines:
+!
+      integer  nfmpi_bput_varm
+      integer  nfmpi_bput_varm_text
+      integer  nfmpi_bput_varm_int1
+      integer  nfmpi_bput_varm_int2
+      integer  nfmpi_bput_varm_int
+      integer  nfmpi_bput_varm_real
+      integer  nfmpi_bput_varm_double
+      integer  nfmpi_bput_varm_int8
+
+      external nfmpi_bput_varm
+      external nfmpi_bput_varm_text
+      external nfmpi_bput_varm_int1
+      external nfmpi_bput_varm_int2
+      external nfmpi_bput_varm_int
+      external nfmpi_bput_varm_real
+      external nfmpi_bput_varm_double
+      external nfmpi_bput_varm_int8
+
+!
+! Nonblocking control APIs
+!
+      integer  nfmpi_wait
+      integer  nfmpi_wait_all
+      integer  nfmpi_cancel
+
+      external nfmpi_wait
+      external nfmpi_wait_all
+      external nfmpi_cancel
+
+      integer  nfmpi_buffer_attach
+      integer  nfmpi_buffer_detach
+      integer  nfmpi_inq_buffer_usage
+      integer  nfmpi_inq_buffer_size
+      integer  nfmpi_inq_put_size
+      integer  nfmpi_inq_get_size
+      integer  nfmpi_inq_header_size
+      integer  nfmpi_inq_header_extent
+      integer  nfmpi_inq_varoffset
+      integer  nfmpi_inq_nreqs
+
+      external nfmpi_buffer_attach
+      external nfmpi_buffer_detach
+      external nfmpi_inq_buffer_usage
+      external nfmpi_inq_buffer_size
+      external nfmpi_inq_put_size
+      external nfmpi_inq_get_size
+      external nfmpi_inq_header_size
+      external nfmpi_inq_header_extent
+      external nfmpi_inq_varoffset
+      external nfmpi_inq_nreqs
+
+!
+! varn routines:
+!
+      integer  nfmpi_put_varn,        nfmpi_put_varn_all
+      integer  nfmpi_put_varn_text,   nfmpi_put_varn_text_all
+      integer  nfmpi_put_varn_int1,   nfmpi_put_varn_int1_all
+      integer  nfmpi_put_varn_int2,   nfmpi_put_varn_int2_all
+      integer  nfmpi_put_varn_int,    nfmpi_put_varn_int_all
+      integer  nfmpi_put_varn_real,   nfmpi_put_varn_real_all
+      integer  nfmpi_put_varn_double, nfmpi_put_varn_double_all
+      integer  nfmpi_put_varn_int8,   nfmpi_put_varn_int8_all
+
+      external nfmpi_put_varn,        nfmpi_put_varn_all
+      external nfmpi_put_varn_text,   nfmpi_put_varn_text_all
+      external nfmpi_put_varn_int1,   nfmpi_put_varn_int1_all
+      external nfmpi_put_varn_int2,   nfmpi_put_varn_int2_all
+      external nfmpi_put_varn_int,    nfmpi_put_varn_int_all
+      external nfmpi_put_varn_real,   nfmpi_put_varn_real_all
+      external nfmpi_put_varn_double, nfmpi_put_varn_double_all
+      external nfmpi_put_varn_int8,   nfmpi_put_varn_int8_all
+
+      integer  nfmpi_get_varn,        nfmpi_get_varn_all
+      integer  nfmpi_get_varn_text,   nfmpi_get_varn_text_all
+      integer  nfmpi_get_varn_int1,   nfmpi_get_varn_int1_all
+      integer  nfmpi_get_varn_int2,   nfmpi_get_varn_int2_all
+      integer  nfmpi_get_varn_int,    nfmpi_get_varn_int_all
+      integer  nfmpi_get_varn_real,   nfmpi_get_varn_real_all
+      integer  nfmpi_get_varn_double, nfmpi_get_varn_double_all
+      integer  nfmpi_get_varn_int8,   nfmpi_get_varn_int8_all
+
+      external nfmpi_get_varn,        nfmpi_get_varn_all
+      external nfmpi_get_varn_text,   nfmpi_get_varn_text_all
+      external nfmpi_get_varn_int1,   nfmpi_get_varn_int1_all
+      external nfmpi_get_varn_int2,   nfmpi_get_varn_int2_all
+      external nfmpi_get_varn_int,    nfmpi_get_varn_int_all
+      external nfmpi_get_varn_real,   nfmpi_get_varn_real_all
+      external nfmpi_get_varn_double, nfmpi_get_varn_double_all
+      external nfmpi_get_varn_int8,   nfmpi_get_varn_int8_all
+
+!
+! Nonblocking varn routines:
+!
+      integer  nfmpi_iput_varn
+      integer  nfmpi_iput_varn_text
+      integer  nfmpi_iput_varn_int1
+      integer  nfmpi_iput_varn_int2
+      integer  nfmpi_iput_varn_int
+      integer  nfmpi_iput_varn_real
+      integer  nfmpi_iput_varn_double
+      integer  nfmpi_iput_varn_int8
+
+      external nfmpi_iput_varn
+      external nfmpi_iput_varn_text
+      external nfmpi_iput_varn_int1
+      external nfmpi_iput_varn_int2
+      external nfmpi_iput_varn_int
+      external nfmpi_iput_varn_real
+      external nfmpi_iput_varn_double
+      external nfmpi_iput_varn_int8
+
+      integer  nfmpi_iget_varn
+      integer  nfmpi_iget_varn_text
+      integer  nfmpi_iget_varn_int1
+      integer  nfmpi_iget_varn_int2
+      integer  nfmpi_iget_varn_int
+      integer  nfmpi_iget_varn_real
+      integer  nfmpi_iget_varn_double
+      integer  nfmpi_iget_varn_int8
+
+      external nfmpi_iget_varn
+      external nfmpi_iget_varn_text
+      external nfmpi_iget_varn_int1
+      external nfmpi_iget_varn_int2
+      external nfmpi_iget_varn_int
+      external nfmpi_iget_varn_real
+      external nfmpi_iget_varn_double
+      external nfmpi_iget_varn_int8
+
+      integer  nfmpi_bput_varn
+      integer  nfmpi_bput_varn_text
+      integer  nfmpi_bput_varn_int1
+      integer  nfmpi_bput_varn_int2
+      integer  nfmpi_bput_varn_int
+      integer  nfmpi_bput_varn_real
+      integer  nfmpi_bput_varn_double
+      integer  nfmpi_bput_varn_int8
+
+      external nfmpi_bput_varn
+      external nfmpi_bput_varn_text
+      external nfmpi_bput_varn_int1
+      external nfmpi_bput_varn_int2
+      external nfmpi_bput_varn_int
+      external nfmpi_bput_varn_real
+      external nfmpi_bput_varn_double
+      external nfmpi_bput_varn_int8
+
+!
+! vard routines:
+!
+      integer  nfmpi_put_vard, nfmpi_put_vard_all
+      integer  nfmpi_get_vard, nfmpi_get_vard_all
+
+      external nfmpi_put_vard, nfmpi_put_vard_all
+      external nfmpi_get_vard, nfmpi_get_vard_all
+
diff --git a/src/libf/strerrorf.f b/src/libf/strerrorf.f
new file mode 100644
index 0000000..fc0444c
--- /dev/null
+++ b/src/libf/strerrorf.f
@@ -0,0 +1,10 @@
+      character *80 function nfmpi_strerror( err )
+      integer err, ierr
+      character *(80) tmpstr
+
+      integer nfmpi_xstrerror
+      external nfmpi_xstrerror
+
+      ierr = nfmpi_xstrerror( err, tmpstr )
+      nfmpi_strerror = tmpstr
+      end
diff --git a/src/libf90/Makefile.in b/src/libf90/Makefile.in
new file mode 100644
index 0000000..fe9a55e
--- /dev/null
+++ b/src/libf90/Makefile.in
@@ -0,0 +1,84 @@
+#
+# Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2285 2015-12-30 20:48:25Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+# generated by configure, so it's in the build dir, not srcdirr
+include ../../macros.make
+
+# F90FLAGS = @FC_DEFINE at MPI_OFFSET_KIND=@SIZEOF_MPI_OFFSET@
+
+# For VPATH build:
+# Add . into search path because api.f90 and nfmpi_constants.f90 are created in
+# the build directory at configure time and they are included in pnetcdf.f90.
+# If NAG compiler is used, $(srcdir) must also be added into search path
+# because NAG does not seem to look for include file in the same directory as
+# the source file.
+INCLUDES = -I. -I$(srcdir)
+
+LIBRARY = ../lib/libpnetcdf.a
+
+PNETCDF_MOD = pnetcdf. at FC_MODEXT@
+ifeq (@UPPER_CASE_MOD@, yes)
+  PNETCDF_MOD = PNETCDF. at FC_MODEXT@
+endif
+
+F90FLAGS += @FC_MODOUT at .
+M4FLAGS  += -DINTENTV=@INTENTV@
+
+M4_SRCS = getput_text.m4 \
+          getput_var.m4 \
+          getput_varn.m4 \
+          getput_vard.m4
+
+F90_SRCS = nf90_constants.f90 \
+           overloads.f90 \
+           visibility.f90 \
+           file.f90 \
+           dims.f90 \
+           attributes.f90 \
+           variables.f90 \
+           pnetcdf.f90
+
+SRCS     = $(F90_SRCS) $(M4_SRCS:.m4=.f90) \
+           api.f90 nfmpi_constants.f90
+
+LIB_OBJS = pnetcdf.o
+
+PACKING_LIST = $(F90_SRCS) \
+               $(M4_SRCS) \
+               Makefile.in \
+               api.f90.in \
+               nfmpi_constants.f90.in
+
+GARBAGE		= $(PNETCDF_MOD) $(M4_SRCS:.m4=.f90)
+DIST_GARBAGE	= api.f90 nfmpi_constants.f90
+
+%.mod: %.f90 $(SRCS)
+	$(COMPILE.f90) $<
+
+all: $(LIBRARY)
+
+library $(LIBRARY): $(LIB_OBJS)
+	$(AR) $(ARFLAGS) $(LIBRARY) $(LIB_OBJS)
+	$(RANLIB) $(LIBRARY)
+
+$(LIB_OBJS): $(SRCS)
+
+$(PNETCDF_MOD): $(SRCS)
+
+install: $(PNETCDF_MOD)
+	$(INSTALL) -d -m 755 $(INCDIR)
+	$(INSTALL_DATA) $(PNETCDF_MOD) $(INCDIR)
+
+uninstall:
+	$(RM) -f $(INCDIR)/$(PNETCDF_MOD)
+
+include $(srcdir)/../../rules.make
+
diff --git a/src/libf90/api.f90.in b/src/libf90/api.f90.in
new file mode 100644
index 0000000..a277c0a
--- /dev/null
+++ b/src/libf90/api.f90.in
@@ -0,0 +1,4110 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: api.f90.in 2221 2015-12-12 00:39:15Z wkliao $
+!
+
+!
+! miscellaneous subroutines:
+!
+INTERFACE
+    character(LEN=80) FUNCTION nfmpi_inq_libvers()
+    END FUNCTION   nfmpi_inq_libvers
+
+    character(LEN=80) FUNCTION nfmpi_strerror(ncerr)
+                            INTEGER,                       INTENT(IN)  :: ncerr
+    END FUNCTION   nfmpi_strerror
+
+    logical        FUNCTION nfmpi_issyserr(ncerr)
+                            INTEGER,                       INTENT(IN)  :: ncerr
+    END FUNCTION   nfmpi_issyserr
+
+!
+! control subroutines:
+!
+    INTEGER        FUNCTION nfmpi_create(mpi_comm, path, cmode, mpi_info, ncid)
+                            INTEGER,                       INTENT(IN)  :: mpi_comm
+                            CHARACTER(len=*),              INTENT(IN)  :: path
+                            INTEGER,                       INTENT(IN)  :: cmode
+                            INTEGER,                       INTENT(IN)  :: mpi_info
+                            INTEGER,                       INTENT(OUT) :: ncid
+    END FUNCTION   nfmpi_create
+
+    INTEGER        FUNCTION nfmpi_open(mpi_comm, path, mode, mpi_info, ncid)
+                            INTEGER,                       INTENT(IN)  :: mpi_comm
+                            CHARACTER(len=*),              INTENT(IN)  :: path
+                            INTEGER,                       INTENT(IN)  :: mode
+                            INTEGER,                       INTENT(IN)  :: mpi_info
+                            INTEGER,                       INTENT(OUT) :: ncid
+    END FUNCTION   nfmpi_open
+
+    INTEGER        FUNCTION nfmpi_inq_format(ncid, format)
+                            INTEGER,                       INTENT(IN)   :: ncid
+                            INTEGER,                       INTENT(OUT)  :: format
+    END FUNCTION   nfmpi_inq_format
+
+    INTEGER        FUNCTION nfmpi_inq_file_format(path, format)
+                            CHARACTER(len=*),              INTENT(IN)  :: path
+                            INTEGER,                       INTENT(OUT)  :: format
+    END FUNCTION   nfmpi_inq_file_format
+
+    INTEGER        FUNCTION nfmpi_inq_file_info(ncid, mpi_info)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(OUT) :: mpi_info
+    END FUNCTION   nfmpi_inq_file_info
+
+    INTEGER        FUNCTION nfmpi_get_file_info(ncid, mpi_info)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(OUT) :: mpi_info
+    END FUNCTION   nfmpi_get_file_info
+
+    INTEGER        FUNCTION nfmpi_delete(path, mpi_info)
+                            CHARACTER(len=*),              INTENT(IN)  :: path
+                            INTEGER,                       INTENT(IN)  :: mpi_info
+    END FUNCTION   nfmpi_delete
+
+    INTEGER        FUNCTION nfmpi_enddef(ncid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+    END FUNCTION   nfmpi_enddef
+
+    INTEGER        FUNCTION nfmpi__enddef(ncid, h_minfree, v_align, v_minfree, r_align)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: h_minfree
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: v_align
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: v_minfree
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: r_align
+    END FUNCTION   nfmpi__enddef
+
+    INTEGER        FUNCTION nfmpi_redef(ncid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+    END FUNCTION   nfmpi_redef
+
+    INTEGER        FUNCTION nfmpi_set_default_format(new_format, old_format)
+                            INTEGER,                       INTENT(IN)  :: new_format
+                            INTEGER,                       INTENT(OUT) :: old_format
+    END FUNCTION   nfmpi_set_default_format
+
+    INTEGER        FUNCTION nfmpi_inq_default_format(default_format)
+                            INTEGER,                       INTENT(OUT) :: default_format
+    END FUNCTION   nfmpi_inq_default_format
+
+    INTEGER        FUNCTION nfmpi_sync(ncid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+    END FUNCTION   nfmpi_sync
+
+    INTEGER        FUNCTION nfmpi_abort(ncid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+    END FUNCTION   nfmpi_abort
+
+    INTEGER        FUNCTION nfmpi_close(ncid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+    END FUNCTION   nfmpi_close
+
+    INTEGER        FUNCTION nfmpi_set_fill(ncid, fillmode, old_mode)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: fillmode
+                            INTEGER,                       INTENT(OUT) :: old_mode
+    END FUNCTION   nfmpi_set_fill
+
+!
+! general inquiry subroutines:
+!
+
+    INTEGER        FUNCTION nfmpi_inq(ncid, ndims, nvars, ngatts, unlimdimid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(OUT) :: ndims
+                            INTEGER,                       INTENT(OUT) :: nvars
+                            INTEGER,                       INTENT(OUT) :: ngatts
+                            INTEGER,                       INTENT(OUT) :: unlimdimid
+    END FUNCTION   nfmpi_inq
+
+    INTEGER        FUNCTION nfmpi_inq_striping(ncid, striping_size, striping_count)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(OUT) :: striping_size
+                            INTEGER,                       INTENT(OUT) :: striping_count
+    END FUNCTION   nfmpi_inq_striping
+
+    INTEGER        FUNCTION nfmpi_inq_ndims(ncid, ndims)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(OUT) :: ndims
+    END FUNCTION   nfmpi_inq_ndims
+
+    INTEGER        FUNCTION nfmpi_inq_nvars(ncid, nvars)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(OUT) :: nvars
+    END FUNCTION   nfmpi_inq_nvars
+
+    INTEGER        FUNCTION nfmpi_inq_num_rec_vars(ncid, nvars)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(OUT) :: nvars
+    END FUNCTION   nfmpi_inq_num_rec_vars
+
+    INTEGER        FUNCTION nfmpi_inq_num_fix_vars(ncid, nvars)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(OUT) :: nvars
+    END FUNCTION   nfmpi_inq_num_fix_vars
+
+    INTEGER        FUNCTION nfmpi_inq_natts(ncid, ngatts)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(OUT) :: ngatts
+    END FUNCTION   nfmpi_inq_natts
+
+    INTEGER        FUNCTION nfmpi_inq_unlimdim(ncid, unlimdimid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(OUT) :: unlimdimid
+    END FUNCTION   nfmpi_inq_unlimdim
+
+!
+! dimension subroutines:
+!
+
+    INTEGER        FUNCTION nfmpi_def_dim(ncid, name, len, dimid)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: len
+                            INTEGER,                       INTENT(OUT) :: dimid
+    END FUNCTION   nfmpi_def_dim
+
+    INTEGER        FUNCTION nfmpi_inq_dimid(ncid, name, dimid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(OUT) :: dimid
+    END FUNCTION   nfmpi_inq_dimid
+
+    INTEGER        FUNCTION nfmpi_inq_dim(ncid, dimid, name, len)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: dimid
+                            CHARACTER(len=*),              INTENT(OUT) :: name
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: len
+    END FUNCTION   nfmpi_inq_dim
+
+    INTEGER        FUNCTION nfmpi_inq_dimname(ncid, dimid, name)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: dimid
+                            CHARACTER(len=*),              INTENT(OUT) :: name
+    END FUNCTION   nfmpi_inq_dimname
+
+    INTEGER        FUNCTION nfmpi_inq_dimlen(ncid, dimid, len)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: dimid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: len
+    END FUNCTION   nfmpi_inq_dimlen
+
+    INTEGER        FUNCTION nfmpi_rename_dim(ncid, dimid, name)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: dimid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+    END FUNCTION   nfmpi_rename_dim
+
+!
+! general attribute subroutines:
+!
+
+    INTEGER        FUNCTION nfmpi_inq_att(ncid, varid, name, xtype, len)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(OUT) :: xtype
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: len
+    END FUNCTION   nfmpi_inq_att
+
+    INTEGER        FUNCTION nfmpi_inq_attid(ncid, varid, name, attid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(OUT) :: attid
+    END FUNCTION   nfmpi_inq_attid
+
+    INTEGER        FUNCTION nfmpi_inq_atttype(ncid, varid, name, xtype)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(OUT) :: xtype
+    END FUNCTION   nfmpi_inq_atttype
+
+    INTEGER        FUNCTION nfmpi_inq_attlen(ncid, varid, name, len)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: len
+    END FUNCTION   nfmpi_inq_attlen
+
+    INTEGER        FUNCTION nfmpi_inq_attname(ncid, varid, attid, name)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER,                       INTENT(IN)  :: attid
+                            CHARACTER(len=*),              INTENT(OUT) :: name
+    END FUNCTION   nfmpi_inq_attname
+
+    INTEGER        FUNCTION nfmpi_copy_att(ncid_in, varid_in, name, ncid_out, varid_out)
+                            INTEGER,                       INTENT(IN)  :: ncid_in
+                            INTEGER,                       INTENT(IN)  :: varid_in
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(IN)  :: ncid_out
+                            INTEGER,                       INTENT(IN)  :: varid_out
+    END FUNCTION   nfmpi_copy_att
+
+    INTEGER        FUNCTION nfmpi_rename_att(ncid, varid, curname, newname)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: curname
+                            CHARACTER(len=*),              INTENT(IN)  :: newname
+    END FUNCTION   nfmpi_rename_att
+
+    INTEGER        FUNCTION nfmpi_del_att(ncid, varid, name)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+    END FUNCTION   nfmpi_del_att
+
+!
+! attribute put/get subroutines:
+!
+
+    INTEGER        FUNCTION nfmpi_put_att_text(ncid, varid, name, len, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: len
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+    END FUNCTION   nfmpi_put_att_text
+
+    INTEGER        FUNCTION nfmpi_get_att_text(ncid, varid, name, text)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+    END FUNCTION   nfmpi_get_att_text
+
+    INTEGER        FUNCTION nfmpi_put_att_int1(ncid, varid, name, xtype, len, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(IN)  :: xtype
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: len
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+    END FUNCTION   nfmpi_put_att_int1
+
+    INTEGER        FUNCTION nfmpi_get_att_int1(ncid, varid, name, i1vals)
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+    END FUNCTION   nfmpi_get_att_int1
+
+    INTEGER        FUNCTION nfmpi_put_att_int2(ncid, varid, name, xtype, len, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(IN)  :: xtype
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: len
+                            INTEGER(KIND=TwoByteInt),      INTENT(IN)  :: i2vals(*)
+    END FUNCTION   nfmpi_put_att_int2
+
+    INTEGER        FUNCTION nfmpi_get_att_int2(ncid, varid, name, i2vals)
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+    END FUNCTION   nfmpi_get_att_int2
+
+    INTEGER        FUNCTION nfmpi_put_att_int(ncid, varid, name, xtype, len, IVALS)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(IN)  :: xtype
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: len
+                            INTEGER,                       INTENT(IN)  :: ivals(*)
+    END FUNCTION   nfmpi_put_att_int
+
+    INTEGER        FUNCTION nfmpi_get_att_int(ncid, varid, name, IVALS)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+    END FUNCTION   nfmpi_get_att_int
+
+    INTEGER        FUNCTION nfmpi_put_att_real(ncid, varid, name, xtype, len, RVALS)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(IN)  :: xtype
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: len
+                            REAL,                          INTENT(IN)  :: rvals(*)
+    END FUNCTION   nfmpi_put_att_real
+
+    INTEGER        FUNCTION nfmpi_get_att_real(ncid, varid, name, rvals)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            REAL,                          INTENT(OUT) :: rvals(*)
+    END FUNCTION   nfmpi_get_att_real
+
+    INTEGER        FUNCTION nfmpi_put_att_double(ncid, varid, name, xtype, len, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(IN)  :: xtype
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: len
+                            DOUBLE PRECISION,              INTENT(IN)  :: dvals(*)
+    END FUNCTION   nfmpi_put_att_double
+
+    INTEGER        FUNCTION nfmpi_get_att_double(ncid, varid, name, dvals)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+    END FUNCTION   nfmpi_get_att_double
+
+    INTEGER        FUNCTION nfmpi_put_att_int8(ncid, varid, name, xtype, len, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(IN)  :: xtype
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: len
+                            INTEGER(KIND=EightByteInt),    INTENT(IN)  :: i8vals(*)
+    END FUNCTION   nfmpi_put_att_int8
+
+    INTEGER        FUNCTION nfmpi_get_att_int8(ncid, varid, name, i8vals)
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+    END FUNCTION   nfmpi_get_att_int8
+
+!
+! independent data mode subroutines:
+!
+    INTEGER        FUNCTION nfmpi_begin_indep_data(ncid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+    END FUNCTION   nfmpi_begin_indep_data
+
+    INTEGER        FUNCTION nfmpi_end_indep_data(ncid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+    END FUNCTION   nfmpi_end_indep_data
+!
+! general variable subroutines:
+!
+
+    INTEGER        FUNCTION nfmpi_def_var(ncid, name, datatype, ndims, dimids, varid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(IN)  :: datatype
+                            INTEGER,                       INTENT(IN)  :: ndims
+                            INTEGER,                       INTENT(IN)  :: dimids(ndims)
+                            INTEGER,                       INTENT(OUT) :: varid
+    END FUNCTION   nfmpi_def_var
+
+    INTEGER        FUNCTION nfmpi_inq_var(ncid, varid, name, datatype, ndims, dimids, natts)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(OUT) :: name
+                            INTEGER,                       INTENT(OUT) :: datatype
+                            INTEGER,                       INTENT(OUT) :: ndims
+                            INTEGER,                       INTENT(OUT) :: dimids(*)
+                            INTEGER,                       INTENT(OUT) :: natts
+    END FUNCTION   nfmpi_inq_var
+
+    INTEGER        FUNCTION nfmpi_inq_varid(ncid, name, varid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+                            INTEGER,                       INTENT(OUT) :: varid
+    END FUNCTION   nfmpi_inq_varid
+
+    INTEGER        FUNCTION nfmpi_inq_varname(ncid, varid, name)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(OUT) :: name
+    END FUNCTION   nfmpi_inq_varname
+
+    INTEGER        FUNCTION nfmpi_inq_vartype(ncid, varid, xtype)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER,                       INTENT(OUT) :: xtype
+    END FUNCTION   nfmpi_inq_vartype
+
+    INTEGER        FUNCTION nfmpi_inq_varndims(ncid, varid, ndims)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER,                       INTENT(OUT) :: ndims
+    END FUNCTION   nfmpi_inq_varndims
+
+    INTEGER        FUNCTION nfmpi_inq_vardimid(ncid, varid, dimids)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER,                       INTENT(OUT) :: dimids(*)
+    END FUNCTION   nfmpi_inq_vardimid
+
+    INTEGER        FUNCTION nfmpi_inq_varnatts(ncid, varid, natts)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER,                       INTENT(OUT) :: natts
+    END FUNCTION   nfmpi_inq_varnatts
+
+    INTEGER        FUNCTION nfmpi_rename_var(ncid, varid, name)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: name
+    END FUNCTION   nfmpi_rename_var
+
+!   INTEGER        FUNCTION nfmpi_def_var_fill(ncid, varid, no_fill, fill_value)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER,                       INTENT(IN)  :: no_fill
+!                           <type>,                        INTENT(IN)  :: fill_value
+!   END FUNCTION   nfmpi_def_var_fill
+
+!   INTEGER        FUNCTION nfmpi_inq_var_fill(ncid, varid, no_fill, fill_value)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER,                       INTENT(OUT) :: no_fill
+!                           <type>,                        INTENT(OUT) :: fill_value
+!   END FUNCTION   nfmpi_inq_var_fill
+
+    INTEGER        FUNCTION nfmpi_fill_var_rec(ncid, varid, recno)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: recno
+    END FUNCTION   nfmpi_fill_var_rec
+
+!
+! entire variable put/get subroutines:
+!
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_put_var(ncid, varid, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_put_var
+
+!   INTEGER        FUNCTION nfmpi_get_var(ncid, varid, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_get_var
+
+!   INTEGER        FUNCTION nfmpi_get_var_all (ncid, varid, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_get_var_all
+
+    INTEGER        FUNCTION nfmpi_put_var_text(ncid, varid, text)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+    END FUNCTION   nfmpi_put_var_text
+
+    INTEGER        FUNCTION nfmpi_get_var_text(ncid, varid, text)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+    END FUNCTION   nfmpi_get_var_text
+
+    INTEGER        FUNCTION nfmpi_get_var_text_all(ncid, varid, text)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+    END FUNCTION   nfmpi_get_var_text_all
+
+    INTEGER        FUNCTION nfmpi_put_var_int1(ncid, varid, i1vals)
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+    END FUNCTION   nfmpi_put_var_int1
+
+    INTEGER        FUNCTION nfmpi_get_var_int1(ncid, varid, i1vals)
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+    END FUNCTION   nfmpi_get_var_int1
+
+    INTEGER        FUNCTION nfmpi_get_var_int1_all(ncid, varid, i1vals)
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+    END FUNCTION   nfmpi_get_var_int1_all
+
+    INTEGER        FUNCTION nfmpi_put_var_int2(ncid, varid, i2vals)
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+    END FUNCTION   nfmpi_put_var_int2
+
+    INTEGER        FUNCTION nfmpi_get_var_int2(ncid, varid, i2vals)
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+    END FUNCTION   nfmpi_get_var_int2
+
+    INTEGER        FUNCTION nfmpi_get_var_int2_all(ncid, varid, i2vals)
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+    END FUNCTION   nfmpi_get_var_int2_all
+
+    INTEGER        FUNCTION nfmpi_put_var_int(ncid, varid, ivals)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+    END FUNCTION   nfmpi_put_var_int
+
+    INTEGER        FUNCTION nfmpi_get_var_int(ncid, varid, ivals)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+    END FUNCTION   nfmpi_get_var_int
+
+    INTEGER        FUNCTION nfmpi_get_var_int_all(ncid, varid, ivals)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+    END FUNCTION   nfmpi_get_var_int_all
+
+    INTEGER        FUNCTION nfmpi_put_var_real(ncid, varid, rvals)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            REAL,                          INTENT(@INTENTV@) :: rvals(*)
+    END FUNCTION   nfmpi_put_var_real
+
+    INTEGER        FUNCTION nfmpi_get_var_real(ncid, varid, rvals)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            REAL,                          INTENT(OUT) :: rvals(*)
+    END FUNCTION   nfmpi_get_var_real
+
+    INTEGER        FUNCTION nfmpi_get_var_real_all(ncid, varid, rvals)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            REAL,                          INTENT(OUT) :: rvals(*)
+    END FUNCTION   nfmpi_get_var_real_all
+
+    INTEGER        FUNCTION nfmpi_put_var_double(ncid, varid, dvals)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+    END FUNCTION   nfmpi_put_var_double
+
+    INTEGER        FUNCTION nfmpi_get_var_double(ncid, varid, dvals)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+    END FUNCTION   nfmpi_get_var_double
+
+    INTEGER        FUNCTION nfmpi_get_var_double_all(ncid, varid, dvals)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+    END FUNCTION   nfmpi_get_var_double_all
+
+    INTEGER        FUNCTION nfmpi_put_var_int8(ncid, varid, i8vals)
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+    END FUNCTION   nfmpi_put_var_int8
+
+    INTEGER        FUNCTION nfmpi_get_var_int8(ncid, varid, i8vals)
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+    END FUNCTION   nfmpi_get_var_int8
+
+    INTEGER        FUNCTION nfmpi_get_var_int8_all(ncid, varid, i8vals)
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+    END FUNCTION   nfmpi_get_var_int8_all
+
+!
+! single variable put/get subroutines:
+!
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_put_var1(ncid, varid, index, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_put_var1
+
+!   INTEGER        FUNCTION nfmpi_put_var1_all(ncid, varid, index, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_put_var1_all
+
+!   INTEGER        FUNCTION nfmpi_get_var1(ncid, varid, index, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_get_var1
+
+!   INTEGER        FUNCTION nfmpi_get_var1_all(ncid, varid, index, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_get_var1_all
+
+    INTEGER        FUNCTION nfmpi_put_var1_text(ncid, varid, index, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            CHARACTER,                     INTENT(IN)  :: text
+    END FUNCTION   nfmpi_put_var1_text
+
+    INTEGER        FUNCTION nfmpi_put_var1_text_all(ncid, varid, index, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            CHARACTER,                     INTENT(IN)  :: text
+    END FUNCTION   nfmpi_put_var1_text_all
+
+    INTEGER        FUNCTION nfmpi_get_var1_text(ncid, varid, index, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            CHARACTER,                     INTENT(OUT) :: text
+    END FUNCTION   nfmpi_get_var1_text
+
+    INTEGER        FUNCTION nfmpi_get_var1_text_all(ncid, varid, index, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            CHARACTER,                     INTENT(OUT) :: text
+    END FUNCTION   nfmpi_get_var1_text_all
+
+    INTEGER        FUNCTION nfmpi_put_var1_int1(ncid, varid, index, i1val)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1val
+    END FUNCTION   nfmpi_put_var1_int1
+
+    INTEGER        FUNCTION nfmpi_put_var1_int1_all(ncid, varid, index, i1val)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1val
+    END FUNCTION   nfmpi_put_var1_int1_all
+
+    INTEGER        FUNCTION nfmpi_get_var1_int1(ncid, varid, index, i1val)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1val
+    END FUNCTION   nfmpi_get_var1_int1
+
+    INTEGER        FUNCTION nfmpi_get_var1_int1_all(ncid, varid, index, i1val)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1val
+    END FUNCTION   nfmpi_get_var1_int1_all
+
+    INTEGER        FUNCTION nfmpi_put_var1_int2(ncid, varid, index, i2val)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2val
+    END FUNCTION   nfmpi_put_var1_int2
+
+    INTEGER        FUNCTION nfmpi_put_var1_int2_all(ncid, varid, index, i2val)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2val
+    END FUNCTION   nfmpi_put_var1_int2_all
+
+    INTEGER        FUNCTION nfmpi_get_var1_int2(ncid, varid, index, i2val)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2val
+    END FUNCTION   nfmpi_get_var1_int2
+
+    INTEGER        FUNCTION nfmpi_get_var1_int2_all(ncid, varid, index, i2val)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2val
+    END FUNCTION   nfmpi_get_var1_int2_all
+
+    INTEGER        FUNCTION nfmpi_put_var1_int(ncid, varid, index, ival)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER,                       INTENT(@INTENTV@) :: ival
+    END FUNCTION   nfmpi_put_var1_int
+
+    INTEGER        FUNCTION nfmpi_put_var1_int_all(ncid, varid, index, ival)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER,                       INTENT(@INTENTV@) :: ival
+    END FUNCTION   nfmpi_put_var1_int_all
+
+    INTEGER        FUNCTION nfmpi_get_var1_int(ncid, varid, index, ival)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER,                       INTENT(OUT) :: ival
+    END FUNCTION   nfmpi_get_var1_int
+
+    INTEGER        FUNCTION nfmpi_get_var1_int_all(ncid, varid, index, ival)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER,                       INTENT(OUT) :: ival
+    END FUNCTION   nfmpi_get_var1_int_all
+
+    INTEGER        FUNCTION nfmpi_put_var1_real(ncid, varid, index, rval)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            REAL,                          INTENT(@INTENTV@) :: rval
+    END FUNCTION   nfmpi_put_var1_real
+
+    INTEGER        FUNCTION nfmpi_put_var1_real_all(ncid, varid, index, rval)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            REAL,                          INTENT(@INTENTV@) :: rval
+    END FUNCTION   nfmpi_put_var1_real_all
+
+    INTEGER        FUNCTION nfmpi_get_var1_real(ncid, varid, index, rval)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            REAL,                          INTENT(OUT) :: rval
+    END FUNCTION   nfmpi_get_var1_real
+
+    INTEGER        FUNCTION nfmpi_get_var1_real_all(ncid, varid, index, rval)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            REAL,                          INTENT(OUT) :: rval
+    END FUNCTION   nfmpi_get_var1_real_all
+
+    INTEGER        FUNCTION nfmpi_put_var1_double(ncid, varid, index, dval)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dval
+    END FUNCTION   nfmpi_put_var1_double
+
+    INTEGER        FUNCTION nfmpi_put_var1_double_all(ncid, varid, index, dval)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dval
+    END FUNCTION   nfmpi_put_var1_double_all
+
+    INTEGER        FUNCTION nfmpi_get_var1_double(ncid, varid, index, dval)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            DOUBLE PRECISION,              INTENT(OUT) :: dval
+    END FUNCTION   nfmpi_get_var1_double
+
+    INTEGER        FUNCTION nfmpi_get_var1_double_all(ncid, varid, index, dval)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            DOUBLE PRECISION,              INTENT(OUT) :: dval
+    END FUNCTION   nfmpi_get_var1_double_all
+
+    INTEGER        FUNCTION nfmpi_put_var1_int8(ncid, varid, index, i8val)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8val
+    END FUNCTION   nfmpi_put_var1_int8
+
+    INTEGER        FUNCTION nfmpi_put_var1_int8_all(ncid, varid, index, i8val)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8val
+    END FUNCTION   nfmpi_put_var1_int8_all
+
+    INTEGER        FUNCTION nfmpi_get_var1_int8(ncid, varid, index, i8val)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8val
+    END FUNCTION   nfmpi_get_var1_int8
+
+    INTEGER        FUNCTION nfmpi_get_var1_int8_all(ncid, varid, index, i8val)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8val
+    END FUNCTION   nfmpi_get_var1_int8_all
+
+!
+! variable array put/get subroutines:
+!
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_put_vara(ncid, varid, start, count, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_put_vara
+
+!   INTEGER        FUNCTION nfmpi_put_vara_all(ncid, varid, start, count, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_put_vara_all
+
+!   INTEGER        FUNCTION nfmpi_get_vara(ncid, varid, start, count, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_get_vara
+
+!   INTEGER        FUNCTION nfmpi_get_vara_all (ncid, varid, start, count, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_get_vara_all
+
+    INTEGER        FUNCTION nfmpi_put_vara_text(ncid, varid, start, count, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+    END FUNCTION   nfmpi_put_vara_text
+
+    INTEGER        FUNCTION nfmpi_put_vara_text_all(ncid, varid, start, count, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+    END FUNCTION   nfmpi_put_vara_text_all
+
+    INTEGER        FUNCTION nfmpi_get_vara_text(ncid, varid, start, count, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+    END FUNCTION   nfmpi_get_vara_text
+
+    INTEGER        FUNCTION nfmpi_get_vara_text_all(ncid, varid, start, count, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+    END FUNCTION   nfmpi_get_vara_text_all
+
+    INTEGER        FUNCTION nfmpi_put_vara_int1(ncid, varid, start, count, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+    END FUNCTION   nfmpi_put_vara_int1
+
+    INTEGER        FUNCTION nfmpi_put_vara_int1_all(ncid, varid, start, count, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+    END FUNCTION   nfmpi_put_vara_int1_all
+
+    INTEGER        FUNCTION nfmpi_get_vara_int1(ncid, varid, start, count, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+    END FUNCTION   nfmpi_get_vara_int1
+
+    INTEGER        FUNCTION nfmpi_get_vara_int1_all(ncid, varid, start, count, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+    END FUNCTION   nfmpi_get_vara_int1_all
+
+    INTEGER        FUNCTION nfmpi_put_vara_int2(ncid, varid, start, count, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+    END FUNCTION   nfmpi_put_vara_int2
+
+    INTEGER        FUNCTION nfmpi_put_vara_int2_all(ncid, varid, start, count, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+    END FUNCTION   nfmpi_put_vara_int2_all
+
+    INTEGER        FUNCTION nfmpi_get_vara_int2(ncid, varid, start, count, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+    END FUNCTION   nfmpi_get_vara_int2
+
+    INTEGER        FUNCTION nfmpi_get_vara_int2_all(ncid, varid, start, count, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+    END FUNCTION   nfmpi_get_vara_int2_all
+
+    INTEGER        FUNCTION nfmpi_put_vara_int(ncid, varid, start, count, ivals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+    END FUNCTION   nfmpi_put_vara_int
+
+    INTEGER        FUNCTION nfmpi_put_vara_int_all(ncid, varid, start, count, ivals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+    END FUNCTION   nfmpi_put_vara_int_all
+
+    INTEGER        FUNCTION nfmpi_get_vara_int(ncid, varid, start, count, ivals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+    END FUNCTION   nfmpi_get_vara_int
+
+    INTEGER        FUNCTION nfmpi_get_vara_int_all(ncid, varid, start, count, ivals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+    END FUNCTION   nfmpi_get_vara_int_all
+
+    INTEGER        FUNCTION nfmpi_put_vara_real(ncid, varid, start, count, rvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            REAL,                          INTENT(@INTENTV@) :: rvals(*)
+    END FUNCTION   nfmpi_put_vara_real
+
+    INTEGER        FUNCTION nfmpi_put_vara_real_all(ncid, varid, start, count, rvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            REAL,                          INTENT(@INTENTV@) :: rvals(*)
+    END FUNCTION   nfmpi_put_vara_real_all
+
+    INTEGER        FUNCTION nfmpi_get_vara_real(ncid, varid, start, count, rvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            REAL,                          INTENT(OUT) :: rvals(*)
+    END FUNCTION   nfmpi_get_vara_real
+
+    INTEGER        FUNCTION nfmpi_get_vara_real_all(ncid, varid, start, count, rvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            REAL,                          INTENT(OUT) :: rvals(*)
+    END FUNCTION   nfmpi_get_vara_real_all
+
+    INTEGER        FUNCTION nfmpi_put_vara_double(ncid, varid, start, count, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+    END FUNCTION   nfmpi_put_vara_double
+
+    INTEGER        FUNCTION nfmpi_put_vara_double_all(ncid, varid, start, count, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+    END FUNCTION   nfmpi_put_vara_double_all
+
+    INTEGER        FUNCTION nfmpi_get_vara_double(ncid, varid, start, count, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+    END FUNCTION   nfmpi_get_vara_double
+
+    INTEGER        FUNCTION nfmpi_get_vara_double_all(ncid, varid, start, count, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+    END FUNCTION   nfmpi_get_vara_double_all
+
+    INTEGER        FUNCTION nfmpi_put_vara_int8(ncid, varid, start, count, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+    END FUNCTION   nfmpi_put_vara_int8
+
+    INTEGER        FUNCTION nfmpi_put_vara_int8_all(ncid, varid, start, count, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+    END FUNCTION   nfmpi_put_vara_int8_all
+
+    INTEGER        FUNCTION nfmpi_get_vara_int8(ncid, varid, start, count, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+    END FUNCTION   nfmpi_get_vara_int8
+
+    INTEGER        FUNCTION nfmpi_get_vara_int8_all(ncid, varid, start, count, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+    END FUNCTION   nfmpi_get_vara_int8_all
+
+!
+! strided variable put/get subroutines:
+!
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_put_vars(ncid, varid, start, count, stride, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_put_vars
+
+!   INTEGER        FUNCTION nfmpi_put_vars_all(ncid, varid, start, count, stride, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_put_vars_all
+
+!   INTEGER        FUNCTION nfmpi_get_vars(ncid, varid, start, count, stride, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_get_vars
+
+!   INTEGER        FUNCTION nfmpi_get_vars_all(ncid, varid, start, count, stride, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_get_vars_all
+
+    INTEGER        FUNCTION nfmpi_put_vars_text(ncid, varid, start, count, stride, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+    END FUNCTION   nfmpi_put_vars_text
+
+    INTEGER        FUNCTION nfmpi_put_vars_text_all(ncid, varid, start, count, stride, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+    END FUNCTION   nfmpi_put_vars_text_all
+
+    INTEGER        FUNCTION nfmpi_get_vars_text(ncid, varid, start, count, stride, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+    END FUNCTION   nfmpi_get_vars_text
+
+    INTEGER        FUNCTION nfmpi_get_vars_text_all(ncid, varid, start, count, stride, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+    END FUNCTION   nfmpi_get_vars_text_all
+
+    INTEGER        FUNCTION nfmpi_put_vars_int1(ncid, varid, start, count, stride, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+    END FUNCTION   nfmpi_put_vars_int1
+
+    INTEGER        FUNCTION nfmpi_put_vars_int1_all(ncid, varid, start, count, stride, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+    END FUNCTION   nfmpi_put_vars_int1_all
+
+    INTEGER        FUNCTION nfmpi_get_vars_int1(ncid, varid, start, count, stride, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+    END FUNCTION   nfmpi_get_vars_int1
+
+    INTEGER        FUNCTION nfmpi_get_vars_int1_all(ncid, varid, start, count, stride, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+    END FUNCTION   nfmpi_get_vars_int1_all
+
+    INTEGER        FUNCTION nfmpi_put_vars_int2(ncid, varid, start, count, stride, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+    END FUNCTION   nfmpi_put_vars_int2
+
+    INTEGER        FUNCTION nfmpi_put_vars_int2_all(ncid, varid, start, count, stride, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+    END FUNCTION   nfmpi_put_vars_int2_all
+
+    INTEGER        FUNCTION nfmpi_get_vars_int2(ncid, varid, start, count, stride, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+    END FUNCTION   nfmpi_get_vars_int2
+
+    INTEGER        FUNCTION nfmpi_get_vars_int2_all(ncid, varid, start, count, stride, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+    END FUNCTION   nfmpi_get_vars_int2_all
+
+    INTEGER        FUNCTION nfmpi_put_vars_int(ncid, varid, start, count, stride, ivals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+    END FUNCTION   nfmpi_put_vars_int
+
+    INTEGER        FUNCTION nfmpi_put_vars_int_all(ncid, varid, start, count, stride, ivals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+    END FUNCTION   nfmpi_put_vars_int_all
+
+    INTEGER        FUNCTION nfmpi_get_vars_int(ncid, varid, start, count, stride, ivals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+    END FUNCTION   nfmpi_get_vars_int
+
+    INTEGER        FUNCTION nfmpi_get_vars_int_all(ncid, varid, start, count, stride, ivals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+    END FUNCTION   nfmpi_get_vars_int_all
+
+    INTEGER        FUNCTION nfmpi_put_vars_real(ncid, varid, start, count, stride, rvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            REAL,                          INTENT(@INTENTV@) :: rvals(*)
+    END FUNCTION   nfmpi_put_vars_real
+
+    INTEGER        FUNCTION nfmpi_put_vars_real_all(ncid, varid, start, count, stride, rvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            REAL,                          INTENT(@INTENTV@) :: rvals(*)
+    END FUNCTION   nfmpi_put_vars_real_all
+
+    INTEGER        FUNCTION nfmpi_get_vars_real(ncid, varid, start, count, stride, rvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            REAL,                          INTENT(OUT) :: rvals(*)
+    END FUNCTION   nfmpi_get_vars_real
+
+    INTEGER        FUNCTION nfmpi_get_vars_real_all(ncid, varid, start, count, stride, rvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            REAL,                          INTENT(OUT) :: rvals(*)
+    END FUNCTION   nfmpi_get_vars_real_all
+
+    INTEGER        FUNCTION nfmpi_put_vars_double(ncid, varid, start, count, stride, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+    END FUNCTION   nfmpi_put_vars_double
+
+    INTEGER        FUNCTION nfmpi_put_vars_double_all(ncid, varid, start, count, stride, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+    END FUNCTION   nfmpi_put_vars_double_all
+
+    INTEGER        FUNCTION nfmpi_get_vars_double(ncid, varid, start, count, stride, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+    END FUNCTION   nfmpi_get_vars_double
+
+    INTEGER        FUNCTION nfmpi_get_vars_double_all(ncid, varid, start, count, stride, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+    END FUNCTION   nfmpi_get_vars_double_all
+
+    INTEGER        FUNCTION nfmpi_put_vars_int8(ncid, varid, start, count, stride, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+    END FUNCTION   nfmpi_put_vars_int8
+
+    INTEGER        FUNCTION nfmpi_put_vars_int8_all(ncid, varid, start, count, stride, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+    END FUNCTION   nfmpi_put_vars_int8_all
+
+    INTEGER        FUNCTION nfmpi_get_vars_int8(ncid, varid, start, count, stride, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+    END FUNCTION   nfmpi_get_vars_int8
+
+    INTEGER        FUNCTION nfmpi_get_vars_int8_all(ncid, varid, start, count, stride, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+    END FUNCTION   nfmpi_get_vars_int8_all
+
+!
+! mapped variable put/get subroutines:
+!
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_put_varm(ncid, varid, start, count, stride, imap, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_put_varm
+
+!   INTEGER        FUNCTION nfmpi_put_varm_all(ncid, varid, start, count, stride, imap, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_put_varm_all
+
+!   INTEGER        FUNCTION nfmpi_get_varm(ncid, varid, start, count, stride, imap, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_get_varm
+
+!   INTEGER        FUNCTION nfmpi_get_varm_all(ncid, varid, start, count, stride, imap, buf, bufcount, datatype)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!   END FUNCTION   nfmpi_get_varm_all
+
+    INTEGER        FUNCTION nfmpi_put_varm_text(ncid, varid, start, count, stride, imap, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+    END FUNCTION   nfmpi_put_varm_text
+
+    INTEGER        FUNCTION nfmpi_put_varm_text_all(ncid, varid, start, count, stride, imap, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+    END FUNCTION   nfmpi_put_varm_text_all
+
+    INTEGER        FUNCTION nfmpi_get_varm_text(ncid, varid, start, count, stride, imap, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+    END FUNCTION   nfmpi_get_varm_text
+
+    INTEGER        FUNCTION nfmpi_get_varm_text_all(ncid, varid, start, count, stride, imap, text)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+    END FUNCTION   nfmpi_get_varm_text_all
+
+    INTEGER        FUNCTION nfmpi_put_varm_int1(ncid, varid, start, count, stride, imap, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+    END FUNCTION   nfmpi_put_varm_int1
+
+    INTEGER        FUNCTION nfmpi_put_varm_int1_all(ncid, varid, start, count, stride, imap, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+    END FUNCTION   nfmpi_put_varm_int1_all
+
+    INTEGER        FUNCTION nfmpi_get_varm_int1(ncid, varid, start, count, stride, imap, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+    END FUNCTION   nfmpi_get_varm_int1
+
+    INTEGER        FUNCTION nfmpi_get_varm_int1_all(ncid, varid, start, count, stride, imap, i1vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+    END FUNCTION   nfmpi_get_varm_int1_all
+
+    INTEGER        FUNCTION nfmpi_put_varm_int2(ncid, varid, start, count, stride, imap, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+    END FUNCTION   nfmpi_put_varm_int2
+
+    INTEGER        FUNCTION nfmpi_put_varm_int2_all(ncid, varid, start, count, stride, imap, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+    END FUNCTION   nfmpi_put_varm_int2_all
+
+    INTEGER        FUNCTION nfmpi_get_varm_int2(ncid, varid, start, count, stride, imap, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+    END FUNCTION   nfmpi_get_varm_int2
+
+    INTEGER        FUNCTION nfmpi_get_varm_int2_all(ncid, varid, start, count, stride, imap, i2vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+    END FUNCTION   nfmpi_get_varm_int2_all
+
+    INTEGER        FUNCTION nfmpi_put_varm_int (ncid, varid, start, count, stride, imap, ivals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+    END FUNCTION   nfmpi_put_varm_int
+
+    INTEGER        FUNCTION nfmpi_put_varm_int_all(ncid, varid, start, count, stride, imap, ivals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+    END FUNCTION   nfmpi_put_varm_int_all
+
+    INTEGER        FUNCTION nfmpi_get_varm_int (ncid, varid, start, count, stride, imap, ivals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+    END FUNCTION   nfmpi_get_varm_int
+
+    INTEGER        FUNCTION nfmpi_get_varm_int_all(ncid, varid, start, count, stride, imap, ivals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+    END FUNCTION   nfmpi_get_varm_int_all
+
+    INTEGER        FUNCTION nfmpi_put_varm_real(ncid, varid, start, count, stride, imap, rvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            REAL,                          INTENT(@INTENTV@) :: rvals(*)
+    END FUNCTION   nfmpi_put_varm_real
+
+    INTEGER        FUNCTION nfmpi_put_varm_real_all(ncid, varid, start, count, stride, imap, rvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            REAL,                          INTENT(@INTENTV@) :: rvals(*)
+    END FUNCTION   nfmpi_put_varm_real_all
+
+    INTEGER        FUNCTION nfmpi_get_varm_real(ncid, varid, start, count, stride, imap, rvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            REAL,                          INTENT(OUT) :: rvals(*)
+    END FUNCTION   nfmpi_get_varm_real
+
+    INTEGER        FUNCTION nfmpi_get_varm_real_all(ncid, varid, start, count, stride, imap, rvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            REAL,                          INTENT(OUT) :: rvals(*)
+    END FUNCTION   nfmpi_get_varm_real_all
+
+    INTEGER        FUNCTION nfmpi_put_varm_double(ncid, varid, start, count, stride, imap, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+    END FUNCTION   nfmpi_put_varm_double
+
+    INTEGER        FUNCTION nfmpi_put_varm_double_all(ncid, varid, start, count, stride, imap, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+    END FUNCTION   nfmpi_put_varm_double_all
+
+    INTEGER        FUNCTION nfmpi_get_varm_double(ncid, varid, start, count, stride, imap, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+    END FUNCTION   nfmpi_get_varm_double
+
+    INTEGER        FUNCTION nfmpi_get_varm_double_all(ncid, varid, start, count, stride, imap, dvals)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+    END FUNCTION   nfmpi_get_varm_double_all
+
+    INTEGER        FUNCTION nfmpi_put_varm_int8(ncid, varid, start, count, stride, imap, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+    END FUNCTION   nfmpi_put_varm_int8
+
+    INTEGER        FUNCTION nfmpi_put_varm_int8_all(ncid, varid, start, count, stride, imap, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+    END FUNCTION   nfmpi_put_varm_int8_all
+
+    INTEGER        FUNCTION nfmpi_get_varm_int8(ncid, varid, start, count, stride, imap, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+    END FUNCTION   nfmpi_get_varm_int8
+
+    INTEGER        FUNCTION nfmpi_get_varm_int8_all(ncid, varid, start, count, stride, imap, i8vals)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+    END FUNCTION   nfmpi_get_varm_int8_all
+
+!
+! non-blocking variable array iput/iget subroutines:
+!
+
+!
+! entire variable iput/iget subroutines:
+!
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_iput_var(ncid, varid, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_iput_var
+
+!   INTEGER        FUNCTION nfmpi_iget_var(ncid, varid, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_iget_var
+
+
+    INTEGER        FUNCTION nfmpi_iput_var_text(ncid, varid, text, req)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var_text
+
+    INTEGER        FUNCTION nfmpi_iget_var_text(ncid, varid, text, req)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var_text
+
+    INTEGER        FUNCTION nfmpi_iput_var_int1(ncid, varid, i1vals, req)
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var_int1
+
+    INTEGER        FUNCTION nfmpi_iget_var_int1(ncid, varid, i1vals, req)
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var_int1
+
+    INTEGER        FUNCTION nfmpi_iput_var_int2(ncid, varid, i2vals, req)
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var_int2
+
+    INTEGER        FUNCTION nfmpi_iget_var_int2(ncid, varid, i2vals, req)
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var_int2
+
+    INTEGER        FUNCTION nfmpi_iput_var_int(ncid, varid, ivals, req)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var_int
+
+    INTEGER        FUNCTION nfmpi_iget_var_int(ncid, varid, ivals, req)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var_int
+
+    INTEGER        FUNCTION nfmpi_iput_var_real(ncid, varid, rvals, req)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            REAL,                          INTENT(@INTENTV@) :: rvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var_real
+
+    INTEGER        FUNCTION nfmpi_iget_var_real(ncid, varid, rvals, req)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            REAL,                          INTENT(OUT) :: rvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var_real
+
+    INTEGER        FUNCTION nfmpi_iput_var_double(ncid, varid, dvals, req)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var_double
+
+    INTEGER        FUNCTION nfmpi_iget_var_double(ncid, varid, dvals, req)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var_double
+
+    INTEGER        FUNCTION nfmpi_iput_var_int8(ncid, varid, i8vals, req)
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var_int8
+
+    INTEGER        FUNCTION nfmpi_iget_var_int8(ncid, varid, i8vals, req)
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var_int8
+
+!
+! single variable iput/iget subroutines:
+!
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_iput_var1(ncid, varid, index, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_iput_var1
+
+!   INTEGER        FUNCTION nfmpi_iget_var1(ncid, varid, index, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_iget_var1
+
+    INTEGER        FUNCTION nfmpi_iput_var1_text(ncid, varid, index, text, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            CHARACTER,                     INTENT(IN)  :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var1_text
+
+    INTEGER        FUNCTION nfmpi_iget_var1_text(ncid, varid, index, text, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            CHARACTER,                     INTENT(OUT) :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var1_text
+
+    INTEGER        FUNCTION nfmpi_iput_var1_int1(ncid, varid, index, i1val, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1val
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var1_int1
+
+    INTEGER        FUNCTION nfmpi_iget_var1_int1(ncid, varid, index, i1val, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1val
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var1_int1
+
+    INTEGER        FUNCTION nfmpi_iput_var1_int2(ncid, varid, index, i2val, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2val
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var1_int2
+
+    INTEGER        FUNCTION nfmpi_iget_var1_int2(ncid, varid, index, i2val, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2val
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var1_int2
+
+    INTEGER        FUNCTION nfmpi_iput_var1_int(ncid, varid, index, ival, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER,                       INTENT(@INTENTV@) :: ival
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var1_int
+
+    INTEGER        FUNCTION nfmpi_iget_var1_int(ncid, varid, index, ival, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER,                       INTENT(OUT) :: ival
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var1_int
+
+    INTEGER        FUNCTION nfmpi_iput_var1_real(ncid, varid, index, rval, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            REAL,                          INTENT(@INTENTV@) :: rval
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var1_real
+
+    INTEGER        FUNCTION nfmpi_iget_var1_real(ncid, varid, index, rval, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            REAL,                          INTENT(OUT) :: rval
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var1_real
+
+    INTEGER        FUNCTION nfmpi_iput_var1_double(ncid, varid, index, dval, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dval
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var1_double
+
+    INTEGER        FUNCTION nfmpi_iget_var1_double(ncid, varid, index, dval, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            DOUBLE PRECISION,              INTENT(OUT) :: dval
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var1_double
+
+    INTEGER        FUNCTION nfmpi_iput_var1_int8(ncid, varid, index, i8val, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8val
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_var1_int8
+
+    INTEGER        FUNCTION nfmpi_iget_var1_int8(ncid, varid, index, i8val, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8val
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_var1_int8
+
+!
+! variable array iput/iget subroutines:
+!
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_iput_vara(ncid, varid, start, count, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_iput_vara
+
+!   INTEGER        FUNCTION nfmpi_iget_vara(ncid, varid, start, count, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_iget_vara
+
+    INTEGER        FUNCTION nfmpi_iput_vara_text(ncid, varid, start, count, text, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vara_text
+
+    INTEGER        FUNCTION nfmpi_iget_vara_text(ncid, varid, start, count, text, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vara_text
+
+    INTEGER        FUNCTION nfmpi_iput_vara_int1(ncid, varid, start, count, i1vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vara_int1
+
+    INTEGER        FUNCTION nfmpi_iget_vara_int1(ncid, varid, start, count, i1vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vara_int1
+
+    INTEGER        FUNCTION nfmpi_iput_vara_int2(ncid, varid, start, count, i2vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vara_int2
+
+    INTEGER        FUNCTION nfmpi_iget_vara_int2(ncid, varid, start, count, i2vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vara_int2
+
+    INTEGER        FUNCTION nfmpi_iput_vara_int(ncid, varid, start, count, ivals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vara_int
+
+    INTEGER        FUNCTION nfmpi_iget_vara_int(ncid, varid, start, count, ivals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vara_int
+
+    INTEGER        FUNCTION nfmpi_iput_vara_real(ncid, varid, start, count, rvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            REAL,                          INTENT(@INTENTV@) :: rvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vara_real
+
+    INTEGER        FUNCTION nfmpi_iget_vara_real(ncid, varid, start, count, rvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            REAL,                          INTENT(OUT) :: rvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vara_real
+
+    INTEGER        FUNCTION nfmpi_iput_vara_double(ncid, varid, start, count, dvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vara_double
+
+    INTEGER        FUNCTION nfmpi_iget_vara_double(ncid, varid, start, count, dvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vara_double
+
+    INTEGER        FUNCTION nfmpi_iput_vara_int8(ncid, varid, start, count, i8vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vara_int8
+
+    INTEGER        FUNCTION nfmpi_iget_vara_int8(ncid, varid, start, count, i8vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vara_int8
+
+!
+! strided variable iput/iget subroutines:
+!
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_iput_vars(ncid, varid, start, count, stride, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_iput_vars
+
+!   INTEGER        FUNCTION nfmpi_iget_vars(ncid, varid, start, count, stride, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_iget_vars
+
+    INTEGER        FUNCTION nfmpi_iput_vars_text(ncid, varid, start, count, stride, text, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vars_text
+
+    INTEGER        FUNCTION nfmpi_iget_vars_text(ncid, varid, start, count, stride, text, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vars_text
+
+    INTEGER        FUNCTION nfmpi_iput_vars_int1(ncid, varid, start, count, stride, i1vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vars_int1
+
+    INTEGER        FUNCTION nfmpi_iget_vars_int1(ncid, varid, start, count, stride, i1vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vars_int1
+
+    INTEGER        FUNCTION nfmpi_iput_vars_int2(ncid, varid, start, count, stride, i2vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vars_int2
+
+    INTEGER        FUNCTION nfmpi_iget_vars_int2(ncid, varid, start, count, stride, i2vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vars_int2
+
+    INTEGER        FUNCTION nfmpi_iput_vars_int(ncid, varid, start, count, stride, ivals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vars_int
+
+    INTEGER        FUNCTION nfmpi_iget_vars_int(ncid, varid, start, count, stride, ivals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vars_int
+
+    INTEGER        FUNCTION nfmpi_iput_vars_real(ncid, varid, start, count, stride, rvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            REAL,                          INTENT(@INTENTV@) :: rvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vars_real
+
+    INTEGER        FUNCTION nfmpi_iget_vars_real(ncid, varid, start, count, stride, rvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            REAL,                          INTENT(OUT) :: rvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vars_real
+
+    INTEGER        FUNCTION nfmpi_iput_vars_double(ncid, varid, start, count, stride, dvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vars_double
+
+    INTEGER        FUNCTION nfmpi_iget_vars_double(ncid, varid, start, count, stride, dvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vars_double
+
+    INTEGER        FUNCTION nfmpi_iput_vars_int8(ncid, varid, start, count, stride, i8vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_vars_int8
+
+    INTEGER        FUNCTION nfmpi_iget_vars_int8(ncid, varid, start, count, stride, i8vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_vars_int8
+
+!
+! mapped variable iput/iget subroutines:
+!
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_iput_varm(ncid, varid, start, count, stride, imap, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_iput_varm
+
+!   INTEGER        FUNCTION nfmpi_iget_varm(ncid, varid, start, count, stride, imap, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_iget_varm
+
+    INTEGER        FUNCTION nfmpi_iput_varm_text(ncid, varid, start, count, stride, imap, text, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_varm_text
+
+    INTEGER        FUNCTION nfmpi_iget_varm_text(ncid, varid, start, count, stride, imap, text, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            CHARACTER(len=*),              INTENT(OUT) :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_varm_text
+
+    INTEGER        FUNCTION nfmpi_iput_varm_int1(ncid, varid, start, count, stride, imap, i1vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_varm_int1
+
+    INTEGER        FUNCTION nfmpi_iget_varm_int1(ncid, varid, start, count, stride, imap, i1vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_varm_int1
+
+    INTEGER        FUNCTION nfmpi_iput_varm_int2(ncid, varid, start, count, stride, imap, i2vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_varm_int2
+
+    INTEGER        FUNCTION nfmpi_iget_varm_int2(ncid, varid, start, count, stride, imap, i2vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_varm_int2
+
+    INTEGER        FUNCTION nfmpi_iput_varm_int (ncid, varid, start, count, stride, imap, ivals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_varm_int
+
+    INTEGER        FUNCTION nfmpi_iget_varm_int (ncid, varid, start, count, stride, imap, ivals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER,                       INTENT(OUT) :: ivals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_varm_int
+
+    INTEGER        FUNCTION nfmpi_iput_varm_real(ncid, varid, start, count, stride, imap, rvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            REAL,                          INTENT(@INTENTV@) :: rvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_varm_real
+
+    INTEGER        FUNCTION nfmpi_iget_varm_real(ncid, varid, start, count, stride, imap, rvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            REAL,                          INTENT(OUT) :: rvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_varm_real
+
+    INTEGER        FUNCTION nfmpi_iput_varm_double(ncid, varid, start, count, stride, imap, dvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_varm_double
+
+    INTEGER        FUNCTION nfmpi_iget_varm_double(ncid, varid, start, count, stride, imap, dvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_varm_double
+
+    INTEGER        FUNCTION nfmpi_iput_varm_int8(ncid, varid, start, count, stride, imap, i8vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iput_varm_int8
+
+    INTEGER        FUNCTION nfmpi_iget_varm_int8(ncid, varid, start, count, stride, imap, i8vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_iget_varm_int8
+
+!
+! Begin buffered put non-blocking subroutines:
+!
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_bput_var(ncid, varid, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_bput_var
+
+!   INTEGER        FUNCTION nfmpi_bget_var(ncid, varid, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_bget_var
+
+    INTEGER        FUNCTION nfmpi_bput_var_text(ncid, varid, text, req)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            CHARACTER(len=*),              INTENT(IN)  :: text(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var_text
+
+    INTEGER        FUNCTION nfmpi_bput_var_int1(ncid, varid, i1vals, req)
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var_int1
+
+    INTEGER        FUNCTION nfmpi_bput_var_int2(ncid, varid, i2vals, req)
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=TwoByteInt),      INTENT(IN)  :: i2vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var_int2
+
+    INTEGER        FUNCTION nfmpi_bput_var_int(ncid, varid, ivals, req)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER,                       INTENT(IN)  :: ivals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var_int
+
+    INTEGER        FUNCTION nfmpi_bput_var_real(ncid, varid, rvals, req)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            REAL,                          INTENT(IN)  :: rvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var_real
+
+    INTEGER        FUNCTION nfmpi_bput_var_double(ncid, varid, dvals, req)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            DOUBLE PRECISION,              INTENT(IN)  :: dvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var_double
+
+    INTEGER        FUNCTION nfmpi_bput_var_int8(ncid, varid, i8vals, req)
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=EightByteInt),    INTENT(IN)  :: i8vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var_int8
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_bput_var1(ncid, varid, start, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_bput_var1
+
+!   INTEGER        FUNCTION nfmpi_bget_var1(ncid, varid, start, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_bget_var1
+
+    INTEGER        FUNCTION nfmpi_bput_var1_text(ncid, varid, index, text, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            CHARACTER,                     INTENT(IN)  :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var1_text
+
+    INTEGER        FUNCTION nfmpi_bput_var1_int1(ncid, varid, index, i1val, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1val
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var1_int1
+
+    INTEGER        FUNCTION nfmpi_bput_var1_int2(ncid, varid, index, i2val, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(IN)  :: i2val
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var1_int2
+
+    INTEGER        FUNCTION nfmpi_bput_var1_int(ncid, varid, index, ival, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER,                       INTENT(IN)  :: ival
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var1_int
+
+    INTEGER        FUNCTION nfmpi_bput_var1_real(ncid, varid, index, rval, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            REAL,                          INTENT(IN)  :: rval
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var1_real
+
+    INTEGER        FUNCTION nfmpi_bput_var1_double(ncid, varid, index, dval, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            DOUBLE PRECISION,              INTENT(IN)  :: dval
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var1_double
+
+    INTEGER        FUNCTION nfmpi_bput_var1_int8(ncid, varid, index, i8val, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: index(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(IN)  :: i8val
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_var1_int8
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_bput_vara(ncid, varid, start, count, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_bput_vara
+
+!   INTEGER        FUNCTION nfmpi_bget_vara(ncid, varid, start, count, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_bget_vara
+
+    INTEGER        FUNCTION nfmpi_bput_vara_text(ncid, varid, start, count, text, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            CHARACTER(len=*),              INTENT(IN)  :: text(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vara_text
+
+    INTEGER        FUNCTION nfmpi_bput_vara_int1(ncid, varid, start, count, i1vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vara_int1
+
+    INTEGER        FUNCTION nfmpi_bput_vara_int2(ncid, varid, start, count, i2vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(IN)  :: i2vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vara_int2
+
+    INTEGER        FUNCTION nfmpi_bput_vara_int(ncid, varid, start, count, ivals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER,                       INTENT(IN)  :: ivals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vara_int
+
+    INTEGER        FUNCTION nfmpi_bput_vara_real(ncid, varid, start, count, rvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            REAL,                          INTENT(IN)  :: rvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vara_real
+
+    INTEGER        FUNCTION nfmpi_bput_vara_double(ncid, varid, start, count, dvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            DOUBLE PRECISION,              INTENT(IN)  :: dvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vara_double
+
+    INTEGER        FUNCTION nfmpi_bput_vara_int8(ncid, varid, start, count, i8vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(IN)  :: i8vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vara_int8
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_bput_vars(ncid, varid, start, count, stride, imap, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_bput_vars
+
+!   INTEGER        FUNCTION nfmpi_bget_vars(ncid, varid, start, count, stride, imap, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_bget_vars
+
+    INTEGER        FUNCTION nfmpi_bput_vars_text(ncid, varid, start, count, stride, text, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vars_text
+
+    INTEGER        FUNCTION nfmpi_bput_vars_int1(ncid, varid, start, count, stride, i1vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vars_int1
+
+    INTEGER        FUNCTION nfmpi_bput_vars_int2(ncid, varid, start, count, stride, i2vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(IN)  :: i2vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vars_int2
+
+    INTEGER        FUNCTION nfmpi_bput_vars_int(ncid, varid, start, count, stride, ivals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER,                       INTENT(IN)  :: ivals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vars_int
+
+    INTEGER        FUNCTION nfmpi_bput_vars_real(ncid, varid, start, count, stride, rvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            REAL,                          INTENT(IN)  :: rvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vars_real
+
+    INTEGER        FUNCTION nfmpi_bput_vars_double(ncid, varid, start, count, stride, dvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            DOUBLE PRECISION,              INTENT(IN)  :: dvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vars_double
+
+    INTEGER        FUNCTION nfmpi_bput_vars_int8(ncid, varid, start, count, stride, i8vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(IN)  :: i8vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_vars_int8
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER        FUNCTION nfmpi_bput_varm(ncid, varid, start, count, stride, imap, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+!                           <type>,                        INTENT(IN)  :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_bput_varm
+
+!   INTEGER        FUNCTION nfmpi_bget_varm(ncid, varid, start, count, stride, imap, buf, bufcount, datatype, req)
+!                           INTEGER,                       INTENT(IN)  :: ncid
+!                           INTEGER,                       INTENT(IN)  :: varid
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+!                           <type>,                        INTENT(OUT) :: buf(*)
+!                           INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                           INTEGER,                       INTENT(IN)  :: datatype
+!                           INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION   nfmpi_bget_varm
+
+    INTEGER        FUNCTION nfmpi_bput_varm_text(ncid, varid, start, count, stride, imap, text, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            CHARACTER(len=*),              INTENT(IN)  :: text
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_varm_text
+
+    INTEGER        FUNCTION nfmpi_bput_varm_int1(ncid, varid, start, count, stride, imap, i1vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: OneByteInt = selected_int_kind(2)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_varm_int1
+
+    INTEGER        FUNCTION nfmpi_bput_varm_int2(ncid, varid, start, count, stride, imap, i2vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: TwoByteInt = selected_int_kind(4)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=TwoByteInt),      INTENT(IN)  :: i2vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_varm_int2
+
+    INTEGER        FUNCTION nfmpi_bput_varm_int (ncid, varid, start, count, stride, imap, ivals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER,                       INTENT(IN)  :: ivals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_varm_int
+
+    INTEGER        FUNCTION nfmpi_bput_varm_real(ncid, varid, start, count, stride, imap, rvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            REAL,                          INTENT(IN)  :: rvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_varm_real
+
+    INTEGER        FUNCTION nfmpi_bput_varm_double(ncid, varid, start, count, stride, imap, dvals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            DOUBLE PRECISION,              INTENT(IN)  :: dvals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_varm_double
+
+    INTEGER        FUNCTION nfmpi_bput_varm_int8(ncid, varid, start, count, stride, imap, i8vals, req)
+                   use mpi, only: MPI_OFFSET_KIND
+                   integer, parameter :: EightByteInt = selected_int_kind(18)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: start(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: count(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: stride(*)
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: imap(*)
+                            INTEGER(KIND=EightByteInt),    INTENT(IN)  :: i8vals(*)
+                            INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION   nfmpi_bput_varm_int8
+
+    INTEGER        FUNCTION nfmpi_buffer_attach(ncid, bufsize)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufsize
+    END FUNCTION   nfmpi_buffer_attach
+
+    INTEGER        FUNCTION nfmpi_buffer_detach(ncid)
+                            INTEGER,                       INTENT(IN)  :: ncid
+    END FUNCTION   nfmpi_buffer_detach
+
+    INTEGER        FUNCTION nfmpi_inq_buffer_usage(ncid, usage)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: usage
+    END FUNCTION   nfmpi_inq_buffer_usage
+
+    INTEGER        FUNCTION nfmpi_inq_buffer_size(ncid, buf_size)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: buf_size
+    END FUNCTION   nfmpi_inq_buffer_size
+
+!
+! End buffered put non-blocking subroutines:
+!
+
+    INTEGER        FUNCTION nfmpi_wait(ncid, count, req, status)
+                            INTEGER,                       INTENT(IN)   :: ncid
+                            INTEGER,                       INTENT(IN)   :: count
+                            INTEGER,                       INTENT(INOUT):: req(count)
+                            INTEGER,                       INTENT(OUT)  :: status(count)
+    END FUNCTION   nfmpi_wait
+
+    INTEGER        FUNCTION nfmpi_wait_all(ncid, count, req, status)
+                            INTEGER,                       INTENT(IN)   :: ncid
+                            INTEGER,                       INTENT(IN)   :: count
+                            INTEGER,                       INTENT(INOUT):: req(count)
+                            INTEGER,                       INTENT(OUT)  :: status(count)
+    END FUNCTION   nfmpi_wait_all
+
+    INTEGER        FUNCTION nfmpi_cancel(ncid, count, req, status)
+                            INTEGER,                       INTENT(IN)   :: ncid
+                            INTEGER,                       INTENT(IN)   :: count
+                            INTEGER,                       INTENT(INOUT):: req(count)
+                            INTEGER,                       INTENT(OUT)  :: status(count)
+    END FUNCTION   nfmpi_cancel
+
+    INTEGER        FUNCTION nfmpi_inq_put_size(ncid, size)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: size
+    END FUNCTION   nfmpi_inq_put_size
+
+    INTEGER        FUNCTION nfmpi_inq_get_size(ncid, size)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: size
+    END FUNCTION   nfmpi_inq_get_size
+
+    INTEGER        FUNCTION nfmpi_inq_header_size(ncid, size)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: size
+    END FUNCTION   nfmpi_inq_header_size
+
+    INTEGER        FUNCTION nfmpi_inq_header_extent(ncid, extent)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: extent
+    END FUNCTION   nfmpi_inq_header_extent
+
+    INTEGER        FUNCTION nfmpi_inq_varoffset(ncid, varid, offset)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(IN)  :: varid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: offset
+    END FUNCTION   nfmpi_inq_varoffset
+
+    INTEGER        FUNCTION nfmpi_inq_nreqs(ncid, nreqs)
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER,                       INTENT(OUT) :: nreqs
+    END FUNCTION   nfmpi_inq_nreqs
+
+    INTEGER        FUNCTION nfmpi_inq_malloc_size(size)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: size
+    END FUNCTION   nfmpi_inq_malloc_size
+
+    INTEGER        FUNCTION nfmpi_inq_malloc_max_size(size)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: size
+    END FUNCTION   nfmpi_inq_malloc_max_size
+
+    INTEGER        FUNCTION nfmpi_inq_malloc_list()
+    END FUNCTION   nfmpi_inq_malloc_list
+
+    INTEGER        FUNCTION nfmpi_inq_files_opened(nfiles, ncids)
+                            INTEGER,                       INTENT(OUT) :: nfiles
+                            INTEGER,                       INTENT(OUT) :: ncids(*)
+    END FUNCTION   nfmpi_inq_files_opened
+
+    INTEGER        FUNCTION nfmpi_inq_recsize(ncid, recsize)
+                   use mpi, only: MPI_OFFSET_KIND
+                            INTEGER,                       INTENT(IN)  :: ncid
+                            INTEGER(KIND=MPI_OFFSET_KIND), INTENT(OUT) :: recsize
+    END FUNCTION   nfmpi_inq_recsize
+
+!
+! Begin of varn subroutines:
+!
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER FUNCTION nfmpi_get_varn(ncid, varid, num, starts, counts, buf, bufcount, buftype)
+!                    INTEGER,                       INTENT(IN)  :: ncid
+!                    INTEGER,                       INTENT(IN)  :: varid
+!                    INTEGER,                       INTENT(IN)  :: num
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+!                    <type>,                        INTENT(OUT) :: buf(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                    INTEGER,                       INTENT(IN)  :: buftype
+!   END FUNCTION nfmpi_get_varn
+
+!   INTEGER FUNCTION nfmpi_get_varn_all(ncid, varid, num, starts, counts, buf, bufcount, buftype)
+!                    INTEGER,                       INTENT(IN)  :: ncid
+!                    INTEGER,                       INTENT(IN)  :: varid
+!                    INTEGER,                       INTENT(IN)  :: num
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+!                    <type>,                        INTENT(OUT) :: buf(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                    INTEGER,                       INTENT(IN)  :: buftype
+!   END FUNCTION nfmpi_get_varn_all
+
+!   INTEGER FUNCTION nfmpi_put_varn(ncid, varid, num, starts, counts, buf, bufcount, buftype)
+!                    INTEGER,                       INTENT(IN)  :: ncid
+!                    INTEGER,                       INTENT(IN)  :: varid
+!                    INTEGER,                       INTENT(IN)  :: num
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+!                    <type>,                        INTENT(IN)  :: buf(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                    INTEGER,                       INTENT(IN)  :: buftype
+!   END FUNCTION nfmpi_put_varn
+
+!   INTEGER FUNCTION nfmpi_put_varn_all(ncid, varid, num, starts, counts, buf, bufcount, buftype)
+!                    INTEGER,                       INTENT(IN)  :: ncid
+!                    INTEGER,                       INTENT(IN)  :: varid
+!                    INTEGER,                       INTENT(IN)  :: num
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+!                    <type>,                        INTENT(IN)  :: buf(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                    INTEGER,                       INTENT(IN)  :: buftype
+!   END FUNCTION nfmpi_put_varn_all
+
+
+    INTEGER FUNCTION nfmpi_get_varn_text(ncid, varid, num, starts, counts, text)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     CHARACTER(len=*),              INTENT(OUT) :: text
+    END FUNCTION nfmpi_get_varn_text
+
+    INTEGER FUNCTION nfmpi_get_varn_int1(ncid, varid, num, starts, counts, i1vals)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: OneByteInt = selected_int_kind(2)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+    END FUNCTION nfmpi_get_varn_int1
+
+    INTEGER FUNCTION nfmpi_get_varn_int2(ncid, varid, num, starts, counts, i2vals)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: TwoByteInt = selected_int_kind(4)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+    END FUNCTION nfmpi_get_varn_int2
+
+    INTEGER FUNCTION nfmpi_get_varn_int(ncid, varid, num, starts, counts, ivals)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER,                       INTENT(OUT) :: ivals(*)
+    END FUNCTION nfmpi_get_varn_int
+
+    INTEGER FUNCTION nfmpi_get_varn_real(ncid, varid, num, starts, counts, rvals)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     REAL,                          INTENT(OUT) :: rvals(*)
+    END FUNCTION nfmpi_get_varn_real
+
+    INTEGER FUNCTION nfmpi_get_varn_double(ncid, varid, num, starts, counts, dvals)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+    END FUNCTION nfmpi_get_varn_double
+
+    INTEGER FUNCTION nfmpi_get_varn_int8(ncid, varid, num, starts, counts, i8vals)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: EightByteInt = selected_int_kind(18)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+    END FUNCTION nfmpi_get_varn_int8
+
+    INTEGER FUNCTION nfmpi_get_varn_text_all(ncid, varid, num, starts, counts, text)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     CHARACTER(len=*),              INTENT(OUT) :: text
+    END FUNCTION nfmpi_get_varn_text_all
+
+    INTEGER FUNCTION nfmpi_get_varn_int1_all(ncid, varid, num, starts, counts, i1vals)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: OneByteInt = selected_int_kind(2)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+    END FUNCTION nfmpi_get_varn_int1_all
+
+    INTEGER FUNCTION nfmpi_get_varn_int2_all(ncid, varid, num, starts, counts, i2vals)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: TwoByteInt = selected_int_kind(4)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+    END FUNCTION nfmpi_get_varn_int2_all
+
+    INTEGER FUNCTION nfmpi_get_varn_int_all(ncid, varid, num, starts, counts, ivals)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER,                       INTENT(OUT) :: ivals(*)
+    END FUNCTION nfmpi_get_varn_int_all
+
+    INTEGER FUNCTION nfmpi_get_varn_real_all(ncid, varid, num, starts, counts, rvals)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     REAL,                          INTENT(OUT) :: rvals(*)
+    END FUNCTION nfmpi_get_varn_real_all
+
+    INTEGER FUNCTION nfmpi_get_varn_double_all(ncid, varid, num, starts, counts, dvals)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+    END FUNCTION nfmpi_get_varn_double_all
+
+    INTEGER FUNCTION nfmpi_get_varn_int8_all(ncid, varid, num, starts, counts, i8vals)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: EightByteInt = selected_int_kind(18)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+    END FUNCTION nfmpi_get_varn_int8_all
+
+
+    INTEGER FUNCTION nfmpi_put_varn_text(ncid, varid, num, starts, counts, text)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     CHARACTER(len=*),              INTENT(IN)  :: text
+    END FUNCTION nfmpi_put_varn_text
+
+    INTEGER FUNCTION nfmpi_put_varn_int1(ncid, varid, num, starts, counts, i1vals)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: OneByteInt = selected_int_kind(2)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+    END FUNCTION nfmpi_put_varn_int1
+
+    INTEGER FUNCTION nfmpi_put_varn_int2(ncid, varid, num, starts, counts, i2vals)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: TwoByteInt = selected_int_kind(4)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+    END FUNCTION nfmpi_put_varn_int2
+
+    INTEGER FUNCTION nfmpi_put_varn_int(ncid, varid, num, starts, counts, ivals)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+    END FUNCTION nfmpi_put_varn_int
+
+    INTEGER FUNCTION nfmpi_put_varn_real(ncid, varid, num, starts, counts, rvals)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     REAL,                          INTENT(@INTENTV@) :: rvals(*)
+    END FUNCTION nfmpi_put_varn_real
+
+    INTEGER FUNCTION nfmpi_put_varn_double(ncid, varid, num, starts, counts, dvals)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+    END FUNCTION nfmpi_put_varn_double
+
+    INTEGER FUNCTION nfmpi_put_varn_int8(ncid, varid, num, starts, counts, i8vals)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: EightByteInt = selected_int_kind(18)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+    END FUNCTION nfmpi_put_varn_int8
+
+    INTEGER FUNCTION nfmpi_put_varn_text_all(ncid, varid, num, starts, counts, text)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     CHARACTER(len=*),              INTENT(IN)  :: text
+    END FUNCTION nfmpi_put_varn_text_all
+
+    INTEGER FUNCTION nfmpi_put_varn_int1_all(ncid, varid, num, starts, counts, i1vals)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: OneByteInt = selected_int_kind(2)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+    END FUNCTION nfmpi_put_varn_int1_all
+
+    INTEGER FUNCTION nfmpi_put_varn_int2_all(ncid, varid, num, starts, counts, i2vals)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: TwoByteInt = selected_int_kind(4)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+    END FUNCTION nfmpi_put_varn_int2_all
+
+    INTEGER FUNCTION nfmpi_put_varn_int_all(ncid, varid, num, starts, counts, ivals)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+    END FUNCTION nfmpi_put_varn_int_all
+
+    INTEGER FUNCTION nfmpi_put_varn_real_all(ncid, varid, num, starts, counts, rvals)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     REAL,                          INTENT(@INTENTV@) :: rvals(*)
+    END FUNCTION nfmpi_put_varn_real_all
+
+    INTEGER FUNCTION nfmpi_put_varn_double_all(ncid, varid, num, starts, counts, dvals)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+    END FUNCTION nfmpi_put_varn_double_all
+
+    INTEGER FUNCTION nfmpi_put_varn_int8_all(ncid, varid, num, starts, counts, i8vals)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: EightByteInt = selected_int_kind(18)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+    END FUNCTION nfmpi_put_varn_int8_all
+
+!
+! flexible APIs, not ready yet for Fortran 77
+!
+!   INTEGER FUNCTION nfmpi_iget_varn(ncid, varid, num, starts, counts, buf, bufcount, buftype, req)
+!                    INTEGER,                       INTENT(IN)  :: ncid
+!                    INTEGER,                       INTENT(IN)  :: varid
+!                    INTEGER,                       INTENT(IN)  :: num
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+!                    <type>,                        INTENT(OUT) :: buf(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                    INTEGER,                       INTENT(IN)  :: buftype
+!                    INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION nfmpi_iget_varn
+
+!   INTEGER FUNCTION nfmpi_iput_varn(ncid, varid, num, starts, counts, buf, bufcount, buftype, req)
+!                    INTEGER,                       INTENT(IN)  :: ncid
+!                    INTEGER,                       INTENT(IN)  :: varid
+!                    INTEGER,                       INTENT(IN)  :: num
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+!                    <type>,                        INTENT(IN)  :: buf(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                    INTEGER,                       INTENT(IN)  :: buftype
+!                    INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION nfmpi_iput_varn
+
+    INTEGER FUNCTION nfmpi_iget_varn_text(ncid, varid, num, starts, counts, text, req)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     CHARACTER(len=*),              INTENT(OUT) :: text
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iget_varn_text
+
+    INTEGER FUNCTION nfmpi_iget_varn_int1(ncid, varid, num, starts, counts, i1vals, req)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: OneByteInt = selected_int_kind(2)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=OneByteInt),      INTENT(OUT) :: i1vals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iget_varn_int1
+
+    INTEGER FUNCTION nfmpi_iget_varn_int2(ncid, varid, num, starts, counts, i2vals, req)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: TwoByteInt = selected_int_kind(4)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=TwoByteInt),      INTENT(OUT) :: i2vals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iget_varn_int2
+
+    INTEGER FUNCTION nfmpi_iget_varn_int(ncid, varid, num, starts, counts, ivals, req)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER,                       INTENT(OUT) :: ivals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iget_varn_int
+
+    INTEGER FUNCTION nfmpi_iget_varn_real(ncid, varid, num, starts, counts, rvals, req)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     REAL,                          INTENT(OUT) :: rvals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iget_varn_real
+
+    INTEGER FUNCTION nfmpi_iget_varn_double(ncid, varid, num, starts, counts, dvals, req)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     DOUBLE PRECISION,              INTENT(OUT) :: dvals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iget_varn_double
+
+    INTEGER FUNCTION nfmpi_iget_varn_int8(ncid, varid, num, starts, counts, i8vals, req)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: EightByteInt = selected_int_kind(18)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=EightByteInt),    INTENT(OUT) :: i8vals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iget_varn_int8
+
+    INTEGER FUNCTION nfmpi_iput_varn_text(ncid, varid, num, starts, counts, text, req)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     CHARACTER(len=*),              INTENT(IN)  :: text
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iput_varn_text
+
+    INTEGER FUNCTION nfmpi_iput_varn_int1(ncid, varid, num, starts, counts, i1vals, req)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: OneByteInt = selected_int_kind(2)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iput_varn_int1
+
+    INTEGER FUNCTION nfmpi_iput_varn_int2(ncid, varid, num, starts, counts, i2vals, req)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: TwoByteInt = selected_int_kind(4)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iput_varn_int2
+
+    INTEGER FUNCTION nfmpi_iput_varn_int(ncid, varid, num, starts, counts, ivals, req)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iput_varn_int
+
+    INTEGER FUNCTION nfmpi_iput_varn_real(ncid, varid, num, starts, counts, rvals, req)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     REAL,                          INTENT(@INTENTV@) :: rvals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iput_varn_real
+
+    INTEGER FUNCTION nfmpi_iput_varn_double(ncid, varid, num, starts, counts, dvals, req)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iput_varn_double
+
+    INTEGER FUNCTION nfmpi_iput_varn_int8(ncid, varid, num, starts, counts, i8vals, req)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: EightByteInt = selected_int_kind(18)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_iput_varn_int8
+
+!   INTEGER FUNCTION nfmpi_bput_varn(ncid, varid, num, starts, counts, buf, bufcount, buftype, req)
+!                    INTEGER,                       INTENT(IN)  :: ncid
+!                    INTEGER,                       INTENT(IN)  :: varid
+!                    INTEGER,                       INTENT(IN)  :: num
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+!                    <type>,                        INTENT(IN)  :: buf(*)
+!                    INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: bufcount
+!                    INTEGER,                       INTENT(IN)  :: buftype
+!                    INTEGER,                       INTENT(OUT) :: req
+!   END FUNCTION nfmpi_bput_varn
+
+    INTEGER FUNCTION nfmpi_bput_varn_text(ncid, varid, num, starts, counts, text, req)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     CHARACTER(len=*),              INTENT(IN)  :: text
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_bput_varn_text
+
+    INTEGER FUNCTION nfmpi_bput_varn_int1(ncid, varid, num, starts, counts, i1vals, req)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: OneByteInt = selected_int_kind(2)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=OneByteInt),      INTENT(IN)  :: i1vals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_bput_varn_int1
+
+    INTEGER FUNCTION nfmpi_bput_varn_int2(ncid, varid, num, starts, counts, i2vals, req)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: TwoByteInt = selected_int_kind(4)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=TwoByteInt),      INTENT(@INTENTV@) :: i2vals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_bput_varn_int2
+
+    INTEGER FUNCTION nfmpi_bput_varn_int(ncid, varid, num, starts, counts, ivals, req)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER,                       INTENT(@INTENTV@) :: ivals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_bput_varn_int
+
+    INTEGER FUNCTION nfmpi_bput_varn_real(ncid, varid, num, starts, counts, rvals, req)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     REAL,                          INTENT(@INTENTV@) :: rvals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_bput_varn_real
+
+    INTEGER FUNCTION nfmpi_bput_varn_double(ncid, varid, num, starts, counts, dvals, req)
+            use mpi, only: MPI_OFFSET_KIND
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     DOUBLE PRECISION,              INTENT(@INTENTV@) :: dvals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_bput_varn_double
+
+    INTEGER FUNCTION nfmpi_bput_varn_int8(ncid, varid, num, starts, counts, i8vals, req)
+            use mpi, only: MPI_OFFSET_KIND
+            integer, parameter :: EightByteInt = selected_int_kind(18)
+                     INTEGER,                       INTENT(IN)  :: ncid
+                     INTEGER,                       INTENT(IN)  :: varid
+                     INTEGER,                       INTENT(IN)  :: num
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: starts(*)
+                     INTEGER(KIND=MPI_OFFSET_KIND), INTENT(IN)  :: counts(*)
+                     INTEGER(KIND=EightByteInt),    INTENT(@INTENTV@) :: i8vals(*)
+                     INTEGER,                       INTENT(OUT) :: req
+    END FUNCTION nfmpi_bput_varn_int8
+
+!
+! End of varn subroutines:
+!
+
+END INTERFACE
+
+! PnetCDF flexible APIs
+      integer, external :: &
+          nfmpi_put_var, &
+          nfmpi_put_var1, &
+          nfmpi_put_vara, &
+          nfmpi_put_vars, &
+          nfmpi_put_varm, &
+          nfmpi_get_var, &
+          nfmpi_get_var1, &
+          nfmpi_get_vara, &
+          nfmpi_get_vars, &
+          nfmpi_get_varm, &
+          nfmpi_put_vard, &
+          nfmpi_get_vard, &
+          nfmpi_def_var_fill, &
+          nfmpi_inq_var_fill
+
+!         nfmpi_put_var_all
+! collective put an entire variable does not make sense
+!
+
+      integer, external :: &
+          nfmpi_put_var1_all, &
+          nfmpi_put_vara_all, &
+          nfmpi_put_vars_all, &
+          nfmpi_put_varm_all, &
+          nfmpi_get_var_all, &
+          nfmpi_get_var1_all, &
+          nfmpi_get_vara_all, &
+          nfmpi_get_vars_all, &
+          nfmpi_get_varm_all, &
+          nfmpi_iput_var, &
+          nfmpi_iput_var1, &
+          nfmpi_iput_vara, &
+          nfmpi_iput_vars, &
+          nfmpi_iput_varm, &
+          nfmpi_iget_var, &
+          nfmpi_iget_var1, &
+          nfmpi_iget_vara, &
+          nfmpi_iget_vars, &
+          nfmpi_iget_varm, &
+          nfmpi_bput_var, &
+          nfmpi_bput_var1, &
+          nfmpi_bput_vara, &
+          nfmpi_bput_vars, &
+          nfmpi_bput_varm, &
+          nfmpi_get_varn, &
+          nfmpi_put_varn, &
+          nfmpi_get_varn_all, &
+          nfmpi_put_varn_all, &
+          nfmpi_iget_varn, &
+          nfmpi_iput_varn, &
+          nfmpi_bput_varn, &
+          nfmpi_put_vard_all, &
+          nfmpi_get_vard_all
+
diff --git a/src/libf90/attributes.f90 b/src/libf90/attributes.f90
new file mode 100644
index 0000000..68a67f9
--- /dev/null
+++ b/src/libf90/attributes.f90
@@ -0,0 +1,352 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: attributes.f90 1525 2013-12-14 17:17:42Z wkliao $
+!
+! This file is taken from netcdf_attributes.f90 with changes for PnetCDF use
+!  
+!
+
+  !
+  ! Attribute routines:
+  !
+  ! -------
+  function nf90mpi_copy_att(ncid_in, varid_in, name, ncid_out, varid_out)
+    integer,             intent(in) :: ncid_in,  varid_in
+    character (len = *), intent(in) :: name
+    integer,             intent(in) :: ncid_out, varid_out
+    integer                         :: nf90mpi_copy_att
+
+    nf90mpi_copy_att = nfmpi_copy_att(ncid_in, varid_in, name, ncid_out, varid_out)
+  end function nf90mpi_copy_att
+  ! -------
+  function nf90mpi_rename_att(ncid, varid, curname, newname)
+    integer,             intent(in) :: ncid,  varid
+    character (len = *), intent(in) :: curname, newname
+    integer                         :: nf90mpi_rename_att
+
+    nf90mpi_rename_att = nfmpi_rename_att(ncid, varid, curname, newname)
+  end function nf90mpi_rename_att
+  ! -------
+  function nf90mpi_del_att(ncid, varid, name)
+    integer,             intent(in) :: ncid, varid
+    character (len = *), intent(in) :: name
+    integer                         :: nf90mpi_del_att
+
+    nf90mpi_del_att = nfmpi_del_att(ncid, varid, name)
+  end function nf90mpi_del_att
+  ! -------
+  ! Attribute inquiry functions
+  ! -------
+  function nf90mpi_inq_attname(ncid, varid, attnum, name)
+    integer,             intent( in) :: ncid, varid, attnum
+    character (len = *), intent(out) :: name
+    integer                          :: nf90mpi_inq_attname
+
+    nf90mpi_inq_attname = nfmpi_inq_attname(ncid, varid, attnum, name)
+  end function nf90mpi_inq_attname
+  ! -------
+  function nf90mpi_inquire_attribute(ncid, varid, name, xtype, len, attnum)
+    integer,             intent( in)           :: ncid, varid
+    character (len = *), intent( in)           :: name
+    integer,             intent(out), optional :: xtype, attnum
+    integer (kind=MPI_OFFSET_KIND), intent(out), optional :: len
+    integer                                    :: nf90mpi_inquire_attribute
+    integer                                    :: local_xtype
+    integer (kind=MPI_OFFSET_KIND)             :: local_len
+
+    ! Do we need to worry about not saving the state from this call?
+    if(present(attnum)) &
+      nf90mpi_inquire_attribute = nfmpi_inq_attid(ncid, varid, name, attnum)
+
+    nf90mpi_inquire_attribute   = nfmpi_inq_att  (ncid, varid, name, local_xtype, local_len)
+
+    if(present(xtype)) xtype = local_xtype
+    if(present(len  )) len   = local_len
+  end function nf90mpi_inquire_attribute
+  ! -------
+  ! Put and get functions; these will get overloaded
+  ! -------
+  ! Text
+  ! -------
+  function nf90mpi_put_att_text(ncid, varid, name, values)
+    integer,                          intent(in) :: ncid, varid
+    character(len = *),               intent(in) :: name
+    character(len = *),               intent(in) :: values
+    integer                                      :: nf90mpi_put_att_text
+    integer (kind=MPI_OFFSET_KIND)               :: ilen
+
+    ilen = len_trim(values)
+    nf90mpi_put_att_text = nfmpi_put_att_text(ncid, varid, name, ilen, trim(values))
+  end function nf90mpi_put_att_text
+  ! -------
+  function nf90mpi_get_att_text(ncid, varid, name, values)
+    integer,                          intent( in) :: ncid, varid
+    character(len = *),               intent( in) :: name
+    character(len = *),               intent(out) :: values
+    integer                                       :: nf90mpi_get_att_text
+
+    values = ' '  !! make sure result will be blank padded
+    nf90mpi_get_att_text = nfmpi_get_att_text(ncid, varid, name, values)
+  end function nf90mpi_get_att_text
+  ! -------
+  ! Integer attributes
+  ! -------
+  function nf90mpi_put_att_OneByteInt(ncid, varid, name, values)
+    integer,                                    intent( in) :: ncid, varid
+    character(len = *),                         intent( in) :: name
+    integer (kind =  OneByteInt), dimension(:), intent( in) :: values
+    integer                                                 :: nf90mpi_put_att_OneByteInt
+    integer (kind=MPI_OFFSET_KIND)                          :: ilen
+
+    ilen = size(values)
+    nf90mpi_put_att_OneByteInt = nfmpi_put_att_int1(ncid, varid, name, nf90_int1, ilen, values)
+  end function nf90mpi_put_att_OneByteInt
+  ! -------
+  function nf90mpi_put_att_one_OneByteInt(ncid, varid, name, values)
+    integer,                                    intent( in) :: ncid, varid
+    character(len = *),                         intent( in) :: name
+    integer (kind =  OneByteInt),               intent( in) :: values
+    integer                                                 :: nf90mpi_put_att_one_OneByteInt
+    integer (kind =  OneByteInt), dimension(1)              :: valuesA
+
+    valuesA(1) = values
+    nf90mpi_put_att_one_OneByteInt = nfmpi_put_att_int1(ncid, varid, name, nf90_int1, 1_MPI_OFFSET_KIND, valuesA)
+  end function nf90mpi_put_att_one_OneByteInt
+  ! -------
+  function nf90mpi_get_att_OneByteInt(ncid, varid, name, values)
+    integer,                                    intent( in) :: ncid, varid
+    character(len = *),                         intent( in) :: name
+    integer (kind =  OneByteInt), dimension(:), intent(out) :: values
+    integer                                                 :: nf90mpi_get_att_OneByteInt
+
+    nf90mpi_get_att_OneByteInt = nfmpi_get_att_int1(ncid, varid, name, values)
+  end function nf90mpi_get_att_OneByteInt
+  ! -------
+  function nf90mpi_get_att_one_OneByteInt(ncid, varid, name, values)
+    integer,                                    intent( in) :: ncid, varid
+    character(len = *),                         intent( in) :: name
+    integer (kind =  OneByteInt),               intent(out) :: values
+    integer                                                 :: nf90mpi_get_att_one_OneByteInt
+    integer (kind =  OneByteInt), dimension(1)              :: valuesA
+
+    nf90mpi_get_att_one_OneByteInt = nfmpi_get_att_int1(ncid, varid, name, valuesA)
+    values = valuesA(1)
+  end function nf90mpi_get_att_one_OneByteInt
+  ! -------
+  function nf90mpi_put_att_TwoByteInt(ncid, varid, name, values)
+    integer,                                    intent(in)  :: ncid, varid
+    character(len = *),                         intent(in)  :: name
+    integer (kind =  TwoByteInt), dimension(:), intent(in)  :: values
+    integer                                                 :: nf90mpi_put_att_TwoByteInt
+    integer (kind=MPI_OFFSET_KIND)                          :: ilen
+
+    ilen = size(values)
+    nf90mpi_put_att_TwoByteInt = nfmpi_put_att_int2(ncid, varid, name, nf90_int2, ilen, values)
+  end function nf90mpi_put_att_TwoByteInt
+  ! -------
+  function nf90mpi_put_att_one_TwoByteInt(ncid, varid, name, values)
+    integer,                                    intent(in)  :: ncid, varid
+    character(len = *),                         intent(in)  :: name
+    integer (kind =  TwoByteInt),               intent(in)  :: values
+    integer                                                 :: nf90mpi_put_att_one_TwoByteInt
+    integer (kind =  TwoByteInt), dimension(1)              :: valuesA
+
+    valuesA(1) = values
+    nf90mpi_put_att_one_TwoByteInt = nfmpi_put_att_int2(ncid, varid, name, nf90_int2, 1_MPI_OFFSET_KIND, valuesA)
+  end function nf90mpi_put_att_one_TwoByteInt
+  ! -------
+  function nf90mpi_get_att_TwoByteInt(ncid, varid, name, values)
+    integer,                                    intent( in) :: ncid, varid
+    character(len = *),                         intent( in) :: name
+    integer (kind =  TwoByteInt), dimension(:), intent(out) :: values
+    integer                                                 :: nf90mpi_get_att_TwoByteInt
+
+    nf90mpi_get_att_TwoByteInt = nfmpi_get_att_int2(ncid, varid, name, values)
+  end function nf90mpi_get_att_TwoByteInt
+  ! -------
+  function nf90mpi_get_att_one_TwoByteInt(ncid, varid, name, values)
+    integer,                                    intent( in) :: ncid, varid
+    character(len = *),                         intent( in) :: name
+    integer (kind =  TwoByteInt),               intent(out) :: values
+    integer                                                 :: nf90mpi_get_att_one_TwoByteInt
+    integer (kind =  TwoByteInt), dimension(1)              :: valuesA
+
+    nf90mpi_get_att_one_TwoByteInt = nfmpi_get_att_int2(ncid, varid, name, valuesA)
+    values = valuesA(1)
+  end function nf90mpi_get_att_one_TwoByteInt
+  ! -------
+  function nf90mpi_put_att_FourByteInt(ncid, varid, name, values)
+    integer,                                    intent(in)  :: ncid, varid
+    character(len = *),                         intent(in)  :: name
+    integer (kind = FourByteInt), dimension(:), intent(in)  :: values
+    integer                                                 :: nf90mpi_put_att_FourByteInt
+    integer (kind=MPI_OFFSET_KIND)                          :: ilen
+
+    ilen = size(values)
+    nf90mpi_put_att_FourByteInt = nfmpi_put_att_int(ncid, varid, name, nf90_int, ilen, values)
+  end function nf90mpi_put_att_FourByteInt
+  ! -------
+  function nf90mpi_put_att_one_FourByteInt(ncid, varid, name, values)
+    integer,                                    intent(in)  :: ncid, varid
+    character(len = *),                         intent(in)  :: name
+    integer (kind = FourByteInt),               intent(in)  :: values
+    integer                                                 :: nf90mpi_put_att_one_FourByteInt
+    integer (kind = FourByteInt), dimension(1)              :: valuesA
+
+    valuesA(1) = int(values)
+    nf90mpi_put_att_one_FourByteInt = nfmpi_put_att_int(ncid, varid, name, nf90_int, 1_MPI_OFFSET_KIND, valuesA)
+  end function nf90mpi_put_att_one_FourByteInt
+  ! -------
+  function nf90mpi_get_att_FourByteInt(ncid, varid, name, values)
+    integer,                                    intent(in)  :: ncid, varid
+    character(len = *),                         intent(in)  :: name
+    integer (kind = FourByteInt), dimension(:), intent(out) :: values
+    integer                                                 :: nf90mpi_get_att_FourByteInt
+    integer, dimension(size(values))                        :: defaultInteger
+
+    nf90mpi_get_att_FourByteInt = nfmpi_get_att_int(ncid, varid, name, defaultInteger)
+    values(:) = defaultInteger(:)
+  end function nf90mpi_get_att_FourByteInt
+  ! -------
+  function nf90mpi_get_att_one_FourByteInt(ncid, varid, name, values)
+    integer,                                    intent(in)  :: ncid, varid
+    character(len = *),                         intent(in)  :: name
+    integer (kind = FourByteInt),               intent(out) :: values
+    integer                                                 :: nf90mpi_get_att_one_FourByteInt
+    integer, dimension(1)                                   :: defaultInteger
+
+    nf90mpi_get_att_one_FourByteInt = nfmpi_get_att_int(ncid, varid, name, defaultInteger)
+    values = defaultInteger(1)
+  end function nf90mpi_get_att_one_FourByteInt
+  ! -------
+  function nf90mpi_put_att_EightByteInt(ncid, varid, name, values)
+    integer,                                     intent(in) :: ncid, varid
+    character(len = *),                          intent(in) :: name
+    integer (kind = EightByteInt), dimension(:), intent(in) :: values
+    integer                                                 :: nf90mpi_put_att_EightByteInt
+    integer (kind=MPI_OFFSET_KIND)                          :: ilen
+
+    ilen = size(values)
+    nf90mpi_put_att_EightByteInt = nfmpi_put_att_int8(ncid, varid, name, nf90_int, ilen, values)
+  end function nf90mpi_put_att_EightByteInt
+  ! -------
+  function nf90mpi_put_att_one_EightByteInt(ncid, varid, name, values)
+    integer,                                     intent(in) :: ncid, varid
+    character(len = *),                          intent(in) :: name
+    integer (kind = EightByteInt),               intent(in) :: values
+    integer                                                 :: nf90mpi_put_att_one_EightByteInt
+
+    integer (kind = EightByteInt), dimension(1) :: valuesA
+    valuesA(1) = values
+    nf90mpi_put_att_one_EightByteInt = nfmpi_put_att_int8(ncid, varid, name, nf90_int, 1_MPI_OFFSET_KIND, valuesA)
+  end function nf90mpi_put_att_one_EightByteInt
+  ! -------
+  function nf90mpi_get_att_EightByteInt(ncid, varid, name, values)
+    integer,                                     intent(in)  :: ncid, varid
+    character(len = *),                          intent(in)  :: name
+    integer (kind = EightByteInt), dimension(:), intent(out) :: values
+    integer                                                  :: nf90mpi_get_att_EightByteInt
+
+    nf90mpi_get_att_EightByteInt = nfmpi_get_att_int8(ncid, varid, name, values)
+  end function nf90mpi_get_att_EightByteInt
+  ! -------
+  function nf90mpi_get_att_one_EightByteInt(ncid, varid, name, values)
+    integer,                                     intent(in)  :: ncid, varid
+    character(len = *),                          intent(in)  :: name
+    integer (kind = EightByteInt),               intent(out) :: values
+    integer                                                  :: nf90mpi_get_att_one_EightByteInt
+
+    integer (kind = EightByteInt), dimension(1) :: valuesA
+
+    nf90mpi_get_att_one_EightByteInt = nfmpi_get_att_int8(ncid, varid, name, valuesA)
+    values = valuesA(1)
+  end function nf90mpi_get_att_one_EightByteInt
+  ! -------
+  ! Real attributes
+  ! -------
+  function nf90mpi_put_att_FourByteReal(ncid, varid, name, values)
+    integer,                                   intent(in)  :: ncid, varid
+    character(len = *),                        intent(in)  :: name
+    real (kind =  FourByteReal), dimension(:), intent(in)  :: values
+    integer                                                :: nf90mpi_put_att_FourByteReal
+    integer (kind=MPI_OFFSET_KIND)                         :: ilen
+
+    ilen = size(values)
+    nf90mpi_put_att_FourByteReal = nfmpi_put_att_real(ncid, varid, name, nf90_real4, ilen, values)
+  end function nf90mpi_put_att_FourByteReal
+  ! -------
+  function nf90mpi_put_att_one_FourByteReal(ncid, varid, name, values)
+    integer,                                   intent(in)  :: ncid, varid
+    character(len = *),                        intent(in)  :: name
+    real (kind =  FourByteReal),               intent(in)  :: values
+    integer                                                :: nf90mpi_put_att_one_FourByteReal
+
+    real (kind =  FourByteReal), dimension(1) :: valuesA
+    valuesA(1) = values
+    nf90mpi_put_att_one_FourByteReal = nfmpi_put_att_real(ncid, varid, name, nf90_real4, 1_MPI_OFFSET_KIND, valuesA)
+  end function nf90mpi_put_att_one_FourByteReal
+  ! -------
+  function nf90mpi_get_att_FourByteReal(ncid, varid, name, values)
+    integer,                                   intent(in)  :: ncid, varid
+    character(len = *),                        intent(in)  :: name
+    real (kind =  FourByteReal), dimension(:), intent(out) :: values
+    integer                                                :: nf90mpi_get_att_FourByteReal
+
+    nf90mpi_get_att_FourByteReal = nfmpi_get_att_real(ncid, varid, name, values)
+  end function nf90mpi_get_att_FourByteReal
+  ! -------
+  function nf90mpi_get_att_one_FourByteReal(ncid, varid, name, values)
+    integer,                                   intent(in)  :: ncid, varid
+    character(len = *),                        intent(in)  :: name
+    real (kind =  FourByteReal),               intent(out) :: values
+    integer                                                :: nf90mpi_get_att_one_FourByteReal
+
+    real (kind =  FourByteReal), dimension(1) :: valuesA
+    nf90mpi_get_att_one_FourByteReal = nfmpi_get_att_real(ncid, varid, name, valuesA)
+    values = valuesA(1)
+  end function nf90mpi_get_att_one_FourByteReal
+  ! -------
+  function nf90mpi_put_att_EightByteReal(ncid, varid, name, values)
+    integer,                                   intent(in)  :: ncid, varid
+    character(len = *),                        intent(in)  :: name
+    real (kind = EightByteReal), dimension(:), intent(in)  :: values
+    integer                                                :: nf90mpi_put_att_EightByteReal
+    integer (kind=MPI_OFFSET_KIND)                         :: ilen
+
+    ilen = size(values)
+    nf90mpi_put_att_EightByteReal = nfmpi_put_att_double(ncid, varid, name, nf90_real8, ilen, values)
+  end function nf90mpi_put_att_EightByteReal
+  ! -------
+  function nf90mpi_put_att_one_EightByteReal(ncid, varid, name, values)
+    integer,                                   intent(in)  :: ncid, varid
+    character(len = *),                        intent(in)  :: name
+    real (kind = EightByteReal),               intent(in)  :: values
+    integer                                                :: nf90mpi_put_att_one_EightByteReal
+
+    real (kind = EightByteReal), dimension(1) :: valuesA
+    valuesA(1) = values
+    nf90mpi_put_att_one_EightByteReal = nfmpi_put_att_double(ncid, varid, name, nf90_real8, 1_MPI_OFFSET_KIND, valuesA)
+  end function nf90mpi_put_att_one_EightByteReal
+  ! -------
+  function nf90mpi_get_att_EightByteReal(ncid, varid, name, values)
+    integer,                                   intent(in)  :: ncid, varid
+    character(len = *),                        intent(in)  :: name
+    real (kind = EightByteReal), dimension(:), intent(out) :: values
+    integer                                                :: nf90mpi_get_att_EightByteReal
+
+    nf90mpi_get_att_EightByteReal = nfmpi_get_att_double(ncid, varid, name, values)
+  end function nf90mpi_get_att_EightByteReal
+  ! -------
+  function nf90mpi_get_att_one_EightByteReal(ncid, varid, name, values)
+    integer,                                   intent(in)  :: ncid, varid
+    character(len = *),                        intent(in)  :: name
+    real (kind = EightByteReal),               intent(out) :: values
+    integer                                                :: nf90mpi_get_att_one_EightByteReal
+
+    real (kind = EightByteReal), dimension(1) :: valuesA
+    nf90mpi_get_att_one_EightByteReal = nfmpi_get_att_double(ncid, varid, name, valuesA)
+    values = valuesA(1)
+  end function nf90mpi_get_att_one_EightByteReal
+  ! -------
diff --git a/src/libf90/dims.f90 b/src/libf90/dims.f90
new file mode 100644
index 0000000..92f4f4d
--- /dev/null
+++ b/src/libf90/dims.f90
@@ -0,0 +1,56 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: dims.f90 1468 2013-10-26 16:53:18Z wkliao $
+!
+! This file is taken from netcdf_dims.f90 with changes for PnetCDF use
+!  
+!
+
+  !
+  ! Dimension routines:
+  !
+  ! -----------
+  function nf90mpi_def_dim(ncid, name, len, dimid)
+    integer,                        intent( in) :: ncid
+    character (len=*),              intent( in) :: name
+    integer (kind=MPI_OFFSET_KIND), intent( in) :: len
+    integer,                        intent(out) :: dimid
+    integer                                     :: nf90mpi_def_dim
+  
+    nf90mpi_def_dim = nfmpi_def_dim(ncid, name, len, dimid)
+  end function nf90mpi_def_dim
+  ! -----------
+  function nf90mpi_inq_dimid(ncid, name, dimid)
+    integer,             intent( in) :: ncid
+    character (len=*),   intent( in) :: name
+    integer,             intent(out) :: dimid
+    integer                          :: nf90mpi_inq_dimid
+    
+    nf90mpi_inq_dimid = nfmpi_inq_dimid(ncid, name, dimid)
+  end function nf90mpi_inq_dimid
+  ! -----------
+  function nf90mpi_rename_dim(ncid, dimid, name)
+    integer,             intent( in) :: ncid
+    character (len=*),   intent( in) :: name
+    integer,             intent( in) :: dimid
+    integer                          :: nf90mpi_rename_dim
+
+    nf90mpi_rename_dim = nfmpi_rename_dim(ncid, dimid, name)
+  end function nf90mpi_rename_dim
+  ! -----------
+  function nf90mpi_inquire_dimension(ncid, dimid, name, len)
+    integer,                                  intent( in) :: ncid, dimid
+    character (len=*), optional,              intent(out) :: name
+    integer (kind=MPI_OFFSET_KIND), optional, intent(out) :: len
+    integer                                               :: nf90mpi_inquire_dimension
+    
+    character (len=nf90_max_name)  :: dimName
+    integer (kind=MPI_OFFSET_KIND) :: length
+    
+    nf90mpi_inquire_dimension = nfmpi_inq_dim(ncid, dimid, dimName, length)
+    if(present(name)) name = trim(dimName)
+    if(present(len )) len  = length
+  end function nf90mpi_inquire_dimension
+  ! -----------
diff --git a/src/libf90/file.f90 b/src/libf90/file.f90
new file mode 100644
index 0000000..53f7267
--- /dev/null
+++ b/src/libf90/file.f90
@@ -0,0 +1,331 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: file.f90 2013 2015-02-18 17:14:26Z wkliao $
+!
+! This file is taken from netcdf_file.f90 with changes for PnetCDF use
+!  
+!
+
+! This is part of the netCDF F90 API, or. Copyright 2006 UCAR. See COPYRIGHT file
+! for details.
+
+! This file contains the netcdf file functions that are shared by
+! netcdf-3 and netcdf-4.
+
+! $Id: file.f90 2013 2015-02-18 17:14:26Z wkliao $
+! -------
+function nf90mpi_inq_libvers()
+  character(len = 80) :: nf90mpi_inq_libvers
+
+  nf90mpi_inq_libvers = nfmpi_inq_libvers()
+end function nf90mpi_inq_libvers
+! -------
+function nf90mpi_strerror(ncerr)
+  integer, intent( in) :: ncerr
+  character(len = 80)  :: nf90mpi_strerror
+
+  nf90mpi_strerror = nfmpi_strerror(ncerr)
+end function nf90mpi_strerror
+! -------
+!
+! File level control routines:
+!
+! function nf90mpi_inq_base_pe(ncid, pe)
+!   integer, intent( in) :: ncid
+!   integer, intent(out) :: pe
+!   integer              :: nf90mpi_inq_base_pe
+! 
+!   nf90mpi_inq_base_pe = nfmpi_inq_base_pe(ncid, pe)
+! end function nf90mpi_inq_base_pe
+! -------
+! function nf90mpi_set_base_pe(ncid, pe)
+!   integer, intent( in) :: ncid, pe
+!   integer              :: nf90mpi_set_base_pe
+! 
+!   nf90mpi_set_base_pe = nfmpi_set_base_pe(ncid, pe)
+! end function nf90mpi_set_base_pe
+! -------
+function nf90mpi_create(mpi_comm, path, cmode, mpi_info, ncid)
+  character (len = *), intent( in) :: path
+  integer,             intent( in) :: mpi_comm, cmode, mpi_info
+  integer,             intent(out) :: ncid
+  integer                          :: nf90mpi_create
+
+  nf90mpi_create = nfmpi_create(mpi_comm, path, cmode, mpi_info, ncid)
+end function nf90mpi_create
+! -------
+function nf90mpi_open(mpi_comm, path, omode, mpi_info, ncid)
+  character (len = *), intent( in) :: path
+  integer,             intent( in) :: mpi_comm, omode, mpi_info
+  integer,             intent(out) :: ncid
+  integer                          :: nf90mpi_open
+
+  nf90mpi_open = nfmpi_open(mpi_comm, path, omode, mpi_info, ncid)
+end function nf90mpi_open
+! -------
+function nf90mpi_set_fill(ncid, fillmode, old_mode)
+  integer, intent( in) :: ncid, fillmode 
+  integer, intent(out) :: old_mode
+  integer              :: nf90mpi_set_fill
+
+  nf90mpi_set_fill = nfmpi_set_fill(ncid, fillmode, old_mode)
+end function nf90mpi_set_fill
+! -------
+function nf90mpi_redef(ncid)
+  integer, intent( in) :: ncid
+  integer              :: nf90mpi_redef
+
+  nf90mpi_redef = nfmpi_redef(ncid)
+end function nf90mpi_redef
+! -------
+function nf90mpi_enddef(ncid, h_minfree, v_align, v_minfree, r_align)
+  integer,                                    intent(in) :: ncid
+  integer (kind = MPI_OFFSET_KIND), optional, intent(in) :: h_minfree
+  integer (kind = MPI_OFFSET_KIND), optional, intent(in) :: v_align
+  integer (kind = MPI_OFFSET_KIND), optional, intent(in) :: v_minfree
+  integer (kind = MPI_OFFSET_KIND), optional, intent(in) :: r_align
+  integer                                                :: nf90mpi_enddef
+
+  integer (kind = MPI_OFFSET_KIND) :: hMinFree, VAlign, VMinFree, RAlign
+
+  if (.not. any( (/ present(h_minfree), present(v_align), &
+                    present(v_minfree), present(r_align) /) ) )then
+     nf90mpi_enddef = nfmpi_enddef(ncid)
+  else
+     ! Default values per the man page
+     hMinFree = 0; VMinFree = 0
+     VAlign   = 4; RAlign   = 4
+     if(present(h_minfree)) HMinFree = h_minfree
+     if(present(v_align  )) VAlign   = v_align
+     if(present(v_minfree)) VMinFree = v_minfree
+     if(present(r_align  )) RAlign   = r_align
+     nf90mpi_enddef = nfmpi__enddef(ncid, hMinFree, VAlign, VMinFree, RAlign)
+  end if
+end function nf90mpi_enddef
+! -------
+function nf90mpi_sync(ncid)
+  integer, intent( in) :: ncid
+  integer              :: nf90mpi_sync
+
+  nf90mpi_sync = nfmpi_sync(ncid)
+end function nf90mpi_sync
+! -------
+function nf90mpi_abort(ncid)
+  integer, intent( in) :: ncid
+  integer              :: nf90mpi_abort
+
+  nf90mpi_abort = nfmpi_abort(ncid)
+end function nf90mpi_abort
+! -------
+function nf90mpi_close(ncid)
+  integer, intent( in) :: ncid
+  integer              :: nf90mpi_close
+
+  nf90mpi_close = nfmpi_close(ncid)
+end function nf90mpi_close
+! -------
+function nf90mpi_delete(name, mpi_info)
+  character(len = *), intent( in) :: name
+  integer                         :: nf90mpi_delete
+  integer,            intent( in) :: mpi_info
+
+  nf90mpi_delete = nfmpi_delete(name, mpi_info)
+end function nf90mpi_delete
+
+!
+! A single file level inquiry routine 
+! 
+function nf90mpi_inquire(ncid, nDimensions, nVariables, nAttributes, unlimitedDimId, formatNum)
+  integer,           intent( in) :: ncid
+  integer, optional, intent(out) :: nDimensions, nVariables, nAttributes, unlimitedDimId, formatNum
+  integer                        :: nf90mpi_inquire
+
+  integer :: nDims, nVars, nGAtts, unlimDimId, frmt
+
+  nf90mpi_inquire = nfmpi_inq(ncid, nDims, nVars, nGAtts, unlimDimId)
+  if(present(nDimensions))    nDimensions    = nDims 
+  if(present(nVariables))     nVariables     = nVars
+  if(present(nAttributes))    nAttributes    = nGAtts
+  if(present(unlimitedDimId)) unlimitedDimId = unlimDimId
+  if(present(formatNum)) then
+     nf90mpi_inquire = nfmpi_inq_format(ncid, frmt)
+     formatNum = frmt
+  endif
+end function nf90mpi_inquire
+
+! -------
+function nf90mpi_inq_striping(ncid, striping_size, striping_count)
+  integer,            intent( in) :: ncid
+  integer,            intent(out) :: striping_size
+  integer,            intent(out) :: striping_count
+  integer                         :: nf90mpi_inq_striping
+
+  nf90mpi_inq_striping = nfmpi_inq_striping(ncid, striping_size, striping_count)
+end function nf90mpi_inq_striping
+
+! -------
+function nf90mpi_begin_indep_data(ncid)
+  integer,            intent( in) :: ncid
+  integer                         :: nf90mpi_begin_indep_data
+
+  nf90mpi_begin_indep_data = nfmpi_begin_indep_data(ncid)
+end function nf90mpi_begin_indep_data
+
+! -------
+function nf90mpi_end_indep_data(ncid)
+  integer,            intent( in) :: ncid
+  integer                         :: nf90mpi_end_indep_data
+
+  nf90mpi_end_indep_data = nfmpi_end_indep_data(ncid)
+end function nf90mpi_end_indep_data
+
+! -------
+function nf90mpi_inq_put_size(ncid, put_size)
+  integer,                          intent( in) :: ncid
+  integer (kind = MPI_OFFSET_KIND), intent(out) :: put_size
+  integer                                       :: nf90mpi_inq_put_size
+
+  nf90mpi_inq_put_size = nfmpi_inq_put_size(ncid, put_size)
+end function nf90mpi_inq_put_size
+
+! -------
+function nf90mpi_inq_get_size(ncid, get_size)
+  integer,                          intent( in) :: ncid
+  integer (kind = MPI_OFFSET_KIND), intent(out) :: get_size
+  integer                                       :: nf90mpi_inq_get_size
+
+  nf90mpi_inq_get_size = nfmpi_inq_get_size(ncid, get_size)
+end function nf90mpi_inq_get_size
+
+! -------
+function nf90mpi_inq_header_size(ncid, h_size)
+  integer,                          intent( in) :: ncid
+  integer (kind = MPI_OFFSET_KIND), intent(out) :: h_size
+  integer                                       :: nf90mpi_inq_header_size
+
+  nf90mpi_inq_header_size = nfmpi_inq_header_size(ncid, h_size)
+end function nf90mpi_inq_header_size
+
+! -------
+function nf90mpi_inq_header_extent(ncid, h_extent)
+  integer,                          intent( in) :: ncid
+  integer (kind = MPI_OFFSET_KIND), intent(out) :: h_extent
+  integer                                       :: nf90mpi_inq_header_extent
+
+  nf90mpi_inq_header_extent = nfmpi_inq_header_extent(ncid, h_extent)
+end function nf90mpi_inq_header_extent
+
+! -------
+function nf90mpi_inq_varoffset(ncid, varid, offset)
+  integer,                          intent( in) :: ncid, varid
+  integer (kind = MPI_OFFSET_KIND), intent(out) :: offset
+  integer                                       :: nf90mpi_inq_varoffset
+
+  nf90mpi_inq_varoffset = nfmpi_inq_varoffset(ncid, varid, offset)
+end function nf90mpi_inq_varoffset
+
+! -------
+function nf90mpi_inq_nreqs(ncid, nreqs)
+  integer, intent( in) :: ncid
+  integer, intent(out) :: nreqs
+  integer              :: nf90mpi_inq_nreqs
+
+  nf90mpi_inq_nreqs = nfmpi_inq_nreqs(ncid, nreqs)
+end function nf90mpi_inq_nreqs
+
+! -------
+function nf90mpi_inq_file_info(ncid, mpi_info)
+  integer, intent( in) :: ncid
+  integer, intent(out) :: mpi_info
+  integer              :: nf90mpi_inq_file_info
+
+  nf90mpi_inq_file_info = nfmpi_inq_file_info(ncid, mpi_info)
+end function nf90mpi_inq_file_info
+
+! -------
+function nf90mpi_get_file_info(ncid, mpi_info)
+  integer, intent( in) :: ncid
+  integer, intent(out) :: mpi_info
+  integer              :: nf90mpi_get_file_info
+
+  nf90mpi_get_file_info = nfmpi_get_file_info(ncid, mpi_info)
+end function nf90mpi_get_file_info
+
+! -------
+function nf90mpi_inq_malloc_size(size)
+  integer (kind = MPI_OFFSET_KIND), intent(out) :: size
+  integer                                       :: nf90mpi_inq_malloc_size
+
+  nf90mpi_inq_malloc_size = nfmpi_inq_malloc_size(size)
+end function nf90mpi_inq_malloc_size
+
+! -------
+function nf90mpi_inq_malloc_max_size(size)
+  integer (kind = MPI_OFFSET_KIND), intent(out) :: size
+  integer                                       :: nf90mpi_inq_malloc_max_size
+
+  nf90mpi_inq_malloc_max_size = nfmpi_inq_malloc_max_size(size)
+end function nf90mpi_inq_malloc_max_size
+
+! -------
+function nf90mpi_inq_malloc_list()
+  integer                                       :: nf90mpi_inq_malloc_list
+
+  nf90mpi_inq_malloc_list = nfmpi_inq_malloc_list()
+end function nf90mpi_inq_malloc_list
+
+! -------
+function nf90mpi_inq_files_opened(nfiles, ncids)
+  integer,               intent(out) :: nfiles
+  integer, dimension(:), intent(out) :: ncids
+  integer                            :: nf90mpi_inq_files_opened
+
+  nf90mpi_inq_files_opened = nfmpi_inq_files_opened(nfiles, ncids)
+end function nf90mpi_inq_files_opened
+
+! -------
+function nf90mpi_inq_num_rec_vars(ncid, nvars)
+  integer, intent( in) :: ncid
+  integer, intent(out) :: nvars
+  integer              :: nf90mpi_inq_num_rec_vars
+
+  nf90mpi_inq_num_rec_vars = nfmpi_inq_num_rec_vars(ncid, nvars)
+end function nf90mpi_inq_num_rec_vars
+
+! -------
+function nf90mpi_inq_num_fix_vars(ncid, nvars)
+  integer, intent( in) :: ncid
+  integer, intent(out) :: nvars
+  integer              :: nf90mpi_inq_num_fix_vars
+
+  nf90mpi_inq_num_fix_vars = nfmpi_inq_num_fix_vars(ncid, nvars)
+end function nf90mpi_inq_num_fix_vars
+
+! -------
+function nf90mpi_inq_recsize(ncid, recsize)
+  integer,                          intent( in) :: ncid
+  integer (kind = MPI_OFFSET_KIND), intent(out) :: recsize
+  integer                                       :: nf90mpi_inq_recsize
+
+  nf90mpi_inq_recsize = nfmpi_inq_recsize(ncid, recsize)
+end function nf90mpi_inq_recsize
+
+! -------
+function nf90mpi_set_default_format(new_format, old_format)
+  integer, intent( in) :: new_format
+  integer, intent(out) :: old_format
+  integer              :: nf90mpi_set_default_format
+
+  nf90mpi_set_default_format = nfmpi_set_default_format(new_format, old_format)
+end function nf90mpi_set_default_format
+
+! -------
+function nf90mpi_inq_default_format(default_format)
+  integer, intent(out) :: default_format
+  integer              :: nf90mpi_inq_default_format
+
+  nf90mpi_inq_default_format = nfmpi_inq_default_format(default_format)
+end function nf90mpi_inq_default_format
+
diff --git a/src/libf90/getput_text.m4 b/src/libf90/getput_text.m4
new file mode 100644
index 0000000..0ffd27c
--- /dev/null
+++ b/src/libf90/getput_text.m4
@@ -0,0 +1,251 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source
+dnl
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: getput_text.m4 1882 2014-11-21 17:44:34Z wkliao $
+!
+
+dnl
+dnl TEXTVAR1(ncid, varid, values, start, count, stride, map)
+dnl
+define(`TEXTVAR1',dnl
+`dnl
+   function nf90mpi_$1_var_text$3(ncid, varid, values, start, count, stride, map)
+     integer,                                                intent(in) :: ncid, varid
+     character (len=*),                                      intent($2) :: values
+     integer (kind=MPI_OFFSET_KIND), dimension(:), optional, intent(in) :: start, count, stride, map
+
+     integer                                                            :: nf90mpi_$1_var_text$3
+     integer (kind=MPI_OFFSET_KIND), dimension(nf90_max_var_dims)       :: localStart, localCount, localStride
+ 
+     ! Set local arguments to default values
+     localStart (:)  = 1
+     localCount (1)  = LEN(values); localCount (2:) = 1
+     localStride(:)  = 1
+
+     if(present(start))  localStart (:size(start) ) = start(:)
+     if(present(count))  localCount (:size(count) ) = count(:)
+     if(present(stride)) localStride(:size(stride)) = stride(:)
+     if(present(map)) then
+       nf90mpi_$1_var_text$3 = nfmpi_$1_varm_text$3(ncid, varid, localStart, localCount, localStride, map, values)
+     else
+       nf90mpi_$1_var_text$3 = nfmpi_$1_vars_text$3(ncid, varid, localStart, localCount, localStride, values)
+     end if
+   end function nf90mpi_$1_var_text$3
+')dnl
+
+!
+! Independent put APIs
+!
+
+TEXTVAR1(put, in)
+TEXTVAR1(get, out)
+
+!
+! Collective put APIs
+!
+
+TEXTVAR1(put, in,  _all)
+TEXTVAR1(get, out, _all)
+
+
+dnl
+dnl TEXTVAR(ncid, varid, values, start, count, stride, map)
+dnl
+define(`TEXTVAR',dnl
+`dnl
+   function nf90mpi_$1_var_$2_text$6(ncid, varid, values, start, count, stride, map)
+     integer,                                                intent(in) :: ncid, varid
+     character (len=*), dimension($3),                       intent($5) :: values
+     integer (kind=MPI_OFFSET_KIND), dimension(:), optional, intent(in) :: start, count, stride, map
+ 
+     integer                                                            :: nf90mpi_$1_var_$2_text$6
+     integer (kind=MPI_OFFSET_KIND), dimension(nf90_max_var_dims)       :: localStart, localCount, localStride, localMap
+     integer                                                            :: numDims, counter
+ 
+     ! Set local arguments to default values
+     numDims = substr(`$2', `0', `1')
+
+     localStart (:         ) = 1
+     localCount (:numDims+1) = (/ LEN(values($4)), shape(values) /)
+     localCount (numDims+2:) = 0
+     localStride(:         ) = 1
+     ! localMap   (:numDims  ) = (/ 1, (product(localCount(:counter)), counter = 1, numDims - 1) /)
+     localMap(1) = 1
+     do counter = 1, numDims - 1
+        localMap(counter+1) = localMap(counter) * localCount(counter)
+     enddo
+ 
+     if(present(start))  localStart (:size(start))  = start(:)
+     if(present(count))  localCount (:size(count))  = count(:)
+     if(present(stride)) localStride(:size(stride)) = stride(:)
+     if(present(map))  then
+       localMap   (:size(map))    = map(:)
+       nf90mpi_$1_var_$2_text$6 = &
+          nfmpi_$1_varm_text$6(ncid, varid, localStart, localCount, localStride, localMap, values($4))
+     else
+       nf90mpi_$1_var_$2_text$6 = &
+          nfmpi_$1_vars_text$6(ncid, varid, localStart, localCount, localStride, values($4))
+     end if
+   end function nf90mpi_$1_var_$2_text$6
+')dnl
+
+TEXTVAR(put, 1D,  :,               1,              in)
+TEXTVAR(put, 2D, `:,:',           `1,1',           in)
+TEXTVAR(put, 3D, `:,:,:',         `1,1,1',         in)
+TEXTVAR(put, 4D, `:,:,:,:',       `1,1,1,1',       in)
+TEXTVAR(put, 5D, `:,:,:,:,:',     `1,1,1,1,1',     in)
+TEXTVAR(put, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   in)
+TEXTVAR(put, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', in)
+
+TEXTVAR(get, 1D,  :,               1,              out)
+TEXTVAR(get, 2D, `:,:',           `1,1',           out)
+TEXTVAR(get, 3D, `:,:,:',         `1,1,1',         out)
+TEXTVAR(get, 4D, `:,:,:,:',       `1,1,1,1',       out)
+TEXTVAR(get, 5D, `:,:,:,:,:',     `1,1,1,1,1',     out)
+TEXTVAR(get, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   out)
+TEXTVAR(get, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', out)
+
+!
+! Collective APIs
+!
+
+TEXTVAR(put, 1D,  :,               1,              in, _all)
+TEXTVAR(put, 2D, `:,:',           `1,1',           in, _all)
+TEXTVAR(put, 3D, `:,:,:',         `1,1,1',         in, _all)
+TEXTVAR(put, 4D, `:,:,:,:',       `1,1,1,1',       in, _all)
+TEXTVAR(put, 5D, `:,:,:,:,:',     `1,1,1,1,1',     in, _all)
+TEXTVAR(put, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   in, _all)
+TEXTVAR(put, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', in, _all)
+
+TEXTVAR(get, 1D,  :,               1,              out, _all)
+TEXTVAR(get, 2D, `:,:',           `1,1',           out, _all)
+TEXTVAR(get, 3D, `:,:,:',         `1,1,1',         out, _all)
+TEXTVAR(get, 4D, `:,:,:,:',       `1,1,1,1',       out, _all)
+TEXTVAR(get, 5D, `:,:,:,:,:',     `1,1,1,1,1',     out, _all)
+TEXTVAR(get, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   out, _all)
+TEXTVAR(get, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', out, _all)
+
+!
+! Nonblocking APIs
+!
+
+dnl
+dnl NBTEXTVAR1(ncid, varid, values, req, start, count, stride, map)
+dnl
+define(`NBTEXTVAR1',dnl
+`dnl
+   function nf90mpi_$1_var_text(ncid, varid, values, req, start, count, stride, map)
+     integer,                                                intent( in) :: ncid, varid
+     integer,                                                intent(out) :: req
+     character (len=*),                                      intent( $2) :: values
+     integer (kind=MPI_OFFSET_KIND), dimension(:), optional, intent( in) :: start, count, stride, map
+
+     integer                                                             :: nf90mpi_$1_var_text
+     integer (kind=MPI_OFFSET_KIND), dimension(nf90_max_var_dims)        :: localStart, localCount, localStride
+ 
+     ! Set local arguments to default values
+     localStart (:)  = 1
+     localCount (1)  = LEN(values); localCount (2:) = 1
+     localStride(:)  = 1
+          
+     if(present(start))  localStart (:size(start) ) = start(:)
+     if(present(count))  localCount (:size(count) ) = count(:)
+     if(present(stride)) localStride(:size(stride)) = stride(:)
+     if(present(map)) then
+       nf90mpi_$1_var_text = nfmpi_$1_varm_text(ncid, varid, localStart, localCount, localStride, map, values, req)
+     else
+       nf90mpi_$1_var_text = nfmpi_$1_vars_text(ncid, varid, localStart, localCount, localStride, values, req)
+     end if
+   end function nf90mpi_$1_var_text
+')dnl
+
+!
+! iput APIs
+!
+
+NBTEXTVAR1(iput, in)
+NBTEXTVAR1(iget, out)
+
+!
+! bput APIs
+!
+
+NBTEXTVAR1(bput, in)
+
+
+dnl
+dnl NBTEXTVAR(ncid, varid, values, req, start, count, stride, map)
+dnl
+define(`NBTEXTVAR',dnl
+`dnl
+   function nf90mpi_$1_var_$2_text(ncid, varid, values, req, start, count, stride, map)
+     integer,                                                intent( in) :: ncid, varid
+     integer,                                                intent(out) :: req
+     character (len=*), dimension($3),                       intent( $5) :: values
+     integer (kind=MPI_OFFSET_KIND), dimension(:), optional, intent( in) :: start, count, stride, map
+ 
+     integer                                                             :: nf90mpi_$1_var_$2_text
+     integer (kind=MPI_OFFSET_KIND), dimension(nf90_max_var_dims)        :: localStart, localCount, localStride, localMap
+     integer                                                             :: numDims, counter
+ 
+     ! Set local arguments to default values
+     numDims = substr(`$2', `0', `1')
+
+     localStart (:         ) = 1
+     localCount ( :numDims+1) = (/ LEN(values($4)), shape(values) /)
+     localCount (numDims+2:) = 0
+     localStride(:         ) = 1
+     ! localMap   (:numDims  ) = (/ 1, (product(localCount(:counter)), counter = 1, numDims - 1) /)
+     localMap(1) = 1
+     do counter = 1, numDims - 1
+        localMap(counter+1) = localMap(counter) * localCount(counter)
+     enddo
+ 
+     if(present(start))  localStart (:size(start))  = start(:)
+     if(present(count))  localCount (:size(count))  = count(:)
+     if(present(stride)) localStride(:size(stride)) = stride(:)
+     if(present(map))  then
+       localMap   (:size(map))    = map(:)
+       nf90mpi_$1_var_$2_text = &
+          nfmpi_$1_varm_text(ncid, varid, localStart, localCount, localStride, localMap, values($4), req)
+     else
+       nf90mpi_$1_var_$2_text = &
+          nfmpi_$1_vars_text(ncid, varid, localStart, localCount, localStride, values($4), req)
+     end if
+   end function nf90mpi_$1_var_$2_text
+')dnl
+
+NBTEXTVAR(iput, 1D,  :,               1,              in)
+NBTEXTVAR(iput, 2D, `:,:',           `1,1',           in)
+NBTEXTVAR(iput, 3D, `:,:,:',         `1,1,1',         in)
+NBTEXTVAR(iput, 4D, `:,:,:,:',       `1,1,1,1',       in)
+NBTEXTVAR(iput, 5D, `:,:,:,:,:',     `1,1,1,1,1',     in)
+NBTEXTVAR(iput, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   in)
+NBTEXTVAR(iput, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', in)
+
+NBTEXTVAR(iget, 1D,  :,               1,              out)
+NBTEXTVAR(iget, 2D, `:,:',           `1,1',           out)
+NBTEXTVAR(iget, 3D, `:,:,:',         `1,1,1',         out)
+NBTEXTVAR(iget, 4D, `:,:,:,:',       `1,1,1,1',       out)
+NBTEXTVAR(iget, 5D, `:,:,:,:,:',     `1,1,1,1,1',     out)
+NBTEXTVAR(iget, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   out)
+NBTEXTVAR(iget, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', out)
+
+!
+! bput APIs
+!
+
+NBTEXTVAR(bput, 1D,  :,               1,              in)
+NBTEXTVAR(bput, 2D, `:,:',           `1,1',           in)
+NBTEXTVAR(bput, 3D, `:,:,:',         `1,1,1',         in)
+NBTEXTVAR(bput, 4D, `:,:,:,:',       `1,1,1,1',       in)
+NBTEXTVAR(bput, 5D, `:,:,:,:,:',     `1,1,1,1,1',     in)
+NBTEXTVAR(bput, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   in)
+NBTEXTVAR(bput, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', in)
+
diff --git a/src/libf90/getput_var.m4 b/src/libf90/getput_var.m4
new file mode 100644
index 0000000..9849fe9
--- /dev/null
+++ b/src/libf90/getput_var.m4
@@ -0,0 +1,678 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source
+dnl
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: getput_var.m4 2221 2015-12-12 00:39:15Z wkliao $
+!
+
+dnl
+dnl VAR_SCALAR
+dnl
+define(`VAR_SCALAR',dnl
+`dnl
+   function nf90mpi_$1_var_$3$2(ncid, varid, values, start, bufcount, buftype)
+     integer,                                                intent( in) :: ncid, varid
+     $4 (kind=$3),                                           intent($6)  :: values
+     integer (kind=MPI_OFFSET_KIND), dimension(:), optional, intent( in) :: start
+     integer (kind=MPI_OFFSET_KIND),               optional, intent( in) :: bufcount
+     integer,                                      optional, intent( in) :: buftype
+
+     integer                                                             :: nf90mpi_$1_var_$3$2
+     integer (kind=MPI_OFFSET_KIND), dimension(nf90_max_var_dims)        :: localIndex
+ 
+     ! Set local arguments to default values
+     localIndex(:) = 1
+     if (present(start)) localIndex(:size(start)) = start(:)
+ 
+     if (present(buftype)) then
+         nf90mpi_$1_var_$3$2 = nfmpi_$1_var1$2(ncid, varid, localIndex, values, bufcount, buftype)
+     else
+         nf90mpi_$1_var_$3$2 = nfmpi_$1_var1_$5$2(ncid, varid, localIndex, values)
+     endif
+   end function nf90mpi_$1_var_$3$2
+')dnl
+
+VAR_SCALAR(put,     , OneByteInt,    integer, int1,   in)
+VAR_SCALAR(put,     , TwoByteInt,    integer, int2,   INTENTV)
+VAR_SCALAR(put,     , FourByteInt,   integer, int,    INTENTV)
+VAR_SCALAR(put,     , FourByteReal,  real,    real,   INTENTV)
+VAR_SCALAR(put,     , EightByteReal, real,    double, INTENTV)
+VAR_SCALAR(put,     , EightByteInt,  integer, int8,   INTENTV)
+
+VAR_SCALAR(put, _all, OneByteInt,    integer, int1,   in)
+VAR_SCALAR(put, _all, TwoByteInt,    integer, int2,   INTENTV)
+VAR_SCALAR(put, _all, FourByteInt,   integer, int,    INTENTV)
+VAR_SCALAR(put, _all, FourByteReal,  real,    real,   INTENTV)
+VAR_SCALAR(put, _all, EightByteReal, real,    double, INTENTV)
+VAR_SCALAR(put, _all, EightByteInt,  integer, int8,   INTENTV)
+
+VAR_SCALAR(get,     , OneByteInt,    integer, int1,   out)
+VAR_SCALAR(get,     , TwoByteInt,    integer, int2,   out)
+VAR_SCALAR(get,     , FourByteInt,   integer, int,    out)
+VAR_SCALAR(get,     , FourByteReal,  real,    real,   out)
+VAR_SCALAR(get,     , EightByteReal, real,    double, out)
+VAR_SCALAR(get,     , EightByteInt,  integer, int8,   out)
+
+VAR_SCALAR(get, _all, OneByteInt,    integer, int1,   out)
+VAR_SCALAR(get, _all, TwoByteInt,    integer, int2,   out)
+VAR_SCALAR(get, _all, FourByteInt,   integer, int,    out)
+VAR_SCALAR(get, _all, FourByteReal,  real,    real,   out)
+VAR_SCALAR(get, _all, EightByteReal, real,    double, out)
+VAR_SCALAR(get, _all, EightByteInt,  integer, int8,   out)
+
+dnl
+dnl NBVAR1(ncid, varid, values, start, count, req)
+dnl
+define(`NBVAR1',dnl
+`dnl
+   function nf90mpi_$1_var_$2(ncid, varid, values, req, start, bufcount, buftype)
+     integer,                                                intent( in) :: ncid, varid
+     $3 (kind=$2),                                           intent($5)  :: values
+     integer,                                                intent(out) :: req
+     integer (kind=MPI_OFFSET_KIND), dimension(:), optional, intent( in) :: start
+     integer (kind=MPI_OFFSET_KIND),               optional, intent( in) :: bufcount
+     integer,                                      optional, intent( in) :: buftype
+
+     integer                                                             :: nf90mpi_$1_var_$2
+     integer (kind=MPI_OFFSET_KIND), dimension(nf90_max_var_dims)        :: localIndex
+ 
+     ! Set local arguments to default values
+     localIndex(:) = 1
+     if (present(start)) localIndex(:size(start)) = start(:)
+ 
+     if (present(buftype)) then
+         nf90mpi_$1_var_$2 = nfmpi_$1_var1(ncid, varid, localIndex, values, bufcount, buftype, req)
+     else
+         nf90mpi_$1_var_$2 = nfmpi_$1_var1_$4(ncid, varid, localIndex, values, req)
+     endif
+   end function nf90mpi_$1_var_$2
+')dnl
+
+!
+! Nonblocking iput APIs
+!
+
+NBVAR1(iput, OneByteInt,    integer, int1,   in)
+NBVAR1(iput, TwoByteInt,    integer, int2,   INTENTV)
+NBVAR1(iput, FourByteInt,   integer, int,    INTENTV)
+NBVAR1(iput, FourByteReal,  real,    real,   INTENTV)
+NBVAR1(iput, EightByteReal, real,    double, INTENTV)
+NBVAR1(iput, EightByteInt,  integer, int8,   INTENTV)
+
+!
+! Nonblocking iget APIs
+!
+
+NBVAR1(iget, OneByteInt,    integer, int1,   out)
+NBVAR1(iget, TwoByteInt,    integer, int2,   out)
+NBVAR1(iget, FourByteInt,   integer, int,    out)
+NBVAR1(iget, FourByteReal,  real,    real,   out)
+NBVAR1(iget, EightByteReal, real,    double, out)
+NBVAR1(iget, EightByteInt,  integer, int8,   out)
+
+!
+! Nonblocking bput APIs
+!
+
+NBVAR1(bput, OneByteInt,    integer, int1,   in)
+NBVAR1(bput, TwoByteInt,    integer, int2,   INTENTV)
+NBVAR1(bput, FourByteInt,   integer, int,    INTENTV)
+NBVAR1(bput, FourByteReal,  real,    real,   INTENTV)
+NBVAR1(bput, EightByteReal, real,    double, INTENTV)
+NBVAR1(bput, EightByteInt,  integer, int8,   INTENTV)
+
+dnl
+dnl VAR(ncid, varid, values, start, count, stride, map)
+dnl
+define(`VAR',dnl
+`dnl
+   function nf90mpi_$1_var_$2_$3$8(ncid, varid, values, start, count, stride, map, bufcount, buftype)
+     integer,                                                intent( in) :: ncid, varid
+     $4 (kind=$3), dimension($6),                            intent( $7) :: values
+     integer (kind=MPI_OFFSET_KIND), dimension(:), optional, intent( in) :: start, count, stride, map
+     integer (kind=MPI_OFFSET_KIND),               optional, intent( in) :: bufcount
+     integer,                                      optional, intent( in) :: buftype
+ 
+     integer                                                             :: nf90mpi_$1_var_$2_$3$8
+     integer (kind=MPI_OFFSET_KIND), dimension(nf90_max_var_dims)        :: localStart, localCount, localStride, localMap
+     integer                                                             :: numDims, counter
+ 
+     ! Set local arguments to default values
+     numDims = substr(`$2', `0', `1')
+     localStart (:         ) = 1
+     localCount (:numDims  ) = shape(values)
+     localCount (numDims+1:) = 1
+     localStride(:         ) = 1
+     ! localMap   (:numDims  ) = (/ 1, (product(localCount(:counter)), counter = 1, numDims - 1) /)
+     localMap(1) = 1
+     do counter = 1, numDims - 1
+        localMap(counter+1) = localMap(counter) * localCount(counter)
+     enddo
+ 
+     if (present(start))  localStart (:size(start) )  = start(:)
+     if (present(count))  localCount (:size(count) )  = count(:)
+     if (present(stride)) localStride(:size(stride)) = stride(:)
+     if (present(map))  then
+         localMap   (:size(map))    = map(:)
+         if (present(buftype)) then
+             nf90mpi_$1_var_$2_$3$8 = &
+                nfmpi_$1_varm$8(ncid, varid, localStart, localCount, localStride, localMap, values, bufcount, buftype)
+         else
+             nf90mpi_$1_var_$2_$3$8 = &
+                nfmpi_$1_varm_$5$8(ncid, varid, localStart, localCount, localStride, localMap, values)
+         endif
+     else if (present(stride)) then
+         if (present(buftype)) then
+             nf90mpi_$1_var_$2_$3$8 = &
+                nfmpi_$1_vars$8(ncid, varid, localStart, localCount, localStride, values, bufcount, buftype)
+         else
+             nf90mpi_$1_var_$2_$3$8 = &
+                nfmpi_$1_vars_$5$8(ncid, varid, localStart, localCount, localStride, values)
+         endif
+     else
+         if (present(buftype)) then
+             nf90mpi_$1_var_$2_$3$8 = &
+                nfmpi_$1_vara$8(ncid, varid, localStart, localCount, values, bufcount, buftype)
+         else
+             nf90mpi_$1_var_$2_$3$8 = &
+                nfmpi_$1_vara_$5$8(ncid, varid, localStart, localCount, values)
+         endif
+     end if
+   end function nf90mpi_$1_var_$2_$3$8
+')dnl
+
+!
+! Independent put APIs
+!
+
+VAR(put, 1D, OneByteInt, integer, int1,  :,              in)
+VAR(put, 2D, OneByteInt, integer, int1, `:,:',           in)
+VAR(put, 3D, OneByteInt, integer, int1, `:,:,:',         in)
+VAR(put, 4D, OneByteInt, integer, int1, `:,:,:,:',       in)
+VAR(put, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     in)
+VAR(put, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   in)
+VAR(put, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', in)
+
+VAR(put, 1D, TwoByteInt, integer, int2,  :,              INTENTV)
+VAR(put, 2D, TwoByteInt, integer, int2, `:,:',           INTENTV)
+VAR(put, 3D, TwoByteInt, integer, int2, `:,:,:',         INTENTV)
+VAR(put, 4D, TwoByteInt, integer, int2, `:,:,:,:',       INTENTV)
+VAR(put, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     INTENTV)
+VAR(put, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   INTENTV)
+VAR(put, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', INTENTV)
+
+VAR(put, 1D, FourByteInt, integer, int,  :,              INTENTV)
+VAR(put, 2D, FourByteInt, integer, int, `:,:',           INTENTV)
+VAR(put, 3D, FourByteInt, integer, int, `:,:,:',         INTENTV)
+VAR(put, 4D, FourByteInt, integer, int, `:,:,:,:',       INTENTV)
+VAR(put, 5D, FourByteInt, integer, int, `:,:,:,:,:',     INTENTV)
+VAR(put, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   INTENTV)
+VAR(put, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', INTENTV)
+
+VAR(put, 1D, FourByteReal, real,   real,  :,              INTENTV)
+VAR(put, 2D, FourByteReal, real,   real, `:,:',           INTENTV)
+VAR(put, 3D, FourByteReal, real,   real, `:,:,:',         INTENTV)
+VAR(put, 4D, FourByteReal, real,   real, `:,:,:,:',       INTENTV)
+VAR(put, 5D, FourByteReal, real,   real, `:,:,:,:,:',     INTENTV)
+VAR(put, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   INTENTV)
+VAR(put, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', INTENTV)
+
+VAR(put, 1D, EightByteReal, real, double,  :,              INTENTV)
+VAR(put, 2D, EightByteReal, real, double, `:,:',           INTENTV)
+VAR(put, 3D, EightByteReal, real, double, `:,:,:',         INTENTV)
+VAR(put, 4D, EightByteReal, real, double, `:,:,:,:',       INTENTV)
+VAR(put, 5D, EightByteReal, real, double, `:,:,:,:,:',     INTENTV)
+VAR(put, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   INTENTV)
+VAR(put, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', INTENTV)
+
+VAR(put, 1D, EightByteInt, integer, int8,  :,              INTENTV)
+VAR(put, 2D, EightByteInt, integer, int8, `:,:',           INTENTV)
+VAR(put, 3D, EightByteInt, integer, int8, `:,:,:',         INTENTV)
+VAR(put, 4D, EightByteInt, integer, int8, `:,:,:,:',       INTENTV)
+VAR(put, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     INTENTV)
+VAR(put, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   INTENTV)
+VAR(put, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', INTENTV)
+
+!
+! Independent get APIs
+!
+
+VAR(get, 1D, OneByteInt, integer, int1,  :,              out)
+VAR(get, 2D, OneByteInt, integer, int1, `:,:',           out)
+VAR(get, 3D, OneByteInt, integer, int1, `:,:,:',         out)
+VAR(get, 4D, OneByteInt, integer, int1, `:,:,:,:',       out)
+VAR(get, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     out)
+VAR(get, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   out)
+VAR(get, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', out)
+
+VAR(get, 1D, TwoByteInt, integer, int2,  :,              out)
+VAR(get, 2D, TwoByteInt, integer, int2, `:,:',           out)
+VAR(get, 3D, TwoByteInt, integer, int2, `:,:,:',         out)
+VAR(get, 4D, TwoByteInt, integer, int2, `:,:,:,:',       out)
+VAR(get, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     out)
+VAR(get, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   out)
+VAR(get, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', out)
+
+VAR(get, 1D, FourByteInt, integer, int,  :,              out)
+VAR(get, 2D, FourByteInt, integer, int, `:,:',           out)
+VAR(get, 3D, FourByteInt, integer, int, `:,:,:',         out)
+VAR(get, 4D, FourByteInt, integer, int, `:,:,:,:',       out)
+VAR(get, 5D, FourByteInt, integer, int, `:,:,:,:,:',     out)
+VAR(get, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   out)
+VAR(get, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', out)
+
+VAR(get, 1D, FourByteReal, real,   real,  :,              out)
+VAR(get, 2D, FourByteReal, real,   real, `:,:',           out)
+VAR(get, 3D, FourByteReal, real,   real, `:,:,:',         out)
+VAR(get, 4D, FourByteReal, real,   real, `:,:,:,:',       out)
+VAR(get, 5D, FourByteReal, real,   real, `:,:,:,:,:',     out)
+VAR(get, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   out)
+VAR(get, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', out)
+
+VAR(get, 1D, EightByteReal, real, double,  :,              out)
+VAR(get, 2D, EightByteReal, real, double, `:,:',           out)
+VAR(get, 3D, EightByteReal, real, double, `:,:,:',         out)
+VAR(get, 4D, EightByteReal, real, double, `:,:,:,:',       out)
+VAR(get, 5D, EightByteReal, real, double, `:,:,:,:,:',     out)
+VAR(get, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   out)
+VAR(get, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', out)
+
+VAR(get, 1D, EightByteInt, integer, int8,  :,              out)
+VAR(get, 2D, EightByteInt, integer, int8, `:,:',           out)
+VAR(get, 3D, EightByteInt, integer, int8, `:,:,:',         out)
+VAR(get, 4D, EightByteInt, integer, int8, `:,:,:,:',       out)
+VAR(get, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     out)
+VAR(get, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   out)
+VAR(get, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', out)
+
+!
+! collective put APIs
+!
+
+VAR(put, 1D, OneByteInt, integer, int1,  :,              in, _all)
+VAR(put, 2D, OneByteInt, integer, int1, `:,:',           in, _all)
+VAR(put, 3D, OneByteInt, integer, int1, `:,:,:',         in, _all)
+VAR(put, 4D, OneByteInt, integer, int1, `:,:,:,:',       in, _all)
+VAR(put, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     in, _all)
+VAR(put, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   in, _all)
+VAR(put, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', in, _all)
+
+VAR(put, 1D, TwoByteInt, integer, int2,  :,              INTENTV, _all)
+VAR(put, 2D, TwoByteInt, integer, int2, `:,:',           INTENTV, _all)
+VAR(put, 3D, TwoByteInt, integer, int2, `:,:,:',         INTENTV, _all)
+VAR(put, 4D, TwoByteInt, integer, int2, `:,:,:,:',       INTENTV, _all)
+VAR(put, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     INTENTV, _all)
+VAR(put, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   INTENTV, _all)
+VAR(put, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', INTENTV, _all)
+
+VAR(put, 1D, FourByteInt, integer, int,  :,              INTENTV, _all)
+VAR(put, 2D, FourByteInt, integer, int, `:,:',           INTENTV, _all)
+VAR(put, 3D, FourByteInt, integer, int, `:,:,:',         INTENTV, _all)
+VAR(put, 4D, FourByteInt, integer, int, `:,:,:,:',       INTENTV, _all)
+VAR(put, 5D, FourByteInt, integer, int, `:,:,:,:,:',     INTENTV, _all)
+VAR(put, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   INTENTV, _all)
+VAR(put, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', INTENTV, _all)
+
+VAR(put, 1D, FourByteReal, real,   real,  :,              INTENTV, _all)
+VAR(put, 2D, FourByteReal, real,   real, `:,:',           INTENTV, _all)
+VAR(put, 3D, FourByteReal, real,   real, `:,:,:',         INTENTV, _all)
+VAR(put, 4D, FourByteReal, real,   real, `:,:,:,:',       INTENTV, _all)
+VAR(put, 5D, FourByteReal, real,   real, `:,:,:,:,:',     INTENTV, _all)
+VAR(put, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   INTENTV, _all)
+VAR(put, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', INTENTV, _all)
+
+VAR(put, 1D, EightByteReal, real, double,  :,              INTENTV, _all)
+VAR(put, 2D, EightByteReal, real, double, `:,:',           INTENTV, _all)
+VAR(put, 3D, EightByteReal, real, double, `:,:,:',         INTENTV, _all)
+VAR(put, 4D, EightByteReal, real, double, `:,:,:,:',       INTENTV, _all)
+VAR(put, 5D, EightByteReal, real, double, `:,:,:,:,:',     INTENTV, _all)
+VAR(put, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   INTENTV, _all)
+VAR(put, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', INTENTV, _all)
+
+VAR(put, 1D, EightByteInt, integer, int8,  :,              INTENTV, _all)
+VAR(put, 2D, EightByteInt, integer, int8, `:,:',           INTENTV, _all)
+VAR(put, 3D, EightByteInt, integer, int8, `:,:,:',         INTENTV, _all)
+VAR(put, 4D, EightByteInt, integer, int8, `:,:,:,:',       INTENTV, _all)
+VAR(put, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     INTENTV, _all)
+VAR(put, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   INTENTV, _all)
+VAR(put, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', INTENTV, _all)
+!
+! collective get APIs
+!
+
+VAR(get, 1D, OneByteInt, integer, int1,  :,              out, _all)
+VAR(get, 2D, OneByteInt, integer, int1, `:,:',           out, _all)
+VAR(get, 3D, OneByteInt, integer, int1, `:,:,:',         out, _all)
+VAR(get, 4D, OneByteInt, integer, int1, `:,:,:,:',       out, _all)
+VAR(get, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     out, _all)
+VAR(get, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   out, _all)
+VAR(get, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', out, _all)
+
+VAR(get, 1D, TwoByteInt, integer, int2,  :,              out, _all)
+VAR(get, 2D, TwoByteInt, integer, int2, `:,:',           out, _all)
+VAR(get, 3D, TwoByteInt, integer, int2, `:,:,:',         out, _all)
+VAR(get, 4D, TwoByteInt, integer, int2, `:,:,:,:',       out, _all)
+VAR(get, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     out, _all)
+VAR(get, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   out, _all)
+VAR(get, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', out, _all)
+
+VAR(get, 1D, FourByteInt, integer, int,  :,              out, _all)
+VAR(get, 2D, FourByteInt, integer, int, `:,:',           out, _all)
+VAR(get, 3D, FourByteInt, integer, int, `:,:,:',         out, _all)
+VAR(get, 4D, FourByteInt, integer, int, `:,:,:,:',       out, _all)
+VAR(get, 5D, FourByteInt, integer, int, `:,:,:,:,:',     out, _all)
+VAR(get, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   out, _all)
+VAR(get, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', out, _all)
+
+VAR(get, 1D, FourByteReal, real,   real,  :,              out, _all)
+VAR(get, 2D, FourByteReal, real,   real, `:,:',           out, _all)
+VAR(get, 3D, FourByteReal, real,   real, `:,:,:',         out, _all)
+VAR(get, 4D, FourByteReal, real,   real, `:,:,:,:',       out, _all)
+VAR(get, 5D, FourByteReal, real,   real, `:,:,:,:,:',     out, _all)
+VAR(get, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   out, _all)
+VAR(get, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', out, _all)
+
+VAR(get, 1D, EightByteReal, real, double,  :,              out, _all)
+VAR(get, 2D, EightByteReal, real, double, `:,:',           out, _all)
+VAR(get, 3D, EightByteReal, real, double, `:,:,:',         out, _all)
+VAR(get, 4D, EightByteReal, real, double, `:,:,:,:',       out, _all)
+VAR(get, 5D, EightByteReal, real, double, `:,:,:,:,:',     out, _all)
+VAR(get, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   out, _all)
+VAR(get, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', out, _all)
+
+VAR(get, 1D, EightByteInt, integer, int8,  :,              out, _all)
+VAR(get, 2D, EightByteInt, integer, int8, `:,:',           out, _all)
+VAR(get, 3D, EightByteInt, integer, int8, `:,:,:',         out, _all)
+VAR(get, 4D, EightByteInt, integer, int8, `:,:,:,:',       out, _all)
+VAR(get, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     out, _all)
+VAR(get, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   out, _all)
+VAR(get, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', out, _all)
+
+!
+! Nonblocking APIs
+!
+
+dnl
+dnl NBVAR(ncid, varid, values, start, count, stride, map, req)
+dnl
+define(`NBVAR',dnl
+`dnl
+   function nf90mpi_$1_var_$2_$3(ncid, varid, values, req, start, count, stride, map, bufcount, buftype)
+     integer,                                                intent( in) :: ncid, varid
+     $4 (kind=$3), dimension($6),                            intent( $7) :: values
+     integer,                                                intent(out) :: req
+     integer (kind=MPI_OFFSET_KIND), dimension(:), optional, intent( in) :: start, count, stride, map
+     integer (kind=MPI_OFFSET_KIND),               optional, intent( in) :: bufcount
+     integer,                                      optional, intent( in) :: buftype
+ 
+     integer                                                             :: nf90mpi_$1_var_$2_$3
+     integer (kind=MPI_OFFSET_KIND), dimension(nf90_max_var_dims)        :: localStart, localCount, localStride, localMap
+     integer                                                             :: numDims, counter
+ 
+     ! Set local arguments to default values
+     numDims = substr(`$2', `0', `1')
+     localStart (:         ) = 1
+     localCount (:numDims  ) = shape(values)
+     localCount (numDims+1:) = 1
+     localStride(:         ) = 1
+     ! localMap   (:numDims  ) = (/ 1, (product(localCount(:counter)), counter = 1, numDims - 1) /)
+     localMap(1) = 1
+     do counter = 1, numDims - 1
+        localMap(counter+1) = localMap(counter) * localCount(counter)
+     enddo
+ 
+     if (present(start))  localStart (:size(start) )  = start(:)
+     if (present(count))  localCount (:size(count) )  = count(:)
+     if (present(stride)) localStride(:size(stride)) = stride(:)
+     if (present(map))  then
+         localMap   (:size(map))    = map(:)
+         if (present(buftype)) then
+             nf90mpi_$1_var_$2_$3 = &
+                 nfmpi_$1_varm(ncid, varid, localStart, localCount, localStride, localMap, values, bufcount, buftype, req)
+         else
+             nf90mpi_$1_var_$2_$3 = &
+                 nfmpi_$1_varm_$5(ncid, varid, localStart, localCount, localStride, localMap, values, req)
+         endif
+     else if (present(stride)) then
+         if (present(buftype)) then
+             nf90mpi_$1_var_$2_$3 = &
+                 nfmpi_$1_vars(ncid, varid, localStart, localCount, localStride, values, bufcount, buftype, req)
+         else
+             nf90mpi_$1_var_$2_$3 = &
+                 nfmpi_$1_vars_$5(ncid, varid, localStart, localCount, localStride, values, req)
+         endif
+     else
+         if (present(buftype)) then
+             nf90mpi_$1_var_$2_$3 = &
+                 nfmpi_$1_vara(ncid, varid, localStart, localCount, values, bufcount, buftype, req)
+         else
+             nf90mpi_$1_var_$2_$3 = &
+                 nfmpi_$1_vara_$5(ncid, varid, localStart, localCount, values, req)
+         endif
+     end if
+   end function nf90mpi_$1_var_$2_$3
+')dnl
+
+!
+! iput APIs
+!
+
+NBVAR(iput, 1D, OneByteInt, integer, int1,  :,              in)
+NBVAR(iput, 2D, OneByteInt, integer, int1, `:,:',           in)
+NBVAR(iput, 3D, OneByteInt, integer, int1, `:,:,:',         in)
+NBVAR(iput, 4D, OneByteInt, integer, int1, `:,:,:,:',       in)
+NBVAR(iput, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     in)
+NBVAR(iput, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   in)
+NBVAR(iput, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', in)
+
+NBVAR(iput, 1D, TwoByteInt, integer, int2,  :,              INTENTV)
+NBVAR(iput, 2D, TwoByteInt, integer, int2, `:,:',           INTENTV)
+NBVAR(iput, 3D, TwoByteInt, integer, int2, `:,:,:',         INTENTV)
+NBVAR(iput, 4D, TwoByteInt, integer, int2, `:,:,:,:',       INTENTV)
+NBVAR(iput, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     INTENTV)
+NBVAR(iput, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   INTENTV)
+NBVAR(iput, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', INTENTV)
+
+NBVAR(iput, 1D, FourByteInt, integer, int,  :,              INTENTV)
+NBVAR(iput, 2D, FourByteInt, integer, int, `:,:',           INTENTV)
+NBVAR(iput, 3D, FourByteInt, integer, int, `:,:,:',         INTENTV)
+NBVAR(iput, 4D, FourByteInt, integer, int, `:,:,:,:',       INTENTV)
+NBVAR(iput, 5D, FourByteInt, integer, int, `:,:,:,:,:',     INTENTV)
+NBVAR(iput, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   INTENTV)
+NBVAR(iput, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', INTENTV)
+
+NBVAR(iput, 1D, FourByteReal, real,   real,  :,              INTENTV)
+NBVAR(iput, 2D, FourByteReal, real,   real, `:,:',           INTENTV)
+NBVAR(iput, 3D, FourByteReal, real,   real, `:,:,:',         INTENTV)
+NBVAR(iput, 4D, FourByteReal, real,   real, `:,:,:,:',       INTENTV)
+NBVAR(iput, 5D, FourByteReal, real,   real, `:,:,:,:,:',     INTENTV)
+NBVAR(iput, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   INTENTV)
+NBVAR(iput, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', INTENTV)
+
+NBVAR(iput, 1D, EightByteReal, real, double,  :,              INTENTV)
+NBVAR(iput, 2D, EightByteReal, real, double, `:,:',           INTENTV)
+NBVAR(iput, 3D, EightByteReal, real, double, `:,:,:',         INTENTV)
+NBVAR(iput, 4D, EightByteReal, real, double, `:,:,:,:',       INTENTV)
+NBVAR(iput, 5D, EightByteReal, real, double, `:,:,:,:,:',     INTENTV)
+NBVAR(iput, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   INTENTV)
+NBVAR(iput, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', INTENTV)
+
+NBVAR(iput, 1D, EightByteInt, integer, int8,  :,              INTENTV)
+NBVAR(iput, 2D, EightByteInt, integer, int8, `:,:',           INTENTV)
+NBVAR(iput, 3D, EightByteInt, integer, int8, `:,:,:',         INTENTV)
+NBVAR(iput, 4D, EightByteInt, integer, int8, `:,:,:,:',       INTENTV)
+NBVAR(iput, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     INTENTV)
+NBVAR(iput, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   INTENTV)
+NBVAR(iput, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', INTENTV)
+
+!
+! iget APIs
+!
+
+NBVAR(iget, 1D, OneByteInt, integer, int1,  :,              out)
+NBVAR(iget, 2D, OneByteInt, integer, int1, `:,:',           out)
+NBVAR(iget, 3D, OneByteInt, integer, int1, `:,:,:',         out)
+NBVAR(iget, 4D, OneByteInt, integer, int1, `:,:,:,:',       out)
+NBVAR(iget, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     out)
+NBVAR(iget, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   out)
+NBVAR(iget, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', out)
+
+NBVAR(iget, 1D, TwoByteInt, integer, int2,  :,              out)
+NBVAR(iget, 2D, TwoByteInt, integer, int2, `:,:',           out)
+NBVAR(iget, 3D, TwoByteInt, integer, int2, `:,:,:',         out)
+NBVAR(iget, 4D, TwoByteInt, integer, int2, `:,:,:,:',       out)
+NBVAR(iget, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     out)
+NBVAR(iget, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   out)
+NBVAR(iget, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', out)
+
+NBVAR(iget, 1D, FourByteInt, integer, int,  :,              out)
+NBVAR(iget, 2D, FourByteInt, integer, int, `:,:',           out)
+NBVAR(iget, 3D, FourByteInt, integer, int, `:,:,:',         out)
+NBVAR(iget, 4D, FourByteInt, integer, int, `:,:,:,:',       out)
+NBVAR(iget, 5D, FourByteInt, integer, int, `:,:,:,:,:',     out)
+NBVAR(iget, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   out)
+NBVAR(iget, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', out)
+
+NBVAR(iget, 1D, FourByteReal, real,   real,  :,              out)
+NBVAR(iget, 2D, FourByteReal, real,   real, `:,:',           out)
+NBVAR(iget, 3D, FourByteReal, real,   real, `:,:,:',         out)
+NBVAR(iget, 4D, FourByteReal, real,   real, `:,:,:,:',       out)
+NBVAR(iget, 5D, FourByteReal, real,   real, `:,:,:,:,:',     out)
+NBVAR(iget, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   out)
+NBVAR(iget, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', out)
+
+NBVAR(iget, 1D, EightByteReal, real, double,  :,              out)
+NBVAR(iget, 2D, EightByteReal, real, double, `:,:',           out)
+NBVAR(iget, 3D, EightByteReal, real, double, `:,:,:',         out)
+NBVAR(iget, 4D, EightByteReal, real, double, `:,:,:,:',       out)
+NBVAR(iget, 5D, EightByteReal, real, double, `:,:,:,:,:',     out)
+NBVAR(iget, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   out)
+NBVAR(iget, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', out)
+
+NBVAR(iget, 1D, EightByteInt, integer, int8,  :,              out)
+NBVAR(iget, 2D, EightByteInt, integer, int8, `:,:',           out)
+NBVAR(iget, 3D, EightByteInt, integer, int8, `:,:,:',         out)
+NBVAR(iget, 4D, EightByteInt, integer, int8, `:,:,:,:',       out)
+NBVAR(iget, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     out)
+NBVAR(iget, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   out)
+NBVAR(iget, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', out)
+
+!
+! bput APIs
+!
+
+NBVAR(bput, 1D, OneByteInt, integer, int1,  :,              in)
+NBVAR(bput, 2D, OneByteInt, integer, int1, `:,:',           in)
+NBVAR(bput, 3D, OneByteInt, integer, int1, `:,:,:',         in)
+NBVAR(bput, 4D, OneByteInt, integer, int1, `:,:,:,:',       in)
+NBVAR(bput, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     in)
+NBVAR(bput, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   in)
+NBVAR(bput, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', in)
+
+NBVAR(bput, 1D, TwoByteInt, integer, int2,  :,              INTENTV)
+NBVAR(bput, 2D, TwoByteInt, integer, int2, `:,:',           INTENTV)
+NBVAR(bput, 3D, TwoByteInt, integer, int2, `:,:,:',         INTENTV)
+NBVAR(bput, 4D, TwoByteInt, integer, int2, `:,:,:,:',       INTENTV)
+NBVAR(bput, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     INTENTV)
+NBVAR(bput, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   INTENTV)
+NBVAR(bput, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', INTENTV)
+
+NBVAR(bput, 1D, FourByteInt, integer, int,  :,              INTENTV)
+NBVAR(bput, 2D, FourByteInt, integer, int, `:,:',           INTENTV)
+NBVAR(bput, 3D, FourByteInt, integer, int, `:,:,:',         INTENTV)
+NBVAR(bput, 4D, FourByteInt, integer, int, `:,:,:,:',       INTENTV)
+NBVAR(bput, 5D, FourByteInt, integer, int, `:,:,:,:,:',     INTENTV)
+NBVAR(bput, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   INTENTV)
+NBVAR(bput, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', INTENTV)
+
+NBVAR(bput, 1D, FourByteReal, real,   real,  :,              INTENTV)
+NBVAR(bput, 2D, FourByteReal, real,   real, `:,:',           INTENTV)
+NBVAR(bput, 3D, FourByteReal, real,   real, `:,:,:',         INTENTV)
+NBVAR(bput, 4D, FourByteReal, real,   real, `:,:,:,:',       INTENTV)
+NBVAR(bput, 5D, FourByteReal, real,   real, `:,:,:,:,:',     INTENTV)
+NBVAR(bput, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   INTENTV)
+NBVAR(bput, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', INTENTV)
+
+NBVAR(bput, 1D, EightByteReal, real, double,  :,              INTENTV)
+NBVAR(bput, 2D, EightByteReal, real, double, `:,:',           INTENTV)
+NBVAR(bput, 3D, EightByteReal, real, double, `:,:,:',         INTENTV)
+NBVAR(bput, 4D, EightByteReal, real, double, `:,:,:,:',       INTENTV)
+NBVAR(bput, 5D, EightByteReal, real, double, `:,:,:,:,:',     INTENTV)
+NBVAR(bput, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   INTENTV)
+NBVAR(bput, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', INTENTV)
+
+NBVAR(bput, 1D, EightByteInt, integer, int8,  :,              INTENTV)
+NBVAR(bput, 2D, EightByteInt, integer, int8, `:,:',           INTENTV)
+NBVAR(bput, 3D, EightByteInt, integer, int8, `:,:,:',         INTENTV)
+NBVAR(bput, 4D, EightByteInt, integer, int8, `:,:,:,:',       INTENTV)
+NBVAR(bput, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     INTENTV)
+NBVAR(bput, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   INTENTV)
+NBVAR(bput, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', INTENTV)
+
+!
+! Other nonblocking control APIs
+!
+
+   function nf90mpi_wait(ncid, num, req, st)
+     integer,               intent(in)    :: ncid, num
+     integer, dimension(:), intent(inout) :: req
+     integer, dimension(:), intent(out)   :: st
+     integer                              :: nf90mpi_wait
+ 
+     nf90mpi_wait = nfmpi_wait(ncid, num, req, st)
+   end function nf90mpi_wait
+
+   function nf90mpi_wait_all(ncid, num, req, st)
+     integer,               intent(in)    :: ncid, num
+     integer, dimension(:), intent(inout) :: req
+     integer, dimension(:), intent(out)   :: st
+     integer                              :: nf90mpi_wait_all
+ 
+     nf90mpi_wait_all = nfmpi_wait_all(ncid, num, req, st)
+   end function nf90mpi_wait_all
+
+   function nf90mpi_cancel(ncid, num, req, st)
+     integer,               intent(in)    :: ncid, num
+     integer, dimension(:), intent(inout) :: req
+     integer, dimension(:), intent(out)   :: st
+     integer                              :: nf90mpi_cancel
+ 
+     nf90mpi_cancel = nfmpi_cancel(ncid, num, req, st)
+   end function nf90mpi_cancel
+
+   function nf90mpi_buffer_attach(ncid, bufsize)
+     integer,                        intent( in) :: ncid
+     integer (kind=MPI_OFFSET_KIND), intent( in) :: bufsize
+     integer                                     :: nf90mpi_buffer_attach
+
+     nf90mpi_buffer_attach = nfmpi_buffer_attach(ncid, bufsize)
+   end function nf90mpi_buffer_attach
+
+   function nf90mpi_inq_buffer_usage(ncid, usage)
+     integer,                        intent( in) :: ncid
+     integer (kind=MPI_OFFSET_KIND), intent(out) :: usage
+     integer                                     :: nf90mpi_inq_buffer_usage
+
+     nf90mpi_inq_buffer_usage = nfmpi_inq_buffer_usage(ncid, usage)
+   end function nf90mpi_inq_buffer_usage
+
+   function nf90mpi_inq_buffer_size(ncid, buf_size)
+     integer,                        intent( in) :: ncid
+     integer (kind=MPI_OFFSET_KIND), intent(out) :: buf_size
+     integer                                     :: nf90mpi_inq_buffer_size
+
+     nf90mpi_inq_buffer_size = nfmpi_inq_buffer_usage(ncid, buf_size)
+   end function nf90mpi_inq_buffer_size
+
+   function nf90mpi_buffer_detach(ncid)
+     integer,                       intent( in) :: ncid
+     integer                                    :: nf90mpi_buffer_detach
+
+     nf90mpi_buffer_detach = nfmpi_buffer_detach(ncid)
+   end function nf90mpi_buffer_detach
+
diff --git a/src/libf90/getput_vard.m4 b/src/libf90/getput_vard.m4
new file mode 100644
index 0000000..c1810b3
--- /dev/null
+++ b/src/libf90/getput_vard.m4
@@ -0,0 +1,375 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source
+dnl
+!
+!  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: getput_vard.m4 2221 2015-12-12 00:39:15Z wkliao $
+!
+
+dnl
+dnl VARD1(ncid, varid, filetype, buf, bufcount, buftype)
+dnl
+define(`VARD1',dnl
+`dnl
+   function nf90mpi_$1_vard_$3$6(ncid, varid, filetype, buf, bufcount, buftype)
+     integer,                        intent(in) :: ncid, varid
+     integer,                        intent(in) :: filetype
+     $4 (kind=$3),                   intent($2) :: buf
+     integer (kind=MPI_OFFSET_KIND), intent(in) :: bufcount
+     integer,                        intent(in) :: buftype
+     integer                                    :: nf90mpi_$1_vard_$3$6
+     nf90mpi_$1_vard_$3$6 = nfmpi_$1_vard$6(ncid, varid, filetype, buf, bufcount, buftype)
+   end function nf90mpi_$1_vard_$3$6
+')dnl
+
+!
+! Independent put APIs
+!
+
+VARD1(put, INTENTV, OneByteInt,    integer, int1)
+VARD1(put, INTENTV, TwoByteInt,    integer, int2)
+VARD1(put, INTENTV, FourByteInt,   integer, int)
+VARD1(put, INTENTV, FourByteReal,  real,    real)
+VARD1(put, INTENTV, EightByteReal, real,    double)
+VARD1(put, INTENTV, EightByteInt,  integer, int8)
+
+!
+! Independent get APIs
+!
+
+VARD1(get, out, OneByteInt,    integer, int1)
+VARD1(get, out, TwoByteInt,    integer, int2)
+VARD1(get, out, FourByteInt,   integer, int)
+VARD1(get, out, FourByteReal,  real,    real)
+VARD1(get, out, EightByteReal, real,    double)
+VARD1(get, out, EightByteInt,  integer, int8)
+
+!
+! Collective put APIs
+!
+
+VARD1(put, INTENTV, OneByteInt,    integer, int1,   _all)
+VARD1(put, INTENTV, TwoByteInt,    integer, int2,   _all)
+VARD1(put, INTENTV, FourByteInt,   integer, int,    _all)
+VARD1(put, INTENTV, FourByteReal,  real,    real,   _all)
+VARD1(put, INTENTV, EightByteReal, real,    double, _all)
+VARD1(put, INTENTV, EightByteInt,  integer, int8,   _all)
+
+!
+! Collective get APIs
+!
+
+VARD1(get, out, OneByteInt,    integer, int1,   _all)
+VARD1(get, out, TwoByteInt,    integer, int2,   _all)
+VARD1(get, out, FourByteInt,   integer, int,    _all)
+VARD1(get, out, FourByteReal,  real,    real,   _all)
+VARD1(get, out, EightByteReal, real,    double, _all)
+VARD1(get, out, EightByteInt,  integer, int8,   _all)
+
+
+dnl
+dnl VARD(ncid, varid, values, num, start, count)
+dnl
+define(`VARD',dnl
+`dnl
+   function nf90mpi_$1_vard_$2_$3$8(ncid, varid, filetype, buf, bufcount, buftype)
+     integer,                        intent(in) :: ncid, varid
+     integer,                        intent(in) :: filetype
+     $4 (kind=$3),   dimension($6),  intent($7) :: buf
+     integer (kind=MPI_OFFSET_KIND), intent(in) :: bufcount
+     integer,                        intent(in) :: buftype
+     integer                                    :: nf90mpi_$1_vard_$2_$3$8
+     nf90mpi_$1_vard_$2_$3$8 = nfmpi_$1_vard$8(ncid, varid, filetype, buf, bufcount, buftype)
+   end function nf90mpi_$1_vard_$2_$3$8
+')dnl
+
+!
+! put APIs
+!
+
+VARD(put, 1D, OneByteInt, integer, int1,  :,              in)
+VARD(put, 2D, OneByteInt, integer, int1, `:,:',           in)
+VARD(put, 3D, OneByteInt, integer, int1, `:,:,:',         in)
+VARD(put, 4D, OneByteInt, integer, int1, `:,:,:,:',       in)
+VARD(put, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     in)
+VARD(put, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   in)
+VARD(put, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', in)
+
+VARD(put, 1D, TwoByteInt, integer, int2,  :,              INTENTV)
+VARD(put, 2D, TwoByteInt, integer, int2, `:,:',           INTENTV)
+VARD(put, 3D, TwoByteInt, integer, int2, `:,:,:',         INTENTV)
+VARD(put, 4D, TwoByteInt, integer, int2, `:,:,:,:',       INTENTV)
+VARD(put, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     INTENTV)
+VARD(put, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   INTENTV)
+VARD(put, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', INTENTV)
+
+VARD(put, 1D, FourByteInt, integer, int,  :,              INTENTV)
+VARD(put, 2D, FourByteInt, integer, int, `:,:',           INTENTV)
+VARD(put, 3D, FourByteInt, integer, int, `:,:,:',         INTENTV)
+VARD(put, 4D, FourByteInt, integer, int, `:,:,:,:',       INTENTV)
+VARD(put, 5D, FourByteInt, integer, int, `:,:,:,:,:',     INTENTV)
+VARD(put, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   INTENTV)
+VARD(put, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', INTENTV)
+
+VARD(put, 1D, FourByteReal, real,   real,  :,              INTENTV)
+VARD(put, 2D, FourByteReal, real,   real, `:,:',           INTENTV)
+VARD(put, 3D, FourByteReal, real,   real, `:,:,:',         INTENTV)
+VARD(put, 4D, FourByteReal, real,   real, `:,:,:,:',       INTENTV)
+VARD(put, 5D, FourByteReal, real,   real, `:,:,:,:,:',     INTENTV)
+VARD(put, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   INTENTV)
+VARD(put, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', INTENTV)
+
+VARD(put, 1D, EightByteReal, real, double,  :,              INTENTV)
+VARD(put, 2D, EightByteReal, real, double, `:,:',           INTENTV)
+VARD(put, 3D, EightByteReal, real, double, `:,:,:',         INTENTV)
+VARD(put, 4D, EightByteReal, real, double, `:,:,:,:',       INTENTV)
+VARD(put, 5D, EightByteReal, real, double, `:,:,:,:,:',     INTENTV)
+VARD(put, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   INTENTV)
+VARD(put, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', INTENTV)
+
+VARD(put, 1D, EightByteInt, integer, int8,  :,              INTENTV)
+VARD(put, 2D, EightByteInt, integer, int8, `:,:',           INTENTV)
+VARD(put, 3D, EightByteInt, integer, int8, `:,:,:',         INTENTV)
+VARD(put, 4D, EightByteInt, integer, int8, `:,:,:,:',       INTENTV)
+VARD(put, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     INTENTV)
+VARD(put, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   INTENTV)
+VARD(put, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', INTENTV)
+
+!
+! get APIs
+!
+
+VARD(get, 1D, OneByteInt, integer, int1,  :,              out)
+VARD(get, 2D, OneByteInt, integer, int1, `:,:',           out)
+VARD(get, 3D, OneByteInt, integer, int1, `:,:,:',         out)
+VARD(get, 4D, OneByteInt, integer, int1, `:,:,:,:',       out)
+VARD(get, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     out)
+VARD(get, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   out)
+VARD(get, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', out)
+
+VARD(get, 1D, TwoByteInt, integer, int2,  :,              out)
+VARD(get, 2D, TwoByteInt, integer, int2, `:,:',           out)
+VARD(get, 3D, TwoByteInt, integer, int2, `:,:,:',         out)
+VARD(get, 4D, TwoByteInt, integer, int2, `:,:,:,:',       out)
+VARD(get, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     out)
+VARD(get, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   out)
+VARD(get, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', out)
+
+VARD(get, 1D, FourByteInt, integer, int,  :,              out)
+VARD(get, 2D, FourByteInt, integer, int, `:,:',           out)
+VARD(get, 3D, FourByteInt, integer, int, `:,:,:',         out)
+VARD(get, 4D, FourByteInt, integer, int, `:,:,:,:',       out)
+VARD(get, 5D, FourByteInt, integer, int, `:,:,:,:,:',     out)
+VARD(get, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   out)
+VARD(get, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', out)
+
+VARD(get, 1D, FourByteReal, real,   real,  :,              out)
+VARD(get, 2D, FourByteReal, real,   real, `:,:',           out)
+VARD(get, 3D, FourByteReal, real,   real, `:,:,:',         out)
+VARD(get, 4D, FourByteReal, real,   real, `:,:,:,:',       out)
+VARD(get, 5D, FourByteReal, real,   real, `:,:,:,:,:',     out)
+VARD(get, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   out)
+VARD(get, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', out)
+
+VARD(get, 1D, EightByteReal, real, double,  :,              out)
+VARD(get, 2D, EightByteReal, real, double, `:,:',           out)
+VARD(get, 3D, EightByteReal, real, double, `:,:,:',         out)
+VARD(get, 4D, EightByteReal, real, double, `:,:,:,:',       out)
+VARD(get, 5D, EightByteReal, real, double, `:,:,:,:,:',     out)
+VARD(get, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   out)
+VARD(get, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', out)
+
+VARD(get, 1D, EightByteInt, integer, int8,  :,              out)
+VARD(get, 2D, EightByteInt, integer, int8, `:,:',           out)
+VARD(get, 3D, EightByteInt, integer, int8, `:,:,:',         out)
+VARD(get, 4D, EightByteInt, integer, int8, `:,:,:,:',       out)
+VARD(get, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     out)
+VARD(get, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   out)
+VARD(get, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', out)
+
+!
+! collective put APIs
+!
+
+VARD(put, 1D, OneByteInt, integer, int1,  :,              in, _all)
+VARD(put, 2D, OneByteInt, integer, int1, `:,:',           in, _all)
+VARD(put, 3D, OneByteInt, integer, int1, `:,:,:',         in, _all)
+VARD(put, 4D, OneByteInt, integer, int1, `:,:,:,:',       in, _all)
+VARD(put, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     in, _all)
+VARD(put, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   in, _all)
+VARD(put, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', in, _all)
+
+VARD(put, 1D, TwoByteInt, integer, int2,  :,              INTENTV, _all)
+VARD(put, 2D, TwoByteInt, integer, int2, `:,:',           INTENTV, _all)
+VARD(put, 3D, TwoByteInt, integer, int2, `:,:,:',         INTENTV, _all)
+VARD(put, 4D, TwoByteInt, integer, int2, `:,:,:,:',       INTENTV, _all)
+VARD(put, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     INTENTV, _all)
+VARD(put, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   INTENTV, _all)
+VARD(put, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', INTENTV, _all)
+
+VARD(put, 1D, FourByteInt, integer, int,  :,              INTENTV, _all)
+VARD(put, 2D, FourByteInt, integer, int, `:,:',           INTENTV, _all)
+VARD(put, 3D, FourByteInt, integer, int, `:,:,:',         INTENTV, _all)
+VARD(put, 4D, FourByteInt, integer, int, `:,:,:,:',       INTENTV, _all)
+VARD(put, 5D, FourByteInt, integer, int, `:,:,:,:,:',     INTENTV, _all)
+VARD(put, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   INTENTV, _all)
+VARD(put, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', INTENTV, _all)
+
+VARD(put, 1D, FourByteReal, real,   real,  :,              INTENTV, _all)
+VARD(put, 2D, FourByteReal, real,   real, `:,:',           INTENTV, _all)
+VARD(put, 3D, FourByteReal, real,   real, `:,:,:',         INTENTV, _all)
+VARD(put, 4D, FourByteReal, real,   real, `:,:,:,:',       INTENTV, _all)
+VARD(put, 5D, FourByteReal, real,   real, `:,:,:,:,:',     INTENTV, _all)
+VARD(put, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   INTENTV, _all)
+VARD(put, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', INTENTV, _all)
+
+VARD(put, 1D, EightByteReal, real, double,  :,              INTENTV, _all)
+VARD(put, 2D, EightByteReal, real, double, `:,:',           INTENTV, _all)
+VARD(put, 3D, EightByteReal, real, double, `:,:,:',         INTENTV, _all)
+VARD(put, 4D, EightByteReal, real, double, `:,:,:,:',       INTENTV, _all)
+VARD(put, 5D, EightByteReal, real, double, `:,:,:,:,:',     INTENTV, _all)
+VARD(put, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   INTENTV, _all)
+VARD(put, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', INTENTV, _all)
+
+VARD(put, 1D, EightByteInt, integer, int8,  :,              INTENTV, _all)
+VARD(put, 2D, EightByteInt, integer, int8, `:,:',           INTENTV, _all)
+VARD(put, 3D, EightByteInt, integer, int8, `:,:,:',         INTENTV, _all)
+VARD(put, 4D, EightByteInt, integer, int8, `:,:,:,:',       INTENTV, _all)
+VARD(put, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     INTENTV, _all)
+VARD(put, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   INTENTV, _all)
+VARD(put, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', INTENTV, _all)
+
+!
+! collective get APIs
+!
+
+VARD(get, 1D, OneByteInt, integer, int1,  :,              out, _all)
+VARD(get, 2D, OneByteInt, integer, int1, `:,:',           out, _all)
+VARD(get, 3D, OneByteInt, integer, int1, `:,:,:',         out, _all)
+VARD(get, 4D, OneByteInt, integer, int1, `:,:,:,:',       out, _all)
+VARD(get, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     out, _all)
+VARD(get, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   out, _all)
+VARD(get, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', out, _all)
+
+VARD(get, 1D, TwoByteInt, integer, int2,  :,              out, _all)
+VARD(get, 2D, TwoByteInt, integer, int2, `:,:',           out, _all)
+VARD(get, 3D, TwoByteInt, integer, int2, `:,:,:',         out, _all)
+VARD(get, 4D, TwoByteInt, integer, int2, `:,:,:,:',       out, _all)
+VARD(get, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     out, _all)
+VARD(get, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   out, _all)
+VARD(get, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', out, _all)
+
+VARD(get, 1D, FourByteInt, integer, int,  :,              out, _all)
+VARD(get, 2D, FourByteInt, integer, int, `:,:',           out, _all)
+VARD(get, 3D, FourByteInt, integer, int, `:,:,:',         out, _all)
+VARD(get, 4D, FourByteInt, integer, int, `:,:,:,:',       out, _all)
+VARD(get, 5D, FourByteInt, integer, int, `:,:,:,:,:',     out, _all)
+VARD(get, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   out, _all)
+VARD(get, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', out, _all)
+
+VARD(get, 1D, FourByteReal, real,   real,  :,              out, _all)
+VARD(get, 2D, FourByteReal, real,   real, `:,:',           out, _all)
+VARD(get, 3D, FourByteReal, real,   real, `:,:,:',         out, _all)
+VARD(get, 4D, FourByteReal, real,   real, `:,:,:,:',       out, _all)
+VARD(get, 5D, FourByteReal, real,   real, `:,:,:,:,:',     out, _all)
+VARD(get, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   out, _all)
+VARD(get, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', out, _all)
+
+VARD(get, 1D, EightByteReal, real, double,  :,              out, _all)
+VARD(get, 2D, EightByteReal, real, double, `:,:',           out, _all)
+VARD(get, 3D, EightByteReal, real, double, `:,:,:',         out, _all)
+VARD(get, 4D, EightByteReal, real, double, `:,:,:,:',       out, _all)
+VARD(get, 5D, EightByteReal, real, double, `:,:,:,:,:',     out, _all)
+VARD(get, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   out, _all)
+VARD(get, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', out, _all)
+
+VARD(get, 1D, EightByteInt, integer, int8,  :,              out, _all)
+VARD(get, 2D, EightByteInt, integer, int8, `:,:',           out, _all)
+VARD(get, 3D, EightByteInt, integer, int8, `:,:,:',         out, _all)
+VARD(get, 4D, EightByteInt, integer, int8, `:,:,:,:',       out, _all)
+VARD(get, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     out, _all)
+VARD(get, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   out, _all)
+VARD(get, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', out, _all)
+
+!
+! text variable
+!
+
+dnl
+dnl TEXTVARD1(ncid, varid, values, num, start, count)
+dnl
+define(`TEXTVARD1',dnl
+`dnl
+   function nf90mpi_$1_vard_text$3(ncid, varid, filetype, buf, bufcount, buftype)
+     integer,                        intent(in) :: ncid, varid
+     integer,                        intent(in) :: filetype
+     character (len = *),            intent($2) :: buf
+     integer (kind=MPI_OFFSET_KIND), intent(in) :: bufcount
+     integer,                        intent(in) :: buftype
+     integer                                    :: nf90mpi_$1_vard_text$3
+     nf90mpi_$1_vard_text$3 = nfmpi_$1_vard$3(ncid, varid, filetype, buf, bufcount, buftype)
+   end function nf90mpi_$1_vard_text$3
+')dnl
+
+TEXTVARD1(put, in)
+TEXTVARD1(get, out)
+
+TEXTVARD1(put, in, _all)
+TEXTVARD1(get, out, _all)
+
+dnl
+dnl TEXTVARD(ncid, varid, values, num, start, count)
+dnl
+define(`TEXTVARD',dnl
+`dnl
+   function nf90mpi_$1_vard_$2_text$6(ncid, varid, filetype, buf, bufcount, buftype)
+     integer,                            intent(in) :: ncid, varid
+     integer,                            intent(in) :: filetype
+     character (len = *), dimension($3), intent($5) :: buf
+     integer (kind=MPI_OFFSET_KIND),     intent(in) :: bufcount
+     integer,                            intent(in) :: buftype
+     integer                                        :: nf90mpi_$1_vard_$2_text$6
+     nf90mpi_$1_vard_$2_text$6 = nfmpi_$1_vard$6(ncid, varid, filetype, buf($4), bufcount, buftype)
+   end function nf90mpi_$1_vard_$2_text$6
+')dnl
+
+TEXTVARD(put, 1D,  :,               1,              in)
+TEXTVARD(put, 2D, `:,:',           `1,1',           in)
+TEXTVARD(put, 3D, `:,:,:',         `1,1,1',         in)
+TEXTVARD(put, 4D, `:,:,:,:',       `1,1,1,1',       in)
+TEXTVARD(put, 5D, `:,:,:,:,:',     `1,1,1,1,1',     in)
+TEXTVARD(put, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   in)
+TEXTVARD(put, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', in)
+
+TEXTVARD(get, 1D,  :,               1,              out)
+TEXTVARD(get, 2D, `:,:',           `1,1',           out)
+TEXTVARD(get, 3D, `:,:,:',         `1,1,1',         out)
+TEXTVARD(get, 4D, `:,:,:,:',       `1,1,1,1',       out)
+TEXTVARD(get, 5D, `:,:,:,:,:',     `1,1,1,1,1',     out)
+TEXTVARD(get, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   out)
+TEXTVARD(get, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', out)
+
+!
+! Collective APIs
+!
+
+TEXTVARD(put, 1D,  :,               1,              in, _all)
+TEXTVARD(put, 2D, `:,:',           `1,1',           in, _all)
+TEXTVARD(put, 3D, `:,:,:',         `1,1,1',         in, _all)
+TEXTVARD(put, 4D, `:,:,:,:',       `1,1,1,1',       in, _all)
+TEXTVARD(put, 5D, `:,:,:,:,:',     `1,1,1,1,1',     in, _all)
+TEXTVARD(put, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   in, _all)
+TEXTVARD(put, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', in, _all)
+
+TEXTVARD(get, 1D,  :,               1,              out, _all)
+TEXTVARD(get, 2D, `:,:',           `1,1',           out, _all)
+TEXTVARD(get, 3D, `:,:,:',         `1,1,1',         out, _all)
+TEXTVARD(get, 4D, `:,:,:,:',       `1,1,1,1',       out, _all)
+TEXTVARD(get, 5D, `:,:,:,:,:',     `1,1,1,1,1',     out, _all)
+TEXTVARD(get, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   out, _all)
+TEXTVARD(get, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', out, _all)
+
diff --git a/src/libf90/getput_varn.m4 b/src/libf90/getput_varn.m4
new file mode 100644
index 0000000..e15d299
--- /dev/null
+++ b/src/libf90/getput_varn.m4
@@ -0,0 +1,666 @@
+dnl Process this m4 file to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source
+dnl
+!
+!  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: getput_varn.m4 2221 2015-12-12 00:39:15Z wkliao $
+!
+
+dnl
+dnl VARN1
+dnl
+define(`VARN1',dnl
+`dnl
+   ! $1 a scalar of type $5 (kind=$4)
+   function nf90mpi_$1_varn_$4$2(ncid, varid, value, start)
+     integer,                                        intent(in) :: ncid, varid
+     $5 (kind=$4),                                   intent($3) :: value
+     integer (kind=MPI_OFFSET_KIND), dimension(:,:), intent(in) :: start
+     integer                                                    :: nf90mpi_$1_varn_$4$2
+ 
+     nf90mpi_$1_varn_$4$2 = nfmpi_$1_var1_$6$2(ncid, varid, start(:,1), value)
+   end function nf90mpi_$1_varn_$4$2
+')dnl
+
+VARN1(put,     , in,    OneByteInt,    integer, int1)
+VARN1(put,     , INTENTV, TwoByteInt,    integer, int2)
+VARN1(put,     , INTENTV, FourByteInt,   integer, int)
+VARN1(put,     , INTENTV, FourByteReal,  real,    real)
+VARN1(put,     , INTENTV, EightByteReal, real,    double)
+VARN1(put,     , INTENTV, EightByteInt,  integer, int8)
+
+VARN1(put, _all, in,    OneByteInt,    integer, int1)
+VARN1(put, _all, INTENTV, TwoByteInt,    integer, int2)
+VARN1(put, _all, INTENTV, FourByteInt,   integer, int)
+VARN1(put, _all, INTENTV, FourByteReal,  real,    real)
+VARN1(put, _all, INTENTV, EightByteReal, real,    double)
+VARN1(put, _all, INTENTV, EightByteInt,  integer, int8)
+
+VARN1(get,     , out,   OneByteInt,    integer, int1)
+VARN1(get,     , out,   TwoByteInt,    integer, int2)
+VARN1(get,     , out,   FourByteInt,   integer, int)
+VARN1(get,     , out,   FourByteReal,  real,    real)
+VARN1(get,     , out,   EightByteReal, real,    double)
+VARN1(get,     , out,   EightByteInt,  integer, int8)
+
+VARN1(get, _all, out,   OneByteInt,    integer, int1)
+VARN1(get, _all, out,   TwoByteInt,    integer, int2)
+VARN1(get, _all, out,   FourByteInt,   integer, int)
+VARN1(get, _all, out,   FourByteReal,  real,    real)
+VARN1(get, _all, out,   EightByteReal, real,    double)
+VARN1(get, _all, out,   EightByteInt,  integer, int8)
+
+dnl
+dnl VARN(ncid, varid, values, num, start, count)
+dnl
+define(`VARN',dnl
+`dnl
+   function nf90mpi_$1_varn_$2_$3$8(ncid, varid, values, num, start, count)
+     integer,                                                  intent(in) :: ncid, varid, num
+     $4 (kind=$3),                   dimension($6),            intent($7) :: values
+     integer (kind=MPI_OFFSET_KIND), dimension(:,:),           intent(in) :: start
+     integer (kind=MPI_OFFSET_KIND), dimension(:,:), optional, intent(in) :: count
+     integer                                                              :: nf90mpi_$1_varn_$2_$3$8
+     integer (kind=MPI_OFFSET_KIND), dimension(nf90_max_var_dims,num)     :: localCount
+     integer                                                              :: numDims
+ 
+     ! Set local arguments to default values
+     numDims = size(start(:,1))
+     localCount(1:numDims,1:num) = 1
+     if (present(count)) localCount(1:numDims,1:num) = count(1:numDims,1:num)
+     nf90mpi_$1_varn_$2_$3$8 = nfmpi_$1_varn_$5$8(ncid, varid, num, start, &
+                                                  localCount(1:numDims,1:num), values)
+   end function nf90mpi_$1_varn_$2_$3$8
+')dnl
+
+!
+! put APIs
+!
+
+VARN(put, 1D, OneByteInt, integer, int1,  :,              in)
+VARN(put, 2D, OneByteInt, integer, int1, `:,:',           in)
+VARN(put, 3D, OneByteInt, integer, int1, `:,:,:',         in)
+VARN(put, 4D, OneByteInt, integer, int1, `:,:,:,:',       in)
+VARN(put, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     in)
+VARN(put, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   in)
+VARN(put, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', in)
+
+VARN(put, 1D, TwoByteInt, integer, int2,  :,              INTENTV)
+VARN(put, 2D, TwoByteInt, integer, int2, `:,:',           INTENTV)
+VARN(put, 3D, TwoByteInt, integer, int2, `:,:,:',         INTENTV)
+VARN(put, 4D, TwoByteInt, integer, int2, `:,:,:,:',       INTENTV)
+VARN(put, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     INTENTV)
+VARN(put, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   INTENTV)
+VARN(put, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', INTENTV)
+
+VARN(put, 1D, FourByteInt, integer, int,  :,              INTENTV)
+VARN(put, 2D, FourByteInt, integer, int, `:,:',           INTENTV)
+VARN(put, 3D, FourByteInt, integer, int, `:,:,:',         INTENTV)
+VARN(put, 4D, FourByteInt, integer, int, `:,:,:,:',       INTENTV)
+VARN(put, 5D, FourByteInt, integer, int, `:,:,:,:,:',     INTENTV)
+VARN(put, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   INTENTV)
+VARN(put, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', INTENTV)
+
+VARN(put, 1D, FourByteReal, real,   real,  :,              INTENTV)
+VARN(put, 2D, FourByteReal, real,   real, `:,:',           INTENTV)
+VARN(put, 3D, FourByteReal, real,   real, `:,:,:',         INTENTV)
+VARN(put, 4D, FourByteReal, real,   real, `:,:,:,:',       INTENTV)
+VARN(put, 5D, FourByteReal, real,   real, `:,:,:,:,:',     INTENTV)
+VARN(put, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   INTENTV)
+VARN(put, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', INTENTV)
+
+VARN(put, 1D, EightByteReal, real, double,  :,              INTENTV)
+VARN(put, 2D, EightByteReal, real, double, `:,:',           INTENTV)
+VARN(put, 3D, EightByteReal, real, double, `:,:,:',         INTENTV)
+VARN(put, 4D, EightByteReal, real, double, `:,:,:,:',       INTENTV)
+VARN(put, 5D, EightByteReal, real, double, `:,:,:,:,:',     INTENTV)
+VARN(put, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   INTENTV)
+VARN(put, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', INTENTV)
+
+VARN(put, 1D, EightByteInt, integer, int8,  :,              INTENTV)
+VARN(put, 2D, EightByteInt, integer, int8, `:,:',           INTENTV)
+VARN(put, 3D, EightByteInt, integer, int8, `:,:,:',         INTENTV)
+VARN(put, 4D, EightByteInt, integer, int8, `:,:,:,:',       INTENTV)
+VARN(put, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     INTENTV)
+VARN(put, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   INTENTV)
+VARN(put, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', INTENTV)
+
+!
+! get APIs
+!
+
+VARN(get, 1D, OneByteInt, integer, int1,  :,              out)
+VARN(get, 2D, OneByteInt, integer, int1, `:,:',           out)
+VARN(get, 3D, OneByteInt, integer, int1, `:,:,:',         out)
+VARN(get, 4D, OneByteInt, integer, int1, `:,:,:,:',       out)
+VARN(get, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     out)
+VARN(get, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   out)
+VARN(get, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', out)
+
+VARN(get, 1D, TwoByteInt, integer, int2,  :,              out)
+VARN(get, 2D, TwoByteInt, integer, int2, `:,:',           out)
+VARN(get, 3D, TwoByteInt, integer, int2, `:,:,:',         out)
+VARN(get, 4D, TwoByteInt, integer, int2, `:,:,:,:',       out)
+VARN(get, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     out)
+VARN(get, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   out)
+VARN(get, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', out)
+
+VARN(get, 1D, FourByteInt, integer, int,  :,              out)
+VARN(get, 2D, FourByteInt, integer, int, `:,:',           out)
+VARN(get, 3D, FourByteInt, integer, int, `:,:,:',         out)
+VARN(get, 4D, FourByteInt, integer, int, `:,:,:,:',       out)
+VARN(get, 5D, FourByteInt, integer, int, `:,:,:,:,:',     out)
+VARN(get, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   out)
+VARN(get, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', out)
+
+VARN(get, 1D, FourByteReal, real,   real,  :,              out)
+VARN(get, 2D, FourByteReal, real,   real, `:,:',           out)
+VARN(get, 3D, FourByteReal, real,   real, `:,:,:',         out)
+VARN(get, 4D, FourByteReal, real,   real, `:,:,:,:',       out)
+VARN(get, 5D, FourByteReal, real,   real, `:,:,:,:,:',     out)
+VARN(get, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   out)
+VARN(get, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', out)
+
+VARN(get, 1D, EightByteReal, real, double,  :,              out)
+VARN(get, 2D, EightByteReal, real, double, `:,:',           out)
+VARN(get, 3D, EightByteReal, real, double, `:,:,:',         out)
+VARN(get, 4D, EightByteReal, real, double, `:,:,:,:',       out)
+VARN(get, 5D, EightByteReal, real, double, `:,:,:,:,:',     out)
+VARN(get, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   out)
+VARN(get, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', out)
+
+VARN(get, 1D, EightByteInt, integer, int8,  :,              out)
+VARN(get, 2D, EightByteInt, integer, int8, `:,:',           out)
+VARN(get, 3D, EightByteInt, integer, int8, `:,:,:',         out)
+VARN(get, 4D, EightByteInt, integer, int8, `:,:,:,:',       out)
+VARN(get, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     out)
+VARN(get, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   out)
+VARN(get, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', out)
+
+!
+! collective put APIs
+!
+
+VARN(put, 1D, OneByteInt, integer, int1,  :,              in, _all)
+VARN(put, 2D, OneByteInt, integer, int1, `:,:',           in, _all)
+VARN(put, 3D, OneByteInt, integer, int1, `:,:,:',         in, _all)
+VARN(put, 4D, OneByteInt, integer, int1, `:,:,:,:',       in, _all)
+VARN(put, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     in, _all)
+VARN(put, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   in, _all)
+VARN(put, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', in, _all)
+
+VARN(put, 1D, TwoByteInt, integer, int2,  :,              INTENTV, _all)
+VARN(put, 2D, TwoByteInt, integer, int2, `:,:',           INTENTV, _all)
+VARN(put, 3D, TwoByteInt, integer, int2, `:,:,:',         INTENTV, _all)
+VARN(put, 4D, TwoByteInt, integer, int2, `:,:,:,:',       INTENTV, _all)
+VARN(put, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     INTENTV, _all)
+VARN(put, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   INTENTV, _all)
+VARN(put, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', INTENTV, _all)
+
+VARN(put, 1D, FourByteInt, integer, int,  :,              INTENTV, _all)
+VARN(put, 2D, FourByteInt, integer, int, `:,:',           INTENTV, _all)
+VARN(put, 3D, FourByteInt, integer, int, `:,:,:',         INTENTV, _all)
+VARN(put, 4D, FourByteInt, integer, int, `:,:,:,:',       INTENTV, _all)
+VARN(put, 5D, FourByteInt, integer, int, `:,:,:,:,:',     INTENTV, _all)
+VARN(put, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   INTENTV, _all)
+VARN(put, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', INTENTV, _all)
+
+VARN(put, 1D, FourByteReal, real,   real,  :,              INTENTV, _all)
+VARN(put, 2D, FourByteReal, real,   real, `:,:',           INTENTV, _all)
+VARN(put, 3D, FourByteReal, real,   real, `:,:,:',         INTENTV, _all)
+VARN(put, 4D, FourByteReal, real,   real, `:,:,:,:',       INTENTV, _all)
+VARN(put, 5D, FourByteReal, real,   real, `:,:,:,:,:',     INTENTV, _all)
+VARN(put, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   INTENTV, _all)
+VARN(put, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', INTENTV, _all)
+
+VARN(put, 1D, EightByteReal, real, double,  :,              INTENTV, _all)
+VARN(put, 2D, EightByteReal, real, double, `:,:',           INTENTV, _all)
+VARN(put, 3D, EightByteReal, real, double, `:,:,:',         INTENTV, _all)
+VARN(put, 4D, EightByteReal, real, double, `:,:,:,:',       INTENTV, _all)
+VARN(put, 5D, EightByteReal, real, double, `:,:,:,:,:',     INTENTV, _all)
+VARN(put, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   INTENTV, _all)
+VARN(put, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', INTENTV, _all)
+
+VARN(put, 1D, EightByteInt, integer, int8,  :,              INTENTV, _all)
+VARN(put, 2D, EightByteInt, integer, int8, `:,:',           INTENTV, _all)
+VARN(put, 3D, EightByteInt, integer, int8, `:,:,:',         INTENTV, _all)
+VARN(put, 4D, EightByteInt, integer, int8, `:,:,:,:',       INTENTV, _all)
+VARN(put, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     INTENTV, _all)
+VARN(put, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   INTENTV, _all)
+VARN(put, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', INTENTV, _all)
+
+!
+! collective get APIs
+!
+
+VARN(get, 1D, OneByteInt, integer, int1,  :,              out, _all)
+VARN(get, 2D, OneByteInt, integer, int1, `:,:',           out, _all)
+VARN(get, 3D, OneByteInt, integer, int1, `:,:,:',         out, _all)
+VARN(get, 4D, OneByteInt, integer, int1, `:,:,:,:',       out, _all)
+VARN(get, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     out, _all)
+VARN(get, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   out, _all)
+VARN(get, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', out, _all)
+
+VARN(get, 1D, TwoByteInt, integer, int2,  :,              out, _all)
+VARN(get, 2D, TwoByteInt, integer, int2, `:,:',           out, _all)
+VARN(get, 3D, TwoByteInt, integer, int2, `:,:,:',         out, _all)
+VARN(get, 4D, TwoByteInt, integer, int2, `:,:,:,:',       out, _all)
+VARN(get, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     out, _all)
+VARN(get, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   out, _all)
+VARN(get, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', out, _all)
+
+VARN(get, 1D, FourByteInt, integer, int,  :,              out, _all)
+VARN(get, 2D, FourByteInt, integer, int, `:,:',           out, _all)
+VARN(get, 3D, FourByteInt, integer, int, `:,:,:',         out, _all)
+VARN(get, 4D, FourByteInt, integer, int, `:,:,:,:',       out, _all)
+VARN(get, 5D, FourByteInt, integer, int, `:,:,:,:,:',     out, _all)
+VARN(get, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   out, _all)
+VARN(get, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', out, _all)
+
+VARN(get, 1D, FourByteReal, real,   real,  :,              out, _all)
+VARN(get, 2D, FourByteReal, real,   real, `:,:',           out, _all)
+VARN(get, 3D, FourByteReal, real,   real, `:,:,:',         out, _all)
+VARN(get, 4D, FourByteReal, real,   real, `:,:,:,:',       out, _all)
+VARN(get, 5D, FourByteReal, real,   real, `:,:,:,:,:',     out, _all)
+VARN(get, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   out, _all)
+VARN(get, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', out, _all)
+
+VARN(get, 1D, EightByteReal, real, double,  :,              out, _all)
+VARN(get, 2D, EightByteReal, real, double, `:,:',           out, _all)
+VARN(get, 3D, EightByteReal, real, double, `:,:,:',         out, _all)
+VARN(get, 4D, EightByteReal, real, double, `:,:,:,:',       out, _all)
+VARN(get, 5D, EightByteReal, real, double, `:,:,:,:,:',     out, _all)
+VARN(get, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   out, _all)
+VARN(get, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', out, _all)
+
+VARN(get, 1D, EightByteInt, integer, int8,  :,              out, _all)
+VARN(get, 2D, EightByteInt, integer, int8, `:,:',           out, _all)
+VARN(get, 3D, EightByteInt, integer, int8, `:,:,:',         out, _all)
+VARN(get, 4D, EightByteInt, integer, int8, `:,:,:,:',       out, _all)
+VARN(get, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     out, _all)
+VARN(get, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   out, _all)
+VARN(get, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', out, _all)
+
+!
+! text variable
+!
+
+dnl
+dnl TEXTVARN1(ncid, varid, values, num, start, count)
+dnl
+define(`TEXTVARN1',dnl
+`dnl
+   ! $1 a scalar of type character (len = *)
+   function nf90mpi_$1_varn_text$3(ncid, varid, value, start)
+     integer,                                        intent(in) :: ncid, varid
+     character (len=*),                              intent($2) :: value
+     integer (kind=MPI_OFFSET_KIND), dimension(:,:), intent(in) :: start
+     integer                                                    :: nf90mpi_$1_varn_text$3
+ 
+     nf90mpi_$1_varn_text$3 = nfmpi_$1_var1_text$3(ncid, varid, start(:,1), value)
+   end function nf90mpi_$1_varn_text$3
+')dnl
+
+TEXTVARN1(put, in)
+TEXTVARN1(get, out)
+TEXTVARN1(put, in,  _all)
+TEXTVARN1(get, out, _all)
+
+dnl
+dnl TEXTVARN(ncid, varid, values, num, start, count)
+dnl
+define(`TEXTVARN',dnl
+`dnl
+   function nf90mpi_$1_varn_$2_text$6(ncid, varid, values, num, start, count)
+     integer,                                                  intent(in) :: ncid, varid, num
+     character (len=*),              dimension($3),            intent($5) :: values
+     integer (kind=MPI_OFFSET_KIND), dimension(:,:),           intent(in) :: start
+     integer (kind=MPI_OFFSET_KIND), dimension(:,:), optional, intent(in) :: count
+     integer                                                              :: nf90mpi_$1_varn_$2_text$6
+     integer (kind=MPI_OFFSET_KIND), dimension(nf90_max_var_dims,num)     :: localCount
+     integer                                                              :: numDims
+ 
+     ! Set local arguments to default values
+     numDims = size(start(:,1))
+     localCount(1:numDims,1:num) = 1
+     if (present(count)) localCount(1:numDims,1:num) = count(1:numDims,1:num)
+     nf90mpi_$1_varn_$2_text$6 = nfmpi_$1_varn_text$6(ncid, varid, num, start, &
+                                                      localCount(1:numDims,1:num), values($4))
+   end function nf90mpi_$1_varn_$2_text$6
+')dnl
+
+TEXTVARN(put, 1D,  :,               1,              in)
+TEXTVARN(put, 2D, `:,:',           `1,1',           in)
+TEXTVARN(put, 3D, `:,:,:',         `1,1,1',         in)
+TEXTVARN(put, 4D, `:,:,:,:',       `1,1,1,1',       in)
+TEXTVARN(put, 5D, `:,:,:,:,:',     `1,1,1,1,1',     in)
+TEXTVARN(put, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   in)
+TEXTVARN(put, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', in)
+
+TEXTVARN(get, 1D,  :,               1,              out)
+TEXTVARN(get, 2D, `:,:',           `1,1',           out)
+TEXTVARN(get, 3D, `:,:,:',         `1,1,1',         out)
+TEXTVARN(get, 4D, `:,:,:,:',       `1,1,1,1',       out)
+TEXTVARN(get, 5D, `:,:,:,:,:',     `1,1,1,1,1',     out)
+TEXTVARN(get, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   out)
+TEXTVARN(get, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', out)
+
+!
+! Collective APIs
+!
+
+TEXTVARN(put, 1D,  :,               1,              in, _all)
+TEXTVARN(put, 2D, `:,:',           `1,1',           in, _all)
+TEXTVARN(put, 3D, `:,:,:',         `1,1,1',         in, _all)
+TEXTVARN(put, 4D, `:,:,:,:',       `1,1,1,1',       in, _all)
+TEXTVARN(put, 5D, `:,:,:,:,:',     `1,1,1,1,1',     in, _all)
+TEXTVARN(put, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   in, _all)
+TEXTVARN(put, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', in, _all)
+
+TEXTVARN(get, 1D,  :,               1,              out, _all)
+TEXTVARN(get, 2D, `:,:',           `1,1',           out, _all)
+TEXTVARN(get, 3D, `:,:,:',         `1,1,1',         out, _all)
+TEXTVARN(get, 4D, `:,:,:,:',       `1,1,1,1',       out, _all)
+TEXTVARN(get, 5D, `:,:,:,:,:',     `1,1,1,1,1',     out, _all)
+TEXTVARN(get, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   out, _all)
+TEXTVARN(get, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', out, _all)
+
+!
+! Nonblocking APIs
+!
+
+dnl
+dnl IVARN1
+dnl
+define(`IVARN1',dnl
+`dnl
+   ! $1 a scalar of type $4 (kind=$3)
+   function nf90mpi_$1_varn_$3(ncid, varid, value, req, start)
+     integer,                                        intent(in) :: ncid, varid
+     $4 (kind=$3),                                   intent($2) :: value
+     integer,                                        intent(out):: req
+     integer (kind=MPI_OFFSET_KIND), dimension(:,:), intent(in) :: start
+     integer                                                    :: nf90mpi_$1_varn_$3
+ 
+     nf90mpi_$1_varn_$3 = nfmpi_$1_var1_$5(ncid, varid, start(:,1), value, req)
+   end function nf90mpi_$1_varn_$3
+')dnl
+
+IVARN1(iput, in,    OneByteInt,    integer, int1)
+IVARN1(iput, INTENTV, TwoByteInt,    integer, int2)
+IVARN1(iput, INTENTV, FourByteInt,   integer, int)
+IVARN1(iput, INTENTV, FourByteReal,  real,    real)
+IVARN1(iput, INTENTV, EightByteReal, real,    double)
+IVARN1(iput, INTENTV, EightByteInt,  integer, int8)
+
+IVARN1(iget, out,   OneByteInt,    integer, int1)
+IVARN1(iget, out,   TwoByteInt,    integer, int2)
+IVARN1(iget, out,   FourByteInt,   integer, int)
+IVARN1(iget, out,   FourByteReal,  real,    real)
+IVARN1(iget, out,   EightByteReal, real,    double)
+IVARN1(iget, out,   EightByteInt,  integer, int8)
+
+IVARN1(bput, in,    OneByteInt,    integer, int1)
+IVARN1(bput, INTENTV, TwoByteInt,    integer, int2)
+IVARN1(bput, INTENTV, FourByteInt,   integer, int)
+IVARN1(bput, INTENTV, FourByteReal,  real,    real)
+IVARN1(bput, INTENTV, EightByteReal, real,    double)
+IVARN1(bput, INTENTV, EightByteInt,  integer, int8)
+
+dnl
+dnl IVARN(ncid, varid, values, num, start, count)
+dnl
+define(`IVARN',dnl
+`dnl
+   function nf90mpi_$1_varn_$2_$3(ncid, varid, values, req, num, start, count)
+     integer,                                                  intent(in) :: ncid, varid, num
+     $4 (kind=$3),                   dimension($6),            intent($7) :: values
+     integer,                                                  intent(out):: req
+     integer (kind=MPI_OFFSET_KIND), dimension(:,:),           intent(in) :: start
+     integer (kind=MPI_OFFSET_KIND), dimension(:,:), optional, intent(in) :: count
+     integer                                                              :: nf90mpi_$1_varn_$2_$3
+     integer (kind=MPI_OFFSET_KIND), dimension(nf90_max_var_dims,num)     :: localCount
+     integer                                                              :: numDims
+ 
+     ! Set local arguments to default values
+     numDims = size(start(:,1))
+     localCount(1:numDims,1:num) = 1
+     if (present(count)) localCount(1:numDims,1:num) = count(1:numDims,1:num)
+     nf90mpi_$1_varn_$2_$3 = nfmpi_$1_varn_$5(ncid, varid, num, start, &
+                                              localCount(1:numDims,1:num), values, req)
+   end function nf90mpi_$1_varn_$2_$3
+')dnl
+
+!
+! put APIs
+!
+
+IVARN(iput, 1D, OneByteInt, integer, int1,  :,              in)
+IVARN(iput, 2D, OneByteInt, integer, int1, `:,:',           in)
+IVARN(iput, 3D, OneByteInt, integer, int1, `:,:,:',         in)
+IVARN(iput, 4D, OneByteInt, integer, int1, `:,:,:,:',       in)
+IVARN(iput, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     in)
+IVARN(iput, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   in)
+IVARN(iput, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', in)
+
+IVARN(iput, 1D, TwoByteInt, integer, int2,  :,              INTENTV)
+IVARN(iput, 2D, TwoByteInt, integer, int2, `:,:',           INTENTV)
+IVARN(iput, 3D, TwoByteInt, integer, int2, `:,:,:',         INTENTV)
+IVARN(iput, 4D, TwoByteInt, integer, int2, `:,:,:,:',       INTENTV)
+IVARN(iput, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     INTENTV)
+IVARN(iput, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   INTENTV)
+IVARN(iput, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', INTENTV)
+
+IVARN(iput, 1D, FourByteInt, integer, int,  :,              INTENTV)
+IVARN(iput, 2D, FourByteInt, integer, int, `:,:',           INTENTV)
+IVARN(iput, 3D, FourByteInt, integer, int, `:,:,:',         INTENTV)
+IVARN(iput, 4D, FourByteInt, integer, int, `:,:,:,:',       INTENTV)
+IVARN(iput, 5D, FourByteInt, integer, int, `:,:,:,:,:',     INTENTV)
+IVARN(iput, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   INTENTV)
+IVARN(iput, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', INTENTV)
+
+IVARN(iput, 1D, FourByteReal, real,   real,  :,              INTENTV)
+IVARN(iput, 2D, FourByteReal, real,   real, `:,:',           INTENTV)
+IVARN(iput, 3D, FourByteReal, real,   real, `:,:,:',         INTENTV)
+IVARN(iput, 4D, FourByteReal, real,   real, `:,:,:,:',       INTENTV)
+IVARN(iput, 5D, FourByteReal, real,   real, `:,:,:,:,:',     INTENTV)
+IVARN(iput, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   INTENTV)
+IVARN(iput, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', INTENTV)
+
+IVARN(iput, 1D, EightByteReal, real, double,  :,              INTENTV)
+IVARN(iput, 2D, EightByteReal, real, double, `:,:',           INTENTV)
+IVARN(iput, 3D, EightByteReal, real, double, `:,:,:',         INTENTV)
+IVARN(iput, 4D, EightByteReal, real, double, `:,:,:,:',       INTENTV)
+IVARN(iput, 5D, EightByteReal, real, double, `:,:,:,:,:',     INTENTV)
+IVARN(iput, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   INTENTV)
+IVARN(iput, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', INTENTV)
+
+IVARN(iput, 1D, EightByteInt, integer, int8,  :,              INTENTV)
+IVARN(iput, 2D, EightByteInt, integer, int8, `:,:',           INTENTV)
+IVARN(iput, 3D, EightByteInt, integer, int8, `:,:,:',         INTENTV)
+IVARN(iput, 4D, EightByteInt, integer, int8, `:,:,:,:',       INTENTV)
+IVARN(iput, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     INTENTV)
+IVARN(iput, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   INTENTV)
+IVARN(iput, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', INTENTV)
+
+!
+! get APIs
+!
+
+IVARN(iget, 1D, OneByteInt, integer, int1,  :,              out)
+IVARN(iget, 2D, OneByteInt, integer, int1, `:,:',           out)
+IVARN(iget, 3D, OneByteInt, integer, int1, `:,:,:',         out)
+IVARN(iget, 4D, OneByteInt, integer, int1, `:,:,:,:',       out)
+IVARN(iget, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     out)
+IVARN(iget, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   out)
+IVARN(iget, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', out)
+
+IVARN(iget, 1D, TwoByteInt, integer, int2,  :,              out)
+IVARN(iget, 2D, TwoByteInt, integer, int2, `:,:',           out)
+IVARN(iget, 3D, TwoByteInt, integer, int2, `:,:,:',         out)
+IVARN(iget, 4D, TwoByteInt, integer, int2, `:,:,:,:',       out)
+IVARN(iget, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     out)
+IVARN(iget, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   out)
+IVARN(iget, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', out)
+
+IVARN(iget, 1D, FourByteInt, integer, int,  :,              out)
+IVARN(iget, 2D, FourByteInt, integer, int, `:,:',           out)
+IVARN(iget, 3D, FourByteInt, integer, int, `:,:,:',         out)
+IVARN(iget, 4D, FourByteInt, integer, int, `:,:,:,:',       out)
+IVARN(iget, 5D, FourByteInt, integer, int, `:,:,:,:,:',     out)
+IVARN(iget, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   out)
+IVARN(iget, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', out)
+
+IVARN(iget, 1D, FourByteReal, real,   real,  :,              out)
+IVARN(iget, 2D, FourByteReal, real,   real, `:,:',           out)
+IVARN(iget, 3D, FourByteReal, real,   real, `:,:,:',         out)
+IVARN(iget, 4D, FourByteReal, real,   real, `:,:,:,:',       out)
+IVARN(iget, 5D, FourByteReal, real,   real, `:,:,:,:,:',     out)
+IVARN(iget, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   out)
+IVARN(iget, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', out)
+
+IVARN(iget, 1D, EightByteReal, real, double,  :,              out)
+IVARN(iget, 2D, EightByteReal, real, double, `:,:',           out)
+IVARN(iget, 3D, EightByteReal, real, double, `:,:,:',         out)
+IVARN(iget, 4D, EightByteReal, real, double, `:,:,:,:',       out)
+IVARN(iget, 5D, EightByteReal, real, double, `:,:,:,:,:',     out)
+IVARN(iget, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   out)
+IVARN(iget, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', out)
+
+IVARN(iget, 1D, EightByteInt, integer, int8,  :,              out)
+IVARN(iget, 2D, EightByteInt, integer, int8, `:,:',           out)
+IVARN(iget, 3D, EightByteInt, integer, int8, `:,:,:',         out)
+IVARN(iget, 4D, EightByteInt, integer, int8, `:,:,:,:',       out)
+IVARN(iget, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     out)
+IVARN(iget, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   out)
+IVARN(iget, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', out)
+
+!
+! bput APIs
+!
+
+IVARN(bput, 1D, OneByteInt, integer, int1,  :,              in)
+IVARN(bput, 2D, OneByteInt, integer, int1, `:,:',           in)
+IVARN(bput, 3D, OneByteInt, integer, int1, `:,:,:',         in)
+IVARN(bput, 4D, OneByteInt, integer, int1, `:,:,:,:',       in)
+IVARN(bput, 5D, OneByteInt, integer, int1, `:,:,:,:,:',     in)
+IVARN(bput, 6D, OneByteInt, integer, int1, `:,:,:,:,:,:',   in)
+IVARN(bput, 7D, OneByteInt, integer, int1, `:,:,:,:,:,:,:', in)
+
+IVARN(bput, 1D, TwoByteInt, integer, int2,  :,              INTENTV)
+IVARN(bput, 2D, TwoByteInt, integer, int2, `:,:',           INTENTV)
+IVARN(bput, 3D, TwoByteInt, integer, int2, `:,:,:',         INTENTV)
+IVARN(bput, 4D, TwoByteInt, integer, int2, `:,:,:,:',       INTENTV)
+IVARN(bput, 5D, TwoByteInt, integer, int2, `:,:,:,:,:',     INTENTV)
+IVARN(bput, 6D, TwoByteInt, integer, int2, `:,:,:,:,:,:',   INTENTV)
+IVARN(bput, 7D, TwoByteInt, integer, int2, `:,:,:,:,:,:,:', INTENTV)
+
+IVARN(bput, 1D, FourByteInt, integer, int,  :,              INTENTV)
+IVARN(bput, 2D, FourByteInt, integer, int, `:,:',           INTENTV)
+IVARN(bput, 3D, FourByteInt, integer, int, `:,:,:',         INTENTV)
+IVARN(bput, 4D, FourByteInt, integer, int, `:,:,:,:',       INTENTV)
+IVARN(bput, 5D, FourByteInt, integer, int, `:,:,:,:,:',     INTENTV)
+IVARN(bput, 6D, FourByteInt, integer, int, `:,:,:,:,:,:',   INTENTV)
+IVARN(bput, 7D, FourByteInt, integer, int, `:,:,:,:,:,:,:', INTENTV)
+
+IVARN(bput, 1D, FourByteReal, real,   real,  :,              INTENTV)
+IVARN(bput, 2D, FourByteReal, real,   real, `:,:',           INTENTV)
+IVARN(bput, 3D, FourByteReal, real,   real, `:,:,:',         INTENTV)
+IVARN(bput, 4D, FourByteReal, real,   real, `:,:,:,:',       INTENTV)
+IVARN(bput, 5D, FourByteReal, real,   real, `:,:,:,:,:',     INTENTV)
+IVARN(bput, 6D, FourByteReal, real,   real, `:,:,:,:,:,:',   INTENTV)
+IVARN(bput, 7D, FourByteReal, real,   real, `:,:,:,:,:,:,:', INTENTV)
+
+IVARN(bput, 1D, EightByteReal, real, double,  :,              INTENTV)
+IVARN(bput, 2D, EightByteReal, real, double, `:,:',           INTENTV)
+IVARN(bput, 3D, EightByteReal, real, double, `:,:,:',         INTENTV)
+IVARN(bput, 4D, EightByteReal, real, double, `:,:,:,:',       INTENTV)
+IVARN(bput, 5D, EightByteReal, real, double, `:,:,:,:,:',     INTENTV)
+IVARN(bput, 6D, EightByteReal, real, double, `:,:,:,:,:,:',   INTENTV)
+IVARN(bput, 7D, EightByteReal, real, double, `:,:,:,:,:,:,:', INTENTV)
+
+IVARN(bput, 1D, EightByteInt, integer, int8,  :,              INTENTV)
+IVARN(bput, 2D, EightByteInt, integer, int8, `:,:',           INTENTV)
+IVARN(bput, 3D, EightByteInt, integer, int8, `:,:,:',         INTENTV)
+IVARN(bput, 4D, EightByteInt, integer, int8, `:,:,:,:',       INTENTV)
+IVARN(bput, 5D, EightByteInt, integer, int8, `:,:,:,:,:',     INTENTV)
+IVARN(bput, 6D, EightByteInt, integer, int8, `:,:,:,:,:,:',   INTENTV)
+IVARN(bput, 7D, EightByteInt, integer, int8, `:,:,:,:,:,:,:', INTENTV)
+
+!
+! text variable
+!
+
+dnl
+dnl ITEXTVARN1
+dnl
+define(`ITEXTVARN1',dnl
+`dnl
+   ! $1 a scalar of type character (len = *)
+   function nf90mpi_$1_varn_text(ncid, varid, value, req, start)
+     integer,                                        intent(in) :: ncid, varid
+     character (len = *),                            intent($2) :: value
+     integer,                                        intent(out):: req
+     integer (kind=MPI_OFFSET_KIND), dimension(:,:), intent(in) :: start
+     integer                                                    :: nf90mpi_$1_varn_text
+ 
+     nf90mpi_$1_varn_text = nfmpi_$1_var1_text(ncid, varid, start(:,1), value, req)
+   end function nf90mpi_$1_varn_text
+')dnl
+
+ITEXTVARN1(iput, in)
+ITEXTVARN1(iget, out)
+ITEXTVARN1(bput, in)
+
+dnl
+dnl ITEXTVARN(ncid, varid, values, num, start, count)
+dnl
+define(`ITEXTVARN',dnl
+`dnl
+   function nf90mpi_$1_varn_$2_text(ncid, varid, values, req, num, start, count)
+     integer,                                                  intent(in) :: ncid, varid, num
+     character (len=*),              dimension($3),            intent($5) :: values
+     integer,                                                  intent(out):: req
+     integer (kind=MPI_OFFSET_KIND), dimension(:,:),           intent(in) :: start
+     integer (kind=MPI_OFFSET_KIND), dimension(:,:), optional, intent(in) :: count
+     integer                                                              :: nf90mpi_$1_varn_$2_text
+     integer (kind=MPI_OFFSET_KIND), dimension(nf90_max_var_dims,num)     :: localCount
+     integer                                                              :: numDims
+ 
+     ! Set local arguments to default values
+     numDims = size(start(:,1))
+     localCount(1:numDims,1:num) = 1
+     if (present(count)) localCount(1:numDims,1:num) = count(1:numDims,1:num)
+     nf90mpi_$1_varn_$2_text = nfmpi_$1_varn_text(ncid, varid, num, start, &
+                                                  localCount(1:numDims,1:num), values($4), req)
+   end function nf90mpi_$1_varn_$2_text
+')dnl
+
+ITEXTVARN(iput, 1D,  :,               1,              in)
+ITEXTVARN(iput, 2D, `:,:',           `1,1',           in)
+ITEXTVARN(iput, 3D, `:,:,:',         `1,1,1',         in)
+ITEXTVARN(iput, 4D, `:,:,:,:',       `1,1,1,1',       in)
+ITEXTVARN(iput, 5D, `:,:,:,:,:',     `1,1,1,1,1',     in)
+ITEXTVARN(iput, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   in)
+ITEXTVARN(iput, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', in)
+
+ITEXTVARN(iget, 1D,  :,               1,              out)
+ITEXTVARN(iget, 2D, `:,:',           `1,1',           out)
+ITEXTVARN(iget, 3D, `:,:,:',         `1,1,1',         out)
+ITEXTVARN(iget, 4D, `:,:,:,:',       `1,1,1,1',       out)
+ITEXTVARN(iget, 5D, `:,:,:,:,:',     `1,1,1,1,1',     out)
+ITEXTVARN(iget, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   out)
+ITEXTVARN(iget, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', out)
+
+ITEXTVARN(bput, 1D,  :,               1,              in)
+ITEXTVARN(bput, 2D, `:,:',           `1,1',           in)
+ITEXTVARN(bput, 3D, `:,:,:',         `1,1,1',         in)
+ITEXTVARN(bput, 4D, `:,:,:,:',       `1,1,1,1',       in)
+ITEXTVARN(bput, 5D, `:,:,:,:,:',     `1,1,1,1,1',     in)
+ITEXTVARN(bput, 6D, `:,:,:,:,:,:',   `1,1,1,1,1,1',   in)
+ITEXTVARN(bput, 7D, `:,:,:,:,:,:,:', `1,1,1,1,1,1,1', in)
+
diff --git a/src/libf90/nf90_constants.f90 b/src/libf90/nf90_constants.f90
new file mode 100644
index 0000000..cc8caf2
--- /dev/null
+++ b/src/libf90/nf90_constants.f90
@@ -0,0 +1,302 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: nf90_constants.f90 2195 2015-11-27 18:42:11Z wkliao $
+!
+! This file is taken from netcdf_constants.f90 with changes for PnetCDF use
+!
+!
+  !
+  ! external netcdf data types:
+  !
+  integer, parameter, public :: &
+    nf90_byte   = 1,            &
+    nf90_int1   = nf90_byte,    &
+    nf90_char   = 2,            &
+    nf90_short  = 3,            &
+    nf90_int2   = nf90_short,   &
+    nf90_int    = 4,            &
+    nf90_int4   = nf90_int,     &
+    nf90_float  = 5,            &
+    nf90_real   = nf90_float,   &
+    nf90_real4  = nf90_float,   &
+    nf90_double = 6,            &
+    nf90_real8  = nf90_double,  &
+    nf90_ubyte  = 7,            &
+    nf90_ushort = 8,            &
+    nf90_uint   = 9,            &
+    nf90_int64  = 10,           &
+    nf90_uint64 = 11
+
+  !
+  ! default fill values:
+  !
+  ! character (len = 1),           parameter, public :: &
+  !   nf90_fill_char  = achar(0)
+  integer (kind =  OneByteInt),  parameter, public :: &
+    nf90_fill_char  = 0,                              &
+    nf90_fill_byte  = -127,                           &
+    nf90_fill_int1  = nf90_fill_byte
+  integer (kind =  TwoByteInt),  parameter, public :: &
+    nf90_fill_short = -32767,                         &
+    nf90_fill_int2  = nf90_fill_short,                &
+    nf90_fill_ubyte  = 255
+  integer (kind = FourByteInt),  parameter, public :: &
+    nf90_fill_int    = -2147483647,                   &
+    nf90_fill_ushort = 65535
+  real   (kind =  FourByteReal), parameter, public :: &
+    nf90_fill_float = 9.9692099683868690e+36,         &
+    nf90_fill_real  = nf90_fill_float,                &
+    nf90_fill_real4 = nf90_fill_float
+  real   (kind = EightByteReal), parameter, public :: &
+    nf90_fill_double = 9.9692099683868690e+36,        &
+    nf90_fill_real8  = nf90_fill_double,              &
+    nf90_fill_uint64 = 1.8446744073709551614e+19
+  integer (kind = EightByteInt), parameter, public :: &
+    nf90_fill_uint   = 4294967295_EightByteInt,       &
+    nf90_fill_int64  = -9223372036854775806_EightByteInt
+
+  !
+  ! mode flags for opening and creating a netcdf dataset:
+  !
+  integer, parameter, public :: &
+    nf90_nowrite      = 0,      &
+    nf90_write        = 1,      &
+    nf90_clobber      = 0,      &
+    nf90_noclobber    = 4,      &
+    nf90_fill         = 0,      &
+    nf90_nofill       = 256,    &
+    nf90_64bit_offset = 512,    &
+    nf90_64bit_data   = 32,     &
+    nf90_lock         = 1024,   &
+    nf90_share        = 2048
+
+  integer, parameter, public ::  &
+    nf90_sizehint_default = 0,   &
+    nf90_align_chunk      = -1
+
+  !
+  ! size argument for defining an unlimited dimension:
+  !
+  integer, parameter, public :: &
+    nf90_unlimited = 0
+
+  integer(KIND=MPI_OFFSET_KIND), parameter, public :: &
+    nf90mpi_unlimited = 0
+
+  ! NULL request for non-blocking I/O APIs
+  integer, parameter, public :: nf90_req_null = -1
+
+  ! indicate to flush all pending non-blocking requests
+  integer, parameter, public :: nf90_req_all = -1
+
+  !
+  ! global attribute id:
+  !
+  integer, parameter, public :: nf90_global = 0
+
+  !
+  ! implementation limits:
+  !
+  integer, parameter, public :: &
+    nf90_max_dims     = 1024,    &
+    nf90_max_attrs    = 8192,   &
+    nf90_max_vars     = 8192,   &
+    nf90_max_name     = 256,    &
+    nf90_max_var_dims = 1024
+
+  !
+  ! error handling modes:
+  !
+  integer, parameter, public :: &
+    nf90_fatal   = 1,           &
+    nf90_verbose = 2
+
+  !
+  ! format version numbers:
+  !
+  integer, parameter, public :: &
+    nf90_format_classic = 1,    &
+    nf90_format_cdf2 = 2,      &
+    nf90_format_netcdf4 = 3,    &
+    nf90_format_netcdf4_classic = 4, &
+    nf90_format_cdf5 = 5, &
+    nf90_format_64bit = nf90_format_cdf2, &
+    nf90_format_64bit_offset = nf90_format_cdf2, &
+    nf90_format_64bit_data = nf90_format_cdf5
+
+  !
+  ! error codes:
+  !
+  integer, parameter, public :: &
+    NF90_NOERR          = NF_NOERR         , & ! No Error
+    NF90_EBADID         = NF_EBADID        , & ! Not a netcdf id
+    NF90_ENFILE         = NF_ENFILE        , & ! Too many netcdfs open
+    NF90_EEXIST         = NF_EEXIST        , & ! netcdf file exists and NF_NOCLOBBER
+    NF90_EINVAL         = NF_EINVAL        , & ! Invalid Argument
+    NF90_EPERM          = NF_EPERM         , & ! Write to read only
+    NF90_ENOTINDEFINE   = NF_ENOTINDEFINE  , & ! Operation not allowed in data mode
+    NF90_EINDEFINE      = NF_EINDEFINE     , & ! Operation not allowed in define mode
+    NF90_EINVALCOORDS   = NF_EINVALCOORDS  , & ! Index exceeds dimension bound
+    NF90_EMAXDIMS       = NF_EMAXDIMS      , & ! NF_MAX_DIMS exceeded
+    NF90_ENAMEINUSE     = NF_ENAMEINUSE    , & ! String match to name in use
+    NF90_ENOTATT        = NF_ENOTATT       , & ! Attribute not found
+    NF90_EMAXATTS       = NF_EMAXATTS      , & ! NF_MAX_ATTRS exceeded
+    NF90_EBADTYPE       = NF_EBADTYPE      , & ! Not a netcdf data type
+    NF90_EBADDIM        = NF_EBADDIM       , & ! Invalid dimension id or name
+    NF90_EUNLIMPOS      = NF_EUNLIMPOS     , & ! NFMPI_UNLIMITED in the wrong index
+    NF90_EMAXVARS       = NF_EMAXVARS      , & ! NF_MAX_VARS exceeded
+    NF90_ENOTVAR        = NF_ENOTVAR       , & ! Variable not found
+    NF90_EGLOBAL        = NF_EGLOBAL       , & ! Action prohibited on NF_GLOBAL varid
+    NF90_ENOTNC         = NF_ENOTNC        , & ! Not a netcdf file
+    NF90_ESTS           = NF_ESTS          , & ! In Fortran, string too short
+    NF90_EMAXNAME       = NF_EMAXNAME      , & ! NF_MAX_NAME exceeded
+    NF90_EUNLIMIT       = NF_EUNLIMIT      , & ! NFMPI_UNLIMITED size already in use
+    NF90_ENORECVARS     = NF_ENORECVARS    , & ! nc_rec op when there are no record vars
+    NF90_ECHAR          = NF_ECHAR         , & ! Attempt to convert between text & numbers
+    NF90_EEDGE          = NF_EEDGE         , & ! Edge+start exceeds dimension bound
+    NF90_ESTRIDE        = NF_ESTRIDE       , & ! Illegal stride
+    NF90_EBADNAME       = NF_EBADNAME      , & ! Attribute or variable name contains illegal characters
+    NF90_ERANGE         = NF_ERANGE        , & ! Math result not representable
+    NF90_ENOMEM         = NF_ENOMEM        , & ! Memory allocation (malloc) failure
+    NF90_EVARSIZE       = NF_EVARSIZE      , & ! One or more variable sizes violate format constraints
+    NF90_EDIMSIZE       = NF_EDIMSIZE      , & ! Invalid dimension size
+    NF90_ETRUNC         = NF_ETRUNC        , & ! File likely truncated or possibly corrupted
+    NF90_EAXISTYPE      = NF_EAXISTYPE         ! Unknown axis type
+
+  ! Following errors are added for DAP
+  integer, parameter, public :: &
+    NF90_EDAP           = NF_EDAP          , & ! Generic DAP error
+    NF90_ECURL          = NF_ECURL         , & ! Generic libcurl error
+    NF90_EIO            = NF_EIO           , & ! Generic IO error
+    NF90_ENODATA        = NF_ENODATA       , & ! Attempt to access variable with no data
+    NF90_EDAPSVC        = NF_EDAPSVC       , & ! DAP server error
+    NF90_EDAS           = NF_EDAS          , & ! Malformed or inaccessible DAS
+    NF90_EDDS           = NF_EDDS          , & ! Malformed or inaccessible DDS
+    NF90_EDATADDS       = NF_EDATADDS      , & ! Malformed or inaccessible DATADDS
+    NF90_EDAPURL        = NF_EDAPURL       , & ! Malformed DAP URL
+    NF90_EDAPCONSTRAINT = NF_EDAPCONSTRAINT, & ! Malformed DAP Constraint
+    NF90_ETRANSLATION   = NF_ETRANSLATION  , & ! Untranslatable construct
+    NF90_EACCESS        = NF_EACCESS       , & ! Access Failure
+    NF90_EAUTH          = NF_EAUTH             ! Authorization Failure
+
+  ! Misc. additional errors
+  integer, parameter, public :: &
+    NF90_ENOTFOUND      = NF_ENOTFOUND     , & ! No such file
+    NF90_ECANTREMOVE    = NF_ECANTREMOVE       ! Can't remove file
+
+  ! netCDF-4 error codes (copied from netCDF release)
+  integer, parameter, public :: &
+    NF90_EHDFERR        = NF_EHDFERR       , & ! Error at HDF5 layer.
+    NF90_ECANTREAD      = NF_ECANTREAD     , & ! Can't read.
+    NF90_ECANTWRITE     = NF_ECANTWRITE    , & ! Can't write.
+    NF90_ECANTCREATE    = NF_ECANTCREATE   , & ! Can't create.
+    NF90_EFILEMETA      = NF_EFILEMETA     , & ! Problem with file metadata.
+    NF90_EDIMMETA       = NF_EDIMMETA      , & ! Problem with dimension metadata.
+    NF90_EATTMETA       = NF_EATTMETA      , & ! Problem with attribute metadata.
+    NF90_EVARMETA       = NF_EVARMETA      , & ! Problem with variable metadata.
+    NF90_ENOCOMPOUND    = NF_ENOCOMPOUND   , & ! Not a compound type.
+    NF90_EATTEXISTS     = NF_EATTEXISTS    , & ! Attribute already exists.
+    NF90_ENOTNC4        = NF_ENOTNC4       , & ! Attempting netcdf-4 operation on netcdf-3 file.
+    NF90_ESTRICTNC3     = NF_ESTRICTNC3    , & ! Attempting netcdf-4 operation on strict nc3 netcdf-4 file.
+    NF90_ENOTNC3        = NF_ENOTNC3       , & ! Attempting netcdf-3 operation on netcdf-4 file.
+    NF90_ENOPAR         = NF_ENOPAR        , & ! Parallel operation on file opened for non-parallel access.
+    NF90_EPARINIT       = NF_EPARINIT      , & ! Error initializing for parallel access.
+    NF90_EBADGRPID      = NF_EBADGRPID     , & ! Bad group ID.
+    NF90_EBADTYPID      = NF_EBADTYPID     , & ! Bad type ID.
+    NF90_ETYPDEFINED    = NF_ETYPDEFINED   , & ! Type has already been defined and may not be edited.
+    NF90_EBADFIELD      = NF_EBADFIELD     , & ! Bad field ID.
+    NF90_EBADCLASS      = NF_EBADCLASS     , & ! Bad class.
+    NF90_EMAPTYPE       = NF_EMAPTYPE      , & ! Mapped access for atomic types only.
+    NF90_ELATEFILL      = NF_ELATEFILL     , & ! Attempt to define fill value when data already exists.
+    NF90_ELATEDEF       = NF_ELATEDEF      , & ! Attempt to define var properties, like deflate, after enddef.
+    NF90_EDIMSCALE      = NF_EDIMSCALE     , & ! Probem with HDF5 dimscales.
+    NF90_ENOGRP         = NF_ENOGRP        , & ! No group found.
+    NF90_ESTORAGE       = NF_ESTORAGE      , & ! Can't specify both contiguous and chunking.
+    NF90_EBADCHUNK      = NF_EBADCHUNK     , & ! Bad chunksize.
+    NF90_ENOTBUILT      = NF_ENOTBUILT     , & ! Attempt to use feature that was not turned on when netCDF was built
+    NF90_EDISKLESS      = NF_EDISKLESS     , & ! Error in using diskless  access.
+    NF90_ECANTEXTEND    = NF_ECANTEXTEND   , & ! Attempt to extend dataset during ind. I/O operation.
+    NF90_EMPI           = NF_EMPI              ! MPI operation failed.
+
+  ! This is the position of NC_NETCDF4 in cmode, counting from the
+  ! right, starting (uncharacteristically for fortran) at 0. It's needed
+  ! for the BTEST function calls.
+  integer, parameter, private :: NETCDF4_BIT = 12
+
+
+  ! PnetCDF error codes start here
+  integer, parameter, public :: &
+      NF90_ESMALL                   = NF_ESMALL                   , & ! size of off_t too small for format
+      NF90_ENOTINDEP                = NF_ENOTINDEP                , & ! Operation not allowed in collective data mode
+      NF90_EINDEP                   = NF_EINDEP                   , & ! Operation not allowed in independent data mode
+      NF90_EFILE                    = NF_EFILE                    , & ! Unknown error in file operation
+      NF90_EREAD                    = NF_EREAD                    , & ! Unknown error in reading file
+      NF90_EWRITE                   = NF_EWRITE                   , & ! Unknown error in writting to file
+      NF90_EOFILE                   = NF_EOFILE                   , & ! file open/creation failed
+      NF90_EMULTITYPES              = NF_EMULTITYPES              , & ! Multiple types used in memory data
+      NF90_EIOMISMATCH              = NF_EIOMISMATCH              , & ! Input/Output data amount mismatch
+      NF90_ENEGATIVECNT             = NF_ENEGATIVECNT             , & ! Negative count is specified
+      NF90_EUNSPTETYPE              = NF_EUNSPTETYPE              , & ! Unsupported etype in memory MPI datatype
+      NF90_EINVAL_REQUEST           = NF_EINVAL_REQUEST           , & ! invalid nonblocking request ID
+      NF90_EAINT_TOO_SMALL          = NF_EAINT_TOO_SMALL          , & ! MPI_Aint not large enough to hold requested value
+      NF90_ENOTSUPPORT              = NF_ENOTSUPPORT              , & ! feature is not yet supported
+      NF90_ENULLBUF                 = NF_ENULLBUF                 , & ! trying to attach a NULL buffer
+      NF90_EPREVATTACHBUF           = NF_EPREVATTACHBUF           , & ! previous attached buffer is found
+      NF90_ENULLABUF                = NF_ENULLABUF                , & ! no attached buffer is found
+      NF90_EPENDINGBPUT             = NF_EPENDINGBPUT             , & ! pending bput is found, cannot detach buffer
+      NF90_EINSUFFBUF               = NF_EINSUFFBUF               , & ! attached buffer is too small
+      NF90_ENOENT                   = NF_ENOENT                   , & ! File does not exist when calling nfmpi_open()
+      NF90_EINTOVERFLOW             = NF_EINTOVERFLOW             , & ! Overflow when type cast to 4-byte integer
+      NF90_ENOTENABLED              = NF_ENOTENABLED              , & ! Overflow when type cast to 4-byte integer
+      NF90_EBAD_FILE                = NF_EBAD_FILE                , & ! Invalid file name (e.g., path name too long)
+      NF90_ENO_SPACE                = NF_ENO_SPACE                , & ! Not enough space
+      NF90_EQUOTA                   = NF_EQUOTA                   , & ! Quota exceeded
+      NF90_ENULLSTART               = NF_ENULLSTART               , & ! argument start is a NULL pointer
+      NF90_ENULLCOUNT               = NF_ENULLCOUNT               , & ! argument count is a NULL pointer
+      NF90_EINVAL_CMODE             = NF_EINVAL_CMODE             , & ! Invalid file create mode, cannot have both
+                                                                      ! NC_64BIT_OFFSET & NC_64BIT_DATA
+      NF90_ETYPESIZE                = NF_ETYPESIZE                , & ! MPI derived data type size error (bigger than the
+                                                                      ! variable size)
+      NF90_ETYPE_MISMATCH           = NF_ETYPE_MISMATCH           , & ! element type of the MPI derived data type mismatches
+                                                                      ! the variable type
+      NF90_ETYPESIZE_MISMATCH       = NF_ETYPESIZE_MISMATCH       , & ! file type size mismatches buffer type size
+      NF90_ESTRICTCDF2              = NF_ESTRICTCDF2              , & ! Attempting CDF-5 operation on CDF-2 file
+      NF90_ENOTRECVAR               = NF_ENOTRECVAR               , & ! Attempting operation only for record variables
+      NF90_ENOTFILL                 = NF_ENOTFILL                 , & ! Attempting to fill a variable when its fill mode is off
+      NF90_EMULTIDEFINE             = NF_EMULTIDEFINE             , & ! NC definitions on multiprocesses conflict
+      NF90_EMULTIDEFINE_OMODE       = NF_EMULTIDEFINE_OMODE       , & ! file create/open modes are inconsistent among processes
+      NF90_EMULTIDEFINE_DIM_NUM     = NF_EMULTIDEFINE_DIM_NUM     , & ! inconsistent number of dimensions
+      NF90_EMULTIDEFINE_DIM_SIZE    = NF_EMULTIDEFINE_DIM_SIZE    , & ! inconsistent size of dimension
+      NF90_EMULTIDEFINE_DIM_NAME    = NF_EMULTIDEFINE_DIM_NAME    , & ! inconsistent dimension names
+      NF90_EMULTIDEFINE_VAR_NUM     = NF_EMULTIDEFINE_VAR_NUM     , & ! inconsistent number of variables
+      NF90_EMULTIDEFINE_VAR_NAME    = NF_EMULTIDEFINE_VAR_NAME    , & ! inconsistent variable name
+      NF90_EMULTIDEFINE_VAR_NDIMS   = NF_EMULTIDEFINE_VAR_NDIMS   , & ! inconsistent variable's number of dimensions
+      NF90_EMULTIDEFINE_VAR_DIMIDS  = NF_EMULTIDEFINE_VAR_DIMIDS  , & ! inconsistent variable's dimid
+      NF90_EMULTIDEFINE_VAR_TYPE    = NF_EMULTIDEFINE_VAR_TYPE    , & ! inconsistent variable's data type
+      NF90_EMULTIDEFINE_VAR_LEN     = NF_EMULTIDEFINE_VAR_LEN     , & ! inconsistent variable's size
+      NF90_EMULTIDEFINE_NUMRECS     = NF_EMULTIDEFINE_NUMRECS     , & ! inconsistent number of records
+      NF90_EMULTIDEFINE_VAR_BEGIN   = NF_EMULTIDEFINE_VAR_BEGIN   , & ! inconsistent variable file begin offset (internal use)
+      NF90_EMULTIDEFINE_ATTR_NUM    = NF_EMULTIDEFINE_ATTR_NUM    , & ! inconsistent number of attributes
+      NF90_EMULTIDEFINE_ATTR_SIZE   = NF_EMULTIDEFINE_ATTR_SIZE   , & ! inconsistent memory space used by attribute (internal use)
+      NF90_EMULTIDEFINE_ATTR_NAME   = NF_EMULTIDEFINE_ATTR_NAME   , & ! inconsistent attribute name
+      NF90_EMULTIDEFINE_ATTR_TYPE   = NF_EMULTIDEFINE_ATTR_TYPE   , & ! inconsistent attribute type
+      NF90_EMULTIDEFINE_ATTR_LEN    = NF_EMULTIDEFINE_ATTR_LEN    , & ! inconsistent attribute length
+      NF90_EMULTIDEFINE_ATTR_VAL    = NF_EMULTIDEFINE_ATTR_VAL    , & ! inconsistent attribute value
+      NF90_EMULTIDEFINE_FNC_ARGS    = NF_EMULTIDEFINE_FNC_ARGS    , & ! inconsistent function arguments used in collective API
+      NF90_EMULTIDEFINE_FILL_MODE   = NF_EMULTIDEFINE_FILL_MODE   , & !  inconsistent dataset fill mode
+      NF90_EMULTIDEFINE_VAR_FILL_MODE = NF_EMULTIDEFINE_VAR_FILL_MODE, & ! inconsistent variable fill mode
+      NF90_EMULTIDEFINE_VAR_FILL_VALUE = NF_EMULTIDEFINE_VAR_FILL_VALUE, & ! inconsistent variable fill value
+      NF90_ECMODE                   = NF_EMULTIDEFINE_OMODE       , &
+      NF90_EDIMS_NELEMS_MULTIDEFINE = NF_EMULTIDEFINE_DIM_NUM     , &
+      NF90_EDIMS_SIZE_MULTIDEFINE   = NF_EMULTIDEFINE_DIM_SIZE    , &
+      NF90_EDIMS_NAME_MULTIDEFINE   = NF_EMULTIDEFINE_DIM_NAME    , &
+      NF90_EVARS_NELEMS_MULTIDEFINE = NF_EMULTIDEFINE_VAR_NUM     , &
+      NF90_EVARS_NAME_MULTIDEFINE   = NF_EMULTIDEFINE_VAR_NAME    , &
+      NF90_EVARS_NDIMS_MULTIDEFINE  = NF_EMULTIDEFINE_VAR_NDIMS   , &
+      NF90_EVARS_DIMIDS_MULTIDEFINE = NF_EMULTIDEFINE_VAR_DIMIDS  , &
+      NF90_EVARS_TYPE_MULTIDEFINE   = NF_EMULTIDEFINE_VAR_TYPE    , &
+      NF90_EVARS_LEN_MULTIDEFINE    = NF_EMULTIDEFINE_VAR_LEN     , &
+      NF90_ENUMRECS_MULTIDEFINE     = NF_EMULTIDEFINE_NUMRECS     , &
+      NF90_EVARS_BEGIN_MULTIDEFINE  = NF_EMULTIDEFINE_VAR_BEGIN
diff --git a/src/libf90/nfmpi_constants.f90.in b/src/libf90/nfmpi_constants.f90.in
new file mode 100644
index 0000000..083f049
--- /dev/null
+++ b/src/libf90/nfmpi_constants.f90.in
@@ -0,0 +1,423 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: nfmpi_constants.f90.in 2195 2015-11-27 18:42:11Z wkliao $
+!
+! This file lists the Fortran constants used by PnetCDF
+!
+!
+
+!
+! PnetCDF library version numbers
+!
+      integer PNETCDF_VERSION_MAJOR
+      integer PNETCDF_VERSION_MINOR
+      integer PNETCDF_VERSION_SUB
+
+      parameter (PNETCDF_VERSION_MAJOR = @PNETCDF_VERSION_MAJOR@)
+      parameter (PNETCDF_VERSION_MINOR = @PNETCDF_VERSION_MINOR@)
+      parameter (PNETCDF_VERSION_SUB   = @PNETCDF_VERSION_SUB@)
+
+!
+! external netcdf data types:
+!
+      integer, parameter, public :: &
+      nf_byte = 1, &
+      nf_int1 = nf_byte, &
+      nf_char = 2, &
+      nf_short = 3, &
+      nf_int2 = nf_short, &
+      nf_int = 4, &
+      nf_float = 5, &
+      nf_real = nf_float, &
+      nf_double = 6, &
+      nf_ubyte = 7, &
+      nf_ushort = 8, &
+      nf_uint = 9, &
+      nf_int64 = 10, &
+      nf_uint64 = 11
+
+!
+! default fill values:
+!
+      integer, parameter, public :: &
+      nf_fill_byte = -127, &
+      nf_fill_int1 = nf_fill_byte, &
+      nf_fill_char = 0, &
+      nf_fill_short = -32767, &
+      nf_fill_int2 = nf_fill_short, &
+      nf_fill_int = -2147483647, &
+      nf_fill_ubyte = 255, &
+      nf_fill_ushort = 65535
+
+      real, parameter, public :: &
+      nf_fill_float = 9.9692099683868690e+36, &
+      nf_fill_real = nf_fill_float
+
+      double precision, parameter, public :: &
+      nf_fill_double = 9.9692099683868690e+36, &
+      nf_fill_uint64 = 1.8446744073709551614e+19
+
+      integer (KIND=EightByteInt), parameter, public :: &
+      nf_fill_uint  = 4294967295_EightByteInt, &
+      nf_fill_int64 = -9223372036854775806_EightByteInt
+
+!
+! mode flags for opening and creating a netcdf dataset:
+!
+      integer, parameter, public :: &
+      nf_nowrite = 0, &
+      nf_write = 1, &
+      nf_clobber = 0, &
+      nf_noclobber = 4, &
+      nf_fill = 0, &
+      nf_nofill = 256, &
+      nf_lock = 1024, &
+      nf_share = 2048, &
+      nf_64bit_offset = 512, &
+      nf_64bit_data = 32, &
+      nf_32bit = 16777216, &
+      nf_sizehint_default = 0, &
+      nf_align_chunk = -1, &
+      nf_format_classic = 1, &
+      nf_format_cdf2 = 2, &
+      nf_format_cdf5 = 5, &
+      nf_format_64bit = nf_format_cdf2, &
+      nf_format_64bit_offset = nf_format_cdf2, &
+      nf_format_64bit_data = nf_format_cdf5
+
+!
+! size argument for defining an unlimited dimension:
+!
+      integer, parameter, public :: &
+      nf_unlimited = 0
+
+      integer(KIND=MPI_OFFSET_KIND), parameter, public :: &
+      nfmpi_unlimited = 0
+
+!
+! global attribute id:
+!
+      integer, parameter, public :: &
+      nf_global = 0
+
+!
+! implementation limits:
+!
+      integer, parameter, public :: &
+      nf_max_dims     = 1024, &
+      nf_max_attrs    = 8192, &
+      nf_max_vars     = 8192, &
+      nf_max_name     = 256, &
+      nf_max_var_dims = nf_max_dims
+
+!
+! error codes:
+!
+      integer, parameter, public :: &
+      NF_NOERR          =  0,  & ! No Error
+      NF2_ERR           = -1,  & ! Returned for all errors in the v2 API
+      NF_EBADID         = -33, & ! Not a netcdf id
+      NF_ENFILE         = -34, & ! Too many netcdfs open
+      NF_EEXIST         = -35, & ! netcdf file exists and NF_NOCLOBBER
+      NF_EINVAL         = -36, & ! Invalid Argument
+      NF_EPERM          = -37, & ! Write to read only
+      NF_ENOTINDEFINE   = -38, & ! Operation not allowed in data mode
+      NF_EINDEFINE      = -39, & ! Operation not allowed in define mode
+      NF_EINVALCOORDS   = -40, & ! Index exceeds dimension bound
+      NF_EMAXDIMS       = -41, & ! NF_MAX_DIMS exceeded
+      NF_ENAMEINUSE     = -42, & ! String match to name in use
+      NF_ENOTATT        = -43, & ! Attribute not found
+      NF_EMAXATTS       = -44, & ! NF_MAX_ATTRS exceeded
+      NF_EBADTYPE       = -45, & ! Not a netcdf data type
+      NF_EBADDIM        = -46, & ! Invalid dimension id or name
+      NF_EUNLIMPOS      = -47, & ! NFMPI_UNLIMITED in the wrong index
+      NF_EMAXVARS       = -48, & ! NF_MAX_VARS exceeded
+      NF_ENOTVAR        = -49, & ! Variable not found
+      NF_EGLOBAL        = -50, & ! Action prohibited on NF_GLOBAL varid
+      NF_ENOTNC         = -51, & ! Not a netcdf file
+      NF_ESTS           = -52, & ! In Fortran, string too short
+      NF_EMAXNAME       = -53, & ! NF_MAX_NAME exceeded
+      NF_EUNLIMIT       = -54, & ! NFMPI_UNLIMITED size already in use
+      NF_ENORECVARS     = -55, & ! nc_rec op when there are no record vars
+      NF_ECHAR          = -56, & ! Attempt to convert between text & numbers
+      NF_EEDGE          = -57, & ! Edge+start exceeds dimension bound
+      NF_ESTRIDE        = -58, & ! Illegal stride
+      NF_EBADNAME       = -59, & ! Attribute or variable name contains illegal characters
+      NF_ERANGE         = -60, & ! Math result not representable
+      NF_ENOMEM         = -61, & ! Memory allocation (malloc) failure
+      NF_EVARSIZE       = -62, & ! One or more variable sizes violate format constraints
+      NF_EDIMSIZE       = -63, & ! Invalid dimension size
+      NF_ETRUNC         = -64, & ! File likely truncated or possibly corrupted
+      NF_EAXISTYPE      = -65    ! Unknown axis type
+
+! Following errors are added for DAP
+      integer, parameter, public :: &
+      NF_EDAP           = -66, & ! Generic DAP error
+      NF_ECURL          = -67, & ! Generic libcurl error
+      NF_EIO            = -68, & ! Generic IO error
+      NF_ENODATA        = -69, & ! Attempt to access variable with no data
+      NF_EDAPSVC        = -70, & ! DAP server error
+      NF_EDAS           = -71, & ! Malformed or inaccessible DAS
+      NF_EDDS           = -72, & ! Malformed or inaccessible DDS
+      NF_EDATADDS       = -73, & ! Malformed or inaccessible DATADDS
+      NF_EDAPURL        = -74, & ! Malformed DAP URL
+      NF_EDAPCONSTRAINT = -75, & ! Malformed DAP Constraint
+      NF_ETRANSLATION   = -76, & ! Untranslatable construct
+      NF_EACCESS        = -77, & ! Access Failure
+      NF_EAUTH          = -78    ! Authorization Failure
+
+! Misc. additional errors
+      integer, parameter, public :: &
+      NF_ENOTFOUND      = -90, & ! No such file
+      NF_ECANTREMOVE    = -91    ! Can't remove file
+
+! netCDF-4 error codes (copied from netCDF release)
+      integer, parameter, public :: &
+      NF_EHDFERR        = -101, & ! Error at HDF5 layer. 
+      NF_ECANTREAD      = -102, & ! Can't read. 
+      NF_ECANTWRITE     = -103, & ! Can't write. 
+      NF_ECANTCREATE    = -104, & ! Can't create. 
+      NF_EFILEMETA      = -105, & ! Problem with file metadata. 
+      NF_EDIMMETA       = -106, & ! Problem with dimension metadata. 
+      NF_EATTMETA       = -107, & ! Problem with attribute metadata. 
+      NF_EVARMETA       = -108, & ! Problem with variable metadata. 
+      NF_ENOCOMPOUND    = -109, & ! Not a compound type. 
+      NF_EATTEXISTS     = -110, & ! Attribute already exists. 
+      NF_ENOTNC4        = -111, & ! Attempting netcdf-4 operation on netcdf-3 file.   
+      NF_ESTRICTNC3     = -112, & ! Attempting netcdf-4 operation on strict nc3 netcdf-4 file.   
+      NF_ENOTNC3        = -113, & ! Attempting netcdf-3 operation on netcdf-4 file.   
+      NF_ENOPAR         = -114, & ! Parallel operation on file opened for non-parallel access.   
+      NF_EPARINIT       = -115, & ! Error initializing for parallel access.   
+      NF_EBADGRPID      = -116, & ! Bad group ID.   
+      NF_EBADTYPID      = -117, & ! Bad type ID.   
+      NF_ETYPDEFINED    = -118, & ! Type has already been defined and may not be edited. 
+      NF_EBADFIELD      = -119, & ! Bad field ID.   
+      NF_EBADCLASS      = -120, & ! Bad class.   
+      NF_EMAPTYPE       = -121, & ! Mapped access for atomic types only.   
+      NF_ELATEFILL      = -122, & ! Attempt to define fill value when data already exists. 
+      NF_ELATEDEF       = -123, & ! Attempt to define var properties, like deflate, after enddef.
+      NF_EDIMSCALE      = -124, & ! Probem with HDF5 dimscales.
+      NF_ENOGRP         = -125, & ! No group found.
+      NF_ESTORAGE       = -126, & ! Can't specify both contiguous and chunking.
+      NF_EBADCHUNK      = -127, & ! Bad chunksize.
+      NF_ENOTBUILT      = -128, & ! Attempt to use feature that was not turned on when netCDF was built.
+      NF_EDISKLESS      = -129, & ! Error in using diskless  access.
+      NF_ECANTEXTEND    = -130, & ! Attempt to extend dataset during ind. I/O operation.
+      NF_EMPI           = -131    ! MPI operation failed.
+
+
+! PnetCDF error codes start here
+      integer, parameter, public :: &
+      NF_ESMALL                   = -201, & ! size of off_t too small for format
+      NF_ENOTINDEP                = -202, & ! Operation not allowed in collective data mode
+      NF_EINDEP                   = -203, & ! Operation not allowed in independent data mode
+      NF_EFILE                    = -204, & ! Unknown error in file operation
+      NF_EREAD                    = -205, & ! Unknown error in reading file
+      NF_EWRITE                   = -206, & ! Unknown error in writting to file
+      NF_EOFILE                   = -207, & ! file open/creation failed
+      NF_EMULTITYPES              = -208, & ! Multiple types used in memory data
+      NF_EIOMISMATCH              = -209, & ! Input/Output data amount mismatch
+      NF_ENEGATIVECNT             = -210, & ! Negative count is specified
+      NF_EUNSPTETYPE              = -211, & ! Unsupported etype in memory MPI datatype
+      NF_EINVAL_REQUEST           = -212, & ! invalid nonblocking request ID
+      NF_EAINT_TOO_SMALL          = -213, & ! MPI_Aint not large enough to hold requested value
+      NF_ENOTSUPPORT              = -214, & ! feature is not yet supported
+      NF_ENULLBUF                 = -215, & ! trying to attach a NULL buffer
+      NF_EPREVATTACHBUF           = -216, & ! previous attached buffer is found
+      NF_ENULLABUF                = -217, & ! no attached buffer is found
+      NF_EPENDINGBPUT             = -218, & ! pending bput is found, cannot detach buffer
+      NF_EINSUFFBUF               = -219, & ! attached buffer is too small
+      NF_ENOENT                   = -220, & ! File does not exist when calling nfmpi_open()
+      NF_EINTOVERFLOW             = -221, & ! Overflow when type cast to 4-byte integer
+      NF_ENOTENABLED              = -222, & ! feature is not enabled
+      NF_EBAD_FILE                = -223, & ! Invalid file name (e.g., path name too long)
+      NF_ENO_SPACE                = -224, & ! Not enough space
+      NF_EQUOTA                   = -225, & ! Quota exceeded
+      NF_ENULLSTART               = -226, & ! argument start is a NULL pointer
+      NF_ENULLCOUNT               = -227, & ! argument count is a NULL pointer
+      NF_EINVAL_CMODE             = -228, & ! Invalid file create mode, cannot have both NC_64BIT_OFFSET & NC_64BIT_DATA
+      NF_ETYPESIZE                = -229, & ! MPI derived data type size error (bigger than the variable size)
+      NF_ETYPE_MISMATCH           = -230, & ! element type of the MPI derived data type mismatches the variable type
+      NF_ETYPESIZE_MISMATCH       = -231, & ! file type size mismatches buffer type size
+      NF_ESTRICTCDF2              = -232, & ! Attempting CDF-5 operation on CDF-2 file
+      NF_ENOTRECVAR               = -233, & ! Attempting operation only for record variables */
+      NF_ENOTFILL                 = -234    ! Attempting to fill a variable when its fill mode is off */
+
+! header inconsistency error starts in -250
+      integer, parameter, public :: &
+      NF_EMULTIDEFINE             = -250, & ! NC definitions on multiprocesses conflict
+      NF_EMULTIDEFINE_OMODE       = -251, & ! file create/open modes are inconsistent among processes
+      NF_EMULTIDEFINE_DIM_NUM     = -252, & ! inconsistent number of dimensions
+      NF_EMULTIDEFINE_DIM_SIZE    = -253, & ! inconsistent size of dimension
+      NF_EMULTIDEFINE_DIM_NAME    = -254, & ! inconsistent dimension names
+      NF_EMULTIDEFINE_VAR_NUM     = -255, & ! inconsistent number of variables
+      NF_EMULTIDEFINE_VAR_NAME    = -256, & ! inconsistent variable name
+      NF_EMULTIDEFINE_VAR_NDIMS   = -257, & ! inconsistent variable's number of dimensions
+      NF_EMULTIDEFINE_VAR_DIMIDS  = -258, & ! inconsistent variable's dimid
+      NF_EMULTIDEFINE_VAR_TYPE    = -259, & ! inconsistent variable's data type
+      NF_EMULTIDEFINE_VAR_LEN     = -260, & ! inconsistent variable's size
+      NF_EMULTIDEFINE_NUMRECS     = -261, & ! inconsistent number of records
+      NF_EMULTIDEFINE_VAR_BEGIN   = -262, & ! inconsistent variable file begin offset (internal use)
+      NF_EMULTIDEFINE_ATTR_NUM    = -263, & ! inconsistent number of attributes
+      NF_EMULTIDEFINE_ATTR_SIZE   = -264, & ! inconsistent memory space used by attribute (internal use)
+      NF_EMULTIDEFINE_ATTR_NAME   = -265, & ! inconsistent attribute name
+      NF_EMULTIDEFINE_ATTR_TYPE   = -266, & ! inconsistent attribute type
+      NF_EMULTIDEFINE_ATTR_LEN    = -267, & ! inconsistent attribute length
+      NF_EMULTIDEFINE_ATTR_VAL    = -268, & ! inconsistent attribute value
+      NF_EMULTIDEFINE_FNC_ARGS    = -269, & ! inconsistent function arguments used in collective API
+      NF_EMULTIDEFINE_FILL_MODE      = -270, & !  inconsistent dataset fill mode
+      NF_EMULTIDEFINE_VAR_FILL_MODE  = -271, & ! inconsistent variable fill mode
+      NF_EMULTIDEFINE_VAR_FILL_VALUE = -272, & ! inconsistent variable fill value
+      NF_ECMODE                   = NF_EMULTIDEFINE_OMODE,      &
+      NF_EDIMS_NELEMS_MULTIDEFINE = NF_EMULTIDEFINE_DIM_NUM,    &
+      NF_EDIMS_SIZE_MULTIDEFINE   = NF_EMULTIDEFINE_DIM_SIZE,   &
+      NF_EDIMS_NAME_MULTIDEFINE   = NF_EMULTIDEFINE_DIM_NAME,   &
+      NF_EVARS_NELEMS_MULTIDEFINE = NF_EMULTIDEFINE_VAR_NUM,    &
+      NF_EVARS_NAME_MULTIDEFINE   = NF_EMULTIDEFINE_VAR_NAME,   &
+      NF_EVARS_NDIMS_MULTIDEFINE  = NF_EMULTIDEFINE_VAR_NDIMS,  &
+      NF_EVARS_DIMIDS_MULTIDEFINE = NF_EMULTIDEFINE_VAR_DIMIDS, &
+      NF_EVARS_TYPE_MULTIDEFINE   = NF_EMULTIDEFINE_VAR_TYPE,   &
+      NF_EVARS_LEN_MULTIDEFINE    = NF_EMULTIDEFINE_VAR_LEN,    &
+      NF_ENUMRECS_MULTIDEFINE     = NF_EMULTIDEFINE_NUMRECS,    &
+      NF_EVARS_BEGIN_MULTIDEFINE  = NF_EMULTIDEFINE_VAR_BEGIN
+
+! error handling modes:
+!
+      integer, parameter, public :: &
+      nf_fatal = 1, &
+      nf_verbose = 2
+
+! NULL request for non-blocking I/O APIs
+      integer, parameter, public :: &
+      NF_REQ_NULL = -1
+
+! indicate to flush all pending non-blocking requests
+      integer, parameter, public :: &
+      NF_REQ_ALL = -1
+
+!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+! begin netcdf 2.4 backward compatibility:
+!
+
+!
+! functions in the fortran interface
+!
+
+!
+! netcdf data types:
+!
+      integer, parameter, public :: &
+      ncbyte = 1, &
+      ncchar = 2, &
+      ncshort = 3, &
+      nclong = 4, &
+      ncfloat = 5, &
+      ncdouble = 6
+
+!
+!     masks for the struct nc flag field; passed in as 'mode' arg to
+!     nccreate and ncopen.
+!
+      integer, parameter, public :: &
+      ncrdwr = 1, &     ! read/write, 0 => readonly
+      nccreat = 2, &    ! in create phase, cleared by ncendef
+      ncexcl = 4, &     ! on create destroy existing file
+      ncindef = 8, &    ! in define mode, cleared by ncendef
+      ncnsync = 16, &   ! synchronise numrecs on change (x'10')
+      nchsync = 32, &   ! synchronise whole header on change (x'20')
+      ncndirty = 64, &  ! numrecs has changed (x'40')
+      nchdirty = 128, & ! header info has changed (x'80')
+      ncfill = 0, &     ! prefill vars on endef and increase of record, the default behavior
+      ncnofill = 256, & ! do not fill vars on endef and increase of record (x'100')
+      nclink = 32768    ! isa link (x'8000')
+
+!
+!     'mode' arguments for nccreate and ncopen
+!
+      integer, parameter, public :: &
+      ncnowrit = 0, &
+      ncwrite = ncrdwr, &
+      ncclob = nf_clobber, &
+      ncnoclob = nf_noclobber
+
+!
+!     'size' argument to ncdimdef for an unlimited dimension
+!
+      integer, parameter, public :: &
+      ncunlim = 0
+
+!
+!     attribute id to put/get a global attribute
+!
+      integer, parameter, public :: &
+      ncglobal  = 0
+
+!
+!     advisory maximums:
+!
+      integer, parameter, public :: &
+      maxncop = 32, &
+      maxncdim = 100, &
+      maxncatt = 2000, &
+      maxncvar = 2000
+
+!     not enforced
+      integer, parameter, public :: &
+      maxncnam = 128, &
+      maxvdims = maxncdim
+
+!
+!     global netcdf error status variable
+!     initialized in error.c
+!
+      integer, parameter, public :: &
+      ncnoerr = nf_noerr, &         ! no error
+      ncebadid = nf_ebadid, &       ! not a netcdf id
+      ncenfile = -31, &             ! nc_syserr too many netcdfs open
+      nceexist = nf_eexist, &       ! netcdf file exists && ncnoclob
+      nceinval = nf_einval, &       ! invalid argument
+      nceperm = nf_eperm, &         ! write to read only
+      ncenotin = nf_enotindefine, & ! operation not allowed in data mode
+      nceindef = nf_eindefine, &    ! operation not allowed in define mode
+      ncecoord = nf_einvalcoords, & ! coordinates out of domain
+      ncemaxds = nf_emaxdims, &     ! maxncdims exceeded
+      ncename = nf_enameinuse, &    ! string match to name in use
+      ncenoatt = nf_enotatt, &      ! attribute not found
+      ncemaxat = nf_emaxatts, &     ! maxncattrs exceeded
+      ncebadty = nf_ebadtype, &     ! not a netcdf data type
+      ncebadd = nf_ebaddim, &       ! invalid dimension id
+      nceunlim = nf_eunlimpos, &    ! ncunlimited in the wrong index
+      ncemaxvs = nf_emaxvars, &     ! maxncvars exceeded
+      ncenotvr = nf_enotvar, &      ! variable not found
+      nceglob = nf_eglobal, &       ! action prohibited on ncglobal varid
+      ncenotnc = nf_enotnc, &       ! not a netcdf file
+      ncests = nf_ests, &
+      ncentool = nf_emaxname, &
+      ncfoobar = 32, &
+      ncsyserr = -31
+
+!
+!     global options variable. used to determine behavior of error handler.
+!     initialized in lerror.c
+!
+      integer, parameter, public :: &
+      ncfatal = 1, &
+      ncverbos = 2
+
+!
+!     default fill values.  these must be the same as in the c interface.
+!
+      integer, parameter, public :: &
+      filbyte = -127, &
+      filchar = 0, &
+      filshort = -32767, &
+      fillong = -2147483647
+
+      real, parameter, public :: &
+      filfloat = 9.9692099683868690e+36
+
+      double precision, parameter, public :: &
+      fildoub = 9.9692099683868690e+36
+
diff --git a/src/libf90/overloads.f90 b/src/libf90/overloads.f90
new file mode 100644
index 0000000..f8b1099
--- /dev/null
+++ b/src/libf90/overloads.f90
@@ -0,0 +1,693 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: overloads.f90 2002 2015-02-12 07:34:35Z wkliao $
+!
+! This file is taken from netcdf_overloads.f90 with changes for PnetCDF use
+!  
+!
+
+  ! Overloaded variable functions
+  interface nf90mpi_def_var
+    module procedure nf90mpi_def_var_Scalar, nf90mpi_def_var_oneDim, nf90mpi_def_var_ManyDims
+  end interface ! nf90mpi_def_var
+  
+  ! Overloaded variable fill functions
+  interface nf90mpi_def_var_fill
+    module procedure nf90mpi_def_var_fill_text,                                            &
+                     nf90mpi_def_var_fill_OneByteInt,   nf90mpi_def_var_fill_TwoByteInt,   &
+                     nf90mpi_def_var_fill_FourByteInt,  nf90mpi_def_var_fill_EightByteInt, &
+                     nf90mpi_def_var_fill_FourByteReal, nf90mpi_def_var_fill_EightByteReal
+  end interface !nf90mpi_def_var_fill
+  interface nf90mpi_inq_var_fill
+    module procedure nf90mpi_inq_var_fill_text,                                            &
+                     nf90mpi_inq_var_fill_OneByteInt,   nf90mpi_inq_var_fill_TwoByteInt,   &
+                     nf90mpi_inq_var_fill_FourByteInt,  nf90mpi_inq_var_fill_EightByteInt, &
+                     nf90mpi_inq_var_fill_FourByteReal, nf90mpi_inq_var_fill_EightByteReal
+  end interface !nf90mpi_inq_var_fill
+
+  ! Overloaded attribute functions
+  interface nf90mpi_put_att
+    module procedure nf90mpi_put_att_text,                                               &
+                     nf90mpi_put_att_OneByteInt,       nf90mpi_put_att_TwoByteInt,       &
+                     nf90mpi_put_att_FourByteInt,      nf90mpi_put_att_EightByteInt,     &
+                     nf90mpi_put_att_FourByteReal,     nf90mpi_put_att_EightByteReal
+    module procedure nf90mpi_put_att_one_OneByteInt,   nf90mpi_put_att_one_TwoByteInt,   &
+                     nf90mpi_put_att_one_FourByteInt,  nf90mpi_put_att_one_EightByteInt, &
+                     nf90mpi_put_att_one_FourByteReal, nf90mpi_put_att_one_EightByteReal
+  end interface !nf90mpi_put_att
+  interface nf90mpi_get_att
+    module procedure nf90mpi_get_att_text,                                               &
+                     nf90mpi_get_att_OneByteInt,       nf90mpi_get_att_TwoByteInt,       &
+                     nf90mpi_get_att_FourByteInt,      nf90mpi_get_att_EightByteInt,     &
+                     nf90mpi_get_att_FourByteReal,     nf90mpi_get_att_EightByteReal
+    module procedure nf90mpi_get_att_one_OneByteInt,   nf90mpi_get_att_one_TwoByteInt,   &
+                     nf90mpi_get_att_one_FourByteInt,  nf90mpi_get_att_one_EightByteInt, &
+                     nf90mpi_get_att_one_FourByteReal, nf90mpi_get_att_one_EightByteReal
+  end interface ! nf90mpi_get_att
+
+  ! Overloaded variable functions
+  interface nf90mpi_put_var
+    module procedure nf90mpi_put_var_text,                                               &
+                     nf90mpi_put_var_OneByteInt,   nf90mpi_put_var_TwoByteInt,           &
+                     nf90mpi_put_var_FourByteInt,  nf90mpi_put_var_EightByteInt,         &
+                     nf90mpi_put_var_FourByteReal, nf90mpi_put_var_EightByteReal
+    module procedure nf90mpi_put_var_1D_text,                                            &
+                     nf90mpi_put_var_1D_OneByteInt,   nf90mpi_put_var_1D_TwoByteInt,     &
+                     nf90mpi_put_var_1D_FourByteInt,  nf90mpi_put_var_1D_EightByteInt,   &
+                     nf90mpi_put_var_1D_FourByteReal, nf90mpi_put_var_1D_EightByteReal
+    module procedure nf90mpi_put_var_2D_text,                                            &
+                     nf90mpi_put_var_2D_OneByteInt,   nf90mpi_put_var_2D_TwoByteInt,     &
+                     nf90mpi_put_var_2D_FourByteInt,  nf90mpi_put_var_2D_EightByteInt,   &
+                     nf90mpi_put_var_2D_FourByteReal, nf90mpi_put_var_2D_EightByteReal
+    module procedure nf90mpi_put_var_3D_text,                                            &
+                     nf90mpi_put_var_3D_OneByteInt,   nf90mpi_put_var_3D_TwoByteInt,     &
+                     nf90mpi_put_var_3D_FourByteInt,  nf90mpi_put_var_3D_EightByteInt,   &
+                     nf90mpi_put_var_3D_FourByteReal, nf90mpi_put_var_3D_EightByteReal
+    module procedure nf90mpi_put_var_4D_text,                                            &
+                     nf90mpi_put_var_4D_OneByteInt,   nf90mpi_put_var_4D_TwoByteInt,     &
+                     nf90mpi_put_var_4D_FourByteInt,  nf90mpi_put_var_4D_EightByteInt,   &
+                     nf90mpi_put_var_4D_FourByteReal, nf90mpi_put_var_4D_EightByteReal
+    module procedure nf90mpi_put_var_5D_text,                                            &
+                     nf90mpi_put_var_5D_OneByteInt,   nf90mpi_put_var_5D_TwoByteInt,     &
+                     nf90mpi_put_var_5D_FourByteInt,  nf90mpi_put_var_5D_EightByteInt,   &
+                     nf90mpi_put_var_5D_FourByteReal, nf90mpi_put_var_5D_EightByteReal
+    module procedure nf90mpi_put_var_6D_text,                                            &
+                     nf90mpi_put_var_6D_OneByteInt,   nf90mpi_put_var_6D_TwoByteInt,     &
+                     nf90mpi_put_var_6D_FourByteInt,  nf90mpi_put_var_6D_EightByteInt,   &
+                     nf90mpi_put_var_6D_FourByteReal, nf90mpi_put_var_6D_EightByteReal
+    module procedure nf90mpi_put_var_7D_text,                                            &
+                     nf90mpi_put_var_7D_OneByteInt,   nf90mpi_put_var_7D_TwoByteInt,     &
+                     nf90mpi_put_var_7D_FourByteInt,  nf90mpi_put_var_7D_EightByteInt,   &
+                     nf90mpi_put_var_7D_FourByteReal, nf90mpi_put_var_7D_EightByteReal
+  end interface ! nf90mpi_put_var
+
+  interface nf90mpi_get_var
+    module procedure nf90mpi_get_var_text,                                               &
+                     nf90mpi_get_var_OneByteInt,   nf90mpi_get_var_TwoByteInt,           &
+                     nf90mpi_get_var_FourByteInt,  nf90mpi_get_var_EightByteInt,         &
+                     nf90mpi_get_var_FourByteReal, nf90mpi_get_var_EightByteReal
+    module procedure nf90mpi_get_var_1D_text,                                            &
+                     nf90mpi_get_var_1D_OneByteInt,   nf90mpi_get_var_1D_TwoByteInt,     &
+                     nf90mpi_get_var_1D_FourByteInt,  nf90mpi_get_var_1D_EightByteInt,   &
+                     nf90mpi_get_var_1D_FourByteReal, nf90mpi_get_var_1D_EightByteReal
+    module procedure nf90mpi_get_var_2D_text,                                            &
+                     nf90mpi_get_var_2D_OneByteInt,   nf90mpi_get_var_2D_TwoByteInt,     &
+                     nf90mpi_get_var_2D_FourByteInt,  nf90mpi_get_var_2D_EightByteInt,   &
+                     nf90mpi_get_var_2D_FourByteReal, nf90mpi_get_var_2D_EightByteReal
+    module procedure nf90mpi_get_var_3D_text,                                            &
+                     nf90mpi_get_var_3D_OneByteInt,   nf90mpi_get_var_3D_TwoByteInt,     &
+                     nf90mpi_get_var_3D_FourByteInt,  nf90mpi_get_var_3D_EightByteInt,   &
+                     nf90mpi_get_var_3D_FourByteReal, nf90mpi_get_var_3D_EightByteReal
+    module procedure nf90mpi_get_var_4D_text,                                            &
+                     nf90mpi_get_var_4D_OneByteInt,   nf90mpi_get_var_4D_TwoByteInt,     &
+                     nf90mpi_get_var_4D_FourByteInt,  nf90mpi_get_var_4D_EightByteInt,   &
+                     nf90mpi_get_var_4D_FourByteReal, nf90mpi_get_var_4D_EightByteReal
+    module procedure nf90mpi_get_var_5D_text,                                            &
+                     nf90mpi_get_var_5D_OneByteInt,   nf90mpi_get_var_5D_TwoByteInt,     &
+                     nf90mpi_get_var_5D_FourByteInt,  nf90mpi_get_var_5D_EightByteInt,   &
+                     nf90mpi_get_var_5D_FourByteReal, nf90mpi_get_var_5D_EightByteReal
+    module procedure nf90mpi_get_var_6D_text,                                            &
+                     nf90mpi_get_var_6D_OneByteInt,   nf90mpi_get_var_6D_TwoByteInt,     &
+                     nf90mpi_get_var_6D_FourByteInt,  nf90mpi_get_var_6D_EightByteInt,   &
+                     nf90mpi_get_var_6D_FourByteReal, nf90mpi_get_var_6D_EightByteReal
+    module procedure nf90mpi_get_var_7D_text,                                            &
+                     nf90mpi_get_var_7D_OneByteInt,   nf90mpi_get_var_7D_TwoByteInt,     &
+                     nf90mpi_get_var_7D_FourByteInt,  nf90mpi_get_var_7D_EightByteInt,   &
+                     nf90mpi_get_var_7D_FourByteReal, nf90mpi_get_var_7D_EightByteReal
+  end interface ! nf90mpi_get_var
+
+  ! Overloaded variable functions varn
+  interface nf90mpi_put_varn
+    module procedure nf90mpi_put_varn_text,                                              &
+                     nf90mpi_put_varn_OneByteInt,   nf90mpi_put_varn_TwoByteInt,         &
+                     nf90mpi_put_varn_FourByteInt,  nf90mpi_put_varn_EightByteInt,       &
+                     nf90mpi_put_varn_FourByteReal, nf90mpi_put_varn_EightByteReal
+    module procedure nf90mpi_put_varn_1D_text,                                           &
+                     nf90mpi_put_varn_1D_OneByteInt,   nf90mpi_put_varn_1D_TwoByteInt,   &
+                     nf90mpi_put_varn_1D_FourByteInt,  nf90mpi_put_varn_1D_EightByteInt, &
+                     nf90mpi_put_varn_1D_FourByteReal, nf90mpi_put_varn_1D_EightByteReal
+    module procedure nf90mpi_put_varn_2D_text,                                           &
+                     nf90mpi_put_varn_2D_OneByteInt,   nf90mpi_put_varn_2D_TwoByteInt,   &
+                     nf90mpi_put_varn_2D_FourByteInt,  nf90mpi_put_varn_2D_EightByteInt, &
+                     nf90mpi_put_varn_2D_FourByteReal, nf90mpi_put_varn_2D_EightByteReal
+    module procedure nf90mpi_put_varn_3D_text,                                           &
+                     nf90mpi_put_varn_3D_OneByteInt,   nf90mpi_put_varn_3D_TwoByteInt,   &
+                     nf90mpi_put_varn_3D_FourByteInt,  nf90mpi_put_varn_3D_EightByteInt, &
+                     nf90mpi_put_varn_3D_FourByteReal, nf90mpi_put_varn_3D_EightByteReal
+    module procedure nf90mpi_put_varn_4D_text,                                           &
+                     nf90mpi_put_varn_4D_OneByteInt,   nf90mpi_put_varn_4D_TwoByteInt,   &
+                     nf90mpi_put_varn_4D_FourByteInt,  nf90mpi_put_varn_4D_EightByteInt, &
+                     nf90mpi_put_varn_4D_FourByteReal, nf90mpi_put_varn_4D_EightByteReal
+    module procedure nf90mpi_put_varn_5D_text,                                           &
+                     nf90mpi_put_varn_5D_OneByteInt,   nf90mpi_put_varn_5D_TwoByteInt,   &
+                     nf90mpi_put_varn_5D_FourByteInt,  nf90mpi_put_varn_5D_EightByteInt, &
+                     nf90mpi_put_varn_5D_FourByteReal, nf90mpi_put_varn_5D_EightByteReal
+    module procedure nf90mpi_put_varn_6D_text,                                           &
+                     nf90mpi_put_varn_6D_OneByteInt,   nf90mpi_put_varn_6D_TwoByteInt,   &
+                     nf90mpi_put_varn_6D_FourByteInt,  nf90mpi_put_varn_6D_EightByteInt, &
+                     nf90mpi_put_varn_6D_FourByteReal, nf90mpi_put_varn_6D_EightByteReal
+    module procedure nf90mpi_put_varn_7D_text,                                           &
+                     nf90mpi_put_varn_7D_OneByteInt,   nf90mpi_put_varn_7D_TwoByteInt,   &
+                     nf90mpi_put_varn_7D_FourByteInt,  nf90mpi_put_varn_7D_EightByteInt, &
+                     nf90mpi_put_varn_7D_FourByteReal, nf90mpi_put_varn_7D_EightByteReal
+  end interface ! nf90mpi_put_varn
+
+  interface nf90mpi_get_varn
+    module procedure nf90mpi_get_varn_text,                                              &
+                     nf90mpi_get_varn_OneByteInt,   nf90mpi_get_varn_TwoByteInt,         &
+                     nf90mpi_get_varn_FourByteInt,  nf90mpi_get_varn_EightByteInt,       &
+                     nf90mpi_get_varn_FourByteReal, nf90mpi_get_varn_EightByteReal
+    module procedure nf90mpi_get_varn_1D_text,                                           &
+                     nf90mpi_get_varn_1D_OneByteInt,   nf90mpi_get_varn_1D_TwoByteInt,   &
+                     nf90mpi_get_varn_1D_FourByteInt,  nf90mpi_get_varn_1D_EightByteInt, &
+                     nf90mpi_get_varn_1D_FourByteReal, nf90mpi_get_varn_1D_EightByteReal
+    module procedure nf90mpi_get_varn_2D_text,                                           &
+                     nf90mpi_get_varn_2D_OneByteInt,   nf90mpi_get_varn_2D_TwoByteInt,   &
+                     nf90mpi_get_varn_2D_FourByteInt,  nf90mpi_get_varn_2D_EightByteInt, &
+                     nf90mpi_get_varn_2D_FourByteReal, nf90mpi_get_varn_2D_EightByteReal
+    module procedure nf90mpi_get_varn_3D_text,                                           &
+                     nf90mpi_get_varn_3D_OneByteInt,   nf90mpi_get_varn_3D_TwoByteInt,   &
+                     nf90mpi_get_varn_3D_FourByteInt,  nf90mpi_get_varn_3D_EightByteInt, &
+                     nf90mpi_get_varn_3D_FourByteReal, nf90mpi_get_varn_3D_EightByteReal
+    module procedure nf90mpi_get_varn_4D_text,                                           &
+                     nf90mpi_get_varn_4D_OneByteInt,   nf90mpi_get_varn_4D_TwoByteInt,   &
+                     nf90mpi_get_varn_4D_FourByteInt,  nf90mpi_get_varn_4D_EightByteInt, &
+                     nf90mpi_get_varn_4D_FourByteReal, nf90mpi_get_varn_4D_EightByteReal
+    module procedure nf90mpi_get_varn_5D_text,                                           &
+                     nf90mpi_get_varn_5D_OneByteInt,   nf90mpi_get_varn_5D_TwoByteInt,   &
+                     nf90mpi_get_varn_5D_FourByteInt,  nf90mpi_get_varn_5D_EightByteInt, &
+                     nf90mpi_get_varn_5D_FourByteReal, nf90mpi_get_varn_5D_EightByteReal
+    module procedure nf90mpi_get_varn_6D_text,                                           &
+                     nf90mpi_get_varn_6D_OneByteInt,   nf90mpi_get_varn_6D_TwoByteInt,   &
+                     nf90mpi_get_varn_6D_FourByteInt,  nf90mpi_get_varn_6D_EightByteInt, &
+                     nf90mpi_get_varn_6D_FourByteReal, nf90mpi_get_varn_6D_EightByteReal
+    module procedure nf90mpi_get_varn_7D_text,                                           &
+                     nf90mpi_get_varn_7D_OneByteInt,   nf90mpi_get_varn_7D_TwoByteInt,   &
+                     nf90mpi_get_varn_7D_FourByteInt,  nf90mpi_get_varn_7D_EightByteInt, &
+                     nf90mpi_get_varn_7D_FourByteReal, nf90mpi_get_varn_7D_EightByteReal
+  end interface ! nf90mpi_get_varn
+
+  ! Overloaded variable functions vard
+  interface nf90mpi_put_vard
+    module procedure nf90mpi_put_vard_text,                                              &
+                     nf90mpi_put_vard_OneByteInt,   nf90mpi_put_vard_TwoByteInt,         &
+                     nf90mpi_put_vard_FourByteInt,  nf90mpi_put_vard_EightByteInt,       &
+                     nf90mpi_put_vard_FourByteReal, nf90mpi_put_vard_EightByteReal
+    module procedure nf90mpi_put_vard_1D_text,                                           &
+                     nf90mpi_put_vard_1D_OneByteInt,   nf90mpi_put_vard_1D_TwoByteInt,   &
+                     nf90mpi_put_vard_1D_FourByteInt,  nf90mpi_put_vard_1D_EightByteInt, &
+                     nf90mpi_put_vard_1D_FourByteReal, nf90mpi_put_vard_1D_EightByteReal
+    module procedure nf90mpi_put_vard_2D_text,                                           &
+                     nf90mpi_put_vard_2D_OneByteInt,   nf90mpi_put_vard_2D_TwoByteInt,   &
+                     nf90mpi_put_vard_2D_FourByteInt,  nf90mpi_put_vard_2D_EightByteInt, &
+                     nf90mpi_put_vard_2D_FourByteReal, nf90mpi_put_vard_2D_EightByteReal
+    module procedure nf90mpi_put_vard_3D_text,                                           &
+                     nf90mpi_put_vard_3D_OneByteInt,   nf90mpi_put_vard_3D_TwoByteInt,   &
+                     nf90mpi_put_vard_3D_FourByteInt,  nf90mpi_put_vard_3D_EightByteInt, &
+                     nf90mpi_put_vard_3D_FourByteReal, nf90mpi_put_vard_3D_EightByteReal
+    module procedure nf90mpi_put_vard_4D_text,                                           &
+                     nf90mpi_put_vard_4D_OneByteInt,   nf90mpi_put_vard_4D_TwoByteInt,   &
+                     nf90mpi_put_vard_4D_FourByteInt,  nf90mpi_put_vard_4D_EightByteInt, &
+                     nf90mpi_put_vard_4D_FourByteReal, nf90mpi_put_vard_4D_EightByteReal
+    module procedure nf90mpi_put_vard_5D_text,                                           &
+                     nf90mpi_put_vard_5D_OneByteInt,   nf90mpi_put_vard_5D_TwoByteInt,   &
+                     nf90mpi_put_vard_5D_FourByteInt,  nf90mpi_put_vard_5D_EightByteInt, &
+                     nf90mpi_put_vard_5D_FourByteReal, nf90mpi_put_vard_5D_EightByteReal
+    module procedure nf90mpi_put_vard_6D_text,                                           &
+                     nf90mpi_put_vard_6D_OneByteInt,   nf90mpi_put_vard_6D_TwoByteInt,   &
+                     nf90mpi_put_vard_6D_FourByteInt,  nf90mpi_put_vard_6D_EightByteInt, &
+                     nf90mpi_put_vard_6D_FourByteReal, nf90mpi_put_vard_6D_EightByteReal
+    module procedure nf90mpi_put_vard_7D_text,                                           &
+                     nf90mpi_put_vard_7D_OneByteInt,   nf90mpi_put_vard_7D_TwoByteInt,   &
+                     nf90mpi_put_vard_7D_FourByteInt,  nf90mpi_put_vard_7D_EightByteInt, &
+                     nf90mpi_put_vard_7D_FourByteReal, nf90mpi_put_vard_7D_EightByteReal
+  end interface ! nf90mpi_put_vard
+
+  interface nf90mpi_get_vard
+    module procedure nf90mpi_get_vard_text,                                              &
+                     nf90mpi_get_vard_OneByteInt,   nf90mpi_get_vard_TwoByteInt,         &
+                     nf90mpi_get_vard_FourByteInt,  nf90mpi_get_vard_EightByteInt,       &
+                     nf90mpi_get_vard_FourByteReal, nf90mpi_get_vard_EightByteReal
+    module procedure nf90mpi_get_vard_1D_text,                                           &
+                     nf90mpi_get_vard_1D_OneByteInt,   nf90mpi_get_vard_1D_TwoByteInt,   &
+                     nf90mpi_get_vard_1D_FourByteInt,  nf90mpi_get_vard_1D_EightByteInt, &
+                     nf90mpi_get_vard_1D_FourByteReal, nf90mpi_get_vard_1D_EightByteReal
+    module procedure nf90mpi_get_vard_2D_text,                                           &
+                     nf90mpi_get_vard_2D_OneByteInt,   nf90mpi_get_vard_2D_TwoByteInt,   &
+                     nf90mpi_get_vard_2D_FourByteInt,  nf90mpi_get_vard_2D_EightByteInt, &
+                     nf90mpi_get_vard_2D_FourByteReal, nf90mpi_get_vard_2D_EightByteReal
+    module procedure nf90mpi_get_vard_3D_text,                                           &
+                     nf90mpi_get_vard_3D_OneByteInt,   nf90mpi_get_vard_3D_TwoByteInt,   &
+                     nf90mpi_get_vard_3D_FourByteInt,  nf90mpi_get_vard_3D_EightByteInt, &
+                     nf90mpi_get_vard_3D_FourByteReal, nf90mpi_get_vard_3D_EightByteReal
+    module procedure nf90mpi_get_vard_4D_text,                                           &
+                     nf90mpi_get_vard_4D_OneByteInt,   nf90mpi_get_vard_4D_TwoByteInt,   &
+                     nf90mpi_get_vard_4D_FourByteInt,  nf90mpi_get_vard_4D_EightByteInt, &
+                     nf90mpi_get_vard_4D_FourByteReal, nf90mpi_get_vard_4D_EightByteReal
+    module procedure nf90mpi_get_vard_5D_text,                                           &
+                     nf90mpi_get_vard_5D_OneByteInt,   nf90mpi_get_vard_5D_TwoByteInt,   &
+                     nf90mpi_get_vard_5D_FourByteInt,  nf90mpi_get_vard_5D_EightByteInt, &
+                     nf90mpi_get_vard_5D_FourByteReal, nf90mpi_get_vard_5D_EightByteReal
+    module procedure nf90mpi_get_vard_6D_text,                                           &
+                     nf90mpi_get_vard_6D_OneByteInt,   nf90mpi_get_vard_6D_TwoByteInt,   &
+                     nf90mpi_get_vard_6D_FourByteInt,  nf90mpi_get_vard_6D_EightByteInt, &
+                     nf90mpi_get_vard_6D_FourByteReal, nf90mpi_get_vard_6D_EightByteReal
+    module procedure nf90mpi_get_vard_7D_text,                                           &
+                     nf90mpi_get_vard_7D_OneByteInt,   nf90mpi_get_vard_7D_TwoByteInt,   &
+                     nf90mpi_get_vard_7D_FourByteInt,  nf90mpi_get_vard_7D_EightByteInt, &
+                     nf90mpi_get_vard_7D_FourByteReal, nf90mpi_get_vard_7D_EightByteReal
+  end interface ! nf90mpi_get_vard
+
+  !
+  ! Collective APIs
+  !
+
+  ! Overloaded variable functions
+  interface nf90mpi_put_var_all
+    module procedure nf90mpi_put_var_text_all,                                                 &
+                     nf90mpi_put_var_OneByteInt_all,      nf90mpi_put_var_TwoByteInt_all,      &
+                     nf90mpi_put_var_FourByteInt_all,     nf90mpi_put_var_EightByteInt_all,    &
+                     nf90mpi_put_var_FourByteReal_all,    nf90mpi_put_var_EightByteReal_all
+    module procedure nf90mpi_put_var_1D_text_all,                                              &
+                     nf90mpi_put_var_1D_OneByteInt_all,   nf90mpi_put_var_1D_TwoByteInt_all,   &
+                     nf90mpi_put_var_1D_FourByteInt_all,  nf90mpi_put_var_1D_EightByteInt_all, &
+                     nf90mpi_put_var_1D_FourByteReal_all, nf90mpi_put_var_1D_EightByteReal_all
+    module procedure nf90mpi_put_var_2D_text_all,                                              &
+                     nf90mpi_put_var_2D_OneByteInt_all,   nf90mpi_put_var_2D_TwoByteInt_all,   &
+                     nf90mpi_put_var_2D_FourByteInt_all,  nf90mpi_put_var_2D_EightByteInt_all, &
+                     nf90mpi_put_var_2D_FourByteReal_all, nf90mpi_put_var_2D_EightByteReal_all
+    module procedure nf90mpi_put_var_3D_text_all,                                              &
+                     nf90mpi_put_var_3D_OneByteInt_all,   nf90mpi_put_var_3D_TwoByteInt_all,   &
+                     nf90mpi_put_var_3D_FourByteInt_all,  nf90mpi_put_var_3D_EightByteInt_all, &
+                     nf90mpi_put_var_3D_FourByteReal_all, nf90mpi_put_var_3D_EightByteReal_all
+    module procedure nf90mpi_put_var_4D_text_all,                                              &
+                     nf90mpi_put_var_4D_OneByteInt_all,   nf90mpi_put_var_4D_TwoByteInt_all,   &
+                     nf90mpi_put_var_4D_FourByteInt_all,  nf90mpi_put_var_4D_EightByteInt_all, &
+                     nf90mpi_put_var_4D_FourByteReal_all, nf90mpi_put_var_4D_EightByteReal_all
+    module procedure nf90mpi_put_var_5D_text_all,                                              &
+                     nf90mpi_put_var_5D_OneByteInt_all,   nf90mpi_put_var_5D_TwoByteInt_all,   &
+                     nf90mpi_put_var_5D_FourByteInt_all,  nf90mpi_put_var_5D_EightByteInt_all, &
+                     nf90mpi_put_var_5D_FourByteReal_all, nf90mpi_put_var_5D_EightByteReal_all
+    module procedure nf90mpi_put_var_6D_text_all,                                              &
+                     nf90mpi_put_var_6D_OneByteInt_all,   nf90mpi_put_var_6D_TwoByteInt_all,   &
+                     nf90mpi_put_var_6D_FourByteInt_all,  nf90mpi_put_var_6D_EightByteInt_all, &
+                     nf90mpi_put_var_6D_FourByteReal_all, nf90mpi_put_var_6D_EightByteReal_all
+    module procedure nf90mpi_put_var_7D_text_all,                                              &
+                     nf90mpi_put_var_7D_OneByteInt_all,   nf90mpi_put_var_7D_TwoByteInt_all,   &
+                     nf90mpi_put_var_7D_FourByteInt_all,  nf90mpi_put_var_7D_EightByteInt_all, &
+                     nf90mpi_put_var_7D_FourByteReal_all, nf90mpi_put_var_7D_EightByteReal_all
+  end interface ! nf90mpi_put_var_all
+
+  interface nf90mpi_get_var_all
+    module procedure nf90mpi_get_var_text_all,                                                 &
+                     nf90mpi_get_var_OneByteInt_all,      nf90mpi_get_var_TwoByteInt_all,      &
+                     nf90mpi_get_var_FourByteInt_all,     nf90mpi_get_var_EightByteInt_all,    &
+                     nf90mpi_get_var_FourByteReal_all,    nf90mpi_get_var_EightByteReal_all
+    module procedure nf90mpi_get_var_1D_text_all,                                              &
+                     nf90mpi_get_var_1D_OneByteInt_all,   nf90mpi_get_var_1D_TwoByteInt_all,   &
+                     nf90mpi_get_var_1D_FourByteInt_all,  nf90mpi_get_var_1D_EightByteInt_all, &
+                     nf90mpi_get_var_1D_FourByteReal_all, nf90mpi_get_var_1D_EightByteReal_all
+    module procedure nf90mpi_get_var_2D_text_all,                                              &
+                     nf90mpi_get_var_2D_OneByteInt_all,   nf90mpi_get_var_2D_TwoByteInt_all,   &
+                     nf90mpi_get_var_2D_FourByteInt_all,  nf90mpi_get_var_2D_EightByteInt_all, &
+                     nf90mpi_get_var_2D_FourByteReal_all, nf90mpi_get_var_2D_EightByteReal_all
+    module procedure nf90mpi_get_var_3D_text_all,                                              &
+                     nf90mpi_get_var_3D_OneByteInt_all,   nf90mpi_get_var_3D_TwoByteInt_all,   &
+                     nf90mpi_get_var_3D_FourByteInt_all,  nf90mpi_get_var_3D_EightByteInt_all, &
+                     nf90mpi_get_var_3D_FourByteReal_all, nf90mpi_get_var_3D_EightByteReal_all
+    module procedure nf90mpi_get_var_4D_text_all,                                              &
+                     nf90mpi_get_var_4D_OneByteInt_all,   nf90mpi_get_var_4D_TwoByteInt_all,   &
+                     nf90mpi_get_var_4D_FourByteInt_all,  nf90mpi_get_var_4D_EightByteInt_all, &
+                     nf90mpi_get_var_4D_FourByteReal_all, nf90mpi_get_var_4D_EightByteReal_all
+    module procedure nf90mpi_get_var_5D_text_all,                                              &
+                     nf90mpi_get_var_5D_OneByteInt_all,   nf90mpi_get_var_5D_TwoByteInt_all,   &
+                     nf90mpi_get_var_5D_FourByteInt_all,  nf90mpi_get_var_5D_EightByteInt_all, &
+                     nf90mpi_get_var_5D_FourByteReal_all, nf90mpi_get_var_5D_EightByteReal_all
+    module procedure nf90mpi_get_var_6D_text_all,                                              &
+                     nf90mpi_get_var_6D_OneByteInt_all,   nf90mpi_get_var_6D_TwoByteInt_all,   &
+                     nf90mpi_get_var_6D_FourByteInt_all,  nf90mpi_get_var_6D_EightByteInt_all, &
+                     nf90mpi_get_var_6D_FourByteReal_all, nf90mpi_get_var_6D_EightByteReal_all
+    module procedure nf90mpi_get_var_7D_text_all,                                              &
+                     nf90mpi_get_var_7D_OneByteInt_all,   nf90mpi_get_var_7D_TwoByteInt_all,   &
+                     nf90mpi_get_var_7D_FourByteInt_all,  nf90mpi_get_var_7D_EightByteInt_all, &
+                     nf90mpi_get_var_7D_FourByteReal_all, nf90mpi_get_var_7D_EightByteReal_all
+  end interface ! nf90mpi_get_var_all
+
+  ! Overloaded variable functions varn
+  interface nf90mpi_put_varn_all
+    module procedure nf90mpi_put_varn_text_all,                                                  &
+                     nf90mpi_put_varn_OneByteInt_all,   nf90mpi_put_varn_TwoByteInt_all,         &
+                     nf90mpi_put_varn_FourByteInt_all,  nf90mpi_put_varn_EightByteInt_all,       &
+                     nf90mpi_put_varn_FourByteReal_all, nf90mpi_put_varn_EightByteReal_all
+    module procedure nf90mpi_put_varn_1D_text_all,                                               &
+                     nf90mpi_put_varn_1D_OneByteInt_all,   nf90mpi_put_varn_1D_TwoByteInt_all,   &
+                     nf90mpi_put_varn_1D_FourByteInt_all,  nf90mpi_put_varn_1D_EightByteInt_all, &
+                     nf90mpi_put_varn_1D_FourByteReal_all, nf90mpi_put_varn_1D_EightByteReal_all
+    module procedure nf90mpi_put_varn_2D_text_all,                                               &
+                     nf90mpi_put_varn_2D_OneByteInt_all,   nf90mpi_put_varn_2D_TwoByteInt_all,   &
+                     nf90mpi_put_varn_2D_FourByteInt_all,  nf90mpi_put_varn_2D_EightByteInt_all, &
+                     nf90mpi_put_varn_2D_FourByteReal_all, nf90mpi_put_varn_2D_EightByteReal_all
+    module procedure nf90mpi_put_varn_3D_text_all,                                               &
+                     nf90mpi_put_varn_3D_OneByteInt_all,   nf90mpi_put_varn_3D_TwoByteInt_all,   &
+                     nf90mpi_put_varn_3D_FourByteInt_all,  nf90mpi_put_varn_3D_EightByteInt_all, &
+                     nf90mpi_put_varn_3D_FourByteReal_all, nf90mpi_put_varn_3D_EightByteReal_all
+    module procedure nf90mpi_put_varn_4D_text_all,                                               &
+                     nf90mpi_put_varn_4D_OneByteInt_all,   nf90mpi_put_varn_4D_TwoByteInt_all,   &
+                     nf90mpi_put_varn_4D_FourByteInt_all,  nf90mpi_put_varn_4D_EightByteInt_all, &
+                     nf90mpi_put_varn_4D_FourByteReal_all, nf90mpi_put_varn_4D_EightByteReal_all
+    module procedure nf90mpi_put_varn_5D_text_all,                                               &
+                     nf90mpi_put_varn_5D_OneByteInt_all,   nf90mpi_put_varn_5D_TwoByteInt_all,   &
+                     nf90mpi_put_varn_5D_FourByteInt_all,  nf90mpi_put_varn_5D_EightByteInt_all, &
+                     nf90mpi_put_varn_5D_FourByteReal_all, nf90mpi_put_varn_5D_EightByteReal_all
+    module procedure nf90mpi_put_varn_6D_text_all,                                               &
+                     nf90mpi_put_varn_6D_OneByteInt_all,   nf90mpi_put_varn_6D_TwoByteInt_all,   &
+                     nf90mpi_put_varn_6D_FourByteInt_all,  nf90mpi_put_varn_6D_EightByteInt_all, &
+                     nf90mpi_put_varn_6D_FourByteReal_all, nf90mpi_put_varn_6D_EightByteReal_all
+    module procedure nf90mpi_put_varn_7D_text_all,                                               &
+                     nf90mpi_put_varn_7D_OneByteInt_all,   nf90mpi_put_varn_7D_TwoByteInt_all,   &
+                     nf90mpi_put_varn_7D_FourByteInt_all,  nf90mpi_put_varn_7D_EightByteInt_all, &
+                     nf90mpi_put_varn_7D_FourByteReal_all, nf90mpi_put_varn_7D_EightByteReal_all
+  end interface ! nf90mpi_put_varn_all
+
+  interface nf90mpi_get_varn_all
+    module procedure nf90mpi_get_varn_text_all,                                                  &
+                     nf90mpi_get_varn_OneByteInt_all,   nf90mpi_get_varn_TwoByteInt_all,         &
+                     nf90mpi_get_varn_FourByteInt_all,  nf90mpi_get_varn_EightByteInt_all,       &
+                     nf90mpi_get_varn_FourByteReal_all, nf90mpi_get_varn_EightByteReal_all
+    module procedure nf90mpi_get_varn_1D_text_all,                                               &
+                     nf90mpi_get_varn_1D_OneByteInt_all,   nf90mpi_get_varn_1D_TwoByteInt_all,   &
+                     nf90mpi_get_varn_1D_FourByteInt_all,  nf90mpi_get_varn_1D_EightByteInt_all, &
+                     nf90mpi_get_varn_1D_FourByteReal_all, nf90mpi_get_varn_1D_EightByteReal_all
+    module procedure nf90mpi_get_varn_2D_text_all,                                               &
+                     nf90mpi_get_varn_2D_OneByteInt_all,   nf90mpi_get_varn_2D_TwoByteInt_all,   &
+                     nf90mpi_get_varn_2D_FourByteInt_all,  nf90mpi_get_varn_2D_EightByteInt_all, &
+                     nf90mpi_get_varn_2D_FourByteReal_all, nf90mpi_get_varn_2D_EightByteReal_all
+    module procedure nf90mpi_get_varn_3D_text_all,                                               &
+                     nf90mpi_get_varn_3D_OneByteInt_all,   nf90mpi_get_varn_3D_TwoByteInt_all,   &
+                     nf90mpi_get_varn_3D_FourByteInt_all,  nf90mpi_get_varn_3D_EightByteInt_all, &
+                     nf90mpi_get_varn_3D_FourByteReal_all, nf90mpi_get_varn_3D_EightByteReal_all
+    module procedure nf90mpi_get_varn_4D_text_all,                                               &
+                     nf90mpi_get_varn_4D_OneByteInt_all,   nf90mpi_get_varn_4D_TwoByteInt_all,   &
+                     nf90mpi_get_varn_4D_FourByteInt_all,  nf90mpi_get_varn_4D_EightByteInt_all, &
+                     nf90mpi_get_varn_4D_FourByteReal_all, nf90mpi_get_varn_4D_EightByteReal_all
+    module procedure nf90mpi_get_varn_5D_text_all,                                               &
+                     nf90mpi_get_varn_5D_OneByteInt_all,   nf90mpi_get_varn_5D_TwoByteInt_all,   &
+                     nf90mpi_get_varn_5D_FourByteInt_all,  nf90mpi_get_varn_5D_EightByteInt_all, &
+                     nf90mpi_get_varn_5D_FourByteReal_all, nf90mpi_get_varn_5D_EightByteReal_all
+    module procedure nf90mpi_get_varn_6D_text_all,                                               &
+                     nf90mpi_get_varn_6D_OneByteInt_all,   nf90mpi_get_varn_6D_TwoByteInt_all,   &
+                     nf90mpi_get_varn_6D_FourByteInt_all,  nf90mpi_get_varn_6D_EightByteInt_all, &
+                     nf90mpi_get_varn_6D_FourByteReal_all, nf90mpi_get_varn_6D_EightByteReal_all
+    module procedure nf90mpi_get_varn_7D_text_all,                                               &
+                     nf90mpi_get_varn_7D_OneByteInt_all,   nf90mpi_get_varn_7D_TwoByteInt_all,   &
+                     nf90mpi_get_varn_7D_FourByteInt_all,  nf90mpi_get_varn_7D_EightByteInt_all, &
+                     nf90mpi_get_varn_7D_FourByteReal_all, nf90mpi_get_varn_7D_EightByteReal_all
+  end interface ! nf90mpi_get_varn_all
+
+  ! Overloaded variable functions vard
+  ! Overloaded variable functions vard
+  interface nf90mpi_put_vard_all
+    module procedure nf90mpi_put_vard_text_all,                                                  &
+                     nf90mpi_put_vard_OneByteInt_all,      nf90mpi_put_vard_TwoByteInt_all,      &
+                     nf90mpi_put_vard_FourByteInt_all,     nf90mpi_put_vard_EightByteInt_all,    &
+                     nf90mpi_put_vard_FourByteReal_all,    nf90mpi_put_vard_EightByteReal_all
+    module procedure nf90mpi_put_vard_1D_text_all,                                               &
+                     nf90mpi_put_vard_1D_OneByteInt_all,   nf90mpi_put_vard_1D_TwoByteInt_all,   &
+                     nf90mpi_put_vard_1D_FourByteInt_all,  nf90mpi_put_vard_1D_EightByteInt_all, &
+                     nf90mpi_put_vard_1D_FourByteReal_all, nf90mpi_put_vard_1D_EightByteReal_all
+    module procedure nf90mpi_put_vard_2D_text_all,                                               &
+                     nf90mpi_put_vard_2D_OneByteInt_all,   nf90mpi_put_vard_2D_TwoByteInt_all,   &
+                     nf90mpi_put_vard_2D_FourByteInt_all,  nf90mpi_put_vard_2D_EightByteInt_all, &
+                     nf90mpi_put_vard_2D_FourByteReal_all, nf90mpi_put_vard_2D_EightByteReal_all
+    module procedure nf90mpi_put_vard_3D_text_all,                                               &
+                     nf90mpi_put_vard_3D_OneByteInt_all,   nf90mpi_put_vard_3D_TwoByteInt_all,   &
+                     nf90mpi_put_vard_3D_FourByteInt_all,  nf90mpi_put_vard_3D_EightByteInt_all, &
+                     nf90mpi_put_vard_3D_FourByteReal_all, nf90mpi_put_vard_3D_EightByteReal_all
+    module procedure nf90mpi_put_vard_4D_text_all,                                               &
+                     nf90mpi_put_vard_4D_OneByteInt_all,   nf90mpi_put_vard_4D_TwoByteInt_all,   &
+                     nf90mpi_put_vard_4D_FourByteInt_all,  nf90mpi_put_vard_4D_EightByteInt_all, &
+                     nf90mpi_put_vard_4D_FourByteReal_all, nf90mpi_put_vard_4D_EightByteReal_all
+    module procedure nf90mpi_put_vard_5D_text_all,                                               &
+                     nf90mpi_put_vard_5D_OneByteInt_all,   nf90mpi_put_vard_5D_TwoByteInt_all,   &
+                     nf90mpi_put_vard_5D_FourByteInt_all,  nf90mpi_put_vard_5D_EightByteInt_all, &
+                     nf90mpi_put_vard_5D_FourByteReal_all, nf90mpi_put_vard_5D_EightByteReal_all
+    module procedure nf90mpi_put_vard_6D_text_all,                                               &
+                     nf90mpi_put_vard_6D_OneByteInt_all,   nf90mpi_put_vard_6D_TwoByteInt_all,   &
+                     nf90mpi_put_vard_6D_FourByteInt_all,  nf90mpi_put_vard_6D_EightByteInt_all, &
+                     nf90mpi_put_vard_6D_FourByteReal_all, nf90mpi_put_vard_6D_EightByteReal_all
+    module procedure nf90mpi_put_vard_7D_text_all,                                               &
+                     nf90mpi_put_vard_7D_OneByteInt_all,   nf90mpi_put_vard_7D_TwoByteInt_all,   &
+                     nf90mpi_put_vard_7D_FourByteInt_all,  nf90mpi_put_vard_7D_EightByteInt_all, &
+                     nf90mpi_put_vard_7D_FourByteReal_all, nf90mpi_put_vard_7D_EightByteReal_all
+  end interface ! nf90mpi_put_vard_all
+
+  interface nf90mpi_get_vard_all
+    module procedure nf90mpi_get_vard_text_all,                                                  &
+                     nf90mpi_get_vard_OneByteInt_all,      nf90mpi_get_vard_TwoByteInt_all,      &
+                     nf90mpi_get_vard_FourByteInt_all,     nf90mpi_get_vard_EightByteInt_all,    &
+                     nf90mpi_get_vard_FourByteReal_all,    nf90mpi_get_vard_EightByteReal_all
+    module procedure nf90mpi_get_vard_1D_text_all,                                               &
+                     nf90mpi_get_vard_1D_OneByteInt_all,   nf90mpi_get_vard_1D_TwoByteInt_all,   &
+                     nf90mpi_get_vard_1D_FourByteInt_all,  nf90mpi_get_vard_1D_EightByteInt_all, &
+                     nf90mpi_get_vard_1D_FourByteReal_all, nf90mpi_get_vard_1D_EightByteReal_all
+    module procedure nf90mpi_get_vard_2D_text_all,                                               &
+                     nf90mpi_get_vard_2D_OneByteInt_all,   nf90mpi_get_vard_2D_TwoByteInt_all,   &
+                     nf90mpi_get_vard_2D_FourByteInt_all,  nf90mpi_get_vard_2D_EightByteInt_all, &
+                     nf90mpi_get_vard_2D_FourByteReal_all, nf90mpi_get_vard_2D_EightByteReal_all
+    module procedure nf90mpi_get_vard_3D_text_all,                                               &
+                     nf90mpi_get_vard_3D_OneByteInt_all,   nf90mpi_get_vard_3D_TwoByteInt_all,   &
+                     nf90mpi_get_vard_3D_FourByteInt_all,  nf90mpi_get_vard_3D_EightByteInt_all, &
+                     nf90mpi_get_vard_3D_FourByteReal_all, nf90mpi_get_vard_3D_EightByteReal_all
+    module procedure nf90mpi_get_vard_4D_text_all,                                               &
+                     nf90mpi_get_vard_4D_OneByteInt_all,   nf90mpi_get_vard_4D_TwoByteInt_all,   &
+                     nf90mpi_get_vard_4D_FourByteInt_all,  nf90mpi_get_vard_4D_EightByteInt_all, &
+                     nf90mpi_get_vard_4D_FourByteReal_all, nf90mpi_get_vard_4D_EightByteReal_all
+    module procedure nf90mpi_get_vard_5D_text_all,                                               &
+                     nf90mpi_get_vard_5D_OneByteInt_all,   nf90mpi_get_vard_5D_TwoByteInt_all,   &
+                     nf90mpi_get_vard_5D_FourByteInt_all,  nf90mpi_get_vard_5D_EightByteInt_all, &
+                     nf90mpi_get_vard_5D_FourByteReal_all, nf90mpi_get_vard_5D_EightByteReal_all
+    module procedure nf90mpi_get_vard_6D_text_all,                                               &
+                     nf90mpi_get_vard_6D_OneByteInt_all,   nf90mpi_get_vard_6D_TwoByteInt_all,   &
+                     nf90mpi_get_vard_6D_FourByteInt_all,  nf90mpi_get_vard_6D_EightByteInt_all, &
+                     nf90mpi_get_vard_6D_FourByteReal_all, nf90mpi_get_vard_6D_EightByteReal_all
+    module procedure nf90mpi_get_vard_7D_text_all,                                               &
+                     nf90mpi_get_vard_7D_OneByteInt_all,   nf90mpi_get_vard_7D_TwoByteInt_all,   &
+                     nf90mpi_get_vard_7D_FourByteInt_all,  nf90mpi_get_vard_7D_EightByteInt_all, &
+                     nf90mpi_get_vard_7D_FourByteReal_all, nf90mpi_get_vard_7D_EightByteReal_all
+  end interface ! nf90mpi_get_vard_all
+
+  !
+  ! Nonblocking APIs
+  !
+  interface nf90mpi_iput_var
+    module procedure nf90mpi_iput_var_text,                                              &
+                     nf90mpi_iput_var_OneByteInt,   nf90mpi_iput_var_TwoByteInt,         &
+                     nf90mpi_iput_var_FourByteInt,  nf90mpi_iput_var_EightByteInt,       &
+                     nf90mpi_iput_var_FourByteReal, nf90mpi_iput_var_EightByteReal
+    module procedure nf90mpi_iput_var_1D_text,                                           &
+                     nf90mpi_iput_var_1D_OneByteInt,   nf90mpi_iput_var_1D_TwoByteInt,   &
+                     nf90mpi_iput_var_1D_FourByteInt,  nf90mpi_iput_var_1D_EightByteInt, &
+                     nf90mpi_iput_var_1D_FourByteReal, nf90mpi_iput_var_1D_EightByteReal
+    module procedure nf90mpi_iput_var_2D_text,                                           &
+                     nf90mpi_iput_var_2D_OneByteInt,   nf90mpi_iput_var_2D_TwoByteInt,   &
+                     nf90mpi_iput_var_2D_FourByteInt,  nf90mpi_iput_var_2D_EightByteInt, &
+                     nf90mpi_iput_var_2D_FourByteReal, nf90mpi_iput_var_2D_EightByteReal
+    module procedure nf90mpi_iput_var_3D_text,                                           &
+                     nf90mpi_iput_var_3D_OneByteInt,   nf90mpi_iput_var_3D_TwoByteInt,   &
+                     nf90mpi_iput_var_3D_FourByteInt,  nf90mpi_iput_var_3D_EightByteInt, &
+                     nf90mpi_iput_var_3D_FourByteReal, nf90mpi_iput_var_3D_EightByteReal
+    module procedure nf90mpi_iput_var_4D_text,                                           &
+                     nf90mpi_iput_var_4D_OneByteInt,   nf90mpi_iput_var_4D_TwoByteInt,   &
+                     nf90mpi_iput_var_4D_FourByteInt,  nf90mpi_iput_var_4D_EightByteInt, &
+                     nf90mpi_iput_var_4D_FourByteReal, nf90mpi_iput_var_4D_EightByteReal
+    module procedure nf90mpi_iput_var_5D_text,                                           &
+                     nf90mpi_iput_var_5D_OneByteInt,   nf90mpi_iput_var_5D_TwoByteInt,   &
+                     nf90mpi_iput_var_5D_FourByteInt,  nf90mpi_iput_var_5D_EightByteInt, &
+                     nf90mpi_iput_var_5D_FourByteReal, nf90mpi_iput_var_5D_EightByteReal
+    module procedure nf90mpi_iput_var_6D_text,                                           &
+                     nf90mpi_iput_var_6D_OneByteInt,   nf90mpi_iput_var_6D_TwoByteInt,   &
+                     nf90mpi_iput_var_6D_FourByteInt,  nf90mpi_iput_var_6D_EightByteInt, &
+                     nf90mpi_iput_var_6D_FourByteReal, nf90mpi_iput_var_6D_EightByteReal
+    module procedure nf90mpi_iput_var_7D_text,                                           &
+                     nf90mpi_iput_var_7D_OneByteInt,   nf90mpi_iput_var_7D_TwoByteInt,   &
+                     nf90mpi_iput_var_7D_FourByteInt,  nf90mpi_iput_var_7D_EightByteInt, &
+                     nf90mpi_iput_var_7D_FourByteReal, nf90mpi_iput_var_7D_EightByteReal
+  end interface ! nf90mpi_iput_var
+
+  interface nf90mpi_iget_var
+    module procedure nf90mpi_iget_var_text,                                              &
+                     nf90mpi_iget_var_OneByteInt,   nf90mpi_iget_var_TwoByteInt,         &
+                     nf90mpi_iget_var_FourByteInt,  nf90mpi_iget_var_EightByteInt,       &
+                     nf90mpi_iget_var_FourByteReal, nf90mpi_iget_var_EightByteReal
+    module procedure nf90mpi_iget_var_1D_text,                                           &
+                     nf90mpi_iget_var_1D_OneByteInt,   nf90mpi_iget_var_1D_TwoByteInt,   &
+                     nf90mpi_iget_var_1D_FourByteInt,  nf90mpi_iget_var_1D_EightByteInt, &
+                     nf90mpi_iget_var_1D_FourByteReal, nf90mpi_iget_var_1D_EightByteReal
+    module procedure nf90mpi_iget_var_2D_text,                                           &
+                     nf90mpi_iget_var_2D_OneByteInt,   nf90mpi_iget_var_2D_TwoByteInt,   &
+                     nf90mpi_iget_var_2D_FourByteInt,  nf90mpi_iget_var_2D_EightByteInt, &
+                     nf90mpi_iget_var_2D_FourByteReal, nf90mpi_iget_var_2D_EightByteReal
+    module procedure nf90mpi_iget_var_3D_text,                                           &
+                     nf90mpi_iget_var_3D_OneByteInt,   nf90mpi_iget_var_3D_TwoByteInt,   &
+                     nf90mpi_iget_var_3D_FourByteInt,  nf90mpi_iget_var_3D_EightByteInt, &
+                     nf90mpi_iget_var_3D_FourByteReal, nf90mpi_iget_var_3D_EightByteReal
+    module procedure nf90mpi_iget_var_4D_text,                                           &
+                     nf90mpi_iget_var_4D_OneByteInt,   nf90mpi_iget_var_4D_TwoByteInt,   &
+                     nf90mpi_iget_var_4D_FourByteInt,  nf90mpi_iget_var_4D_EightByteInt, &
+                     nf90mpi_iget_var_4D_FourByteReal, nf90mpi_iget_var_4D_EightByteReal
+    module procedure nf90mpi_iget_var_5D_text,                                           &
+                     nf90mpi_iget_var_5D_OneByteInt,   nf90mpi_iget_var_5D_TwoByteInt,   &
+                     nf90mpi_iget_var_5D_FourByteInt,  nf90mpi_iget_var_5D_EightByteInt, &
+                     nf90mpi_iget_var_5D_FourByteReal, nf90mpi_iget_var_5D_EightByteReal
+    module procedure nf90mpi_iget_var_6D_text,                                           &
+                     nf90mpi_iget_var_6D_OneByteInt,   nf90mpi_iget_var_6D_TwoByteInt,   &
+                     nf90mpi_iget_var_6D_FourByteInt,  nf90mpi_iget_var_6D_EightByteInt, &
+                     nf90mpi_iget_var_6D_FourByteReal, nf90mpi_iget_var_6D_EightByteReal
+    module procedure nf90mpi_iget_var_7D_text,                                           &
+                     nf90mpi_iget_var_7D_OneByteInt,   nf90mpi_iget_var_7D_TwoByteInt,   &
+                     nf90mpi_iget_var_7D_FourByteInt,  nf90mpi_iget_var_7D_EightByteInt, &
+                     nf90mpi_iget_var_7D_FourByteReal, nf90mpi_iget_var_7D_EightByteReal
+  end interface ! nf90mpi_iget_var
+
+  interface nf90mpi_iput_varn
+    module procedure nf90mpi_iput_varn_text,                                               &
+                     nf90mpi_iput_varn_OneByteInt,   nf90mpi_iput_varn_TwoByteInt,         &
+                     nf90mpi_iput_varn_FourByteInt,  nf90mpi_iput_varn_EightByteInt,       &
+                     nf90mpi_iput_varn_FourByteReal, nf90mpi_iput_varn_EightByteReal
+    module procedure nf90mpi_iput_varn_1D_text,                                            &
+                     nf90mpi_iput_varn_1D_OneByteInt,   nf90mpi_iput_varn_1D_TwoByteInt,   &
+                     nf90mpi_iput_varn_1D_FourByteInt,  nf90mpi_iput_varn_1D_EightByteInt, &
+                     nf90mpi_iput_varn_1D_FourByteReal, nf90mpi_iput_varn_1D_EightByteReal
+    module procedure nf90mpi_iput_varn_2D_text,                                            &
+                     nf90mpi_iput_varn_2D_OneByteInt,   nf90mpi_iput_varn_2D_TwoByteInt,   &
+                     nf90mpi_iput_varn_2D_FourByteInt,  nf90mpi_iput_varn_2D_EightByteInt, &
+                     nf90mpi_iput_varn_2D_FourByteReal, nf90mpi_iput_varn_2D_EightByteReal
+    module procedure nf90mpi_iput_varn_3D_text,                                            &
+                     nf90mpi_iput_varn_3D_OneByteInt,   nf90mpi_iput_varn_3D_TwoByteInt,   &
+                     nf90mpi_iput_varn_3D_FourByteInt,  nf90mpi_iput_varn_3D_EightByteInt, &
+                     nf90mpi_iput_varn_3D_FourByteReal, nf90mpi_iput_varn_3D_EightByteReal
+    module procedure nf90mpi_iput_varn_4D_text,                                            &
+                     nf90mpi_iput_varn_4D_OneByteInt,   nf90mpi_iput_varn_4D_TwoByteInt,   &
+                     nf90mpi_iput_varn_4D_FourByteInt,  nf90mpi_iput_varn_4D_EightByteInt, &
+                     nf90mpi_iput_varn_4D_FourByteReal, nf90mpi_iput_varn_4D_EightByteReal
+    module procedure nf90mpi_iput_varn_5D_text,                                            &
+                     nf90mpi_iput_varn_5D_OneByteInt,   nf90mpi_iput_varn_5D_TwoByteInt,   &
+                     nf90mpi_iput_varn_5D_FourByteInt,  nf90mpi_iput_varn_5D_EightByteInt, &
+                     nf90mpi_iput_varn_5D_FourByteReal, nf90mpi_iput_varn_5D_EightByteReal
+    module procedure nf90mpi_iput_varn_6D_text,                                            &
+                     nf90mpi_iput_varn_6D_OneByteInt,   nf90mpi_iput_varn_6D_TwoByteInt,   &
+                     nf90mpi_iput_varn_6D_FourByteInt,  nf90mpi_iput_varn_6D_EightByteInt, &
+                     nf90mpi_iput_varn_6D_FourByteReal, nf90mpi_iput_varn_6D_EightByteReal
+    module procedure nf90mpi_iput_varn_7D_text,                                            &
+                     nf90mpi_iput_varn_7D_OneByteInt,   nf90mpi_iput_varn_7D_TwoByteInt,   &
+                     nf90mpi_iput_varn_7D_FourByteInt,  nf90mpi_iput_varn_7D_EightByteInt, &
+                     nf90mpi_iput_varn_7D_FourByteReal, nf90mpi_iput_varn_7D_EightByteReal
+  end interface ! nf90mpi_iput_varn
+
+  interface nf90mpi_iget_varn
+    module procedure nf90mpi_iget_varn_text,                                               &
+                     nf90mpi_iget_varn_OneByteInt,   nf90mpi_iget_varn_TwoByteInt,         &
+                     nf90mpi_iget_varn_FourByteInt,  nf90mpi_iget_varn_EightByteInt,       &
+                     nf90mpi_iget_varn_FourByteReal, nf90mpi_iget_varn_EightByteReal
+    module procedure nf90mpi_iget_varn_1D_text,                                            &
+                     nf90mpi_iget_varn_1D_OneByteInt,   nf90mpi_iget_varn_1D_TwoByteInt,   &
+                     nf90mpi_iget_varn_1D_FourByteInt,  nf90mpi_iget_varn_1D_EightByteInt, &
+                     nf90mpi_iget_varn_1D_FourByteReal, nf90mpi_iget_varn_1D_EightByteReal
+    module procedure nf90mpi_iget_varn_2D_text,                                            &
+                     nf90mpi_iget_varn_2D_OneByteInt,   nf90mpi_iget_varn_2D_TwoByteInt,   &
+                     nf90mpi_iget_varn_2D_FourByteInt,  nf90mpi_iget_varn_2D_EightByteInt, &
+                     nf90mpi_iget_varn_2D_FourByteReal, nf90mpi_iget_varn_2D_EightByteReal
+    module procedure nf90mpi_iget_varn_3D_text,                                            &
+                     nf90mpi_iget_varn_3D_OneByteInt,   nf90mpi_iget_varn_3D_TwoByteInt,   &
+                     nf90mpi_iget_varn_3D_FourByteInt,  nf90mpi_iget_varn_3D_EightByteInt, &
+                     nf90mpi_iget_varn_3D_FourByteReal, nf90mpi_iget_varn_3D_EightByteReal
+    module procedure nf90mpi_iget_varn_4D_text,                                            &
+                     nf90mpi_iget_varn_4D_OneByteInt,   nf90mpi_iget_varn_4D_TwoByteInt,   &
+                     nf90mpi_iget_varn_4D_FourByteInt,  nf90mpi_iget_varn_4D_EightByteInt, &
+                     nf90mpi_iget_varn_4D_FourByteReal, nf90mpi_iget_varn_4D_EightByteReal
+    module procedure nf90mpi_iget_varn_5D_text,                                            &
+                     nf90mpi_iget_varn_5D_OneByteInt,   nf90mpi_iget_varn_5D_TwoByteInt,   &
+                     nf90mpi_iget_varn_5D_FourByteInt,  nf90mpi_iget_varn_5D_EightByteInt, &
+                     nf90mpi_iget_varn_5D_FourByteReal, nf90mpi_iget_varn_5D_EightByteReal
+    module procedure nf90mpi_iget_varn_6D_text,                                            &
+                     nf90mpi_iget_varn_6D_OneByteInt,   nf90mpi_iget_varn_6D_TwoByteInt,   &
+                     nf90mpi_iget_varn_6D_FourByteInt,  nf90mpi_iget_varn_6D_EightByteInt, &
+                     nf90mpi_iget_varn_6D_FourByteReal, nf90mpi_iget_varn_6D_EightByteReal
+    module procedure nf90mpi_iget_varn_7D_text,                                            &
+                     nf90mpi_iget_varn_7D_OneByteInt,   nf90mpi_iget_varn_7D_TwoByteInt,   &
+                     nf90mpi_iget_varn_7D_FourByteInt,  nf90mpi_iget_varn_7D_EightByteInt, &
+                     nf90mpi_iget_varn_7D_FourByteReal, nf90mpi_iget_varn_7D_EightByteReal
+  end interface ! nf90mpi_iget_varn
+
+  interface nf90mpi_bput_var
+    module procedure nf90mpi_bput_var_text,                                              &
+                     nf90mpi_bput_var_OneByteInt,   nf90mpi_bput_var_TwoByteInt,         &
+                     nf90mpi_bput_var_FourByteInt,  nf90mpi_bput_var_EightByteInt,       &
+                     nf90mpi_bput_var_FourByteReal, nf90mpi_bput_var_EightByteReal
+    module procedure nf90mpi_bput_var_1D_text,                                           &
+                     nf90mpi_bput_var_1D_OneByteInt,   nf90mpi_bput_var_1D_TwoByteInt,   &
+                     nf90mpi_bput_var_1D_FourByteInt,  nf90mpi_bput_var_1D_EightByteInt, &
+                     nf90mpi_bput_var_1D_FourByteReal, nf90mpi_bput_var_1D_EightByteReal
+    module procedure nf90mpi_bput_var_2D_text,                                           &
+                     nf90mpi_bput_var_2D_OneByteInt,   nf90mpi_bput_var_2D_TwoByteInt,   &
+                     nf90mpi_bput_var_2D_FourByteInt,  nf90mpi_bput_var_2D_EightByteInt, &
+                     nf90mpi_bput_var_2D_FourByteReal, nf90mpi_bput_var_2D_EightByteReal
+    module procedure nf90mpi_bput_var_3D_text,                                           &
+                     nf90mpi_bput_var_3D_OneByteInt,   nf90mpi_bput_var_3D_TwoByteInt,   &
+                     nf90mpi_bput_var_3D_FourByteInt,  nf90mpi_bput_var_3D_EightByteInt, &
+                     nf90mpi_bput_var_3D_FourByteReal, nf90mpi_bput_var_3D_EightByteReal
+    module procedure nf90mpi_bput_var_4D_text,                                           &
+                     nf90mpi_bput_var_4D_OneByteInt,   nf90mpi_bput_var_4D_TwoByteInt,   &
+                     nf90mpi_bput_var_4D_FourByteInt,  nf90mpi_bput_var_4D_EightByteInt, &
+                     nf90mpi_bput_var_4D_FourByteReal, nf90mpi_bput_var_4D_EightByteReal
+    module procedure nf90mpi_bput_var_5D_text,                                           &
+                     nf90mpi_bput_var_5D_OneByteInt,   nf90mpi_bput_var_5D_TwoByteInt,   &
+                     nf90mpi_bput_var_5D_FourByteInt,  nf90mpi_bput_var_5D_EightByteInt, &
+                     nf90mpi_bput_var_5D_FourByteReal, nf90mpi_bput_var_5D_EightByteReal
+    module procedure nf90mpi_bput_var_6D_text,                                           &
+                     nf90mpi_bput_var_6D_OneByteInt,   nf90mpi_bput_var_6D_TwoByteInt,   &
+                     nf90mpi_bput_var_6D_FourByteInt,  nf90mpi_bput_var_6D_EightByteInt, &
+                     nf90mpi_bput_var_6D_FourByteReal, nf90mpi_bput_var_6D_EightByteReal
+    module procedure nf90mpi_bput_var_7D_text,                                           &
+                     nf90mpi_bput_var_7D_OneByteInt,   nf90mpi_bput_var_7D_TwoByteInt,   &
+                     nf90mpi_bput_var_7D_FourByteInt,  nf90mpi_bput_var_7D_EightByteInt, &
+                     nf90mpi_bput_var_7D_FourByteReal, nf90mpi_bput_var_7D_EightByteReal
+  end interface ! nf90mpi_bput_var
+
+  interface nf90mpi_bput_varn
+    module procedure nf90mpi_bput_varn_text,                                               &
+                     nf90mpi_bput_varn_OneByteInt,   nf90mpi_bput_varn_TwoByteInt,         &
+                     nf90mpi_bput_varn_FourByteInt,  nf90mpi_bput_varn_EightByteInt,       &
+                     nf90mpi_bput_varn_FourByteReal, nf90mpi_bput_varn_EightByteReal
+    module procedure nf90mpi_bput_varn_1D_text,                                            &
+                     nf90mpi_bput_varn_1D_OneByteInt,   nf90mpi_bput_varn_1D_TwoByteInt,   &
+                     nf90mpi_bput_varn_1D_FourByteInt,  nf90mpi_bput_varn_1D_EightByteInt, &
+                     nf90mpi_bput_varn_1D_FourByteReal, nf90mpi_bput_varn_1D_EightByteReal
+    module procedure nf90mpi_bput_varn_2D_text,                                            &
+                     nf90mpi_bput_varn_2D_OneByteInt,   nf90mpi_bput_varn_2D_TwoByteInt,   &
+                     nf90mpi_bput_varn_2D_FourByteInt,  nf90mpi_bput_varn_2D_EightByteInt, &
+                     nf90mpi_bput_varn_2D_FourByteReal, nf90mpi_bput_varn_2D_EightByteReal
+    module procedure nf90mpi_bput_varn_3D_text,                                            &
+                     nf90mpi_bput_varn_3D_OneByteInt,   nf90mpi_bput_varn_3D_TwoByteInt,   &
+                     nf90mpi_bput_varn_3D_FourByteInt,  nf90mpi_bput_varn_3D_EightByteInt, &
+                     nf90mpi_bput_varn_3D_FourByteReal, nf90mpi_bput_varn_3D_EightByteReal
+    module procedure nf90mpi_bput_varn_4D_text,                                            &
+                     nf90mpi_bput_varn_4D_OneByteInt,   nf90mpi_bput_varn_4D_TwoByteInt,   &
+                     nf90mpi_bput_varn_4D_FourByteInt,  nf90mpi_bput_varn_4D_EightByteInt, &
+                     nf90mpi_bput_varn_4D_FourByteReal, nf90mpi_bput_varn_4D_EightByteReal
+    module procedure nf90mpi_bput_varn_5D_text,                                            &
+                     nf90mpi_bput_varn_5D_OneByteInt,   nf90mpi_bput_varn_5D_TwoByteInt,   &
+                     nf90mpi_bput_varn_5D_FourByteInt,  nf90mpi_bput_varn_5D_EightByteInt, &
+                     nf90mpi_bput_varn_5D_FourByteReal, nf90mpi_bput_varn_5D_EightByteReal
+    module procedure nf90mpi_bput_varn_6D_text,                                            &
+                     nf90mpi_bput_varn_6D_OneByteInt,   nf90mpi_bput_varn_6D_TwoByteInt,   &
+                     nf90mpi_bput_varn_6D_FourByteInt,  nf90mpi_bput_varn_6D_EightByteInt, &
+                     nf90mpi_bput_varn_6D_FourByteReal, nf90mpi_bput_varn_6D_EightByteReal
+    module procedure nf90mpi_bput_varn_7D_text,                                            &
+                     nf90mpi_bput_varn_7D_OneByteInt,   nf90mpi_bput_varn_7D_TwoByteInt,   &
+                     nf90mpi_bput_varn_7D_FourByteInt,  nf90mpi_bput_varn_7D_EightByteInt, &
+                     nf90mpi_bput_varn_7D_FourByteReal, nf90mpi_bput_varn_7D_EightByteReal
+  end interface ! nf90mpi_bput_varn
+
diff --git a/src/libf90/pnetcdf.f90 b/src/libf90/pnetcdf.f90
new file mode 100644
index 0000000..3b1775c
--- /dev/null
+++ b/src/libf90/pnetcdf.f90
@@ -0,0 +1,40 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: pnetcdf.f90 1816 2014-10-11 04:19:56Z wkliao $
+!
+! This file is taken from netcdf.f90 with changes for PnetCDF use
+!
+!
+ module pnetcdf
+  use mpi, only: MPI_OFFSET_KIND
+
+  implicit none
+  private
+
+  integer, parameter ::   OneByteInt = selected_int_kind(2), &
+                          TwoByteInt = selected_int_kind(4), &
+                         FourByteInt = selected_int_kind(9), &
+                        EightByteInt = selected_int_kind(18)
+
+  integer, parameter ::                                          &
+                        FourByteReal = selected_real_kind(P =  6, R =  37), &
+                       EightByteReal = selected_real_kind(P = 13, R = 307)
+
+  include "nfmpi_constants.f90"
+  include "nf90_constants.f90"
+  include "api.f90"
+  include "overloads.f90"
+  include "visibility.f90"
+
+contains
+  include "file.f90"
+  include "dims.f90"
+  include "attributes.f90"
+  include "variables.f90"
+  include "getput_text.f90"
+  include "getput_var.f90"
+  include "getput_varn.f90"
+  include "getput_vard.f90"
+end module pnetcdf
diff --git a/src/libf90/variables.f90 b/src/libf90/variables.f90
new file mode 100644
index 0000000..b6a520f
--- /dev/null
+++ b/src/libf90/variables.f90
@@ -0,0 +1,229 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: variables.f90 2012 2015-02-16 05:52:44Z wkliao $
+!
+! This file is taken from netcdf_variables.f90 with changes for PnetCDF use
+!  
+!
+
+  ! ----- 
+  ! Variable definitions and inquiry
+  ! ----- 
+  function nf90mpi_def_var_Scalar(ncid, name, xtype, varid)
+    integer,               intent( in) :: ncid
+    character (len = *),   intent( in) :: name
+    integer,               intent( in) :: xtype
+    integer,               intent(out) :: varid
+    integer                            :: nf90mpi_def_var_Scalar
+    
+    ! Dummy - shouldn't get used
+    integer, dimension(1) :: dimids
+    
+    nf90mpi_def_var_Scalar = nfmpi_def_var(ncid, name, xtype, 0, dimids, varid)
+  end function nf90mpi_def_var_Scalar
+  ! ----- 
+  function nf90mpi_def_var_oneDim(ncid, name, xtype, dimids, varid)
+    integer,               intent( in) :: ncid
+    character (len = *),   intent( in) :: name
+    integer,               intent( in) :: xtype
+    integer,               intent( in) :: dimids
+    integer,               intent(out) :: varid
+    integer                            :: nf90mpi_def_var_oneDim
+    
+    integer, dimension(1) :: dimidsA
+    dimidsA(1) = dimids
+    nf90mpi_def_var_oneDim = nfmpi_def_var(ncid, name, xtype, 1, dimidsA, varid)
+  end function nf90mpi_def_var_oneDim
+  ! ----- 
+  function nf90mpi_def_var_ManyDims(ncid, name, xtype, dimids, varid)
+    integer,               intent( in) :: ncid
+    character (len = *),   intent( in) :: name
+    integer,               intent( in) :: xtype
+    integer, dimension(:), intent( in) :: dimids
+    integer,               intent(out) :: varid
+    integer                            :: nf90mpi_def_var_ManyDims
+    
+    nf90mpi_def_var_ManyDims = nfmpi_def_var(ncid, name, xtype, size(dimids), dimids, varid)
+  end function nf90mpi_def_var_ManyDims
+  ! ----- 
+  function nf90mpi_inq_varid(ncid, name, varid)
+    integer,             intent( in) :: ncid
+    character (len = *), intent( in) :: name
+    integer,             intent(out) :: varid
+    integer                          :: nf90mpi_inq_varid
+    
+    nf90mpi_inq_varid = nfmpi_inq_varid(ncid, name, varid)
+  end function nf90mpi_inq_varid
+  ! ----- 
+  function nf90mpi_inquire_variable(ncid, varid, name, xtype, ndims, dimids, nAtts)
+    integer,                         intent( in) :: ncid, varid
+    character (len = *),   optional, intent(out) :: name
+    integer,               optional, intent(out) :: xtype, ndims 
+    integer, dimension(:), optional, intent(out) :: dimids
+    integer,               optional, intent(out) :: nAtts
+    integer                                      :: nf90mpi_inquire_variable
+    
+    ! Local variables
+    character (len = nf90_max_name)       :: varName
+    integer                               :: externalType, numDimensions
+    integer, dimension(nf90_max_var_dims) :: dimensionIDs
+    integer                               :: numAttributes
+    
+    nf90mpi_inquire_variable = nfmpi_inq_var(ncid, varid, varName, externalType, &
+                                       numDimensions, dimensionIDs, numAttributes)
+    if (nf90mpi_inquire_variable == nf90_noerr) then
+        if(present(name))   name                   = trim(varName)
+        if(present(xtype))  xtype                  = externalType
+        if(present(ndims))  ndims                  = numDimensions
+        if(present(dimids)) then
+            if (size(dimids) .ge. numDimensions) then
+                dimids(:numDimensions) = dimensionIDs(:numDimensions)
+            else
+                nf90mpi_inquire_variable = nf90_einval
+            endif
+        endif
+        if(present(nAtts))  nAtts                  = numAttributes
+    endif
+  end function nf90mpi_inquire_variable
+  ! ----- 
+  function nf90mpi_rename_var(ncid, varid, newname)
+    integer,             intent( in) :: ncid, varid
+    character (len = *), intent( in) :: newname
+    integer                          :: nf90mpi_rename_var
+    
+    nf90mpi_rename_var = nfmpi_rename_var(ncid, varid, newname)
+  end function nf90mpi_rename_var
+  ! ----- 
+  ! nf90mpi_def_var_fill
+  ! ----- 
+  function nf90mpi_def_var_fill_text(ncid, varid, no_fill, fill_value)
+    integer,             intent( in) :: ncid, varid, no_fill
+    character,           intent( in) :: fill_value
+    integer                          :: nf90mpi_def_var_fill_text
+    
+    nf90mpi_def_var_fill_text = nfmpi_def_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_def_var_fill_text
+  ! ----- 
+  function nf90mpi_def_var_fill_OneByteInt(ncid, varid, no_fill, fill_value)
+    integer,                  intent( in) :: ncid, varid, no_fill
+    integer(kind=OneByteInt), intent( in) :: fill_value
+    integer                               :: nf90mpi_def_var_fill_OneByteInt
+    
+    nf90mpi_def_var_fill_OneByteInt = nfmpi_def_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_def_var_fill_OneByteInt
+  ! ----- 
+  function nf90mpi_def_var_fill_TwoByteInt(ncid, varid, no_fill, fill_value)
+    integer,                  intent( in) :: ncid, varid, no_fill
+    integer(kind=TwoByteInt), intent( in) :: fill_value
+    integer                               :: nf90mpi_def_var_fill_TwoByteInt
+    
+    nf90mpi_def_var_fill_TwoByteInt = nfmpi_def_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_def_var_fill_TwoByteInt
+  ! ----- 
+  function nf90mpi_def_var_fill_FourByteInt(ncid, varid, no_fill, fill_value)
+    integer,                   intent( in) :: ncid, varid, no_fill
+    integer(kind=FourByteInt), intent( in) :: fill_value
+    integer                                :: nf90mpi_def_var_fill_FourByteInt
+    
+    nf90mpi_def_var_fill_FourByteInt = nfmpi_def_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_def_var_fill_FourByteInt
+  ! ----- 
+  function nf90mpi_def_var_fill_EightByteInt(ncid, varid, no_fill, fill_value)
+    integer,                    intent( in) :: ncid, varid, no_fill
+    integer(kind=EightByteInt), intent( in) :: fill_value
+    integer                                 :: nf90mpi_def_var_fill_EightByteInt
+    
+    nf90mpi_def_var_fill_EightByteInt = nfmpi_def_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_def_var_fill_EightByteInt
+  ! ----- 
+  function nf90mpi_def_var_fill_FourByteReal(ncid, varid, no_fill, fill_value)
+    integer,                 intent( in) :: ncid, varid, no_fill
+    real(kind=FourByteReal), intent( in) :: fill_value
+    integer                              :: nf90mpi_def_var_fill_FourByteReal
+    
+    nf90mpi_def_var_fill_FourByteReal = nfmpi_def_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_def_var_fill_FourByteReal
+  ! ----- 
+  function nf90mpi_def_var_fill_EightByteReal(ncid, varid, no_fill, fill_value)
+    integer,                  intent( in) :: ncid, varid, no_fill
+    real(kind=EightByteReal), intent( in) :: fill_value
+    integer                               :: nf90mpi_def_var_fill_EightByteReal
+    
+    nf90mpi_def_var_fill_EightByteReal = nfmpi_def_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_def_var_fill_EightByteReal
+  ! ----- 
+  ! nf90mpi_inq_var_fill
+  ! ----- 
+  function nf90mpi_inq_var_fill_text(ncid, varid, no_fill, fill_value)
+    integer,             intent( in) :: ncid, varid
+    integer,             intent(out) :: no_fill
+    character,           intent(out) :: fill_value
+    integer                          :: nf90mpi_inq_var_fill_text
+    
+    nf90mpi_inq_var_fill_text = nfmpi_inq_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_inq_var_fill_text
+  ! ----- 
+  function nf90mpi_inq_var_fill_OneByteInt(ncid, varid, no_fill, fill_value)
+    integer,                  intent( in) :: ncid, varid
+    integer,                  intent(out) :: no_fill
+    integer(kind=OneByteInt), intent(out) :: fill_value
+    integer                               :: nf90mpi_inq_var_fill_OneByteInt
+    
+    nf90mpi_inq_var_fill_OneByteInt = nfmpi_inq_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_inq_var_fill_OneByteInt
+  ! ----- 
+  function nf90mpi_inq_var_fill_TwoByteInt(ncid, varid, no_fill, fill_value)
+    integer,                  intent( in) :: ncid, varid
+    integer,                  intent(out) :: no_fill
+    integer(kind=TwoByteInt), intent(out) :: fill_value
+    integer                               :: nf90mpi_inq_var_fill_TwoByteInt
+    
+    nf90mpi_inq_var_fill_TwoByteInt = nfmpi_inq_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_inq_var_fill_TwoByteInt
+  ! ----- 
+  function nf90mpi_inq_var_fill_FourByteInt(ncid, varid, no_fill, fill_value)
+    integer,                   intent( in) :: ncid, varid
+    integer,                   intent(out) :: no_fill
+    integer(kind=FourByteInt), intent(out) :: fill_value
+    integer                                :: nf90mpi_inq_var_fill_FourByteInt
+    
+    nf90mpi_inq_var_fill_FourByteInt = nfmpi_inq_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_inq_var_fill_FourByteInt
+  ! ----- 
+  function nf90mpi_inq_var_fill_EightByteInt(ncid, varid, no_fill, fill_value)
+    integer,                    intent( in) :: ncid, varid
+    integer,                    intent(out) :: no_fill
+    integer(kind=EightByteInt), intent(out) :: fill_value
+    integer                                 :: nf90mpi_inq_var_fill_EightByteInt
+    
+    nf90mpi_inq_var_fill_EightByteInt = nfmpi_inq_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_inq_var_fill_EightByteInt
+  ! ----- 
+  function nf90mpi_inq_var_fill_FourByteReal(ncid, varid, no_fill, fill_value)
+    integer,                 intent( in) :: ncid, varid
+    integer,                 intent(out) :: no_fill
+    real(kind=FourByteReal), intent(out) :: fill_value
+    integer                              :: nf90mpi_inq_var_fill_FourByteReal
+    
+    nf90mpi_inq_var_fill_FourByteReal = nfmpi_inq_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_inq_var_fill_FourByteReal
+  ! ----- 
+  function nf90mpi_inq_var_fill_EightByteReal(ncid, varid, no_fill, fill_value)
+    integer,                  intent( in) :: ncid, varid
+    integer,                  intent(out) :: no_fill
+    real(kind=EightByteReal), intent(out) :: fill_value
+    integer                               :: nf90mpi_inq_var_fill_EightByteReal
+    
+    nf90mpi_inq_var_fill_EightByteReal = nfmpi_inq_var_fill(ncid, varid, no_fill, fill_value)
+  end function nf90mpi_inq_var_fill_EightByteReal
+  ! ----- 
+  function nf90mpi_fill_var_rec(ncid, varid, recno)
+    integer,                       intent(in) :: ncid, varid
+    integer(kind=MPI_OFFSET_KIND), intent(in) :: recno
+    integer                                   :: nf90mpi_fill_var_rec
+    
+    nf90mpi_fill_var_rec = nfmpi_fill_var_rec(ncid, varid, recno)
+  end function nf90mpi_fill_var_rec
+  ! ----- 
diff --git a/src/libf90/visibility.f90 b/src/libf90/visibility.f90
new file mode 100644
index 0000000..96362da
--- /dev/null
+++ b/src/libf90/visibility.f90
@@ -0,0 +1,617 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: visibility.f90 2013 2015-02-18 17:14:26Z wkliao $
+!
+! This file is taken from netcdf_visibility.f90 with changes for PnetCDF use
+!
+!
+
+  ! Library version, error string
+  public :: nf90mpi_inq_libvers, nf90mpi_strerror
+  
+  ! Control routines 
+  public :: nf90mpi_create,   nf90mpi_open, &
+            nf90mpi_set_fill, nf90mpi_redef, &
+            nf90mpi_enddef,   nf90mpi_sync, &
+            nf90mpi_abort,    nf90mpi_close, &
+            nf90mpi_delete,   nf90mpi_set_default_format
+            
+  ! File level inquiry
+  public :: nf90mpi_inquire,          nf90mpi_inq_striping, &
+            nf90mpi_inq_num_rec_vars, nf90mpi_inq_num_fix_vars, &
+            nf90mpi_inq_default_format
+  
+  ! Dimension routines
+  public :: nf90mpi_def_dim,    nf90mpi_inq_dimid, &
+            nf90mpi_rename_dim, nf90mpi_inquire_dimension
+  
+  ! attribute routines
+  public :: nf90mpi_copy_att,          nf90mpi_rename_att, &
+            nf90mpi_del_att,           nf90mpi_inq_attname, &
+            nf90mpi_inquire_attribute
+
+  ! overloaded functions
+  public :: nf90mpi_put_att, nf90mpi_get_att
+  
+  ! Variable routines
+  public :: nf90mpi_def_var,      nf90mpi_inq_varid, &
+            nf90mpi_rename_var,   nf90mpi_inquire_variable, & 
+            nf90mpi_def_var_fill, nf90mpi_inq_var_fill, &
+            nf90mpi_fill_var_rec
+
+  ! overloaded functions
+  ! independent APIs
+  public :: nf90mpi_put_var,  nf90mpi_get_var, &
+            nf90mpi_put_varn, nf90mpi_get_varn, &
+            nf90mpi_put_vard, nf90mpi_get_vard
+
+  ! collective APIs
+  public :: nf90mpi_put_var_all,  nf90mpi_get_var_all, &
+            nf90mpi_put_varn_all, nf90mpi_get_varn_all, &
+            nf90mpi_put_vard_all, nf90mpi_get_vard_all
+
+  ! nonblocking APIs
+  public :: nf90mpi_iput_var,         nf90mpi_iget_var, &
+            nf90mpi_iput_varn,        nf90mpi_iget_varn, &
+            nf90mpi_bput_varn,        nf90mpi_bput_var, &
+            nf90mpi_inq_nreqs,        nf90mpi_buffer_attach, &
+            nf90mpi_inq_buffer_usage, nf90mpi_buffer_detach, &
+            nf90mpi_wait,             nf90mpi_wait_all, &
+            nf90mpi_cancel,           nf90mpi_inq_buffer_size
+
+  public :: nf90mpi_begin_indep_data,    nf90mpi_end_indep_data, &
+            nf90mpi_inq_put_size,        nf90mpi_inq_get_size, &
+            nf90mpi_inq_header_size,     nf90mpi_inq_header_extent, &
+            nf90mpi_inq_varoffset,       nf90mpi_inq_file_info, &
+            nf90mpi_get_file_info,       nf90mpi_inq_malloc_size, &
+            nf90mpi_inq_malloc_max_size, nf90mpi_inq_malloc_list, &
+            nf90mpi_inq_files_opened,    nf90mpi_inq_recsize
+
+!
+! F77 APIs
+!
+
+    public :: &
+        nfmpi_inq_libvers, &
+        nfmpi_strerror, &
+        nfmpi_issyserr
+!
+! control subroutines:
+!
+    public :: &
+        nfmpi_create, &
+        nfmpi_open, &
+        nfmpi_inq_format, &
+        nfmpi_inq_file_format, &
+        nfmpi_inq_file_info, &
+        nfmpi_get_file_info, &
+        nfmpi_delete, &
+        nfmpi_enddef, &
+        nfmpi__enddef, &
+        nfmpi_redef, &
+        nfmpi_set_default_format, &
+        nfmpi_inq_default_format, &
+        nfmpi_sync, &
+        nfmpi_abort, &
+        nfmpi_close, &
+        nfmpi_set_fill
+!
+! general inquiry subroutines:
+!
+    public :: &
+        nfmpi_inq, &
+        nfmpi_inq_ndims, &
+        nfmpi_inq_nvars, &
+        nfmpi_inq_num_rec_vars, &
+        nfmpi_inq_num_fix_vars, &
+        nfmpi_inq_natts, &
+        nfmpi_inq_unlimdim, &
+        nfmpi_inq_striping
+!
+! dimension subroutines:
+!
+    public :: &
+        nfmpi_def_dim, &
+        nfmpi_inq_dimid, &
+        nfmpi_inq_dim, &
+        nfmpi_inq_dimname, &
+        nfmpi_inq_dimlen, &
+        nfmpi_rename_dim
+!
+! general attribute subroutines:
+!
+    public :: &
+        nfmpi_inq_att, &
+        nfmpi_inq_attid, &
+        nfmpi_inq_atttype, &
+        nfmpi_inq_attlen, &
+        nfmpi_inq_attname, &
+        nfmpi_copy_att, &
+        nfmpi_rename_att, &
+        nfmpi_del_att
+!
+! attribute put/get subroutines:
+!
+    integer nfmpi_put_att, nfmpi_get_att
+    external nfmpi_put_att, nfmpi_get_att
+
+    public :: &
+        nfmpi_put_att_text, &
+        nfmpi_get_att_text, &
+        nfmpi_put_att_int1, &
+        nfmpi_get_att_int1, &
+        nfmpi_put_att_int2, &
+        nfmpi_get_att_int2, &
+        nfmpi_put_att_int, &
+        nfmpi_get_att_int, &
+        nfmpi_put_att_real, &
+        nfmpi_get_att_real, &
+        nfmpi_put_att_double, &
+        nfmpi_get_att_double, &
+        nfmpi_put_att_int8, &
+        nfmpi_get_att_int8
+!
+! independent data mode subroutines:
+!
+    public :: &
+        nfmpi_begin_indep_data, &
+        nfmpi_end_indep_data
+!
+! general variable subroutines:
+!
+    public :: &
+        nfmpi_def_var, &
+        nfmpi_inq_var, &
+        nfmpi_inq_varid, &
+        nfmpi_inq_varname, &
+        nfmpi_inq_vartype, &
+        nfmpi_inq_varndims, &
+        nfmpi_inq_vardimid, &
+        nfmpi_inq_varnatts, &
+        nfmpi_rename_var, &
+        nfmpi_def_var_fill, &
+        nfmpi_inq_var_fill, &
+        nfmpi_fill_var_rec
+
+!
+! entire variable put/get subroutines:
+!
+    public :: &
+        nfmpi_put_var_text, &
+        nfmpi_get_var_text, &
+        nfmpi_get_var_text_all, &
+        nfmpi_put_var_int1, &
+        nfmpi_get_var_int1, &
+        nfmpi_get_var_int1_all, &
+        nfmpi_put_var_int2, &
+        nfmpi_get_var_int2, &
+        nfmpi_get_var_int2_all, &
+        nfmpi_put_var_int, &
+        nfmpi_get_var_int, &
+        nfmpi_get_var_int_all, &
+        nfmpi_put_var_real, &
+        nfmpi_get_var_real, &
+        nfmpi_get_var_real_all, &
+        nfmpi_put_var_double, &
+        nfmpi_get_var_double, &
+        nfmpi_get_var_double_all, &
+        nfmpi_put_var_int8, &
+        nfmpi_get_var_int8, &
+        nfmpi_get_var_int8_all
+!
+! single variable put/get subroutines:
+!
+    public :: &
+        nfmpi_put_var1_text, &
+        nfmpi_put_var1_text_all, &
+        nfmpi_get_var1_text, &
+        nfmpi_get_var1_text_all, &
+        nfmpi_put_var1_int1, &
+        nfmpi_put_var1_int1_all, &
+        nfmpi_get_var1_int1, &
+        nfmpi_get_var1_int1_all, &
+        nfmpi_put_var1_int2, &
+        nfmpi_put_var1_int2_all, &
+        nfmpi_get_var1_int2, &
+        nfmpi_get_var1_int2_all, &
+        nfmpi_put_var1_int, &
+        nfmpi_put_var1_int_all, &
+        nfmpi_get_var1_int, &
+        nfmpi_get_var1_int_all, &
+        nfmpi_put_var1_real, &
+        nfmpi_put_var1_real_all, &
+        nfmpi_get_var1_real, &
+        nfmpi_get_var1_real_all, &
+        nfmpi_put_var1_double, &
+        nfmpi_put_var1_double_all, &
+        nfmpi_get_var1_double, &
+        nfmpi_get_var1_double_all, &
+        nfmpi_put_var1_int8, &
+        nfmpi_put_var1_int8_all, &
+        nfmpi_get_var1_int8, &
+        nfmpi_get_var1_int8_all
+
+!
+! variable array put/get subroutines:
+!
+    public :: &
+        nfmpi_put_vara_text, &
+        nfmpi_put_vara_text_all, &
+        nfmpi_get_vara_text, &
+        nfmpi_get_vara_text_all, &
+        nfmpi_put_vara_int1, &
+        nfmpi_put_vara_int1_all, &
+        nfmpi_get_vara_int1, &
+        nfmpi_get_vara_int1_all, &
+        nfmpi_put_vara_int2, &
+        nfmpi_put_vara_int2_all, &
+        nfmpi_get_vara_int2, &
+        nfmpi_get_vara_int2_all, &
+        nfmpi_put_vara_int, &
+        nfmpi_put_vara_int_all, &
+        nfmpi_get_vara_int, &
+        nfmpi_get_vara_int_all, &
+        nfmpi_put_vara_real, &
+        nfmpi_put_vara_real_all, &
+        nfmpi_get_vara_real, &
+        nfmpi_get_vara_real_all, &
+        nfmpi_put_vara_double, &
+        nfmpi_put_vara_double_all, &
+        nfmpi_get_vara_double, &
+        nfmpi_get_vara_double_all, &
+        nfmpi_put_vara_int8, &
+        nfmpi_put_vara_int8_all, &
+        nfmpi_get_vara_int8, &
+        nfmpi_get_vara_int8_all
+
+!
+! strided variable put/get subroutines:
+!
+    public :: &
+        nfmpi_put_vars_text, &
+        nfmpi_put_vars_text_all, &
+        nfmpi_get_vars_text, &
+        nfmpi_get_vars_text_all, &
+        nfmpi_put_vars_int1, &
+        nfmpi_put_vars_int1_all, &
+        nfmpi_get_vars_int1, &
+        nfmpi_get_vars_int1_all, &
+        nfmpi_put_vars_int2, &
+        nfmpi_put_vars_int2_all, &
+        nfmpi_get_vars_int2, &
+        nfmpi_get_vars_int2_all, &
+        nfmpi_put_vars_int, &
+        nfmpi_put_vars_int_all, &
+        nfmpi_get_vars_int, &
+        nfmpi_get_vars_int_all, &
+        nfmpi_put_vars_real, &
+        nfmpi_put_vars_real_all, &
+        nfmpi_get_vars_real, &
+        nfmpi_get_vars_real_all, &
+        nfmpi_put_vars_double, &
+        nfmpi_put_vars_double_all, &
+        nfmpi_get_vars_double, &
+        nfmpi_get_vars_double_all, &
+        nfmpi_put_vars_int8, &
+        nfmpi_put_vars_int8_all, &
+        nfmpi_get_vars_int8, &
+        nfmpi_get_vars_int8_all
+
+!
+! mapped variable put/get subroutines:
+!
+    public :: &
+        nfmpi_put_varm_text, &
+        nfmpi_put_varm_text_all, &
+        nfmpi_get_varm_text, &
+        nfmpi_get_varm_text_all, &
+        nfmpi_put_varm_int1, &
+        nfmpi_put_varm_int1_all, &
+        nfmpi_get_varm_int1, &
+        nfmpi_get_varm_int1_all, &
+        nfmpi_put_varm_int2, &
+        nfmpi_put_varm_int2_all, &
+        nfmpi_get_varm_int2, &
+        nfmpi_get_varm_int2_all, &
+        nfmpi_put_varm_int , &
+        nfmpi_put_varm_int_all, &
+        nfmpi_get_varm_int , &
+        nfmpi_get_varm_int_all, &
+        nfmpi_put_varm_real, &
+        nfmpi_put_varm_real_all, &
+        nfmpi_get_varm_real, &
+        nfmpi_get_varm_real_all, &
+        nfmpi_put_varm_double, &
+        nfmpi_put_varm_double_all, &
+        nfmpi_get_varm_double, &
+        nfmpi_get_varm_double_all, &
+        nfmpi_put_varm_int8, &
+        nfmpi_put_varm_int8_all, &
+        nfmpi_get_varm_int8, &
+        nfmpi_get_varm_int8_all
+
+!
+! non-blocking variable array iput/iget subroutines:
+!
+
+!
+! entire variable iput/iget subroutines:
+!
+    public :: &
+        nfmpi_iput_var_text, &
+        nfmpi_iget_var_text, &
+        nfmpi_iput_var_int1, &
+        nfmpi_iget_var_int1, &
+        nfmpi_iput_var_int2, &
+        nfmpi_iget_var_int2, &
+        nfmpi_iput_var_int, &
+        nfmpi_iget_var_int, &
+        nfmpi_iput_var_real, &
+        nfmpi_iget_var_real, &
+        nfmpi_iput_var_double, &
+        nfmpi_iget_var_double, &
+        nfmpi_iput_var_int8, &
+        nfmpi_iget_var_int8
+
+!
+! single variable iput/iget subroutines:
+!
+    public :: &
+        nfmpi_iput_var1_text, &
+        nfmpi_iget_var1_text, &
+        nfmpi_iput_var1_int1, &
+        nfmpi_iget_var1_int1, &
+        nfmpi_iput_var1_int2, &
+        nfmpi_iget_var1_int2, &
+        nfmpi_iput_var1_int, &
+        nfmpi_iget_var1_int, &
+        nfmpi_iput_var1_real, &
+        nfmpi_iget_var1_real, &
+        nfmpi_iput_var1_double, &
+        nfmpi_iget_var1_double, &
+        nfmpi_iput_var1_int8, &
+        nfmpi_iget_var1_int8
+
+!
+! variable array iput/iget subroutines:
+!
+    public :: &
+        nfmpi_iput_vara_text, &
+        nfmpi_iget_vara_text, &
+        nfmpi_iput_vara_int1, &
+        nfmpi_iget_vara_int1, &
+        nfmpi_iput_vara_int2, &
+        nfmpi_iget_vara_int2, &
+        nfmpi_iput_vara_int, &
+        nfmpi_iget_vara_int, &
+        nfmpi_iput_vara_real, &
+        nfmpi_iget_vara_real, &
+        nfmpi_iput_vara_double, &
+        nfmpi_iget_vara_double, &
+        nfmpi_iput_vara_int8, &
+        nfmpi_iget_vara_int8
+
+!
+! strided variable iput/iget subroutines:
+!
+    public :: &
+        nfmpi_iput_vars_text, &
+        nfmpi_iget_vars_text, &
+        nfmpi_iput_vars_int1, &
+        nfmpi_iget_vars_int1, &
+        nfmpi_iput_vars_int2, &
+        nfmpi_iget_vars_int2, &
+        nfmpi_iput_vars_int, &
+        nfmpi_iget_vars_int, &
+        nfmpi_iput_vars_real, &
+        nfmpi_iget_vars_real, &
+        nfmpi_iput_vars_double, &
+        nfmpi_iget_vars_double, &
+        nfmpi_iput_vars_int8, &
+        nfmpi_iget_vars_int8
+
+!
+! mapped variable iput/iget subroutines:
+!
+    public :: &
+        nfmpi_iput_varm_text, &
+        nfmpi_iget_varm_text, &
+        nfmpi_iput_varm_int1, &
+        nfmpi_iget_varm_int1, &
+        nfmpi_iput_varm_int2, &
+        nfmpi_iget_varm_int2, &
+        nfmpi_iput_varm_int , &
+        nfmpi_iget_varm_int , &
+        nfmpi_iput_varm_real, &
+        nfmpi_iget_varm_real, &
+        nfmpi_iput_varm_double, &
+        nfmpi_iget_varm_double, &
+        nfmpi_iput_varm_int8, &
+        nfmpi_iget_varm_int8
+
+!
+! Begin buffered put non-blocking subroutines:
+!
+    public :: &
+        nfmpi_bput_var_text, &
+        nfmpi_bput_var_int1, &
+        nfmpi_bput_var_int2, &
+        nfmpi_bput_var_int, &
+        nfmpi_bput_var_real, &
+        nfmpi_bput_var_double, &
+        nfmpi_bput_var_int8, &
+        nfmpi_bput_var1_text, &
+        nfmpi_bput_var1_int1, &
+        nfmpi_bput_var1_int2, &
+        nfmpi_bput_var1_int, &
+        nfmpi_bput_var1_real, &
+        nfmpi_bput_var1_double, &
+        nfmpi_bput_var1_int8, &
+        nfmpi_bput_vara_text, &
+        nfmpi_bput_vara_int1, &
+        nfmpi_bput_vara_int2, &
+        nfmpi_bput_vara_int, &
+        nfmpi_bput_vara_real, &
+        nfmpi_bput_vara_double, &
+        nfmpi_bput_vara_int8, &
+        nfmpi_bput_vars_text, &
+        nfmpi_bput_vars_int1, &
+        nfmpi_bput_vars_int2, &
+        nfmpi_bput_vars_int, &
+        nfmpi_bput_vars_real, &
+        nfmpi_bput_vars_double, &
+        nfmpi_bput_vars_int8, &
+        nfmpi_bput_varm_text, &
+        nfmpi_bput_varm_int1, &
+        nfmpi_bput_varm_int2, &
+        nfmpi_bput_varm_int , &
+        nfmpi_bput_varm_real, &
+        nfmpi_bput_varm_double, &
+        nfmpi_bput_varm_int8, &
+        nfmpi_buffer_attach, &
+        nfmpi_buffer_detach, &
+        nfmpi_inq_buffer_usage, &
+        nfmpi_inq_buffer_size
+
+!
+! End buffered put non-blocking subroutines:
+!
+    public :: &
+        nfmpi_wait, &
+        nfmpi_wait_all, &
+        nfmpi_cancel, &
+        nfmpi_inq_put_size, &
+        nfmpi_inq_get_size, &
+        nfmpi_inq_header_size, &
+        nfmpi_inq_header_extent, &
+        nfmpi_inq_varoffset, &
+        nfmpi_inq_nreqs, &
+        nfmpi_inq_malloc_size, &
+        nfmpi_inq_malloc_max_size, &
+        nfmpi_inq_malloc_list, &
+        nfmpi_inq_files_opened, &
+        nfmpi_inq_recsize
+
+!
+! Begin of varn subroutines:
+!
+    public :: &
+        nfmpi_get_varn_text, &
+        nfmpi_get_varn_int1, &
+        nfmpi_get_varn_int2, &
+        nfmpi_get_varn_int, &
+        nfmpi_get_varn_real, &
+        nfmpi_get_varn_double, &
+        nfmpi_get_varn_int8, &
+        nfmpi_get_varn_text_all, &
+        nfmpi_get_varn_int1_all, &
+        nfmpi_get_varn_int2_all, &
+        nfmpi_get_varn_int_all, &
+        nfmpi_get_varn_real_all, &
+        nfmpi_get_varn_double_all, &
+        nfmpi_get_varn_int8_all, &
+        nfmpi_put_varn_text, &
+        nfmpi_put_varn_int1, &
+        nfmpi_put_varn_int2, &
+        nfmpi_put_varn_int, &
+        nfmpi_put_varn_real, &
+        nfmpi_put_varn_double, &
+        nfmpi_put_varn_int8, &
+        nfmpi_put_varn_text_all, &
+        nfmpi_put_varn_int1_all, &
+        nfmpi_put_varn_int2_all, &
+        nfmpi_put_varn_int_all, &
+        nfmpi_put_varn_real_all, &
+        nfmpi_put_varn_double_all, &
+        nfmpi_put_varn_int8_all, &
+        nfmpi_iget_varn_text, &
+        nfmpi_iget_varn_int1, &
+        nfmpi_iget_varn_int2, &
+        nfmpi_iget_varn_int, &
+        nfmpi_iget_varn_real, &
+        nfmpi_iget_varn_double, &
+        nfmpi_iget_varn_int8, &
+        nfmpi_iput_varn_text, &
+        nfmpi_iput_varn_int1, &
+        nfmpi_iput_varn_int2, &
+        nfmpi_iput_varn_int, &
+        nfmpi_iput_varn_real, &
+        nfmpi_iput_varn_double, &
+        nfmpi_iput_varn_int8, &
+        nfmpi_bput_varn_text, &
+        nfmpi_bput_varn_int1, &
+        nfmpi_bput_varn_int2, &
+        nfmpi_bput_varn_int, &
+        nfmpi_bput_varn_real, &
+        nfmpi_bput_varn_double, &
+        nfmpi_bput_varn_int8
+
+!
+! End of varn subroutines:
+!
+
+! PnetCDF flexible APIs
+      public :: &
+          nfmpi_put_var, &
+          nfmpi_put_var1, &
+          nfmpi_put_vara, &
+          nfmpi_put_vars, &
+          nfmpi_put_varm, &
+          nfmpi_get_var, &
+          nfmpi_get_var1, &
+          nfmpi_get_vara, &
+          nfmpi_get_vars, &
+          nfmpi_get_varm
+
+!         nfmpi_put_var_all
+! collective put an entire variable does not make sense
+!
+
+      public :: &
+          nfmpi_put_var1_all, &
+          nfmpi_put_vara_all, &
+          nfmpi_put_vars_all, &
+          nfmpi_put_varm_all, &
+          nfmpi_get_var_all, &
+          nfmpi_get_var1_all, &
+          nfmpi_get_vara_all, &
+          nfmpi_get_vars_all, &
+          nfmpi_get_varm_all, &
+          nfmpi_iput_var, &
+          nfmpi_iput_var1, &
+          nfmpi_iput_vara, &
+          nfmpi_iput_vars, &
+          nfmpi_iput_varm, &
+          nfmpi_iget_var, &
+          nfmpi_iget_var1, &
+          nfmpi_iget_vara, &
+          nfmpi_iget_vars, &
+          nfmpi_iget_varm, &
+          nfmpi_bput_var, &
+          nfmpi_bput_var1, &
+          nfmpi_bput_vara, &
+          nfmpi_bput_vars, &
+          nfmpi_bput_varm, &
+          nfmpi_get_varn, &
+          nfmpi_put_varn, &
+          nfmpi_get_varn_all, &
+          nfmpi_put_varn_all, &
+          nfmpi_iget_varn, &
+          nfmpi_iput_varn, &
+          nfmpi_bput_varn
+
+!
+! Begin of vard subroutines:
+!
+    public :: &
+        nfmpi_get_vard, &
+        nfmpi_get_vard_all, &
+        nfmpi_put_vard, &
+        nfmpi_put_vard_all
+
+!
+! End of vard subroutines:
+!
+
diff --git a/src/utils/Makefile.in b/src/utils/Makefile.in
new file mode 100644
index 0000000..76a1474
--- /dev/null
+++ b/src/utils/Makefile.in
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2285 2015-12-30 20:48:25Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../macros.make
+
+SUBDIRS = ncmpigen ncmpidump ncmpidiff ncmpivalid pnetcdf_version ncoffsets
+
+PACKING_LIST = Makefile.in
+
+PACKING_SUBDIRS = $(SUBDIRS)
+
+all: $(SUBDIRS)
+$(SUBDIRS):
+	$(MAKE) $(MFLAGS) -C $@
+
+INSTALLDIRS = $(SUBDIRS:%=install-%)
+install: $(INSTALLDIRS)
+$(INSTALLDIRS): 
+	$(MAKE) $(MFLAGS) -C $(@:install-%=%) install
+
+UNINSTALLDIRS = $(SUBDIRS:%=uninstall-%)
+uninstall: $(UNINSTALLDIRS)
+$(UNINSTALLDIRS): 
+	$(MAKE) $(MFLAGS) -C $(@:uninstall-%=%) uninstall
+
+include $(srcdir)/../../rules.make
diff --git a/src/utils/ncmpidiff/Makefile.in b/src/utils/ncmpidiff/Makefile.in
new file mode 100644
index 0000000..c40e95e
--- /dev/null
+++ b/src/utils/ncmpidiff/Makefile.in
@@ -0,0 +1,63 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2103 2015-09-18 23:34:03Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../../macros.make
+
+# For VPATH build:
+# Add ../../lib into search path because ../../lib/pnetcdf.h is created in
+# the build directory at configure time and is included by C files here.
+INCLUDES	= -I../../lib
+
+LDFLAGS        += -L../../lib
+LIBS           := -lpnetcdf $(LIBS) @LCOV_LIB@
+
+C_SOURCES	= ncmpidiff.c
+HEADERS		=
+
+OBJS		= $(C_SOURCES:.c=.o)
+
+PROGRAM		= ncmpidiff
+MANUAL		= ncmpidiff.1
+
+PACKING_LIST	= $(C_SOURCES) $(HEADERS) $(MANUAL) \
+                  depend Makefile.in
+
+GARBAGE		= $(PROGRAM)
+
+all:		$(PROGRAM)
+
+$(PROGRAM):	$(LIBRARY) $(OBJS)
+	$(LINK.c) $(OBJS) $(LDFLAGS) $(LIBS) 
+
+install: $(PROGRAM) $(MANUAL)
+	$(INSTALL) -d -m 755 $(MANDIR)/man1
+	$(INSTALL_DATA) $(srcdir)/$(MANUAL) $(MANDIR)/man1/$(MANUAL)
+
+	$(INSTALL) -d $(BINDIR)
+	$(INSTALL) -m 755 $(PROGRAM) $(BINDIR)/$(PROGRAM)
+
+uninstall:
+	$(RM) -f $(BINDIR)/$(PROGRAM)
+	$(RM) -f $(MANDIR)/man1/$(MANUAL)
+
+$(PROGRAM)_oc : $(C_SOURCES)
+	#setopt primary_language C
+	#load -C $(CPPFLAGS) $(C_SOURCES)
+	#load -C $(LIBS)
+	#setopt program_name $(PROGRAM)
+
+TAGS:		FORCE
+	etags `echo $(PACKING_LIST) | fmt -1 | $(EGREP) '\.c|\.h'
+
+include $(srcdir)/../../../rules.make
+include $(srcdir)/depend
+
+.PHONY: $(LIBRARY)
diff --git a/src/utils/ncmpidiff/depend b/src/utils/ncmpidiff/depend
new file mode 100644
index 0000000..f36f816
--- /dev/null
+++ b/src/utils/ncmpidiff/depend
@@ -0,0 +1 @@
+ncmpidiff.o: ncmpidiff.c ../../lib/pnetcdf.h
diff --git a/src/utils/ncmpidiff/ncmpidiff.1 b/src/utils/ncmpidiff/ncmpidiff.1
new file mode 100644
index 0000000..3a7b045
--- /dev/null
+++ b/src/utils/ncmpidiff/ncmpidiff.1
@@ -0,0 +1,41 @@
+.\" $Header$
+.nr yr \n(yr+1900
+.af mo 01
+.af dy 01
+.TH NCMPIDIFF 1 2013-11-17 "Printed: \n(yr-\n(mo-\n(dy" "UTILITIES"
+.SH NAME
+ncmpidiff \- compares two netCDF files in parallel
+.SH SYNOPSIS
+.ft B
+.HP
+mpiexec -n 4 ncmpidiff
+.nh
+\%[-b]
+\%[-h]
+\%[-v \fIvar1,...\fP]
+\%\fIfile1 file2\fP
+.hy
+.ft
+.SH DESCRIPTION
+\fBncmpidiff\fP compares the contents of the two files and reports
+the difference to the standard output.
+
+If no argument is given besides the two file names, the entire
+files are compared.
+.SH OPTIONS
+.IP "\fB-b\fP"
+Verbose mode 
+.IP "\fB-h\fP"
+Compare file header only
+.IP "\fB-v\fP \fIvar1,...,varn\fP"
+Compare only the given list of variables
+
+.SH "SEE ALSO"
+.LP
+.BR ncmpidump (1),
+.BR pnetcdf (3)
+.SH DATE
+$Date: 2013-11-17 00:21:28 -0600 (Sun, 17 Nov 2013) $
+.LP
+
+
diff --git a/src/utils/ncmpidiff/ncmpidiff.c b/src/utils/ncmpidiff/ncmpidiff.c
new file mode 100644
index 0000000..0ae97f3
--- /dev/null
+++ b/src/utils/ncmpidiff/ncmpidiff.c
@@ -0,0 +1,782 @@
+/*
+ *  Copyright (C) 2010, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: ncmpidiff.c 2150 2015-10-10 05:52:57Z wkliao $ */
+
+/* wkliao: This diff utility compares header and variables of two files
+ *         regardless the define order of the variables and attributes.
+ *
+ *         It can also compare a subset of the variables, for example
+ *           mpiexec -n 8 ncmpidiff -v var1,var2 file1.nc file2.nc
+ *
+ *         or compare the header only, for example,
+ *           mpiexec -n 8 ncmpidiff -h file1.nc file2.nc
+ *
+ *         or compare header + a subset of variables, for example,
+ *           mpiexec -n 8 ncmpidiff -h -v var1,var2 file1.nc file2.nc
+ */
+
+#if HAVE_CONFIG_H
+# include <ncconfig.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#ifndef ubyte
+#define ubyte unsigned char
+#endif
+#ifndef ushort
+#define ushort unsigned short
+#endif
+#ifndef uint
+#define uint unsigned int
+#endif
+#ifndef int64
+#define int64 long long
+#endif
+#ifndef uint64
+#define uint64 unsigned long long
+#endif
+
+#define OOM_ERROR { \
+    fprintf(stderr, "Error: malloc() out of memory at line %d\n",__LINE__); \
+    exit(1); \
+}
+
+#define HANDLE_ERROR {                                         \
+    if (err != NC_NOERR) {                                     \
+        fprintf(stderr, "Error at line %d (%s)\n", __LINE__,   \
+               ncmpi_strerror(err));                           \
+        MPI_Abort(MPI_COMM_WORLD, -1);                         \
+        exit(-1);                                              \
+    }                                                          \
+}
+
+#define CHECK_GLOBAL_ATT_DIFF(type, func, nctype) {                    \
+    int   pos, len = attlen1 * sizeof(type);                           \
+    type *b1 = (type *)malloc(len);                                    \
+    if (!b1) OOM_ERROR                                                 \
+    type *b2 = (type *)malloc(len);                                    \
+    if (!b2) OOM_ERROR                                                 \
+    err = func(ncid1, NC_GLOBAL, name1, b1);                           \
+    HANDLE_ERROR                                                       \
+    err = func(ncid2, NC_GLOBAL, name1, b2);                           \
+    HANDLE_ERROR                                                       \
+    if ((pos = memcmp(b1, b2, len)) != 0) {                            \
+        printf("DIFF: global attribute \"%s\" of type \"%s\" (%d)\n",  \
+                name1,#nctype,pos);                                    \
+        numHeadDIFF++;                                                 \
+    }                                                                  \
+    else if (verbose)                                                  \
+        printf("\tSAME: attribute contents\n");                        \
+    free(b1);                                                          \
+    free(b2);                                                          \
+    break;                                                             \
+}
+
+#define CHECK_VAR_ATT_DIFF(type, func, nctype) {                              \
+    int   pos, len = attlen1 * sizeof(type);                                  \
+    type *b1 = (type *)malloc(len);                                           \
+    if (!b1) OOM_ERROR                                                        \
+    type *b2 = (type *)malloc(len);                                           \
+    if (!b2) OOM_ERROR                                                        \
+    err = func(ncid1, i, attrname, b1);                                       \
+    HANDLE_ERROR                                                              \
+    err = func(ncid2, varid, attrname, b2);                                   \
+    HANDLE_ERROR                                                              \
+    if ((pos = memcmp(b1, b2, len)) != 0) {                                   \
+        printf("DIFF: variable \"%s\" attribute \"%s\" of type \"%s\" (%d)\n",\
+               name1,attrname,#nctype,pos);                                   \
+        numHeadDIFF++;                                                        \
+    }                                                                         \
+    else if (verbose)                                                         \
+        printf("\t\tSAME: attribute contents\n");                             \
+    free(b1);                                                                 \
+    free(b2);                                                                 \
+    break;                                                                    \
+}
+
+#define CHECK_VAR_DIFF(type, func, nctype) {                                 \
+    int   pos, isDiff, len = varsize * sizeof(type);                         \
+    type *b1 = (type *)malloc(len);                                          \
+    if (!b1) OOM_ERROR                                                       \
+    type *b2 = (type *)malloc(len);                                          \
+    if (!b2) OOM_ERROR                                                       \
+    err = func(ncid1, varid1, start, shape, b1);                             \
+    HANDLE_ERROR                                                             \
+    err = func(ncid2, varid2, start, shape, b2);                             \
+    HANDLE_ERROR                                                             \
+    if ((pos = memcmp(b1, b2, len)) != 0) {                                  \
+        printf("DIFF: variable \"%s\" of type \"%s\" (%d)\n",                \
+               name1,#nctype,pos);                                           \
+        numVarDIFF++;                                                        \
+    }                                                                        \
+    MPI_Allreduce(&pos, &isDiff, 1, MPI_INT, MPI_MAX, comm);                 \
+    if (isDiff == 0 && !rank && verbose)                                     \
+        printf("\tSAME: variable \"%s\" contents\n",name1);                  \
+    free(b1);                                                                \
+    free(b2);                                                                \
+    break;                                                                   \
+}
+
+char *progname;
+
+#ifndef EXIT_FAILURE
+#ifndef vms
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+#else
+#define EXIT_SUCCESS 1
+#define EXIT_FAILURE 0
+#endif
+#endif
+
+/*
+ *  * Print error message to stderr and exit
+ */
+#if 0
+static void
+error(const char *fmt, ...)
+{
+    va_list args ;
+
+    (void) fprintf(stderr,"%s: ", progname);
+    va_start(args, fmt) ;
+    (void) vfprintf(stderr,fmt,args) ;
+    va_end(args) ;
+
+    (void) fprintf(stderr, "\n") ;
+    (void) fflush(stderr);      /* to ensure log files are current */
+    exit(EXIT_FAILURE);
+}
+#endif
+
+/*----< usage() >-------------------------------------------------------------*/
+static void
+usage(int rank, char *progname)
+{
+#define USAGE   "\
+  Compare the contents of two netCDF files.\n\n\
+  [-b]             Verbose output\n\
+  [-h]             Compare header information only, no data\n\
+  [-q]             quiet mode (return 0/1 for same/different)\n\
+  [-v var1[,...]]  Compare variable(s) <var1>,... only\n\
+  file1 file2      File names of two input netCDF files to be compared\n"
+
+    if (rank == 0) {
+        printf("  %s [-h] [-v ...] [-b] file1 file2\n%s", progname, USAGE);
+        printf("  PnetCDF library version %s\n", ncmpi_inq_libvers());
+    }
+    MPI_Finalize();
+    exit(1);
+}
+
+struct vspec {
+    int    nvars;
+    char **names; /* [nvars] */
+};
+
+/*----< get_var_names() >-----------------------------------------------------*/
+static void
+get_var_names(char *optarg, struct vspec* vspecp)
+{
+    char *cp=optarg, **cpp;
+    int nvars = 1;
+
+    /* compute number of variable names in comma-delimited list */
+    vspecp->nvars = 1;
+    while (*cp++)
+        if (*cp == ',')
+            nvars++;
+
+    vspecp->names = (char **) malloc(nvars * sizeof(char*));
+    if (!vspecp->names) OOM_ERROR
+
+    cpp = vspecp->names;
+    /* copy variable names into list */
+    for (cp = strtok(optarg, ",");
+         cp != NULL;
+         cp = strtok((char *) NULL, ",")) {
+
+        *cpp = (char *) malloc(strlen(cp) + 1);
+        if (!*cpp) OOM_ERROR
+        strcpy(*cpp, cp);
+        cpp++;
+    }
+    vspecp->nvars = nvars;
+}
+
+/*----< get_type() >----------------------------------------------------------*/
+static char*
+get_type(int type)
+{
+    switch (type) {
+        case NC_CHAR:   return "char";
+        case NC_SHORT:  return "short";
+        case NC_INT:    return "int";
+        case NC_FLOAT:  return "float";
+        case NC_DOUBLE: return "double";
+        case NC_UBYTE:  return "unsigned char";
+        case NC_USHORT: return "unsigned short";
+        case NC_UINT:   return "unsigned int";
+        case NC_INT64:  return "long long";
+        case NC_UINT64: return "unsigned long long";
+    }
+    return "";
+}
+
+/*----< main() >--------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    int i, j, c, err, rank, nprocs, verbose, quiet;
+    int ncid1, ndims1, nvars1, natts1, unlimdimid1, *dimids1;
+    int ncid2, ndims2, nvars2, natts2, unlimdimid2, *dimids2;
+    char *name1, *name2;
+    MPI_Offset *shape, varsize, *start;
+    MPI_Offset attlen1, dimlen1, attlen2, dimlen2;
+    nc_type type1, type2;
+    MPI_Comm comm=MPI_COMM_WORLD;
+    int nvars, check_header, check_variable_list, check_entire_file;
+    long long numVarDIFF=0, numHeadDIFF=0, varDIFF, numDIFF;
+    struct vspec var_list;
+    extern char *optarg;
+    extern int optind;
+    MPI_Info info;
+ 
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(comm, &nprocs);
+    MPI_Comm_rank(comm, &rank);
+
+    progname            = argv[0];
+    verbose             = 0;
+    quiet               = 0;
+    check_header        = 0;
+    check_variable_list = 0;
+    check_entire_file   = 0;
+    var_list.names      = NULL;
+    var_list.nvars      = 0;
+
+    while ((c = getopt(argc, argv, "bhqv:")) != -1)
+        switch(c) {
+            case 'h':               /* compare header only */
+                check_header = 1;
+                break;
+            case 'v':               /* variable names */
+                /* make list of names of variables specified */
+                get_var_names(optarg, &var_list);
+                check_variable_list = 1;
+                break;
+            case 'b':
+                verbose = 1;
+                break;
+            case 'q':
+                quiet = 1;
+                break;
+            case '?':
+                usage(rank, argv[0]);
+                break;
+        }
+
+    /* quiet overwrites verbose */
+    if (quiet) verbose = 0;
+
+    if (argc - optind != 2) usage(rank, argv[0]);
+
+    if (check_header == 0 && check_variable_list == 0) {
+        check_entire_file = 1;
+        check_header      = 1;
+    }
+
+    dimids1 = (int*) malloc(NC_MAX_DIMS * sizeof(int));
+    if (!dimids1) OOM_ERROR
+    dimids2 = (int*) malloc(NC_MAX_DIMS * sizeof(int));
+    if (!dimids2) OOM_ERROR
+    name1   = (char*) malloc(NC_MAX_NAME);
+    if (!name1) OOM_ERROR
+    name2   = (char*) malloc(NC_MAX_NAME);
+    if (!name2) OOM_ERROR
+    shape   = (MPI_Offset*) malloc(NC_MAX_VAR_DIMS * sizeof(MPI_Offset));
+    if (!shape) OOM_ERROR
+    start   = (MPI_Offset*) malloc(NC_MAX_VAR_DIMS * sizeof(MPI_Offset));
+    if (!start) OOM_ERROR
+
+    /* Nov. 18, 2014 -- disable subfiling as it does not correctly handle the
+     * cases when  nprocs < num_subfiles */
+    MPI_Info_create (&info);
+    MPI_Info_set (info, "pnetcdf_subfiling", "disable");
+
+    /* open files */
+    err = ncmpi_open(comm, argv[optind], NC_NOWRITE, info, &ncid1);
+    HANDLE_ERROR
+    err = ncmpi_open(comm, argv[optind+1], NC_NOWRITE, info, &ncid2);
+    HANDLE_ERROR
+
+    MPI_Info_free(&info);
+
+    /* check header */
+    if (check_header && rank == 0) { /* only root checks header */
+        int attnump;
+
+        err = ncmpi_inq(ncid1, &ndims1, &nvars1, &natts1, &unlimdimid1);
+        HANDLE_ERROR
+        err = ncmpi_inq(ncid2, &ndims2, &nvars2, &natts2, &unlimdimid2);
+        HANDLE_ERROR
+        if (ndims1 != ndims2) { /* check number of dimensions if equal */
+            if (!quiet) printf("DIFF: number of dimensions (%d) != (%d)\n",ndims1, ndims2);
+            numHeadDIFF++;
+        }
+        else if (verbose)
+            printf("SAME: number of dimensions (%d)\n",ndims1);
+        if (nvars1 != nvars2) { /* check number of variables if equal */
+            if (!quiet) printf("DIFF: number of variables (%d) != (%d)\n",nvars1, nvars2);
+            numHeadDIFF++;
+        }
+        else if (verbose)
+            printf("SAME: number of variables (%d)\n",nvars1);
+        if (natts1 != natts2) { /* check number of global attributes if equal */
+            if (!quiet) printf("DIFF: number of global attributes (%d) != (%d)\n",natts1, natts2);
+            numHeadDIFF++;
+        }
+        else if (verbose)
+            printf("SAME: number of global attributes (%d)\n",natts1);
+
+        /* Compare global attributes, assume CHAR attributes. */
+        for (i=0; i<natts1; i++) { /* check what's in file1 also in file2 */
+            err = ncmpi_inq_attname(ncid1, NC_GLOBAL, i, name1);
+            HANDLE_ERROR
+            /* find the attr with the same name from ncid2 */
+            err = ncmpi_inq_attid(ncid2, NC_GLOBAL, name1, &attnump);
+            if (err == NC_ENOTATT) {
+                if (!quiet) printf("DIFF: global attribute \"%s\" not found in file %s\n",
+                       name1,argv[optind+1]);
+                numHeadDIFF++;
+                continue;
+            }
+
+            err = ncmpi_inq_att(ncid1, NC_GLOBAL, name1, &type1, &attlen1);
+            HANDLE_ERROR
+            err = ncmpi_inq_att(ncid2, NC_GLOBAL, name1, &type2, &attlen2);
+            HANDLE_ERROR
+            if (type1 != type2) {
+                if (!quiet) printf("DIFF: global attribute \"%s\" data type (%s) != (%s)\n",
+                       name1,get_type(type1),get_type(type2));
+                numHeadDIFF++;
+                continue;
+            }
+            else if (verbose) {
+                printf("Global attribute \"%s\":\n",name1);
+                printf("\tSAME: data type (%s)\n",get_type(type1));
+            }
+
+            if (attlen1 != attlen2) {
+                if (!quiet) printf("DIFF: global attribute \"%s\" length (%lld) != (%lld)\n",
+                       name1,(long long int)attlen1,(long long int)attlen2);
+                numHeadDIFF++;
+                continue;
+            }
+            else if (verbose)
+                printf("\tSAME: length (%lld)\n",(long long int)attlen1);
+
+            switch (type1) {
+                case NC_CHAR:   CHECK_GLOBAL_ATT_DIFF(char,   ncmpi_get_att_text,      NC_CHAR)
+                case NC_SHORT:  CHECK_GLOBAL_ATT_DIFF(short,  ncmpi_get_att_short,     NC_SHORT)
+                case NC_INT:    CHECK_GLOBAL_ATT_DIFF(int,    ncmpi_get_att_int,       NC_INT)
+                case NC_FLOAT:  CHECK_GLOBAL_ATT_DIFF(float,  ncmpi_get_att_float,     NC_FLOAT)
+                case NC_DOUBLE: CHECK_GLOBAL_ATT_DIFF(double, ncmpi_get_att_double,    NC_DOUBLE)
+                case NC_UBYTE:  CHECK_GLOBAL_ATT_DIFF(ubyte,  ncmpi_get_att_uchar,     NC_UBYTE)
+                case NC_USHORT: CHECK_GLOBAL_ATT_DIFF(ushort, ncmpi_get_att_ushort,    NC_USHORT)
+                case NC_UINT:   CHECK_GLOBAL_ATT_DIFF(uint,   ncmpi_get_att_uint,      NC_UINT)
+                case NC_INT64:  CHECK_GLOBAL_ATT_DIFF(int64,  ncmpi_get_att_longlong,  NC_INT64)
+                case NC_UINT64: CHECK_GLOBAL_ATT_DIFF(uint64, ncmpi_get_att_ulonglong, NC_UINT64)
+                default: ; /* TODO: handle unexpected types */
+            }
+        }
+        for (i=0; i<natts2; i++) { /* check attributes in file2 but not in file1 */
+            err = ncmpi_inq_attname(ncid2, NC_GLOBAL, i, name2);
+            HANDLE_ERROR
+            /* find the attr with the same name from ncid1 */
+            if (ncmpi_inq_attid(ncid1, NC_GLOBAL, name2, &attnump) == NC_ENOTATT) {
+                numHeadDIFF++;
+                if (!quiet) printf("DIFF: global attribute \"%s\" not found in file %s\n",
+                       name1,argv[optind]);
+            }
+        }
+
+        /* Compare dimension */
+        if (ndims1 && verbose)
+            printf("Dimension:\n");
+
+        for (i=0; i<ndims1; i++) { /* check dimensions in file1 also in file2 */
+            int dimid;
+            err = ncmpi_inq_dim(ncid1, i, name1, &dimlen1);
+            HANDLE_ERROR
+            /* find the dim with the same name from ncid2 */
+            err = ncmpi_inq_dimid(ncid2, name1, &dimid);
+            if (err == NC_EBADDIM) {
+                if (!quiet) printf("DIFF: dimension \"%s\" not found in file %s\n",
+                       name1,argv[optind+1]);
+                numHeadDIFF++;
+                continue;
+            }
+
+            err = ncmpi_inq_dimlen(ncid2, dimid, &dimlen2);
+            HANDLE_ERROR
+            if (dimlen1 != dimlen2) {
+                /* cast to quiet warning on 32 bit platforms */
+                if (!quiet) printf("DIFF: dimension \"%s\" length (%lld) != (%lld)\n",
+                       name1,(long long int)dimlen1,(long long int)dimlen2);
+                numHeadDIFF++;
+            }
+            else if (verbose)
+                printf("\tSAME: dimension \"%s\" length (%lld)\n",
+                       name1,(long long int)dimlen1);
+        }
+        for (i=0; i<ndims2; i++) { /* check dimensions in file2 but not in file1 */
+            int dimid;
+            err = ncmpi_inq_dim(ncid2, i, name2, &dimlen2);
+            HANDLE_ERROR
+            /* find the dim with the same name from ncid1 */
+            if (ncmpi_inq_dimid(ncid2, name1, &dimid) == NC_EBADDIM) {
+                if (!quiet) printf("DIFF: dimension \"%s\" not found in file %s\n",
+                       name1,argv[optind]);
+                numHeadDIFF++;
+            }
+        }
+
+        /* Compare variables' metadata */
+        for (i=0; i<nvars1; i++) {
+            int varid;
+            err = ncmpi_inq_var(ncid1, i, name1, &type1, &ndims1, dimids1, &natts1);
+            HANDLE_ERROR
+            /* find the variable with the same name from ncid2 */
+            err = ncmpi_inq_varid(ncid2, name1, &varid);
+            if (err == NC_ENOTVAR) {
+                if (!quiet) printf("DIFF: variable \"%s\" not found in file %s\n",
+                       name1,argv[optind+1]);
+                numHeadDIFF++;
+                numVarDIFF++;
+                continue;
+            }
+            err = ncmpi_inq_var(ncid2, varid, name2, &type2, &ndims2, dimids2, &natts2);
+            HANDLE_ERROR
+
+            if (type1 != type2) {
+                if (!quiet) printf("DIFF: variable \"%s\" data type (%s) != (%s)\n",
+                       name1,get_type(type1),get_type(type2));
+                numHeadDIFF++;
+            }
+            else if (verbose) {
+                printf("Variable \"%s\":\n",name1);
+                printf("\tSAME: data type (%s)\n",get_type(type1));
+            }
+
+            if (ndims1 != ndims2) {
+                if (!quiet) printf("DIFF: variable \"%s\" number of dimensions (%d) != (%d)\n",
+                       name1,ndims1,ndims2);
+                numHeadDIFF++;
+            }
+            else {
+                if (verbose)
+                    printf("\tSAME: number of dimensions (%d)\n",ndims1);
+
+                for (j=0; j<ndims1; j++) { /* check variable's dimensionality */
+                    char dimname1[NC_MAX_NAME], dimname2[NC_MAX_NAME];
+                    /* get dim name for each dim ID */
+                    err = ncmpi_inq_dim(ncid1, dimids1[j], dimname1, &dimlen1);
+                    HANDLE_ERROR
+                    err = ncmpi_inq_dim(ncid1, dimids2[j], dimname2, &dimlen2);
+                    HANDLE_ERROR
+                    if (verbose)
+                        printf("\tdimension %d:\n",j);
+                    if (strcmp(dimname1, dimname2) != 0) {
+                        if (!quiet) printf("DIFF: variable \"%s\" of type \"%s\" dimension %d's name (%s) != (%s)\n",
+                               name1,get_type(type1),j,dimname1,dimname2);
+                        numHeadDIFF++;
+                    }
+                    else if (verbose)
+                        printf("\t\tSAME: name (%s)\n",dimname1);
+                    if (dimlen1 != dimlen2) {
+                        if (!quiet) printf("DIFF: variable \"%s\" of type \"%s\" dimension %d's length (%lld) != (%lld)\n",
+                               name1,get_type(type1),j,(long long int)dimlen1,(long long int)dimlen2);
+                        numHeadDIFF++;
+                    }
+                    else if (verbose)
+                        printf("\t\tSAME: length (%lld)\n",(long long int)dimlen1);
+                }
+            }
+
+            if (natts1 != natts2) {
+                if (!quiet) printf("DIFF: variable \"%s\" number of attributes (%d) != (%d)\n",
+                       name1,natts1,natts2);
+                numHeadDIFF++;
+            }
+            else if (verbose)
+                printf("\tSAME: number of attributes (%d)\n",natts1);
+
+            /* var attributes, assume CHAR attributes */
+            for (j=0; j<natts1; j++) {
+                char attrname[NC_MAX_NAME];
+                err = ncmpi_inq_attname(ncid1, i, j, attrname);
+                HANDLE_ERROR
+                err = ncmpi_inq_att(ncid1, i, attrname, &type1, &attlen1);
+                HANDLE_ERROR
+                /* find the variable attr with the same name from ncid2 */
+                err = ncmpi_inq_att(ncid2, varid, attrname, &type2, &attlen2);
+                if (err == NC_ENOTATT) {
+                    if (!quiet) printf("DIFF: variable \"%s\" attribute \"%s\" not found in file %s\n",
+                           name1,attrname,argv[optind+1]);
+                    numHeadDIFF++;
+                    continue;
+                }
+                if (verbose)
+                    printf("\tattribute \"%s\":\n",attrname);
+
+                if (type1 != type2) {
+                    if (!quiet) printf("DIFF: variable \"%s\" attribute \"%s\" data type (%s) != (%s)\n",
+                           name1,attrname,get_type(type1),get_type(type2));
+                    numHeadDIFF++;
+                    continue; /* skip this attribute */
+                }
+                else if (verbose)
+                    printf("\t\tSAME: data type (%s)\n",get_type(type1));
+                if (attlen1 != attlen2) {
+                    if (!quiet) printf("DIFF: variable \"%s\" attribute \"%s\" length (%lld) != (%lld)\n",
+                           name1,attrname,(long long int)attlen1,(long long int)attlen2);
+                    numHeadDIFF++;
+                    continue; /* skip this attribute */
+                }
+                else if (verbose)
+                    printf("\t\tSAME: length (%lld)\n",(long long int)attlen1);
+
+                switch (type1) {
+                    case NC_CHAR:   CHECK_VAR_ATT_DIFF(char,   ncmpi_get_att_text,      NC_CHAR)
+                    case NC_SHORT:  CHECK_VAR_ATT_DIFF(short,  ncmpi_get_att_short,     NC_SHORT)
+                    case NC_INT:    CHECK_VAR_ATT_DIFF(int,    ncmpi_get_att_int,       NC_INT)
+                    case NC_FLOAT:  CHECK_VAR_ATT_DIFF(float,  ncmpi_get_att_float,     NC_FLOAT)
+                    case NC_DOUBLE: CHECK_VAR_ATT_DIFF(double, ncmpi_get_att_double,    NC_DOUBLE)
+                    case NC_UBYTE:  CHECK_VAR_ATT_DIFF(ubyte,  ncmpi_get_att_uchar,     NC_UBYTE)
+                    case NC_USHORT: CHECK_VAR_ATT_DIFF(ushort, ncmpi_get_att_ushort,    NC_USHORT)
+                    case NC_UINT:   CHECK_VAR_ATT_DIFF(uint,   ncmpi_get_att_uint,      NC_UINT)
+                    case NC_INT64:  CHECK_VAR_ATT_DIFF(int64,  ncmpi_get_att_longlong,  NC_INT64)
+                    case NC_UINT64: CHECK_VAR_ATT_DIFF(uint64, ncmpi_get_att_ulonglong, NC_UINT64)
+                    default: ; /* TODO: handle unexpected types */
+                }
+            }
+            for (j=0; j<natts2; j++) {
+                char attrname[NC_MAX_NAME];
+                err = ncmpi_inq_attname(ncid2, varid, j, attrname);
+                HANDLE_ERROR
+                /* find the variable attr with the same name from ncid1 */
+                err = ncmpi_inq_att(ncid1, i, attrname, &type1, &attlen1);
+                if (err == NC_ENOTATT) {
+                    if (!quiet) printf("DIFF: variable \"%s\" attribute \"%s\" not found in file %s\n",
+                           name1,attrname,argv[optind]);
+                    numHeadDIFF++;
+                }
+            }
+        }
+        for (i=0; i<nvars2; i++) { /* check variables in file2 but not in file1 */
+            int varid;
+            err = ncmpi_inq_varname(ncid2, i, name2);
+            HANDLE_ERROR
+            /* find the variable with the same name from ncid1 */
+            err = ncmpi_inq_varid(ncid1, name2, &varid);
+            if (err == NC_ENOTVAR) {
+                if (!quiet) printf("DIFF: variable \"%s\" not found in file %s\n",
+                       name2,argv[optind]);
+                numHeadDIFF++;
+                numVarDIFF++;
+            }
+        }
+    }
+
+    /* compare variable contents */
+    for (i=0; i<NC_MAX_VAR_DIMS; i++) start[i] = 0;
+
+    nvars = 0;
+    if (check_variable_list) nvars = var_list.nvars;
+
+    if (check_entire_file) { /* header has been checked */
+        ncmpi_inq_nvars(ncid1, &nvars);
+        var_list.nvars = nvars;
+        var_list.names = (char**) malloc(nvars * sizeof(char*));
+        if (!var_list.names) OOM_ERROR
+        /* get all the variable names from file1 */
+        for (i=0; i<nvars; i++) {
+            ncmpi_inq_varname(ncid1, i, name1);
+            var_list.names[i] = (char *) malloc(strlen(name1) + 1);
+            if (!var_list.names[i]) OOM_ERROR
+            strcpy(var_list.names[i], name1);
+        }
+    }
+    if (!rank && verbose) printf("number of variables to be compared = %d\n",nvars);
+
+    for (i=0; i<nvars; i++) { /* compare one variable at a time */
+        int varid1, varid2;
+
+        err = ncmpi_inq_varid(ncid1, var_list.names[i], &varid1);
+        if (err == NC_ENOTVAR) {
+            if (!check_header && !rank) {
+                if (!quiet) printf("WARN: variable \"%s\" not found in file %s\n",
+                       var_list.names[i],argv[optind]);
+                numVarDIFF++;
+            }
+            continue;
+        }
+        err = ncmpi_inq_varid(ncid2, var_list.names[i], &varid2);
+        if (err == NC_ENOTVAR) {
+            if (!check_header && !rank) {
+                if (!quiet) printf("WARN: variable \"%s\" not found in file %s\n",
+                       var_list.names[i],argv[optind+1]);
+                numVarDIFF++;
+            }
+            continue;
+        }
+        err = ncmpi_inq_var(ncid1, varid1, name1, &type1, &ndims1, dimids1, &natts1);
+        HANDLE_ERROR
+        err = ncmpi_inq_var(ncid2, varid2, name2, &type2, &ndims2, dimids2, &natts2);
+        HANDLE_ERROR
+
+        /* check data type */
+        if (type1 != type2) {
+            if (!rank) {
+                if (!check_header) /* if header has not been checked */
+                    if (!quiet) printf("DIFF: variable \"%s\" data type (%s) != (%s)\n",
+                       name1,get_type(type1),get_type(type2));
+                numHeadDIFF++;
+                numVarDIFF++;
+            }
+            continue; /* skip this variable */
+        }
+        else if (!check_header && !rank && verbose) {
+            printf("Variable \"%s\":\n",name1);
+            printf("\tSAME: data type (%s)\n",get_type(type1));
+        }
+
+        /* check number of dimensions */
+        if (ndims1 != ndims2) {
+            if (!rank) {
+                if (!check_header) /* if header has not been checked */
+                    if (!quiet) printf("DIFF: variable \"%s\" number of dimensions (%d) != (%d)\n",
+                       name1,ndims1,ndims2);
+                numHeadDIFF++;
+                numVarDIFF++;
+            }
+            continue; /* skip this variable */
+        }
+        else if (!check_header && !rank && verbose)
+            printf("\tSAME: number of dimensions (%d)\n",ndims1);
+
+        /* check dimension length only */
+        for (j=0; j<ndims1; j++) { /* check variable's dimensionality */
+            err = ncmpi_inq_dimlen(ncid1, dimids1[j], &dimlen1);
+            HANDLE_ERROR
+            err = ncmpi_inq_dimlen(ncid2, dimids2[j], &dimlen2);
+            HANDLE_ERROR
+            if (!check_header && !rank && verbose)
+                printf("\tDimension %d:\n",j);
+            if (dimlen1 != dimlen2) {
+                if (!rank) {
+                    if (!check_header) /* if header has not been checked */
+                        if (!quiet) printf("DIFF: variable \"%s\" of type \"%s\" dimension %d's length (%lld) != (%lld)\n",
+                               name1,get_type(type1),j,(long long int)dimlen1,(long long int)dimlen2);
+                    numHeadDIFF++;
+                    numVarDIFF++;
+                }
+                break; /* skip this variable */
+            }
+            else if (!check_header && !rank && verbose)
+                printf("\t\tSAME: length (%lld)\n",(long long int)dimlen1);
+            shape[j] = dimlen1;
+        }
+        if (j != ndims1)
+            continue; /* skip this variable */
+
+        varsize  = 1;
+        /* block partition the variable along the 1st dimension */
+        for (j=0; j<ndims1; j++) {
+            if (j == 0) {
+                shape[j] /= nprocs;
+                start[j] = shape[j] * rank;
+            }
+            varsize *= shape[j];
+        }
+ 
+        /* compare the variable contents */
+        switch (type1) {
+            case NC_CHAR:   CHECK_VAR_DIFF(char,   ncmpi_get_vara_text_all,   NC_CHAR)
+            case NC_SHORT:  CHECK_VAR_DIFF(short,  ncmpi_get_vara_short_all,  NC_SHORT)
+            case NC_INT:    CHECK_VAR_DIFF(int,    ncmpi_get_vara_int_all,    NC_INT)
+            case NC_FLOAT:  CHECK_VAR_DIFF(float,  ncmpi_get_vara_float_all,  NC_FLOAT)
+            case NC_DOUBLE: CHECK_VAR_DIFF(double, ncmpi_get_vara_double_all, NC_DOUBLE)
+            case NC_UBYTE:  CHECK_VAR_DIFF(ubyte,  ncmpi_get_vara_uchar,      NC_UBYTE)
+            case NC_USHORT: CHECK_VAR_DIFF(ushort, ncmpi_get_vara_ushort,     NC_USHORT)
+            case NC_UINT:   CHECK_VAR_DIFF(uint,   ncmpi_get_vara_uint,       NC_UINT)
+            case NC_INT64:  CHECK_VAR_DIFF(int64,  ncmpi_get_vara_longlong,   NC_INT64)
+            case NC_UINT64: CHECK_VAR_DIFF(uint64, ncmpi_get_vara_ulonglong,  NC_UINT64)
+            default: ; /* TODO: handle unexpected types */
+        }
+    }
+
+    /* close files */
+    err = ncmpi_close(ncid1);
+    HANDLE_ERROR
+    err = ncmpi_close(ncid2);
+    HANDLE_ERROR
+
+    /* summary of the difference */
+    MPI_Reduce(&numVarDIFF, &varDIFF, 1, MPI_LONG_LONG_INT, MPI_SUM, 0, comm);
+    if (!quiet && rank == 0) {
+        if (check_header) {
+            if (numHeadDIFF == 0)
+                printf("Headers of two files are the same\n");
+            else
+                printf("Number of differences in header %lld\n",numHeadDIFF);
+        }
+        if (check_variable_list) {
+            if (varDIFF == 0)
+                printf("Compared variable(s) are the same\n");
+            else
+                printf("Compared variables(s) has %lld differences\n",varDIFF);
+        }
+        if (check_entire_file) {
+            if (varDIFF == 0)
+                printf("All variables of two files are the same\n");
+            else
+                printf("Number of differences in variables %lld\n",varDIFF);
+        }
+    }
+
+    /* free up the memory previously allocated */
+    if (var_list.nvars) {
+        for (i=0; i<var_list.nvars; i++)
+            free(var_list.names[i]);
+        free(var_list.names);
+    }
+    free(dimids1);
+    free(dimids2);
+    free(name1);
+    free(name2);
+    free(shape);
+    free(start);
+
+    if (rank == 0) numDIFF = varDIFF + numHeadDIFF;
+    MPI_Bcast(&numDIFF, 1, MPI_LONG_LONG_INT, 0, comm);
+
+    MPI_Finalize();
+#ifdef vms
+    if (quiet) exit((numDIFF == 0) ? 0 : 1);
+    else       exit(EXIT_SUCCESS);
+#else
+    if (quiet) return ((numDIFF == 0) ? 0 : 1);
+    else       return EXIT_SUCCESS;
+#endif
+}
diff --git a/src/utils/ncmpidump/Makefile.in b/src/utils/ncmpidump/Makefile.in
new file mode 100644
index 0000000..34193ce
--- /dev/null
+++ b/src/utils/ncmpidump/Makefile.in
@@ -0,0 +1,74 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2103 2015-09-18 23:34:03Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include ../../../macros.make
+
+NCGEN		= ../ncmpigen/ncmpigen
+
+# For VPATH build:
+# Add ../../lib into search path because ../../lib/pnetcdf.h is created in
+# the build directory at configure time and is included by C files here.
+INCLUDES	= -I../../lib
+
+LDFLAGS        += -L../../lib
+LIBS           := -lpnetcdf $(LIBS) @LCOV_LIB@
+
+C_SOURCES	= ncmpidump.c vardata.c dumplib.c
+HEADERS		= ncmpidump.h vardata.h dumplib.h
+
+OBJS            = $(C_SOURCES:.c=.o)
+
+PROGRAM		= ncmpidump
+MANUAL		= ncmpidump.1
+
+PACKING_LIST    = $(C_SOURCES) $(HEADERS) $(MANUAL) \
+                  depend Makefile.in \
+                  test0.cdl
+
+GARBAGE		= $(PROGRAM) test0.nc test1.nc test1.cdl test2.cdl
+
+all:		$(PROGRAM)
+
+$(PROGRAM):	$(LIBRARY) $(OBJS)
+	$(LINK.c) $(OBJS) $(LDFLAGS) $(LIBS) 
+
+test:		$(PROGRAM) FORCE
+	$(NCGEN) -b $(srcdir)/test0.cdl -o `pwd`/test0.nc
+	./$(PROGRAM) -n test1 test0.nc > test1.cdl
+	$(NCGEN) -b `pwd`/test1.cdl -o `pwd`/test1.nc
+	./$(PROGRAM) test1.nc > test2.cdl
+	@cmp test1.cdl test2.cdl && \
+	     echo "*** $(PROGRAM) test successful ***"
+
+install: $(PROGRAM) $(MANUAL)
+	$(INSTALL) -d -m 755 $(MANDIR)/man1
+	$(INSTALL_DATA) $(srcdir)/$(MANUAL) $(MANDIR)/man1/$(MANUAL)
+
+	$(INSTALL) -d $(BINDIR)
+	$(INSTALL) -m 755 $(PROGRAM) $(BINDIR)/$(PROGRAM)
+
+uninstall:
+	$(RM) -f $(BINDIR)/$(PROGRAM)
+	$(RM) -f $(MANDIR)/man1/$(MANUAL)
+
+$(PROGRAM)_oc : $(C_SOURCES)
+	#setopt primary_language C
+	#load -C $(CPPFLAGS) $(C_SOURCES)
+	#load -C $(LIBS)
+	#setopt program_name $(PROGRAM)
+
+TAGS:		FORCE
+	etags `echo $(PACKING_LIST) | fmt -1 | $(EGREP) '\.c|\.h'
+
+include $(srcdir)/../../../rules.make
+include $(srcdir)/depend
+
+.PHONY: $(LIBRARY)
diff --git a/src/utils/ncmpidump/depend b/src/utils/ncmpidump/depend
new file mode 100644
index 0000000..de556d1
--- /dev/null
+++ b/src/utils/ncmpidump/depend
@@ -0,0 +1,3 @@
+dumplib.o: dumplib.c dumplib.h ../../lib/pnetcdf.h
+ncmpidump.o: ncmpidump.c dumplib.h ncmpidump.h vardata.h ../../lib/pnetcdf.h
+vardata.o: vardata.c dumplib.h ncmpidump.h vardata.h ../../lib/pnetcdf.h
diff --git a/src/utils/ncmpidump/dumplib.c b/src/utils/ncmpidump/dumplib.c
new file mode 100644
index 0000000..d772d52
--- /dev/null
+++ b/src/utils/ncmpidump/dumplib.c
@@ -0,0 +1,225 @@
+/*********************************************************************
+ *   Copyright 1993, University Corporation for Atmospheric Research
+ *   See netcdf/README file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+/* $Id: dumplib.c 1123 2013-01-26 17:35:03Z wkliao $ */
+
+/*
+ * We potentially include <stdarg.h> before <stdio.h> in order to obtain a
+ * definition for va_list from the GNU C compiler.
+ */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pnetcdf.h"
+#include "dumplib.h"
+
+#define ncmpi_advise(x, y, z) 
+
+static char* has_c_format_att(int ncid, int varid);
+static vnode* newvnode(void);
+
+int float_precision_specified = 0; /* -p option specified float precision */
+int double_precision_specified = 0; /* -p option specified double precision */
+char float_var_fmt[] = "%.NNg";
+char double_var_fmt[] = "%.NNg";
+char float_att_fmt[] = "%#.NNgf";
+char double_att_fmt[] = "%#.NNg";
+
+/*
+ * Print error message to stderr and exit
+ */
+void
+error(const char *fmt, ...)
+{
+    va_list args ;
+
+    (void) fprintf(stderr,"%s: ", progname);
+    va_start(args, fmt) ;
+    (void) vfprintf(stderr,fmt,args) ;
+    va_end(args) ;
+
+    (void) fprintf(stderr, "\n") ;
+    (void) fflush(stderr);	/* to ensure log files are current */
+    exit(EXIT_FAILURE);
+}
+
+#define LINEPIND	"    "	/* indent of continued lines */
+
+static int linep;
+static int max_line_len;
+
+void
+set_indent(int in)
+{
+    linep = in;
+}
+
+
+void
+set_max_len(int len)
+{
+    max_line_len = len-2;
+}
+
+
+void
+lput(const char *cp)
+{
+    size_t nn = strlen(cp);
+
+    if (nn+linep > max_line_len && nn > 2) {
+	(void) fputs("\n", stdout);
+	(void) fputs(LINEPIND, stdout);
+	linep = (int)strlen(LINEPIND);
+    }
+    (void) fputs(cp,stdout);
+    linep += nn;
+}
+
+/* In case different formats specified with -d option, set them here. */
+void
+set_formats(int float_digits, int double_digits)
+{
+    (void) sprintf(float_var_fmt, "%%.%dg", float_digits);
+    (void) sprintf(double_var_fmt, "%%.%dg", double_digits);
+    (void) sprintf(float_att_fmt, "%%#.%dgf", float_digits);
+    (void) sprintf(double_att_fmt, "%%#.%dg", double_digits);
+}
+
+
+static char *
+has_c_format_att(
+    int ncid,			/* netcdf id */
+    int varid			/* variable id */
+    )
+{
+    nc_type cfmt_type;
+    MPI_Offset cfmt_len;
+#define C_FMT_NAME	"C_format" /* name of C format attribute */
+#define	MAX_CFMT_LEN	100	/* max length of C format attribute */
+    static char cfmt[MAX_CFMT_LEN];
+    
+    /* we expect ncmpi_inq_att to fail if there is no "C_format" attribute */
+    int ncmpi_stat = ncmpi_inq_att(ncid, varid, "C_format", &cfmt_type, &cfmt_len);
+
+    switch(ncmpi_stat) {
+    case NC_NOERR:
+	if (cfmt_type == NC_CHAR && cfmt_len != 0 && cfmt_len < MAX_CFMT_LEN) {
+	    ncmpi_stat = ncmpi_get_att_text(ncid, varid, "C_format", cfmt);
+	    if(ncmpi_stat != NC_NOERR)
+		ncmpi_advise("Getting 'C_format' attribute", ncmpi_stat, "");
+	    return &cfmt[0];
+	}
+	break;
+    case NC_ENOTATT:
+	break;
+    default:
+	ncmpi_advise("Inquiring about 'C_format' attribute", ncmpi_stat, "");
+	break;
+    }
+    return 0;
+}
+
+
+/*
+ * Determine print format to use for each value for this variable.  Use value
+ * of attribute C_format if it exists, otherwise a sensible default.
+ */
+const char *
+get_fmt(
+     int ncid,			/* netcdf id */
+     int varid,			/* variable id */
+     nc_type type		/* netCDF data type */
+     )
+{
+    char *c_format_att;
+
+    /* float or double precision specified with -p option overrides any
+       C_format attribute value, so check for that first. */
+
+    if (float_precision_specified && type == NC_FLOAT)
+	return float_var_fmt;
+
+    if (double_precision_specified && type == NC_DOUBLE)
+	return double_var_fmt;
+
+    /* If C_format attribute exists, return it */
+    c_format_att = has_c_format_att(ncid, varid);
+    if (c_format_att)
+        return c_format_att;    
+
+    /* Otherwise return sensible default. */
+    switch (type) {
+        case NC_BYTE:   return "%hhd";
+        case NC_CHAR:   return "%s";
+        case NC_SHORT:  return "%hd";
+        case NC_INT:    return "%d";
+        case NC_FLOAT:  return float_var_fmt;
+        case NC_DOUBLE: return double_var_fmt;
+        case NC_UBYTE:  return "%hhu";
+        case NC_USHORT: return "%hu";
+        case NC_UINT:   return "%u";
+        case NC_INT64:  return "%lld";
+        case NC_UINT64: return "%llu";
+        default:
+	    error("pr_vals: bad type");
+    }
+
+    return 0;
+}
+
+
+static vnode*
+newvnode(void)
+{
+    vnode *newvp = (vnode*) malloc(sizeof(vnode));
+    
+    if (!newvp) {
+	error("out of memory!");
+    }
+    return newvp;
+}
+
+
+/*
+ * Get a new, empty variable list.
+ */
+vnode*
+newvlist(void)
+{
+    vnode *vp = newvnode();
+
+    vp -> next = 0;
+    vp -> id = -1;		/* bad id */
+
+    return vp;
+}
+
+
+void
+varadd(vnode* vlist, int varid)
+{
+    vnode *newvp = newvnode();
+    
+    newvp -> next = vlist -> next;
+    newvp -> id = varid;
+    vlist -> next = newvp;
+}
+
+
+int
+varmember(const vnode* vlist, int varid)
+{
+    vnode *vp = vlist -> next;
+
+    for (; vp ; vp = vp->next)
+      if (vp->id == varid)
+	return 1;
+    return 0;    
+}
+
+
diff --git a/src/utils/ncmpidump/dumplib.h b/src/utils/ncmpidump/dumplib.h
new file mode 100644
index 0000000..3654c59
--- /dev/null
+++ b/src/utils/ncmpidump/dumplib.h
@@ -0,0 +1,73 @@
+/*********************************************************************
+ *   Copyright 1993, University Corporation for Atmospheric Research
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+/* $Id: dumplib.h 1468 2013-10-26 16:53:18Z wkliao $ */
+
+extern char *progname;		/* for error messages */
+
+#define NO_NETCDF_2		/* assert we aren't using any netcdf-2 stuff */
+
+#ifndef EXIT_FAILURE
+#ifndef vms
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+#else
+#define EXIT_SUCCESS 1
+#define EXIT_FAILURE 0
+#endif
+#endif
+
+#define FLT_DIGITS 7		/* default sig. digits for float data */
+#define DBL_DIGITS 15		/* default sig. digits for double data */
+
+extern int float_precision_specified; /* -p option specified float precision */
+extern int double_precision_specified; /* -p option specified double precision */
+extern char float_var_fmt[];
+extern char double_var_fmt[];
+extern char float_att_fmt[];
+extern char double_att_fmt[];
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Print error message to stderr and exit */
+extern void	error ( const char *fmt, ... );
+
+/* set position in line before lput() calls */
+extern void	set_indent ( int indent );
+
+/* set maximum line length */
+extern void	set_max_len ( int len );
+
+/* splits lines to keep them short */
+extern void	lput ( const char *string );
+
+/* In case different formats specified with -d option, set them here. */
+extern void	set_formats ( int flt_digs, int dbl_digs );
+
+/* Determine print format to use for each value for this variable. */
+const char *		get_fmt ( int ncid, int varid, nc_type type );
+
+/* structure for list of variables specified with -v option */
+struct vnode
+{
+    struct vnode* next;
+    int id;
+};
+typedef struct vnode vnode;
+
+/* Get new variable list */
+extern vnode*	newvlist ( void );
+
+/* Add a variable id to variable list */
+extern void	varadd ( vnode* vlist, int varid );
+
+/* Test if a variable id is in variable list */
+extern int	varmember ( const vnode* vlist, int varid );
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/utils/ncmpidump/ncmpidump.1 b/src/utils/ncmpidump/ncmpidump.1
new file mode 100644
index 0000000..dfa5c74
--- /dev/null
+++ b/src/utils/ncmpidump/ncmpidump.1
@@ -0,0 +1,200 @@
+.\" $Header$
+.nr yr \n(yr+1900
+.af mo 01
+.af dy 01
+.TH NCMPIDUMP 1 "2013-11-17" "Printed: \n(yr-\n(mo-\n(dy" "UTILITIES"
+.SH NAME
+ncmpidump \- Convert netCDF files to ASCII form (CDL)
+.SH SYNOPSIS
+.ft B
+.HP
+ncmpidump
+.nh
+\%[-ch]
+\%[-v \fIvar1,...\fP]
+\%[-b \fIlang\fP]
+\%[-f \fIlang\fP]
+\%[-l \fIlen\fP]
+\%[-n \fIname\fP]
+\%[-p \fIf_digits[,d_digits]\fP]
+\%\fIfile\fP
+.br
+.ft B
+.HP
+ncmpidump
+.nh
+\%-k
+\%\fIfile\fP
+.hy
+.ft
+.SH DESCRIPTION
+\fBncmpidump\fP generates an ASCII representation of a specified netCDF file on
+standard output.  The ASCII representation is in a form called CDL
+(``network Common Data form Language'') that can be viewed, edited, or serve
+as input to \fBncmpigen\fP.  \fBncmpigen\fP is a companion program that can
+generate a binary netCDF file from a CDL file.  Hence \fBncmpigen\fP and
+\fBncmpidump\fP can be used as inverses to transform the data representation
+between binary and ASCII representations.  See \fBncmpigen\fP for a description
+of CDL and netCDF representations.
+.LP
+\fBncmpidump\fP may also be used to determine what kind of netCDF file is used
+(which variant of the netCDF file format) with the -k option.
+.LP
+\fBncmpidump\fP defines a default format used for each type of netCDF data, but
+this can be changed if a `C_format' attribute is defined for a netCDF
+variable.  In this case, \fBncmpidump\fP will use the `C_format' attribute to
+format each value.  For example, if floating-point data for the netCDF
+variable `Z' is known to be accurate to only three significant digits, it
+would be appropriate to use the variable attribute
+.RS
+.HP
+Z:C_format = "%.3g"
+.RE
+.LP
+\fBncmpidump\fP may also be used as a simple browser for netCDF data
+files, to display the dimension names and sizes; variable names, types,
+and shapes; attribute names and values; and optionally, the values of
+data for all variables or selected variables in a netCDF file.
+.LP
+\fBncmpidump\fP uses `_' to represent data values that are equal to the
+`_FillValue' attribute for a variable, intended to represent data that
+has not yet been written.  If a variable has no `_FillValue' attribute, the
+default fill value for the variable type is used if the variable is not of
+byte type.
+.SH OPTIONS
+.IP "\fB-c\fP"
+Show the values of \fIcoordinate\fP variables (variables that are also
+dimensions) as well as the declarations of all dimensions, variables, and
+attribute values.  Data values of non-coordinate variables are not included
+in the output.  This is the most suitable option to use for a brief look at
+the structure and contents of a netCDF file.
+.IP "\fB-h\fP"
+Show only the \fIheader\fP information in the output, that is the
+declarations of dimensions, variables, and attributes but no data values for
+any variables.  The output is identical to using the \fB-c\fP option except
+that the values of coordinate variables are not included.  (At most one of
+\fB-c\fP or \fB-h\fP options may be present.)
+.IP "\fB-v\fP \fIvar1,...,varn\fP"
+The output will include data values for the specified variables, in addition
+to the declarations of all dimensions, variables, and attributes.  One or
+more variables must be specified by name in the comma-delimited list
+following this option.  The list must be a single argument to the command,
+hence cannot contain blanks or other white space characters.  The named
+variables must be valid netCDF variables in the input-file.  The default,
+without this option and in the absence of the \fB-c\fP or \fB-h\fP
+options, is to include data values for \fIall\fP variables in the output.
+.IP "\fB-b\fP \fIlang\fP"
+A brief annotation in the form of a CDL comment (text beginning with the
+characters ``//'') will be included in the data section of the output for
+each `row' of data, to help identify data values for multidimensional
+variables.  If \fIlang\fP begins with `C' or `c', then C language
+conventions will be used (zero-based indices, last dimension varying
+fastest).  If \fIlang\fP begins with `F' or `f', then Fortran language
+conventions will be used (one-based indices, first dimension varying
+fastest).  In either case, the data will be presented in the same order;
+only the annotations will differ.  This option is useful for browsing
+through large volumes of multidimensional data.
+.IP "\fB-f\fP \fIlang\fP"
+Full annotations in the form of trailing CDL comments (text beginning with
+the characters ``//'') for every data value (except individual characters in
+character arrays) will be included in the data section.  If \fIlang\fP
+begins with `C' or `c', then C language conventions will be used (zero-based
+indices, last dimension varying fastest).  If \fIlang\fP begins with `F' or
+`f', then Fortran language conventions will be used (one-based indices,
+first dimension varying fastest).  In either case, the data will be
+presented in the same order; only the annotations will differ.  This option
+may be useful for piping data into other filters, since each data value
+appears on a separate line, fully identified.
+.IP "\fB-l\fP \fIlen\fP"
+Changes the default maximum line length (80) used in formatting lists of
+non-character data values.
+.IP "\fB-n\fP \fIname\fP"
+CDL requires a name for a netCDF data set, for use by \fBncmpigen -b\fP in
+generating a default netCDF file name.  By default, \fIncmpidump\fP constructs
+this name from the last component of the pathname of the input netCDF file
+by stripping off any extension it has.  Use the \fB-n\fP option to specify a
+different name.  Although the output file name used by \fBncmpigen -b\fP can be
+specified, it may be wise to have \fIncmpidump\fP change the default name to
+avoid inadvertantly overwriting a valuable netCDF file when using
+\fBncmpidump\fP, editing the resulting CDL file, and using \fBncmpigen -b\fP to
+generate a new netCDF file from the edited CDL file.
+.IP "\fB-p\fP \fIfloat_digits[,double_digits]\fP"
+Specifies default precision (number of significant digits) to use in displaying
+floating-point or double precision data values for attributes and variables.
+If specified, this value overrides the value of the `C_format' attribute for
+any variable that has such an attribute.  
+Floating-point data will be displayed with
+\fIfloat_digits\fP significant digits.  If \fIdouble_digits\fP is also
+specified, double-precision values will be displayed with that many
+significant digits.  In the absence of any
+\fB-p\fP specifications, floating-point and double-precision data are
+displayed with 7 and 15 significant digits respectively.  CDL files can be
+made smaller if less precision is required.  If both floating-point and
+double-presision precisions are specified, the two values must appear
+separated by a comma (no blanks) as a single argument to the command.
+If you really want every last bit of precision from the netCDF file
+represented in the CDL file for all possible floating-point values, you will
+have to specify this with \fB-p 9,17\fP (according to Theorem 15 of the
+paper listed under REFERENCES).
+.IP "\fB-k\fP"
+Reports the kind of netCDF file: classic, 64-bit offset, or 64-bit data.
+Before netCDF version 3.6, there was only one kind of netCDF file,
+designated as `classic' (also know as format variant 1 or CDF-1).
+Large file support introduced another variant of the format, designated as
+`64-bit offset' (known as format variant 2 or CDF-2).
+Large data support introduced another variant of the format, designated as
+`64-bit data' (known as format variant 5 or CDF-5).
+
+.SH EXAMPLES
+.LP
+Look at the structure of the data in the netCDF file `\fBfoo.nc\fP':
+.RS
+.HP
+ncmpidump -c foo.nc
+.RE
+.LP
+Produce an annotated CDL version of the structure and data in the
+netCDF file `\fBfoo.nc\fP', using C-style indexing for the annotations:
+.RS
+.HP
+ncmpidump -b c foo.nc > foo.cdl
+.RE
+.LP
+Output data for only the variables `uwind' and `vwind' from the netCDF file
+`\fBfoo.nc\fP', and show the floating-point data with only three significant
+digits of precision:
+.RS
+.HP
+ncmpidump -v uwind,vwind -p 3 foo.nc
+.RE
+.LP
+Produce a fully-annotated (one data value per line) listing of the data for
+the variable `omega', using Fortran conventions for indices, and changing the
+netCDF dataset name in the resulting CDL file to `omega':
+.RS
+.HP
+ncmpidump -v omega -f fortran -n omega foo.nc > Z.cdl
+.RE
+.SH REFERENCES
+ \fIWhat
+Every Computer Scientist should Know About Floating-Point Arithmetic\fP, D.
+Goldberg, \fBACM Computing Surveys, Vol. 23, No. 1\fP, March 1991, pp. 5-48.
+
+.SH "SEE ALSO"
+.LP
+.BR ncmpigen (1),
+.BR pnetcdf (3)
+.SH DATE
+$Date: 2013-11-17 00:21:28 -0600 (Sun, 17 Nov 2013) $
+.SH BUGS
+.LP
+Character arrays that contain a null-byte are treated like C strings, so no
+characters after the null byte appear in the output.
+
+Multidimensional character string arrays are not handled well, since the CDL
+syntax for breaking a long character string into several shorter lines is
+weak.
+
+There should be a way to specify that the data should be displayed in
+`record' order, that is with the all the values for `record' variables
+together that have the same value of the record dimension.
diff --git a/src/utils/ncmpidump/ncmpidump.c b/src/utils/ncmpidump/ncmpidump.c
new file mode 100644
index 0000000..d3dcac9
--- /dev/null
+++ b/src/utils/ncmpidump/ncmpidump.c
@@ -0,0 +1,823 @@
+/*********************************************************************
+ *   Copyright 1993, University Corporation for Atmospheric Research
+ *   See netcdf/README file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+/* $Id: ncmpidump.c 2060 2015-08-03 22:39:58Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include <ncconfig.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>  /* strtol() */
+#include <string.h>  /* strrchr() */
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <mpi.h>
+#include <pnetcdf.h>
+#include "ncmpidump.h"
+#include "dumplib.h"
+#include "vardata.h"
+
+static void usage(void);
+static char* name_path(const char* path);
+static const char* type_name(nc_type  type);
+static void tztrim(char* ss);
+static void pr_att_string(size_t len, const char* string);
+static void pr_att_vals(nc_type  type, size_t len, const double* vals);
+static void pr_att(int ncid, int varid, const char *varname, int ia);
+static void do_ncdump(const char* path, struct fspec* specp);
+static void make_lvars(char* optarg, struct fspec* fspecp);
+static void set_sigdigs( const char* optarg);
+static void set_precision( const char *optarg);
+int main(int argc, char** argv);
+
+#define    STREQ(a, b)    (*(a) == *(b) && strcmp((a), (b)) == 0)
+
+char *progname;
+
+static void
+usage(void)
+{
+#define USAGE   "\
+  [-c]             Coordinate variable data and header information\n\
+  [-h]             Header information only, no data\n\
+  [-v var1[,...]]  Data for variable(s) <var1>,... only\n\
+  [-b [c|f]]       Brief annotations for C or Fortran indices in data\n\
+  [-f [c|f]]       Full annotations for C or Fortran indices in data\n\
+  [-l len]         Line length maximum in data section (default 80)\n\
+  [-n name]        Name for netCDF (default derived from file name)\n\
+  [-p n[,n]]       Display floating-point values with less precision\n\
+  [-V]             Print the file format (CDF-1, CDF-2, or CDF-5)\n\
+  [-k]             Print kind of file (classic, 64-bit offset, or 64-bit data)\n\
+  file             File name of input netCDF file\n"
+
+    fprintf(stderr,
+           "%s [-c|-h] [-v ...] [[-b|-f] [c|f]] [-l len] [-n name] [-p n[,n]] [-k] [-V] file\n%s",
+           progname, USAGE);
+    
+    fprintf(stderr, "PnetCDF library version %s\n", ncmpi_inq_libvers());
+}
+
+
+/* 
+ * convert pathname of netcdf file into name for cdl unit, by taking 
+ * last component of path and stripping off any extension.
+ */
+static char *
+name_path(const char *path)
+{
+    const char *cp;
+    char *new;
+    char *sp;
+
+#ifdef vms
+#define FILE_DELIMITER ']'
+#endif    
+#ifdef MSDOS
+#define FILE_DELIMITER '\\'
+#endif    
+#ifndef FILE_DELIMITER /* default to unix */
+#define FILE_DELIMITER '/'
+#endif
+    cp = strrchr(path, FILE_DELIMITER);
+    if (cp == 0)        /* no delimiter */
+        cp = path;
+    else                /* skip delimeter */
+        cp++;
+
+    new = (char *) malloc((unsigned) (strlen(cp)+1));
+    if (new == 0) error("out of memory!");
+
+    strcpy(new, cp);    /* copy last component of path */
+    if ((sp = strrchr(new, '.')) != NULL)
+        *sp = '\0';     /* strip off any extension */
+    return new;
+}
+
+
+static const char *
+type_name(nc_type type)
+{
+    switch (type) {  /* conform with netcdf4 */
+        case NC_BYTE:    return "byte";
+        case NC_CHAR:    return "char";
+        case NC_SHORT:   return "short";
+        case NC_INT:     return "int";
+        case NC_FLOAT:   return "float";
+        case NC_DOUBLE:  return "double";
+        case NC_UBYTE:   return "ubyte";
+        case NC_USHORT:  return "ushort";
+        case NC_UINT:    return "uint";
+        case NC_INT64:   return "int64";
+        case NC_UINT64:  return "uint64";
+        default:
+            error("type_name: bad type %d", type);
+            return "bogus";
+    }
+}
+
+
+/*
+ * Remove trailing zeros (after decimal point) but not trailing decimal
+ * point from ss, a string representation of a floating-point number that
+ * might include an exponent part.
+ */
+static void
+tztrim(char *ss)
+{
+    char *cp, *ep;
+    
+    cp = ss;
+    if (*cp == '-')
+        cp++;
+    while(isdigit((int)*cp) || *cp == '.')
+        cp++;
+    if (*--cp == '.')
+        return;
+    ep = cp+1;
+    while (*cp == '0')
+        cp--;
+    cp++;
+    if (cp == ep)
+        return;
+    while (*ep)
+        *cp++ = *ep++;
+    *cp = '\0';
+    return;
+}
+
+
+/*
+ * Print attribute string, for text attributes.
+ */
+static void
+pr_att_string(size_t      len,
+              const char *string)
+{
+    int iel;
+    const char *cp;
+    const char *sp;
+    unsigned char uc;
+
+    cp = string;
+    Printf ("\"");
+    /* adjust len so trailing nulls don't get printed */
+    sp = cp + len - 1;
+    while (len != 0 && *sp-- == '\0')
+        len--;
+
+    for (iel = 0; iel < len; iel++)
+        switch (uc = *cp++ & 0377) {
+            case '\b':
+                Printf ("\\b");
+                break;
+            case '\f':
+                Printf ("\\f");
+                break;
+            case '\n':        /* generate linebreaks after new-lines */
+                Printf ("\\n\",\n    \"");
+                break;
+            case '\r':
+                Printf ("\\r");
+                break;
+            case '\t':
+                Printf ("\\t");
+                break;
+            case '\v':
+                Printf ("\\v");
+                break;
+            case '\\':
+                Printf ("\\\\");
+                break;
+            case '\'':
+                Printf ("\\'");
+                break;
+            case '\"':
+                Printf ("\\\"");
+                break;
+            default:
+                Printf ("%c",uc);
+                break;
+        }
+
+    Printf ("\"");
+}
+
+
+/*
+ * Print list of attribute values, for numeric attributes.  Attribute values
+ * must be printed with explicit type tags, because CDL doesn't have explicit
+ * syntax to declare an attribute type.
+ */
+static void
+pr_att_vals(nc_type       type,
+            size_t        len,
+            const double *vals)
+{
+    int iel;
+    char gps[30];
+    signed char        sc;
+    unsigned char      uc;
+    short              ss;
+    unsigned short     us;
+    int                si;
+    unsigned int       ui;
+    float              ff;
+    double             dd;
+    long long          sll;
+    unsigned long long ull;
+
+    if (len == 0) return;
+
+    for (iel=0; iel<len; iel++) {
+        switch (type) {
+            case NC_BYTE:
+                sc = (signed char) vals[iel] & 0377;
+                Printf ("%hhdb", sc);
+                break;
+            case NC_SHORT:
+                ss = vals[iel];
+                Printf ("%hds", ss);
+                break;
+            case NC_INT:
+                si = (int) vals[iel];
+                Printf ("%d", si);
+                break;
+            case NC_FLOAT:
+                ff = vals[iel];
+                (void) sprintf(gps, float_att_fmt, ff);
+                tztrim(gps);    /* trim trailing 0's after '.' */
+                Printf ("%s", gps);
+                break;
+            case NC_DOUBLE:
+                dd = vals[iel];
+                (void) sprintf(gps, double_att_fmt, dd);
+                tztrim(gps);
+                Printf ("%s", gps);
+                break;
+            case NC_UBYTE:
+                uc = (unsigned char) vals[iel] & 0377;
+                Printf ("%hhuUB", uc); /* match netCDF4 ncdump type indicator */
+                break;
+            case NC_USHORT:
+                us = vals[iel];
+                Printf ("%huUS", us); /* match netCDF4 ncdump type indicator */
+                break;
+            case NC_UINT:
+                ui = vals[iel];
+                Printf ("%uU", ui); /* match netCDF4 ncdump type indicator */
+                break;
+            case NC_INT64:
+                sll = vals[iel];
+                Printf ("%lldL", sll); /* match netCDF4 ncdump type indicator */
+                break;
+            case NC_UINT64:
+                ull = vals[iel];
+                Printf ("%lluUL", ull);/* match netCDF4 ncdump type indicator */
+                break;
+            default:
+                error("pr_att_vals: bad type");
+        }
+        /* if not the last element */
+        if (iel < len-1) Printf (", ");
+    }
+}
+
+
+static void
+pr_att(int         ncid,
+       int         varid,
+       const char *varname,
+       int         ia)
+{
+    struct ncatt att;        /* attribute */
+        
+    NC_CHECK(ncmpi_inq_attname(ncid, varid, ia, att.name));
+
+    Printf ("\t\t%s:%s = ", varname, att.name);
+
+    NC_CHECK(ncmpi_inq_att(ncid, varid, att.name, &att.type, &att.len));
+
+    if (att.len == 0) {    /* show 0-length attributes as empty strings */
+        Printf ("\"\" ;\n");
+        return;
+    }
+    switch (att.type) {
+        case NC_CHAR:
+            att.string = (char *) malloc(att.len);
+            if (!att.string) {
+                error("Out of memory!");
+                NC_CHECK(ncmpi_close(ncid));
+                return;
+            }
+            NC_CHECK(ncmpi_get_att_text(ncid, varid, att.name, att.string));
+            pr_att_string(att.len, att.string);
+            free(att.string);
+            break;
+        default:
+            att.vals = (double *) malloc(att.len * sizeof(double));
+            if (!att.vals) {
+                error("Out of memory!");
+                NC_CHECK( ncmpi_close(ncid) );
+                return;
+            }
+            NC_CHECK(ncmpi_get_att_double(ncid, varid, att.name, att.vals));
+            pr_att_vals(att.type, att.len, att.vals);
+            free(att.vals);
+            break;
+    }
+    Printf (" ;\n");
+}
+
+
+static void
+do_ncdump(const char *path, struct fspec* specp)
+{
+    int ndims;            /* number of dimensions */
+    int nvars;            /* number of variables */
+    int ngatts;           /* number of global attributes */
+    int xdimid;           /* id of unlimited dimension */
+    int dimid;            /* dimension id */
+    int varid;            /* variable id */
+    struct ncdim dims[NC_MAX_DIMS]; /* dimensions */
+    size_t vdims[NC_MAX_DIMS];    /* dimension sizes for a single variable */
+    struct ncvar var;     /* variable */
+    struct ncatt att;     /* attribute */
+    int id;               /* dimension number per variable */
+    int ia;               /* attribute number */
+    int iv;               /* variable number */
+    int is_coord;         /* true if variable is a coordinate variable */
+    int ncid;             /* netCDF id */
+    vnode* vlist = 0;     /* list for vars specified with -v option */
+    int ncmpi_status;     /* return from netcdf calls */
+    int NC_mode;
+    MPI_Info info;
+
+    /* Nov. 18, 2014 -- disable subfiling as it does not correctly handle the
+     * cases when  nprocs < num_subfiles */
+    MPI_Info_create (&info);
+    MPI_Info_set (info, "pnetcdf_subfiling", "disable");
+
+    ncmpi_status = ncmpi_open(MPI_COMM_WORLD, path, NC_NOWRITE,
+                              info, &ncid);
+    if (ncmpi_status != NC_NOERR)
+        error("%s: %s", path, ncmpi_strerror(ncmpi_status));
+    MPI_Info_free(&info);
+
+    /*
+     * If any vars were specified with -v option, get list of associated
+     * variable ids
+     */
+    if (specp->nlvars > 0) {
+        vlist = newvlist();    /* list for vars specified with -v option */
+        for (iv=0; iv < specp->nlvars; iv++) {
+            NC_CHECK(ncmpi_inq_varid(ncid, specp->lvars[iv], &varid));
+            varadd(vlist, varid);
+        }
+    }
+
+    /* if name not specified, derive it from path */
+    if (specp->name == (char *)0)
+        specp->name = name_path (path);
+
+    ncmpi_inq_version(ncid, &NC_mode);
+    if (specp->version) {
+        if (NC_mode == NC_64BIT_DATA) 
+            Printf ("%s file format: CDF-5 (big variables)\n", specp->name);
+        else if (NC_mode == NC_64BIT_OFFSET) 
+            Printf ("%s file format: CDF-2 (large file)\n", specp->name);
+        else
+            Printf ("%s file format: CDF-1\n", specp->name);
+    } else if (specp->kind) {
+        if (NC_mode == NC_64BIT_DATA) 
+            Printf ("64-bit data\n");
+        else if (NC_mode == NC_64BIT_OFFSET) 
+            Printf ("64-bit offset\n");
+        else
+            Printf ("classic\n");
+    } else {
+        Printf ("netcdf %s {\n", specp->name);
+
+        if (NC_mode == NC_64BIT_DATA) 
+            Printf ("// file format: CDF-5 (big variables)\n");
+        else if (NC_mode == NC_64BIT_OFFSET) 
+            Printf ("// file format: CDF-2 (large file)\n");
+        else
+            Printf ("// file format: CDF-1\n");
+        /*
+         * get number of dimensions, number of variables, number of global
+         * atts, and dimension id of unlimited dimension, if any
+         */
+        NC_CHECK(ncmpi_inq(ncid, &ndims, &nvars, &ngatts, &xdimid));
+
+        /* print dimension info */
+        if (ndims > 0) Printf ("dimensions:\n");
+
+        for (dimid = 0; dimid < ndims; dimid++) {
+            NC_CHECK(ncmpi_inq_dim(ncid, dimid, dims[dimid].name,
+                                   &dims[dimid].size) );
+            if (dimid == xdimid)
+                Printf ("\t%s = %s ; // (%lld currently)\n",dims[dimid].name,
+                        "UNLIMITED", (long long int)(dims[dimid].size));
+            else
+                Printf ("\t%s = %lld ;\n", dims[dimid].name, 
+			(long long int)(dims[dimid].size));
+        }
+
+        if (nvars > 0) Printf ("variables:\n");
+
+        /* get variable info, with variable attributes */
+        for (varid = 0; varid < nvars; varid++) {
+            NC_CHECK(ncmpi_inq_var(ncid, varid, var.name, &var.type,
+                                   &var.ndims, var.dims, &var.natts) );
+            Printf ("\t%s %s", type_name(var.type), var.name);
+            if (var.ndims > 0) Printf ("(");
+            for (id = 0; id < var.ndims; id++) {
+                Printf ("%s%s", dims[var.dims[id]].name,
+                        id < var.ndims-1 ? ", " : ")");
+            }
+            Printf (" ;\n");
+
+            /* get variable attributes */
+            for (ia = 0; ia < var.natts; ia++)
+                pr_att(ncid, varid, var.name, ia); /* print ia-th attribute */
+        }
+
+
+        /* get global attributes */
+        if (ngatts > 0) Printf ("\n// global attributes:\n");
+
+        for (ia = 0; ia < ngatts; ia++)
+            pr_att(ncid, NC_GLOBAL, "", ia); /* print ia-th global attribute */
+    
+        if (! specp->header_only) {
+            if (nvars > 0) Printf ("data:\n");
+            /* output variable data */
+            for (varid = 0; varid < nvars; varid++) {
+                /* if var list specified, test for membership */
+                if (specp->nlvars > 0 && ! varmember(vlist, varid))
+                    continue;
+                NC_CHECK(ncmpi_inq_var(ncid, varid, var.name, &var.type,
+                                       &var.ndims, var.dims, &var.natts));
+                if (specp->coord_vals) {
+                    /* Find out if this is a coordinate variable */
+                    is_coord = 0;
+                    for (dimid = 0; dimid < ndims; dimid++) {
+                        if (strcmp(dims[dimid].name, var.name) == 0 &&
+                            var.ndims == 1) {
+                            is_coord = 1;
+                            break;
+                        }
+                    }
+                    if (! is_coord) /* don't get data for non-coordinate vars */
+                        continue;
+                }
+                /*
+                 * Only get data for variable if it is not a record variable,
+                 * or if it is a record variable and at least one record has
+                 * been written.
+                 */
+                if (var.ndims == 0 || var.dims[0] != xdimid ||
+                    dims[xdimid].size != 0) { 
+                    /* Collect variable's dim sizes */
+                    for (id = 0; id < var.ndims; id++)
+                         vdims[id] = dims[var.dims[id]].size;
+
+                    var.has_fillval = 1; /* by default, but turn off for bytes */
+
+                    /* get _FillValue attribute */
+                    ncmpi_status = ncmpi_inq_att(ncid, varid, _FillValue,
+                                                 &att.type, &att.len);
+                    if (ncmpi_status == NC_NOERR &&
+                        att.type == var.type && att.len == 1) {
+                        if (var.type == NC_CHAR) {
+                            char fillc;
+                            NC_CHECK(ncmpi_get_att_text(ncid, varid, _FillValue,
+                                                        &fillc));
+                            var.fillval = fillc;
+                        } else
+                            NC_CHECK(ncmpi_get_att_double(ncid, varid, _FillValue,
+                                                          &var.fillval));
+                    } else {
+                        switch (var.type) {
+                            case NC_BYTE:
+                                /* don't do default fill-values for bytes, too risky */
+                                var.has_fillval = 0;
+                                break;
+                            case NC_UBYTE:
+                                var.fillval = NC_FILL_UBYTE;
+                                break;
+                            case NC_CHAR:
+                                var.fillval = NC_FILL_CHAR;
+                                break;
+                            case NC_SHORT:
+                                var.fillval = NC_FILL_SHORT;
+                                break;
+                            case NC_USHORT:
+                                var.fillval = NC_FILL_USHORT;
+                                break;
+                            case NC_INT:
+                                var.fillval = NC_FILL_INT;
+                                break;
+                            case NC_UINT:
+                                var.fillval = NC_FILL_UINT;
+                                break;
+                            case NC_FLOAT:
+                                var.fillval = NC_FILL_FLOAT;
+                                break;
+                            case NC_DOUBLE:
+                                var.fillval = NC_FILL_DOUBLE;
+                                break;
+                            case NC_INT64:
+                                var.fillval = NC_FILL_INT64;
+                                break;
+                            case NC_UINT64:
+                                var.fillval = NC_FILL_UINT64;
+                                break;
+                            default:
+                                break;
+                        }
+                    }
+                    if (vardata(&var, vdims, ncid, varid, specp) == -1) {
+                        error("can't output data for variable %s", var.name);
+                        NC_CHECK(ncmpi_close(ncid));
+                        if (vlist) free(vlist);
+                        return;
+                    }
+                }
+            }
+        }
+        Printf ("}\n");
+    }
+    NC_CHECK(ncmpi_close(ncid));
+    if (vlist) free(vlist);
+}
+
+
+static void
+make_lvars(char *optarg, struct fspec* fspecp)
+{
+    char *cp = optarg;
+    int nvars = 1;
+    char ** cpp;
+
+    /* compute number of variable names in comma-delimited list */
+    fspecp->nlvars = 1;
+    while (*cp++)
+        if (*cp == ',')
+            nvars++;
+
+    fspecp->lvars = (char **) malloc(nvars * sizeof(char*));
+    if (!fspecp->lvars) error("out of memory");
+
+    cpp = fspecp->lvars;
+    /* copy variable names into list */
+    for (cp = strtok(optarg, ",");
+         cp != NULL;
+         cp = strtok((char *) NULL, ",")) {
+    
+        *cpp = (char *) malloc(strlen(cp) + 1);
+        if (!*cpp) error("out of memory");
+
+        strcpy(*cpp, cp);
+        cpp++;
+    }
+    fspecp->nlvars = nvars;
+}
+
+
+/*
+ * Extract the significant-digits specifiers from the -d argument on the
+ * command-line and update the default data formats appropriately.
+ */
+static void
+set_sigdigs(const char *optarg)
+{
+    char *ptr1 = 0;
+    char *ptr2 = 0;
+    int flt_digits = FLT_DIGITS; /* default floating-point digits */
+    int dbl_digits = DBL_DIGITS; /* default double-precision digits */
+
+    if (optarg != 0 && (int) strlen(optarg) > 0 && optarg[0] != ',')
+        flt_digits = (int)strtol(optarg, &ptr1, 10);
+
+    if (flt_digits < 1 || flt_digits > 20)
+        error("unreasonable value for float significant digits: %d",
+              flt_digits);
+
+    if (*ptr1 == ',')
+        dbl_digits = (int)strtol(ptr1+1, &ptr2, 10);
+
+    if (ptr2 == ptr1+1 || dbl_digits < 1 || dbl_digits > 20)
+        error("unreasonable value for double significant digits: %d",
+              dbl_digits);
+
+    set_formats(flt_digits, dbl_digits);
+}
+
+
+/*
+ * Extract the significant-digits specifiers from the -p argument on the
+ * command-line, set flags so we can override C_format attributes (if any),
+ * and update the default data formats appropriately.
+ */
+static void
+set_precision(const char *optarg)
+{
+    char *ptr1 = 0;
+    char *ptr2 = 0;
+    int flt_digits = FLT_DIGITS;    /* default floating-point digits */
+    int dbl_digits = DBL_DIGITS;    /* default double-precision digits */
+
+    if (optarg != 0 && (int) strlen(optarg) > 0 && optarg[0] != ',') {
+        flt_digits = (int)strtol(optarg, &ptr1, 10);
+        float_precision_specified = 1;
+    }
+
+    if (flt_digits < 1 || flt_digits > 20)
+        error("unreasonable value for float significant digits: %d",
+              flt_digits);
+
+    if (*ptr1 == ',') {
+        dbl_digits = (int) strtol(ptr1+1, &ptr2, 10);
+        double_precision_specified = 1;
+    }
+
+    if (ptr2 == ptr1+1 || dbl_digits < 1 || dbl_digits > 20)
+        error("unreasonable value for double significant digits: %d",
+              dbl_digits);
+
+    set_formats(flt_digits, dbl_digits);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+    extern int optind;
+    extern int opterr;
+    extern char *optarg;
+    static struct fspec fspec =    /* defaults, overridden on command line */
+    {
+      0,            /* construct netcdf name from file name */
+      false,        /* print header info only, no data? */
+      false,        /* print CDF version, no data, no header */
+      false,        /* print file kind, no data, no header */
+      false,        /* just print coord vars? */
+      false,        /* brief  comments in data section? */
+      false,        /* full annotations in data section?  */
+      LANG_C,       /* language conventions for indices */
+      0,            /* if -v specified, number of variables */
+      0             /* if -v specified, list of variable names */
+    };
+    int c, rank, err=EXIT_SUCCESS;
+    int max_len = 80;        /* default maximum line length */
+    int nameopt = 0;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    /* If the user called ncmpidump without arguments, print the usage
+     * message and return peacefully. */
+    if (argc <= 1) {
+        if (rank == 0) usage();
+        goto fn_exit;
+    }
+
+    opterr = 1;
+    progname = argv[0];
+    set_formats(FLT_DIGITS, DBL_DIGITS); /* default for float, double data */
+
+    while ((c = getopt(argc, argv, "b:cf:hVkl:n:v:d:p:")) != EOF)
+        switch(c) {
+            case 'h':        /* dump header only, no data */
+                fspec.header_only = true;
+                break;
+            case 'V':        /* dump CDF version, no data, no header */
+                fspec.version = true;
+                break;
+            case 'k':        /* dump CDF version, no data, no header */
+                fspec.kind = true;
+                break;
+            case 'c':        /* header, data only for coordinate dims */
+                fspec.coord_vals = true;
+                break;
+            case 'n':        /* provide different name than derived from
+                              * file name
+                              */
+                fspec.name = optarg;
+                nameopt = 1;
+                break;
+            case 'b':        /* brief comments in data section */
+                fspec.brief_data_cmnts = true;
+                switch (tolower(optarg[0])) {
+                    case 'c':
+                        fspec.data_lang = LANG_C;
+                        break;
+                    case 'f':
+                        fspec.data_lang = LANG_F;
+                        break;
+                    default:
+                        if (rank == 0)
+                            fprintf(stderr,"invalid value for -b option: %s",
+                                    optarg);
+                        err = EXIT_FAILURE;
+                        goto fn_exit;
+                }
+                break;
+            case 'f':        /* full comments in data section */
+                fspec.full_data_cmnts = true;
+                switch (tolower(optarg[0])) {
+                    case 'c':
+                        fspec.data_lang = LANG_C;
+                        break;
+                    case 'f':
+                        fspec.data_lang = LANG_F;
+                        break;
+                    default:
+                        if (rank == 0)
+                            fprintf(stderr,"invalid value for -f option: %s",
+                                    optarg);
+                        err = EXIT_FAILURE;
+                        goto fn_exit;
+                }
+                break;
+            case 'l':        /* maximum line length */
+                max_len = (int) strtol(optarg, 0, 0);
+                if (max_len < 10) {
+                    if (rank == 0)
+                        fprintf(stderr,
+                                "unreasonably small line length specified: %d",
+                                max_len);
+                    err = EXIT_FAILURE;
+                    goto fn_exit;
+                }
+                break;
+            case 'v':        /* variable names */
+                /* make list of names of variables specified */
+                make_lvars (optarg, &fspec);
+                break;
+            case 'd':        /* specify precision for floats (old option) */
+                set_sigdigs(optarg);
+                break;
+            case 'p':        /* specify precision for floats */
+                set_precision(optarg);
+                break;
+            case '?':
+                if (rank == 0) usage();
+                goto fn_exit;
+            default:
+                break;
+        }
+
+    set_max_len(max_len);
+    
+    argc -= optind;
+    argv += optind;
+
+#ifndef MULTI_FILE_DUMP
+    /* If no input file, print usage message. */
+    if (argc != 1) {
+        if (rank == 0) {
+            if (argc == 0)
+                fprintf(stderr,"Error: input filename is missing\n\n");
+            else
+                fprintf(stderr,"Error: only one input file is allowed\n\n");
+            usage();
+        }
+        err = EXIT_FAILURE;
+        goto fn_exit;
+    }
+
+    if (!nameopt) fspec.name = (char *)0;
+    do_ncdump(argv[0], &fspec);
+#else
+    /* support multiple input files */
+    if (argc < 1) {
+        if (rank == 0) {
+            fprintf(stderr,"Error: input filename(s) is missing\n\n");
+            usage();
+        }
+        err = EXIT_FAILURE;
+        goto fn_exit;
+    }
+    int i = 0;
+    do {
+        if (!nameopt) fspec.name = (char *)0;
+        if (argc > 0)
+              do_ncdump(argv[i], &fspec);
+    } while (++i < argc);
+#endif
+
+fn_exit:
+    MPI_Finalize();
+#ifdef vms
+    exit(err);
+#else
+    return err;
+#endif
+}
diff --git a/src/utils/ncmpidump/ncmpidump.h b/src/utils/ncmpidump/ncmpidump.h
new file mode 100644
index 0000000..e340cea
--- /dev/null
+++ b/src/utils/ncmpidump/ncmpidump.h
@@ -0,0 +1,83 @@
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+/* $Id: ncmpidump.h 1468 2013-10-26 16:53:18Z wkliao $ */
+
+
+/* error checking macro */
+#define NC_CHECK(status)    {\
+	    int nc_status = status;\
+	    if(nc_status != NC_NOERR)\
+	        error(ncmpi_strerror(nc_status));\
+	}
+
+#define  Printf  (void) printf
+
+typedef int boolean;
+enum {false=0, true=1};
+
+struct ncdim {			/* dimension */
+    char name[NC_MAX_NAME];
+    MPI_Offset size;
+};
+
+struct ncvar {			/* variable */
+    char name[NC_MAX_NAME];
+    nc_type type;
+    int ndims;
+    int dims[NC_MAX_VAR_DIMS];
+    int natts;
+    boolean has_fillval;
+    double fillval;
+};
+
+struct ncatt {			/* attribute */
+    int var;
+    char name[NC_MAX_NAME];
+    nc_type type;
+    MPI_Offset len;
+    char *string;		/* for text attributes (type = NC_CHAR) */
+    double *vals;		/* for numeric attributes of all types */
+};
+
+typedef
+enum {LANG_C, LANG_F} Nclang; 
+
+struct fspec {			/* specification for how to format dump */
+
+    char *name;			/* name specified with -n or derived from
+				 * file name */
+
+    boolean header_only;	/* if true, don't print any variable data */
+
+    boolean version;	       /* if true, print version */
+    boolean kind;	       /* if true, print kind of file format */
+
+    boolean coord_vals;		/* if true, print header and coordinate
+				 * dimension values (values of variables
+				 * that are also dimensions), but no other
+				 * variable data */
+
+    boolean brief_data_cmnts;	/* if true, put // comments in data section
+				 * identifying variable and indices, useful
+				 * for navigating through large
+				 * multi-dimensional data lists.  */
+
+    boolean full_data_cmnts;	/* if true, put // comments in data section
+				 * identifying every value, useful for
+				 * navigating through large
+				 * multi-dimensional data lists.  */
+
+    Nclang data_lang;		/* Specifies index conventions used in data
+				 * comments, either LANG_C (C, 0-based,
+				 * column major) or LANG_F (Fortran,
+				 * 1-based, row major) */
+
+    int nlvars;			/* Number of variables specified with -v
+				 * option on command line */
+
+    char** lvars;		/* list of variable names specified with -v
+				 * option on command line */
+};
diff --git a/src/utils/ncmpidump/test0.cdl b/src/utils/ncmpidump/test0.cdl
new file mode 100644
index 0000000..1e94bcf
--- /dev/null
+++ b/src/utils/ncmpidump/test0.cdl
@@ -0,0 +1,41 @@
+netcdf test0 {
+
+dimensions:
+	i = 2;
+	j = 3;
+	k = unlimited;
+        l = 3 ;
+
+variables:
+	char broiled(i,j,l);
+		broiled:act = "text string\n\t123";
+		broiled:acb = 10b;
+		broiled:acs = -200s ;
+		broiled:acl = 17000 ;
+		broiled:acf = -2.0f, 1.f, 0.0f ;
+		broiled:acd = -1.0, 2.7182818284590455;
+	short order(i,j);
+	int rigue(i,j);
+	float a_loan(i,j);
+	double entendre(i,j);
+	char cscalar;
+	double dscalar;
+	char cnodata(i);
+	short snodata(i);
+	int inodata(i);
+	float fnodata(i);
+	double dnodata(i);
+	int i(i);
+	float j(j);
+
+	:glob = "Global attribute" ;
+
+data:
+	broiled = "indistinguishable" ;
+	order = 1s, 2s, 3s, 4s, 5s, 6s;
+	rigue = 2, 3, 4, 5, 6, 7 ;
+	a_loan = 3.f, 4.f, 5.f, 6.f, 7.f, 1.0e12f ;
+	entendre = '\4', 5s, 6, 7.0f, 8.0, 1.0e30 ;
+	i = 10, 20;
+	j = 2, 4, 6;
+}
diff --git a/src/utils/ncmpidump/vardata.c b/src/utils/ncmpidump/vardata.c
new file mode 100644
index 0000000..540d376
--- /dev/null
+++ b/src/utils/ncmpidump/vardata.c
@@ -0,0 +1,738 @@
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+/* $Id: vardata.c 1440 2013-10-05 03:47:56Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include <ncconfig.h>
+#endif
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef NO_FLOAT_H
+#include <float.h>		/* for FLT_EPSILON, DBL_EPSILON */
+#endif /* NO_FLOAT_H */
+
+#include <pnetcdf.h>
+#include "ncmpidump.h"
+#include "dumplib.h"
+#include "vardata.h"
+
+static float float_epsilon(void);
+static double double_epsilon(void);
+static void init_epsilons(void);
+static void printbval(char* sout, const char* fmt, const struct ncvar* varp,
+		      signed char val);
+static void printsval(char* sout, const char* fmt, const struct ncvar* varp,
+		      short val);
+static void printival(char* sout, const char* fmt, const struct ncvar* varp,
+		      int val);
+static void printfval(char* sout, const char* fmt, const struct ncvar* varp,
+		      float val);
+static void printdval(char* sout, const char* fmt, const struct ncvar* varp,
+		      double val);
+static void lastdelim(boolean  more, boolean lastrow);
+static void annotate(const struct ncvar* vp, const struct fspec* fsp,
+		     const MPI_Offset* cor, long iel);
+static void pr_tvals(const struct ncvar *vp, size_t len, const char *fmt,
+		     boolean more, boolean lastrow, const char *vals,
+		     const struct fspec* fsp, const MPI_Offset *cor);
+static void pr_bvals(const struct ncvar *vp, size_t len, const char *fmt,
+		     boolean more, boolean lastrow, const signed char *vals,
+		     const struct fspec* fsp, const MPI_Offset *cor);
+static void pr_ubvals(const struct ncvar *vp, size_t len, const char *fmt,
+		     boolean more, boolean lastrow, const unsigned char *vals,
+		     const struct fspec* fsp, const MPI_Offset *cor);
+static void pr_svals(const struct ncvar *vp, size_t len, const char *fmt,
+		     boolean more, boolean lastrow, const short *vals,
+		     const struct fspec* fsp, const MPI_Offset *cor);
+static void pr_usvals(const struct ncvar *vp, size_t len, const char *fmt,
+		     boolean more, boolean lastrow, const unsigned short *vals,
+		     const struct fspec* fsp, const MPI_Offset *cor);
+static void pr_ivals(const struct ncvar *vp, size_t len, const char *fmt,
+		     boolean more, boolean lastrow, const int *vals,
+		     const struct fspec* fsp, const MPI_Offset *cor);
+static void pr_uivals(const struct ncvar *vp, size_t len, const char *fmt,
+		     boolean more, boolean lastrow, const unsigned int *vals,
+		     const struct fspec* fsp, const MPI_Offset *cor);
+static void pr_fvals(const struct ncvar *vp, size_t len, const char *fmt,
+		     boolean more, boolean lastrow, const float *vals,
+		     const struct fspec* fsp, const MPI_Offset *cor);
+static void pr_dvals(const struct ncvar *vp, size_t len, const char *fmt,
+		     boolean more, boolean lastrow, const double *vals,
+		     const struct fspec* fsp, const MPI_Offset *cor);
+static void pr_llvals(const struct ncvar *vp, size_t len, const char *fmt,
+		     boolean more, boolean lastrow, const long long *vals,
+		     const struct fspec* fsp, const MPI_Offset *cor);
+static void pr_ullvals(const struct ncvar *vp, size_t len, const char *fmt,
+		     boolean more, boolean lastrow, const unsigned long long *vals,
+		     const struct fspec* fsp, const MPI_Offset *cor);
+static int  upcorner(const size_t* dims, int ndims, MPI_Offset* odom,
+		     const size_t* add);
+static void lastdelim2 (boolean more, boolean lastrow);
+
+#define	STREQ(a, b)	(*(a) == *(b) && strcmp((a), (b)) == 0)
+
+static float float_eps;
+static double double_eps;
+
+static float
+float_epsilon(void)
+{
+    float float_eps;
+#ifndef NO_FLOAT_H
+    float_eps = FLT_EPSILON;
+#else /* NO_FLOAT_H */
+    {
+	float etop, ebot, eps;
+	float one = 1.0;
+	float two = 2.0;
+	etop = 1.0;
+	ebot = 0.0;
+	eps = ebot + (etop - ebot)/two;
+	while (eps != ebot && eps != etop) {
+	    float epsp1;
+
+	    epsp1 = one + eps;
+	    if (epsp1 > one)
+		etop = eps;
+	    else
+		ebot = eps;
+	    eps = ebot + (etop - ebot)/two;
+	}
+	float_eps = two * etop;
+    }
+#endif /* NO_FLOAT_H */
+    return float_eps;
+}
+
+
+static double
+double_epsilon(void)
+{
+    double double_eps;
+#ifndef NO_FLOAT_H
+    double_eps = DBL_EPSILON;
+#else /* NO_FLOAT_H */
+    {
+	double etop, ebot, eps;
+	double one = 1.0;
+	double two = 2.0;
+	etop = 1.0;
+	ebot = 0.0;
+	eps = ebot + (etop - ebot)/two;
+	while (eps != ebot && eps != etop) {
+	    double epsp1;
+
+	    epsp1 = one + eps;
+	    if (epsp1 > one)
+		etop = eps;
+	    else
+		ebot = eps;
+	    eps = ebot + (etop - ebot)/two;
+	}
+	double_eps = two * etop;
+    }
+#endif /* NO_FLOAT_H */
+    return double_eps;
+}
+
+
+static void
+init_epsilons(void)
+{
+    float_eps = float_epsilon();
+    double_eps = double_epsilon();
+}
+
+/*
+ * Output a value of a "type" variable, except if there is a fill value for
+ * the variable and the value is the fill value, print the fill-value string
+ * instead.
+ */
+#define PRINT_VAL(fn, type)                                                    \
+static void                                                                    \
+print##fn(char               *sout, /* string where output goes */             \
+          const char         *fmt,  /* printf format used for value */         \
+          const struct ncvar *varp, /* variable */                             \
+          type                val)  /* value */                                \
+{                                                                              \
+    if (varp->has_fillval) {                                                   \
+        double fillval = varp->fillval;                                        \
+        if (fillval == val) {                                                  \
+            sprintf(sout, FILL_STRING);                                        \
+            return;                                                            \
+        }                                                                      \
+    }                                                                          \
+    sprintf(sout, fmt, val);                                                   \
+}
+
+/*----< printbval() >---------------------------------------------------------*/
+/*----< printubval() >--------------------------------------------------------*/
+/*----< printsval() >---------------------------------------------------------*/
+/*----< printusval() >--------------------------------------------------------*/
+/*----< printival() >---------------------------------------------------------*/
+/*----< printuival() >--------------------------------------------------------*/
+/*----< printllval() >--------------------------------------------------------*/
+/*----< printullval() >-------------------------------------------------------*/
+PRINT_VAL(bval,   signed char)
+PRINT_VAL(ubval,  unsigned char)
+PRINT_VAL(sval,   short)
+PRINT_VAL(usval,  unsigned short)
+PRINT_VAL(ival,   int)
+PRINT_VAL(uival,  unsigned int)
+PRINT_VAL(llval,  long long)
+PRINT_VAL(ullval, unsigned long long)
+
+#define absval(x)  ( (x) < 0 ? -(x) : (x) )
+
+/*
+ * Output a value of a float variable, except if there is a fill value for
+ * the variable and the value is the fill value, print the fill-value string
+ * instead.  Floating-point fill values need only be within machine epsilon of
+ * defined fill value.
+ */
+static void
+printfval(
+    char *sout,			/* string where output goes */
+    const char *fmt,		/* printf format used for value */
+    const struct ncvar *varp,		/* variable */
+    float val			/* value */
+    )
+{
+    if(varp->has_fillval) {
+	double fillval = varp->fillval;
+	if((val > 0) == (fillval > 0) && /* prevents potential overflow */
+	   (absval(val - fillval) <= absval(float_eps * fillval))) {
+	    (void) sprintf(sout, FILL_STRING);
+	    return;
+	}
+    }
+    (void) sprintf(sout, fmt, val);
+}
+
+
+/*
+ * Output a value of a double variable, except if there is a fill value for
+ * the variable and the value is the fill value, print the fill-value string
+ * instead.  Floating-point fill values need only be within machine epsilon of
+ * defined fill value.
+ */
+static void
+printdval(
+    char *sout,			/* string where output goes */
+    const char *fmt,		/* printf format used for value */
+    const struct ncvar *varp,		/* variable */
+    double val			/* value */
+    )
+{
+    if(varp->has_fillval) {
+	double fillval = varp->fillval;
+	if((val > 0) == (fillval > 0) && /* prevents potential overflow */
+	   (absval(val - fillval) <= absval(double_eps * fillval))) {
+	    (void) sprintf(sout, FILL_STRING);
+	    return;
+	}
+    }
+    (void) sprintf(sout, fmt, val);
+}
+
+
+/*
+ * print last delimiter in each line before annotation (, or ;)
+ */
+static void
+lastdelim (boolean more, boolean lastrow)
+{
+    if (more) {
+	Printf(", ");
+    } else {
+	if(lastrow) {
+	    Printf(";");
+	} else {
+	    Printf(",");
+	}
+    }
+}
+
+/*
+ * print last delimiter in each line before annotation (, or ;)
+ */
+static void
+lastdelim2 (boolean more, boolean lastrow)
+{
+    if (more) {
+	lput(", ");
+    } else {
+	if(lastrow) {
+	    lput(" ;");
+	    lput("\n");
+	} else {
+	    lput(",\n");
+	    lput("  ");
+	}
+    }
+}
+
+
+/*
+ * Annotates a value in data section with var name and indices in comment
+ */
+static void
+annotate(
+     const struct ncvar *vp,	/* variable */
+     const struct fspec* fsp,	/* formatting specs */
+     const MPI_Offset *cor,		/* corner coordinates */
+     long iel			/* which element in current row */
+     )
+{
+    int vrank = vp->ndims;
+    int id;
+    
+    /* print indices according to data_lang */
+    (void) printf("  // %s(", vp->name);
+    switch (fsp->data_lang) {
+      case LANG_C:
+	/* C variable indices */
+	for (id = 0; id < vrank-1; id++)
+	  Printf("%lu,", (unsigned long) cor[id]);
+	Printf("%lu", (unsigned long) cor[id] + iel);
+	break;
+      case LANG_F:
+	/* Fortran variable indices */
+	Printf("%lu", (unsigned long) cor[vrank-1] + iel + 1);
+	for (id = vrank-2; id >=0 ; id--) {
+	    Printf(",%lu", 1 + (unsigned long) cor[id]);
+	}
+	break;
+    }
+    Printf(")\n    ");
+}
+
+
+/*
+ * Print a number of char variable values, where the optional comments
+ * for each value identify the variable, and each dimension index.
+ */
+static void
+pr_tvals(
+     const struct ncvar *vp,		/* variable */
+     size_t len,		/* number of values to print */
+     const char *fmt,		/* printf format used for each value.  If
+				 * ncmpi_type is NC_CHAR and this is NULL,
+				 * character arrays will be printed as
+				 * strings enclosed in quotes.  */
+     boolean more,		/* true if more data for this row will
+				 * follow, so add trailing comma */
+     boolean lastrow,		/* true if this is the last row for this
+				 * variable, so terminate with ";" instead
+				 * of "," */
+     const char *vals,		/* pointer to block of values */
+     const struct fspec* fsp,	/* formatting specs */
+     const MPI_Offset *cor 		/* corner coordinates */
+     )
+{
+    long iel;
+    const char *sp;
+    unsigned char uc;
+    char sout[100];		/* temporary string for each encoded output */
+
+    if (fmt == 0 || STREQ(fmt,"%s") || STREQ(fmt,"")) { /* as string */
+	Printf("\"");
+	/* adjust len so trailing nulls don't get printed */
+	sp = vals + len;
+	while (len != 0 && *--sp == '\0')
+	    len--;
+	for (iel = 0; iel < len; iel++)
+	    switch (uc = *vals++ & 0377) {
+	    case '\b':
+		Printf("\\b");
+		break;
+	    case '\f':
+		Printf("\\f");
+		break;
+	    case '\n':	/* generate linebreaks after new-lines */
+		Printf("\\n\",\n    \"");
+		break;
+	    case '\r':
+		Printf("\\r");
+		break;
+	    case '\t':
+		Printf("\\t");
+		break;
+	    case '\v':
+		Printf("\\v");
+		break;
+	    case '\\':
+		Printf("\\\\");
+		break;
+	    case '\'':
+		Printf("\\\'");
+		break;
+	    case '\"':
+		Printf("\\\"");
+		break;
+	    default:
+		if (isprint(uc))
+		    Printf("%c",uc);
+		else
+		    Printf("\\%.3o",uc);
+		break;
+	    }
+	Printf("\"");
+	if (fsp->full_data_cmnts) {
+	    Printf("\"");
+	    lastdelim (more, lastrow);
+	    annotate (vp, fsp,  (MPI_Offset*)cor, 0L);
+	}
+    } else {		/* use format from C_format attribute */
+	for (iel = 0; iel < len-1; iel++) {
+	    if (fsp->full_data_cmnts) {
+		Printf(fmt, *vals++);
+		Printf(", ");
+		annotate (vp, fsp,  (MPI_Offset *)cor, iel);
+	    } else {
+		(void) sprintf(sout, fmt, *vals++);
+		(void) strcat(sout, ", ");
+		lput(sout);
+	    }
+	}
+	if (fsp->full_data_cmnts) {
+	    Printf(fmt, *vals++);
+	    lastdelim (more, lastrow);
+	    annotate (vp, fsp,  (MPI_Offset *)cor, iel);
+	} else {
+	    (void) sprintf(sout, fmt, *vals++);
+	    lput(sout);
+	}
+    }
+    if (!fsp->full_data_cmnts) {
+	lastdelim2 (more, lastrow);
+    }
+}
+
+
+/*
+ * Print a number of byte variable values, where the optional comments
+ * for each value identify the variable, and each dimension index.
+ */
+#define PR_VALS(fn, type)                                                      \
+static void                                                                    \
+pr_##fn##vals(const struct ncvar *vp,     /* variable */                       \
+              size_t              len,    /* number of values to print */      \
+              const char         *fmt,    /* printf format used for each       \
+                                             value. If ncmpi_type is NC_CHAR   \
+                                             and this is NULL, character       \
+                                             arrays will be printed as         \
+                                             strings enclosed in quotes. */    \
+              boolean             more,   /* true if more data for this row    \
+                                             will follow, so add trailing      \
+                                             comma */                          \
+              boolean             lastrow,/* true if this is the last row      \
+                                             for this variable, so terminate   \
+                                             with ";" instead of "," */        \
+              const type         *vals,   /* pointer to block of values */     \
+              const struct fspec *fsp,    /* formatting specs */               \
+              const MPI_Offset   *cor)    /* corner coordinates */             \
+{                                                                              \
+    long iel;                                                                  \
+    char sout[100];  /* temporary string for each encoded output */            \
+                                                                               \
+    for (iel = 0; iel < len-1; iel++) {                                        \
+        print##fn##val(sout, fmt, vp, *vals++);                                \
+        if (fsp->full_data_cmnts) {                                            \
+            Printf("%s", sout);                                                \
+            Printf(",");                                                       \
+            annotate (vp, fsp, cor, iel);                                      \
+        } else {                                                               \
+            (void) strcat(sout, ", ");                                         \
+            lput(sout);                                                        \
+        }                                                                      \
+    }                                                                          \
+    print##fn##val(sout, fmt, vp, *vals++);                                    \
+    if (fsp->full_data_cmnts) {                                                \
+        Printf("%s", sout);                                                    \
+        lastdelim (more, lastrow);                                             \
+        annotate (vp, fsp, cor, iel);                                          \
+    } else {                                                                   \
+        lput(sout);                                                            \
+        lastdelim2 (more, lastrow);                                            \
+    }                                                                          \
+}
+
+/*----< pr_bvals() >----------------------------------------------------------*/
+/*----< pr_ubvals() >---------------------------------------------------------*/
+/*----< pr_svals() >----------------------------------------------------------*/
+/*----< pr_usvals() >---------------------------------------------------------*/
+/*----< pr_ivals() >----------------------------------------------------------*/
+/*----< pr_uivals() >---------------------------------------------------------*/
+/*----< pr_fvals() >----------------------------------------------------------*/
+/*----< pr_dvals() >----------------------------------------------------------*/
+/*----< pr_llvals() >---------------------------------------------------------*/
+/*----< pr_ullvals() >--------------------------------------------------------*/
+PR_VALS(b,   signed char)
+PR_VALS(ub,  unsigned char)
+PR_VALS(s,   short)
+PR_VALS(us,  unsigned short)
+PR_VALS(i,   int)
+PR_VALS(ui,  unsigned int)
+PR_VALS(f,   float)
+PR_VALS(d,   double)
+PR_VALS(ll,  long long)
+PR_VALS(ull, unsigned long long)
+
+/*
+ * Updates a vector of ints, odometer style.  Returns 0 if odometer
+ * overflowed, else 1.
+ */
+static int
+upcorner(
+     const size_t *dims,	/* The "odometer" limits for each dimension */
+     int ndims,			/* Number of dimensions */
+     MPI_Offset* odom,		/* The "odometer" vector to be updated */
+     const size_t* add		/* A vector to "add" to odom on each update */
+     )
+{
+    int id;
+    int ret = 1;
+
+    for (id = ndims-1; id > 0; id--) {
+	odom[id] += add[id];
+	if(odom[id] >= dims[id]) {
+	    odom[id-1]++;
+	    odom[id] -= dims[id];
+	}
+    }
+    odom[0] += add[0];
+    if (odom[0] >= dims[0])
+      ret = 0;
+    return ret;
+}
+
+
+/* Output the data for a single variable, in CDL syntax. */
+int
+vardata(
+     const struct ncvar *vp,	/* variable */
+     size_t vdims[],		/* variable dimension sizes */
+     int ncid,			/* netcdf id */
+     int varid,			/* variable id */
+     const struct fspec* fsp	/* formatting specs */
+     )
+{
+    MPI_Offset cor[NC_MAX_DIMS];	/* corner coordinates */
+    MPI_Offset edg[NC_MAX_DIMS];	/* edges of hypercube */
+    size_t add[NC_MAX_DIMS];	/* "odometer" increment to next "row"  */
+ 
+    int id;
+    int ir;
+    MPI_Offset nels;
+    MPI_Offset ncols;
+    MPI_Offset nrows;
+    int vrank = vp->ndims;
+    static int initeps = 0;
+
+    /* printf format used to print each value */
+    const char *fmt = get_fmt(ncid, varid, vp->type);
+
+#define VALBUFSIZ 1048576
+    double *vals ; /* aligned buffer */
+    int xsz=1; /* variable element size in byte */
+    int gulp;
+
+    switch(vp->type) {
+        case NC_CHAR:
+        case NC_BYTE:
+        case NC_UBYTE:
+            xsz = 1;
+            break;
+        case NC_SHORT:
+        case NC_USHORT:
+            xsz = 2;
+            break;
+        case NC_INT:
+        case NC_UINT:
+        case NC_FLOAT:
+            xsz = 4;
+            break;
+        case NC_DOUBLE:
+        case NC_INT64:
+        case NC_UINT64:
+            xsz = 8;
+            break;
+        default:
+            error("vardata: bad type");
+    }
+    gulp = VALBUFSIZ / xsz;
+    vals = (double*) malloc(VALBUFSIZ);
+
+    if (!initeps) {		/* make sure epsilons get initialized */
+	init_epsilons();
+	initeps = 1;
+    }
+
+    nels = 1;
+    for (id = 0; id < vrank; id++) {
+	cor[id] = 0;
+	edg[id] = 1;
+	nels *= vdims[id];	/* total number of values for variable */
+    }
+
+    if (vrank <= 1) {
+	Printf("\n %s = ", vp->name);
+	set_indent ((int)strlen(vp->name) + 4);
+    } else {
+	Printf("\n %s =\n  ", vp->name);
+	set_indent (2);
+    }
+
+    if (vrank < 1) {
+	ncols = 1;
+    } else {
+	ncols = vdims[vrank-1];	/* size of "row" along last dimension */
+	edg[vrank-1] = vdims[vrank-1];
+	for (id = 0; id < vrank; id++)
+	  add[id] = 0;
+	if (vrank > 1)
+	  add[vrank-2] = 1;
+    }
+    nrows = nels/ncols;		/* number of "rows" */
+    
+    for (ir = 0; ir < nrows; ir++) {
+	/*
+	 * rather than just printing a whole row at once (which might exceed
+	 * the capacity of MSDOS platforms, for example), we break each row
+	 * into smaller chunks, if necessary.
+	 */
+	size_t corsav = 0;
+	int left = (int)ncols;
+	boolean lastrow;
+
+	if (vrank > 0) {
+	    corsav = cor[vrank-1];
+	    if (fsp->brief_data_cmnts != false
+		&& vrank > 1
+		&& left > 0) {	/* print brief comment with indices range */
+		Printf("// %s(",vp->name);
+		switch (fsp->data_lang) {
+		  case LANG_C:
+		    /* print brief comment with C variable indices */
+		    for (id = 0; id < vrank-1; id++)
+		      Printf("%lu,", (unsigned long)cor[id]);
+		    if (vdims[vrank-1] == 1)
+		      Printf("0");
+		    else
+		      Printf(" 0-%lu", (unsigned long)vdims[vrank-1]-1);
+		    break;
+		  case LANG_F:
+		    /* print brief comment with Fortran variable indices */
+		    if (vdims[vrank-1] == 1)
+		      Printf("1");
+		    else
+		      Printf("1-%lu ", (unsigned long)vdims[vrank-1]);
+		    for (id = vrank-2; id >=0 ; id--) {
+			Printf(",%lu", (unsigned long)(1 + cor[id]));
+		    }
+		    break;
+		}
+		Printf(")\n    ");
+		set_indent(4);
+	    }
+	}
+	lastrow = (boolean)(ir == nrows-1);
+	while (left > 0) {
+	    size_t toget = left < gulp ? left : gulp;
+	    if (vrank > 0)
+	      edg[vrank-1] = toget;
+	    switch(vp->type) {
+	    case NC_CHAR:
+		NC_CHECK(
+		    ncmpi_get_vara_text_all(ncid, varid, cor, edg, (char *)vals) );
+	        pr_tvals(vp, toget, fmt, left > toget, lastrow,
+			 (char *) vals, fsp, cor);
+		break;
+	    case NC_BYTE:
+		NC_CHECK(
+		    ncmpi_get_vara_schar_all(ncid, varid, cor, edg, (signed char *)vals) );
+	        pr_bvals(vp, toget, fmt, left > toget, lastrow,
+			 (signed char *) vals, fsp, cor);
+		break;
+	    case NC_SHORT:
+		NC_CHECK(
+		    ncmpi_get_vara_short_all(ncid, varid, cor, edg, (short *)vals) );
+	        pr_svals(vp, toget, fmt, left > toget, lastrow,
+			 (short *) vals, fsp, cor);
+		break;
+	    case NC_INT:
+		NC_CHECK(
+		    ncmpi_get_vara_int_all(ncid, varid, cor, edg, (int *)vals) );
+	        pr_ivals(vp, toget, fmt, left > toget, lastrow,
+			 (int *) vals, fsp, cor);
+		break;
+	    case NC_FLOAT:
+		NC_CHECK(
+		    ncmpi_get_vara_float_all(ncid, varid, cor, edg, (float *)vals) );
+	        pr_fvals(vp, toget, fmt, left > toget, lastrow,
+			 (float *) vals, fsp, cor);
+		break;
+	    case NC_DOUBLE:
+		NC_CHECK(
+		    ncmpi_get_vara_double_all(ncid, varid, cor, edg, (double *)vals) );
+	        pr_dvals(vp, toget, fmt, left > toget, lastrow,
+			 (double *) vals, fsp, cor);
+		break;
+	    case NC_UBYTE:
+		NC_CHECK(
+		    ncmpi_get_vara_uchar_all(ncid, varid, cor, edg, (unsigned char *)vals) );
+	        pr_ubvals(vp, toget, fmt, left > toget, lastrow,
+			 (unsigned char *) vals, fsp, cor);
+		break;
+	    case NC_USHORT:
+		NC_CHECK(
+		    ncmpi_get_vara_ushort_all(ncid, varid, cor, edg, (unsigned short *)vals) );
+	        pr_usvals(vp, toget, fmt, left > toget, lastrow,
+			 (unsigned short *) vals, fsp, cor);
+		break;
+	    case NC_UINT:
+		NC_CHECK(
+		    ncmpi_get_vara_uint_all(ncid, varid, cor, edg, (unsigned int *)vals) );
+	        pr_uivals(vp, toget, fmt, left > toget, lastrow,
+			 (unsigned int *) vals, fsp, cor);
+		break;
+	    case NC_INT64:
+		NC_CHECK(
+		    ncmpi_get_vara_longlong_all(ncid, varid, cor, edg, (long long *)vals) );
+	        pr_llvals(vp, toget, fmt, left > toget, lastrow,
+			 (long long *) vals, fsp, cor);
+		break;
+	    case NC_UINT64:
+		NC_CHECK(
+		    ncmpi_get_vara_ulonglong_all(ncid, varid, cor, edg, (unsigned long long *)vals) );
+	        pr_ullvals(vp, toget, fmt, left > toget, lastrow,
+			 (unsigned long long *) vals, fsp, cor);
+		break;
+	    default:
+		error("vardata: bad type");
+	    }
+	    left -= toget;
+	    if (vrank > 0)
+	      cor[vrank-1] += toget;
+	}
+	if (vrank > 0)
+	  cor[vrank-1] = corsav;
+	if (ir < nrows-1)
+	  if (!upcorner(vdims,vp->ndims,cor,add))
+	    error("vardata: odometer overflowed!");
+	set_indent(2);
+
+        /* to avoid residue contents from previous read, especially
+           when read beyond the end of file (i.e. read size returned 0) */
+        memset(vals, 0, VALBUFSIZ);
+    }
+    free(vals);
+
+    return 0;
+}
diff --git a/src/utils/ncmpidump/vardata.h b/src/utils/ncmpidump/vardata.h
new file mode 100644
index 0000000..c0cb5bd
--- /dev/null
+++ b/src/utils/ncmpidump/vardata.h
@@ -0,0 +1,28 @@
+/*********************************************************************
+ *   Copyright 1993, University Corporation for Atmospheric Research
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+/* $Id: vardata.h 1468 2013-10-26 16:53:18Z wkliao $ */
+
+extern char *progname;		/* for error messages */
+
+/* Display for user-defined fill values and default floating-point fill
+   values; should match what ncgen looks for in ../ncgen/ncgen.l */
+#define FILL_STRING "_"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Output the data for a single variable, in CDL syntax. */
+extern int vardata ( const struct ncvar*, /* variable */
+		     size_t [], /* variable dimension lengths */
+		     int, /* netcdf id */
+		     int, /* variable id */
+		     const struct fspec* /* formatting specs */
+    );
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/utils/ncmpigen/Makefile.in b/src/utils/ncmpigen/Makefile.in
new file mode 100644
index 0000000..18b1011
--- /dev/null
+++ b/src/utils/ncmpigen/Makefile.in
@@ -0,0 +1,179 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2264 2015-12-22 15:42:59Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include ../../../macros.make
+
+lex		= @LEX@ -Pncmpi
+yacc		= @YACC@ -p ncmpi
+
+NCMPIDUMP	= ../ncmpidump/ncmpidump
+PROGRAM		= ncmpigen
+MANUAL		= ncmpigen.1
+
+# For VPATH build:
+# Add ../../lib into search path because ../../lib/pnetcdf.h is created in
+# the build directory at configure time and is included by C files here.
+INCLUDES	= -I$(srcdir) -I../../lib
+
+LDFLAGS        += -L../../lib
+LIBS           := -lpnetcdf $(LIBS) @LCOV_LIB@
+
+C_SOURCES       = main.c load.c escapes.c getfill.c init.c genlib.c ncmpigentab.c
+HEADERS         = generic.h genlib.h ncmpigen.h ncmpigentab.h
+
+PROGRAM_SRCS	= $(C_SOURCES)
+
+OBJS		= $(PROGRAM_SRCS:.c=.o)
+
+PACKING_LIST    = $(C_SOURCES) $(HEADERS) $(MANUAL) \
+                  ncmpigenyy.c depend Makefile.in \
+                  ncmpigen.l ncmpigen.y c0.cdl
+
+GARBAGE		= $(PROGRAM) \
+		  c0.nc c1.cdl c1.nc c2.cdl \
+		  f0.nc \
+		  ctest.c ctest ctest0.nc ctest1.cdl \
+		  ftest.f ftest ftest0.nc ftest1.cdl \
+		  lex.ncmpi.c y.tab.c y.tab.h
+
+all:		$(PROGRAM)
+
+#  generating the fortran does not work yet
+#test:           $(PROGRAM) b-test c-test f-test FORCE
+test:           $(PROGRAM) b-test c-test FORCE
+
+install: $(PROGRAM) $(MANUAL)
+	$(INSTALL) -d -m 755 $(MANDIR)/man1
+	$(INSTALL_DATA) $(srcdir)/$(MANUAL) $(MANDIR)/man1/$(MANUAL)
+
+	$(INSTALL) -d $(BINDIR)
+	$(INSTALL) -m 755 $(PROGRAM) $(BINDIR)/$(PROGRAM)
+
+uninstall:
+	$(RM) -f $(BINDIR)/$(PROGRAM)
+	$(RM) -f $(MANDIR)/man1/$(MANUAL)
+
+$(PROGRAM):	$(OBJS) $(LIBRARY)
+	$(LINK.c) $(OBJS) $(LDFLAGS) $(LIBS) 
+
+# Below is used if a PnetCDF developer wants to rebuild ncmpigenyy.c or
+# ncmpigentab.c. In that case, configure.in at the root directory needs
+# to check the availability of commands yacc/lex/bison. Otherwise the
+# below is never invoked, but records how to do it.
+$(srcdir)/ncmpigentab.c \
+$(srcdir)/ncmpigentab.h:	ncmpigen.y ncmpigenyy.c ncmpigen.h
+ifeq (@have_yacc_lex@, yes)
+	$(yacc) -d $(srcdir)/ncmpigen.y; \
+	cp -f y.tab.c ncmpigentab.c; \
+	cp -f y.tab.h ncmpigentab.h
+else
+	@echo "Error: one of $? is modified, but cannot find bison or yacc, required to re-generate $@"
+endif
+
+ncmpigenyy.c:	ncmpigen.l
+ifeq (@have_yacc_lex@, yes)
+	$(lex) $(srcdir)/ncmpigen.l; \
+	cp -f lex.ncmpi.c ncmpigenyy.c
+else
+	@echo "Error: $? is modified, but cannot find flex or lex, required to re-generate $@"
+endif
+
+vmstab.h \
+vmstab.c:	ncmpigen.y
+	@echo 1>&2 "$@ is out-of-date with respect to $?"
+	@echo 1>&2 "It must be recreated via POSIX yacc(1) on a VMS system"
+	false
+vms_yy.c:	ncmpigenyy.c
+	@echo 1>&2 "$@ is out-of-date with respect to $?"
+	@echo 1>&2 "It must be recreated via POSIX lex(1) on a VMS system"
+	false
+
+#
+# test "-b" option of ncmpigen
+#
+b-test:		$(PROGRAM) c1.cdl
+	@./$(PROGRAM) -b c1.cdl && \
+	$(NCMPIDUMP) `pwd`/c1.nc > c2.cdl
+	@if diff c1.cdl c2.cdl; then \
+	    echo "*** $(PROGRAM) -b test successful ***"; \
+	else \
+	    echo "*** $(PROGRAM) -b test failed ***"; \
+	    exit 1; \
+	fi
+
+#
+# test "-c" option of ncmpigen
+#
+c-test:	$(PROGRAM) c1.cdl
+	./$(PROGRAM) -c -o ctest0.nc $(srcdir)/c0.cdl > ctest.c && \
+	$(COMPILE.c) ctest.c && \
+	$(LINK.c) ctest.o -o ctest $(LDFLAGS) $(LIBS) && \
+	./ctest	&& \
+	$(NCMPIDUMP) -n c1 `pwd`/ctest0.nc > ctest1.cdl
+	@if diff c1.cdl ctest1.cdl; then \
+	    echo "*** $(PROGRAM) -c test successful ***"; \
+	else \
+	    echo "*** $(PROGRAM) -c test failed ***"; \
+	    exit 1; \
+	fi
+
+c1.cdl:	$(PROGRAM) c0.cdl
+	./$(PROGRAM) -b -o c0.nc $(srcdir)/c0.cdl
+	$(NCMPIDUMP) -n c1 `pwd`/c0.nc > $@
+
+#
+# test "-f" option of ncmpigen
+#
+f-test:	$(PROGRAM) c0.cdl c1.cdl
+	@if [ -n "$(MPIF77)" ]; then \
+	    $(MAKE) $(MFLAGS) ftest1.cdl && \
+	    if diff c1.cdl ftest1.cdl; then \
+		echo "*** $(PROGRAM) -f test successful ***"; \
+	    else \
+		echo "*** $(PROGRAM) -f test failed ***"; \
+		exit 1; \
+	    fi; \
+	else \
+	    echo 1>&2 "\`$@' not made because no FORTRAN compiler"; \
+	fi
+
+ftest1.cdl: $(PROGRAM) c0.cdl pnetcdf.inc
+	./$(PROGRAM) -f -o ftest0.nc $(srcdir)/c0.cdl > ftest.f
+	$(COMPILE.f) ftest.f
+	$(LINK.f) -o ftest ftest.o $(LDFLAGS) $(LIBS)
+	./ftest
+	$(NCMPIDUMP) -n c1 ftest0.nc > ftest1.cdl
+
+pnetcdf.inc:
+	@if [ -n "$(MPIF77)" ]; then \
+	    cp $(srcdir)/../../libf/$@ .; \
+	else \
+	    echo 1>&2 "\`$@' not made because no FORTRAN compiler"; \
+	fi
+
+$(PROGRAM)_src : $(PROGRAM_SRCS)
+	#setopt primary_language C
+	#load -C $(CPPFLAGS) $(PROGRAM_SRCS)
+	#load -C $(LIBS)
+	#load -C /usr/lang/SC2.0.1/libansi.a
+	#setopt program_name gribtonc
+
+$(PROGRAM)_obj : $(PROGRAM_SRCS)
+	#setopt primary_language C
+	#load -C $(CPPFLAGS) $(OBJS)
+	#load -C $(LIBS)
+	#setopt program_name gribtonc
+
+include $(srcdir)/../../../rules.make
+
+include $(srcdir)/depend
+
+.PHONY: $(LIBRARY)
diff --git a/src/utils/ncmpigen/c0.cdl b/src/utils/ncmpigen/c0.cdl
new file mode 100644
index 0000000..b1940c8
--- /dev/null
+++ b/src/utils/ncmpigen/c0.cdl
@@ -0,0 +1,331 @@
+netcdf c0 {
+dimensions:
+	Dr = UNLIMITED ; // (2 currently)
+	D1 = 1 ;
+	D2 = 2 ;
+	D3 = 3 ;
+	dim-name-dashes = 4 ;
+	dim.name.dots = 5 ;
+variables:
+	char c ;
+		c:att-name-dashes = 4 ;
+		c:att.name.dots = 5 ;
+	short s ;
+		s:b = 0b, 127b, -128b, -1b ;
+		s:s = -32768s, 0s, 32767s ;
+	int i ;
+		i:i = -2147483647, 0, 2147483647 ;
+		i:f = -1.e+36f, 0.f, 1.e+36f ;
+		i:d = -1.e+308, 0., 1.e+308 ;
+	float f ;
+		f:c = "x" ;
+	double d ;
+		d:c = "abcd\tZ$&" ;
+	char cr(Dr) ;
+	short sr(Dr) ;
+	int ir(Dr) ;
+	float fr(Dr) ;
+	double dr(Dr) ;
+	char c1(D1) ;
+	short s1(D1) ;
+	int i1(D1) ;
+	float f1(D1) ;
+	double d1(D1) ;
+	char c2(D2) ;
+	short s2(D2) ;
+	int i2(D2) ;
+	float f2(D2) ;
+	double d2(D2) ;
+	char c3(D3) ;
+	short s3(D3) ;
+	int i3(D3) ;
+	float f3(D3) ;
+	double d3(D3) ;
+	char cr1(Dr, D1) ;
+	short sr3(Dr, D3) ;
+	float f11(D1, D1) ;
+	double d12(D1, D2) ;
+	char c13(D1, D3) ;
+	short s21(D2, D1) ;
+	int i22(D2, D2) ;
+	float f23(D2, D3) ;
+	char c31(D3, D1) ;
+	short s33(D3, D3) ;
+	short sr11(Dr, D1, D1) ;
+	int ir12(Dr, D1, D2) ;
+	float fr13(Dr, D1, D3) ;
+	char cr21(Dr, D2, D1) ;
+	short sr23(Dr, D2, D3) ;
+	float fr31(Dr, D3, D1) ;
+	double dr32(Dr, D3, D2) ;
+	char cr33(Dr, D3, D3) ;
+	char c111(D1, D1, D1) ;
+	short s113(D1, D1, D3) ;
+	float f121(D1, D2, D1) ;
+	double d122(D1, D2, D2) ;
+	char c123(D1, D2, D3) ;
+	short s131(D1, D3, D1) ;
+	int i132(D1, D3, D2) ;
+	float f133(D1, D3, D3) ;
+	float f211(D2, D1, D1) ;
+	double d212(D2, D1, D2) ;
+	char c213(D2, D1, D3) ;
+	short s221(D2, D2, D1) ;
+	int i222(D2, D2, D2) ;
+	float f223(D2, D2, D3) ;
+	char c231(D2, D3, D1) ;
+	short s233(D2, D3, D3) ;
+	short s311(D3, D1, D1) ;
+	int i312(D3, D1, D2) ;
+	float f313(D3, D1, D3) ;
+	double var-name-dashes ;
+	double var.name.dots ;
+
+// global attributes:
+		:Gc = "" ;
+		:Gb = -128b, 127b ;
+		:Gs = -32768s, 0s, 32767s ;
+		:Gi = -2147483647, 0, 2147483647 ;
+		:Gf = -1.e+36f, 0.f, 1.e+36f ;
+		:Gd = -1.e+308, 0., 1.e+308 ;
+		:Gatt-name-dashes = -1 ;
+		:Gatt.name.dots = -2 ;
+data:
+
+ c = "2" ;
+
+ s = -5 ;
+
+ i = -20 ;
+
+ f = -9 ;
+
+ d = -10 ;
+
+ cr = "ab" ;
+
+ sr = -32768, 32767 ;
+
+ ir = -2147483646, 2147483647 ;
+
+ fr = -1e+36, 1e+36 ;
+
+ dr = -1e+308, 1e+308 ;
+
+ c1 = "" ;
+
+ s1 = -32768 ;
+
+ i1 = -2147483646 ;
+
+ f1 = -1e+36 ;
+
+ d1 = -1e+308 ;
+
+ c2 = "ab" ;
+
+
+ s2 = -32768, 32767 ;
+
+ i2 = -2147483646, 2147483647 ;
+
+ f2 = -1e+36, 1e+36 ;
+
+ d2 = -1e+308, 1e+308 ;
+
+ c3 = "\001\300." ;
+
+ s3 = -32768, 0, 32767 ;
+
+ i3 = -2147483646, 0, 2147483647 ;
+
+ f3 = -1e+36, 0, 1e+36 ;
+
+ d3 = -1e+308, 0, 1e+308 ;
+
+ cr1 =
+  "x",
+  "y" ;
+
+ sr3 =
+  -375, -380, -385,
+  -350, -355, -360 ;
+
+ f11 =
+  -2187 ;
+
+ d12 =
+  -3000, -3010 ;
+
+ c13 =
+  "\tb\177" ;
+
+ s21 =
+  -375,
+  -350 ;
+
+ i22 =
+  -24000, -24020,
+  -23600, -23620 ;
+
+ f23 =
+  -2187, -2196, -2205,
+  -2106, -2115, -2124 ;
+
+ c31 =
+  "+",
+  "-",
+  " " ;
+
+ s33 =
+  -375, -380, -385,
+  -350, -355, -360,
+  -325, -330, -335 ;
+
+ sr11 =
+  2500,
+  2375 ;
+
+ ir12 =
+  640000, 639980,
+  632000, 631980 ;
+
+ fr13 =
+  26244, 26235, 26226,
+  25515, 25506, 25497 ;
+
+ cr21 =
+  "@",
+  "D",
+  "H",
+  "L" ;
+
+ sr23 =
+  2500, 2495, 2490,
+  2525, 2520, 2515,
+  2375, 2370, 2365,
+  2400, 2395, 2390 ;
+
+ fr31 =
+  26244,
+  26325,
+  26406,
+  25515,
+  25596,
+  25677 ;
+
+ dr32 =
+  40000, 39990,
+  40100, 40090,
+  40200, 40190,
+  39000, 38990,
+  39100, 39090,
+  39200, 39190 ;
+
+ cr33 =
+  "1",
+  "two",
+  "3",
+  "4",
+  "5",
+  "six" ;
+
+ c111 =
+  "@" ;
+
+ s113 =
+  2500, 2495, 2490 ;
+
+ f121 =
+  26244,
+  26325 ;
+
+ d122 =
+  40000, 39990,
+  40100, 40090 ;
+
+ c123 =
+  "one",
+  "2" ;
+
+ s131 =
+  2500,
+  2525,
+  2550 ;
+
+ i132 =
+  640000, 639980,
+  640400, 640380,
+  640800, 640780 ;
+
+ f133 =
+  26244, 26235, 26226,
+  26325, 26316, 26307,
+  26406, 26397, 26388 ;
+
+ f211 =
+  26244,
+  25515 ;
+
+ d212 =
+  40000, 39990,
+  39000, 38990 ;
+
+// The following trips a bug on Cray T3E, but should work on other platforms
+// c213 =
+//  "1",
+//  "two" ;
+
+ s221 =
+  2500,
+  2525,
+  2375,
+  2400 ;
+
+ i222 =
+  640000, 639980,
+  640400, 640380,
+  632000, 631980,
+  632400, 632380 ;
+
+ f223 =
+  26244, 26235, 26226,
+  26325, 26316, 26307,
+  25515, 25506, 25497,
+  25596, 25587, 25578 ;
+
+ c231 =
+  "@",
+  "D",
+  "H",
+  "H",
+  "L",
+  "P" ;
+
+ s233 =
+  2500, 2495, 2490,
+  2525, 2520, 2515,
+  2550, 2545, 2540,
+  2375, 2370, 2365,
+  2400, 2395, 2390,
+  2425, 2420, 2415 ;
+
+ s311 =
+  2500,
+  2375,
+  2250 ;
+
+ i312 =
+  640000, 639980,
+  632000, 631980,
+  624000, 623980 ;
+
+ f313 =
+  26244, 26235, 26226,
+  25515, 25506, 25497,
+  24786, 24777, 24768 ;
+
+ var-name-dashes = -1 ;
+
+ var.name.dots = -2 ;
+}
diff --git a/src/utils/ncmpigen/depend b/src/utils/ncmpigen/depend
new file mode 100644
index 0000000..d3ca56f
--- /dev/null
+++ b/src/utils/ncmpigen/depend
@@ -0,0 +1,9 @@
+escapes.o: escapes.c generic.h ncmpigen.h genlib.h ../../lib/pnetcdf.h
+genlib.o: genlib.c generic.h ncmpigen.h genlib.h ../../lib/pnetcdf.h
+getfill.o: getfill.c generic.h ncmpigen.h genlib.h ../../lib/pnetcdf.h
+init.o: init.c generic.h ncmpigen.h genlib.h ../../lib/pnetcdf.h
+load.o: load.c generic.h ncmpigen.h genlib.h ../../lib/pnetcdf.h
+main.o: main.c generic.h ncmpigen.h genlib.h ../../lib/pnetcdf.h
+ncmpigenyy.o: ncmpigenyy.c genlib.h ncmpigentab.h ../../lib/pnetcdf.h
+ncmpigentab.o: ncmpigentab.c generic.h ncmpigen.h genlib.h ncmpigenyy.c \
+ ncmpigentab.h ../../lib/pnetcdf.h
diff --git a/src/utils/ncmpigen/escapes.c b/src/utils/ncmpigen/escapes.c
new file mode 100644
index 0000000..35686ba
--- /dev/null
+++ b/src/utils/ncmpigen/escapes.c
@@ -0,0 +1,96 @@
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+
+#include <stdlib.h>
+#include <pnetcdf.h>
+#include "generic.h"
+#include "ncmpigen.h"
+#include "genlib.h"
+
+/*
+ * "Expands" valid escape sequences in yystring (read by lex) into the
+ * apropriate characters in termstring.  For example, the two character
+ * sequence "\t" in yystring would be converted into a single tab character
+ * in termstring.  On return, termstring is properly terminated.
+ */
+
+void
+expand_escapes(
+     char *termstring,		/* returned, with escapes expanded */
+     char *yytext,
+     int yyleng)
+{
+    char *s, *t, *endp;
+    
+    yytext[yyleng-1]='\0';	/* don't copy quotes */
+    /* expand "\" escapes, e.g. "\t" to tab character  */
+    s = termstring;
+    t = yytext+1;
+    while(*t) {
+	if (*t == '\\') {
+	    t++;
+	    switch (*t) {
+	      case 'a':
+		*s++ = '\007'; t++; /* will use '\a' when STDC */
+		break;
+	      case 'b':
+		*s++ = '\b'; t++;
+		break;
+	      case 'f':
+		*s++ = '\f'; t++;
+		break;
+	      case 'n':
+		*s++ = '\n'; t++;
+		break;
+	      case 'r':
+		*s++ = '\r'; t++;
+		break;
+	      case 't':
+		*s++ = '\t'; t++;
+		break;
+	      case 'v':
+		*s++ = '\v'; t++;
+		break;
+	      case '\\':
+		*s++ = '\\'; t++;
+		break;
+	      case '?':
+		*s++ = '\177'; t++;
+		break;
+	      case '\'':
+		*s++ = '\''; t++;
+		break;
+	      case '\"':
+		*s++ = '\"'; t++;
+		break;
+	      case 'x':
+		t++; /* now t points to one or more hex digits */
+		*s++ = (char) strtol(t, &endp, 16);
+		t = endp;
+		break;
+	      case '0':
+	      case '1':
+	      case '2':
+	      case '3':
+	      case '4':
+	      case '5':
+	      case '6':
+	      case '7':
+		/* t now points to octal digits */
+		*s++ = (char) strtol(t, &endp, 8);
+		t = endp;
+		break;
+	      default:
+		*s++ = *t++;
+		break;
+	    }
+	} else {
+	    *s++ = *t++;
+	}
+    }
+    *s = '\0';
+    return;
+}
diff --git a/src/utils/ncmpigen/generic.h b/src/utils/ncmpigen/generic.h
new file mode 100644
index 0000000..5c84fff
--- /dev/null
+++ b/src/utils/ncmpigen/generic.h
@@ -0,0 +1,23 @@
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+
+#ifndef UD_GENERIC_H
+#define UD_GENERIC_H
+
+union generic {			/* used to hold any kind of fill_value */
+    float floatv;
+    double doublev;
+    int intv;
+    short shortv;
+    char charv;
+    unsigned char ubytev;
+    unsigned short ushortv;
+    unsigned int uintv;
+    long long int64v;
+    unsigned long long uint64v;
+};
+
+#endif
diff --git a/src/utils/ncmpigen/genlib.c b/src/utils/ncmpigen/genlib.c
new file mode 100644
index 0000000..b159c64
--- /dev/null
+++ b/src/utils/ncmpigen/genlib.c
@@ -0,0 +1,2043 @@
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>	/* for isprint() */
+#ifndef NO_STDARG
+#include	<stdarg.h>
+#else
+/* try varargs instead */
+#include	<varargs.h>
+#endif /* !NO_STDARG */
+#include <pnetcdf.h>
+#include "generic.h"
+#include "ncmpigen.h"
+#include "genlib.h"
+
+#include <mpi.h>
+extern char *netcdf_name; /* output netCDF filename, if on command line. */
+extern int netcdf_flag;
+extern int c_flag;
+extern int fortran_flag;
+extern int giantfile_flag;
+extern int giantvar_flag;
+extern int nofill_flag;
+
+int	lineno = 1;
+int	derror_count = 0;
+
+
+
+/* create netCDF from in-memory structure */
+static void
+gen_netcdf(
+     char *filename)		/* name for output netcdf file */
+{
+    int idim, ivar, iatt;
+    int dimid;
+    int varid;
+    int stat;
+
+    if (giantfile_flag) {
+	    stat = ncmpi_create(MPI_COMM_WORLD, filename, 
+			    NC_CLOBBER|NC_64BIT_OFFSET, MPI_INFO_NULL, &ncid);
+    } else if (giantvar_flag) {
+	    stat = ncmpi_create(MPI_COMM_WORLD, filename,
+			    NC_CLOBBER|NC_64BIT_DATA, MPI_INFO_NULL, &ncid);
+    } else {
+	    stat = ncmpi_create(MPI_COMM_WORLD, filename, 
+			    NC_CLOBBER, MPI_INFO_NULL, &ncid);
+    }
+    check_err(stat, "ncmpi_create", __func__, __LINE__, __FILE__);
+
+    /* define dimensions from info in dims array */
+    for (idim = 0; idim < ndims; idim++) {
+	stat = ncmpi_def_dim(ncid, dims[idim].name, dims[idim].size, &dimid);
+	check_err(stat, "ncmpi_def_dim", __func__, __LINE__, __FILE__);
+    }
+
+    /* define variables from info in vars array */
+    for (ivar = 0; ivar < nvars; ivar++) {
+	stat = ncmpi_def_var(ncid,
+			  vars[ivar].name,
+			  vars[ivar].type,
+			  vars[ivar].ndims,
+			  vars[ivar].dims,
+			  &varid);
+	check_err(stat, "ncmpi_def_var", __func__, __LINE__, __FILE__);
+    }
+
+    /* define attributes from info in atts array */
+    for (iatt = 0; iatt < natts; iatt++) {
+	varid = (atts[iatt].var == -1) ? NC_GLOBAL : atts[iatt].var;
+	switch(atts[iatt].type) {
+	case NC_BYTE:
+	    stat = ncmpi_put_att_schar(ncid, varid, atts[iatt].name,
+				    atts[iatt].type, atts[iatt].len,
+				    (signed char *) atts[iatt].val);
+	    break;
+	case NC_CHAR:
+	    stat = ncmpi_put_att_text(ncid, varid, atts[iatt].name,
+				   atts[iatt].len,
+				   (char *) atts[iatt].val);
+	    break;
+	case NC_SHORT:
+	    stat = ncmpi_put_att_short(ncid, varid, atts[iatt].name,
+				    atts[iatt].type, atts[iatt].len,
+				    (short *) atts[iatt].val);
+	    break;
+	case NC_INT:
+	    stat = ncmpi_put_att_int(ncid, varid, atts[iatt].name,
+				    atts[iatt].type, atts[iatt].len,
+				    (int *) atts[iatt].val);
+	    break;
+	case NC_FLOAT:
+	    stat = ncmpi_put_att_float(ncid, varid, atts[iatt].name,
+				    atts[iatt].type, atts[iatt].len,
+				    (float *) atts[iatt].val);
+	    break;
+	case NC_DOUBLE:
+	    stat = ncmpi_put_att_double(ncid, varid, atts[iatt].name,
+				    atts[iatt].type, atts[iatt].len,
+				    (double *) atts[iatt].val);
+	    break;
+	case NC_UBYTE:
+	    stat = ncmpi_put_att_ubyte(ncid, varid, atts[iatt].name,
+				    atts[iatt].type, atts[iatt].len,
+				    (unsigned char *) atts[iatt].val);
+	    break;
+	case NC_USHORT:
+	    stat = ncmpi_put_att_ushort(ncid, varid, atts[iatt].name,
+				    atts[iatt].type, atts[iatt].len,
+				    (unsigned short *) atts[iatt].val);
+	    break;
+	case NC_UINT:
+	    stat = ncmpi_put_att_uint(ncid, varid, atts[iatt].name,
+				    atts[iatt].type, atts[iatt].len,
+				    (unsigned int *) atts[iatt].val);
+	    break;
+	case NC_INT64:
+	    stat = ncmpi_put_att_longlong(ncid, varid, atts[iatt].name,
+				    atts[iatt].type, atts[iatt].len,
+				    (long long *) atts[iatt].val);
+	    break;
+	case NC_UINT64:
+	    stat = ncmpi_put_att_ulonglong(ncid, varid, atts[iatt].name,
+				    atts[iatt].type, atts[iatt].len,
+				    (unsigned long long *) atts[iatt].val);
+	    break;
+	default:
+	    stat = NC_EBADTYPE;
+	}
+	check_err(stat, "ncmpi_put_att_xxx", __func__, __LINE__, __FILE__);
+    }
+
+    /* serial netcdf calls nc_set_fill(NC_NOFILL) here, but we do not
+     * implement that routine (NC_NOFILL is our default and only behavior) */
+
+    stat = ncmpi_enddef(ncid);
+    check_err(stat, "ncmpi_enddef", __func__, __LINE__, __FILE__);
+}
+
+
+/*
+ * Given a netcdf type, a pointer to a vector of values of that type,
+ * and the index of the vector element desired, returns a pointer to a
+ * malloced string representing the value in C.
+ */
+static char *
+cstring(
+     nc_type type,		/* netCDF type code */
+     void *valp,		/* pointer to vector of values */
+     int num)			/* element of vector desired */
+{
+    static char *cp, *sp, ch;
+    signed char *bytep;
+    short *shortp;
+    int *intp;
+    float *floatp;
+    double *doublep;
+    unsigned char *ubytep;
+    unsigned short *ushortp;
+    unsigned int *uintp;
+    long long *int64p;
+    unsigned long long *uint64p;
+
+    switch (type) {
+      case NC_CHAR:
+	sp = cp = (char *) emalloc (7);
+	*cp++ = '\'';
+	ch = *((char *)valp + num);
+	switch (ch) {
+	  case '\b': *cp++ = '\\'; *cp++ = 'b'; break;
+	  case '\f': *cp++ = '\\'; *cp++ = 'f'; break;
+	  case '\n': *cp++ = '\\'; *cp++ = 'n'; break;
+	  case '\r': *cp++ = '\\'; *cp++ = 'r'; break;
+	  case '\t': *cp++ = '\\'; *cp++ = 't'; break;
+	  case '\v': *cp++ = '\\'; *cp++ = 'v'; break;
+	  case '\\': *cp++ = '\\'; *cp++ = '\\'; break;
+	  case '\'': *cp++ = '\\'; *cp++ = '\''; break;
+	  default:
+	    if (!isprint(ch)) {
+		static char octs[] = "01234567";
+		int rem = ((unsigned char)ch)%64;
+		*cp++ = '\\';
+		*cp++ = octs[((unsigned char)ch)/64]; /* to get, e.g. '\177' */
+		*cp++ = octs[rem/8];
+		*cp++ = octs[rem%8];
+	    } else {
+		*cp++ = ch;
+	    }
+	    break;
+	}
+	*cp++ = '\'';
+	*cp = '\0';
+	return sp;
+	
+      case NC_BYTE:
+	cp = (char *) emalloc (7);
+	bytep = (signed char *)valp;
+	/* Need to convert '\377' to -1, for example, on all platforms */
+	(void) sprintf(cp,"%d", (signed char) *(bytep+num));
+	return cp;
+
+      case NC_SHORT:
+	cp = (char *) emalloc (10);
+	shortp = (short *)valp;
+	(void) sprintf(cp,"%d",* (shortp + num));
+	return cp;
+
+      case NC_INT:
+	cp = (char *) emalloc (20);
+	intp = (int *)valp;
+	(void) sprintf(cp,"%d",* (intp + num));
+	return cp;
+
+      case NC_FLOAT:
+	cp = (char *) emalloc (20);
+	floatp = (float *)valp;
+	(void) sprintf(cp,"%.8g",* (floatp + num));
+	return cp;
+
+      case NC_DOUBLE:
+	cp = (char *) emalloc (20);
+	doublep = (double *)valp;
+	(void) sprintf(cp,"%.16g",* (doublep + num));
+	return cp;
+
+      case NC_UBYTE:
+	cp = (char *) emalloc (7);
+	ubytep = (unsigned char *)valp;
+	/* Need to convert '\377' to -1, for example, on all platforms */
+	(void) sprintf(cp,"%hhu", (unsigned char) *(ubytep+num));
+	return cp;
+
+      case NC_USHORT:
+	cp = (char *) emalloc (10);
+	ushortp = (unsigned short *)valp;
+	(void) sprintf(cp,"%hu",* (ushortp + num));
+	return cp;
+
+      case NC_UINT:
+	cp = (char *) emalloc (20);
+	uintp = (unsigned int *)valp;
+	(void) sprintf(cp,"%u",* (uintp + num));
+	return cp;
+
+      case NC_INT64:
+	cp = (char *) emalloc (20);
+	int64p = (long long *)valp;
+	(void) sprintf(cp,"%lld",* (int64p + num));
+	return cp;
+
+      case NC_UINT64:
+	cp = (char *) emalloc (20);
+	uint64p = (unsigned long long *)valp;
+	(void) sprintf(cp,"%llu",* (uint64p + num));
+	return cp;
+
+      default:
+	derror("cstring: bad type code");
+	return 0;
+    }
+}
+
+
+/*
+ * Generate C code for creating netCDF from in-memory structure.
+ */
+static void
+gen_c(
+     const char *filename)
+{
+    int idim, ivar, iatt, jatt, maxdims;
+    int vector_atts;
+    char *val_string;
+    char stmnt[C_MAX_STMNT];
+
+    /* wrap in main program */
+    cline("#include <stdio.h>");
+    cline("#include <stdlib.h>");
+    cline("#include <pnetcdf.h>");
+    cline("#include <mpi.h>");
+    cline("");
+    cline("void");
+    cline("check_err(int stat, const char *ncmpi_func, const char *calling_func, int lineno, const char *calling_file) {");
+    cline("    if (stat != NC_NOERR) {");
+    cline("        fprintf(stderr, \"ncmpigen error when calling %s in %s() at line %d of %s: %s\\n\", ncmpi_func, calling_func, lineno, calling_file, ncmpi_strerror(stat));");
+    cline("        exit(1);");
+    cline("    }");
+    cline("}");
+    cline("");
+    cline("int");
+    sprintf(stmnt, "main(int argc, char **argv) {\t\t\t/* create %s */", filename);
+    cline(stmnt);
+
+    /* create necessary declarations */
+    cline("");
+    cline("   int  stat;\t\t\t/* return status */");
+    cline("   int  ncid;\t\t\t/* netCDF id */");
+
+    if (ndims > 0) {
+	cline("");
+	cline("   /* dimension ids */");
+	for (idim = 0; idim < ndims; idim++) {
+	    sprintf(stmnt, "   int %s_dim;", dims[idim].lname);
+	    cline(stmnt);
+	    }
+
+	cline("");
+	cline("   /* dimension lengths */");
+	for (idim = 0; idim < ndims; idim++) {
+	    if (dims[idim].size == NC_UNLIMITED) {
+		sprintf(stmnt, "   MPI_Offset %s_len = NC_UNLIMITED;",
+			dims[idim].lname);
+	    } else {
+		sprintf(stmnt, "   MPI_Offset %s_len = %lu;",
+			dims[idim].lname,
+			(unsigned long) dims[idim].size);
+	    }
+	    cline(stmnt);
+	}
+    }
+
+    maxdims = 0;	/* most dimensions of any variable */
+    for (ivar = 0; ivar < nvars; ivar++)
+      if (vars[ivar].ndims > maxdims)
+	maxdims = vars[ivar].ndims;
+
+    if (nvars > 0) {
+	cline("");
+	cline("   /* variable ids */");
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    sprintf(stmnt, "   int %s_id;", vars[ivar].lname);
+	    cline(stmnt);
+	}
+
+	cline("");
+	cline("   /* rank (number of dimensions) for each variable */");
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    sprintf(stmnt, "#  define RANK_%s %d", vars[ivar].lname,
+		    vars[ivar].ndims);
+	    cline(stmnt);
+	}
+	if (maxdims > 0) {	/* we have dimensioned variables */
+	    cline("");
+	    cline("   /* variable shapes */");
+	    for (ivar = 0; ivar < nvars; ivar++) {
+		if (vars[ivar].ndims > 0) {
+		    sprintf(stmnt, "   int %s_dims[RANK_%s];",
+			    vars[ivar].lname, vars[ivar].lname);
+		    cline(stmnt);
+		}
+	    }
+	}
+    }
+
+    /* determine if we need any attribute vectors */
+    vector_atts = 0;
+    for (iatt = 0; iatt < natts; iatt++) {
+	if (atts[iatt].type != NC_CHAR) {
+	    vector_atts = 1;
+	    break;
+	}
+    }
+    if (vector_atts) {
+	cline("");
+	cline("   /* attribute vectors */");
+	for (iatt = 0; iatt < natts; iatt++) {
+	    if (atts[iatt].type != NC_CHAR) {
+		sprintf(stmnt,
+		    "   %s %s_%s[%lu];",
+		    ncatype(atts[iatt].type),
+		    atts[iatt].var == -1 ? "cdf" : vars[atts[iatt].var].lname,
+		    atts[iatt].lname,
+		    (unsigned long) atts[iatt].len);
+		cline(stmnt);
+	    }
+	}
+    }
+
+    /* create netCDF file, uses NC_CLOBBER mode */
+    cline("");
+    /* stat already declared above */
+    cline("   MPI_Init(&argc, &argv);");
+    cline("   /* enter define mode */");
+
+    if (giantfile_flag) {
+	    sprintf(stmnt,
+		    "   stat = ncmpi_create(MPI_COMM_WORLD, \"%s\", NC_CLOBBER|NC_64BIT_OFFSET, MPI_INFO_NULL, &ncid);",
+	    filename);
+    } else if (giantvar_flag) {
+	    sprintf(stmnt,
+		    "   stat = ncmpi_create(MPI_COMM_WORLD, \"%s\", NC_CLOBBER|NC_64BIT_DATA, MPI_INFO_NULL, &ncid);",
+		    filename);
+    } else {
+	    sprintf(stmnt, "   stat = ncmpi_create(MPI_COMM_WORLD, \"%s\", NC_CLOBBER, MPI_INFO_NULL, &ncid);", 
+			    filename);
+    }
+    cline(stmnt);
+    cline("   check_err(stat,\"ncmpi_create\", __func__, __LINE__,__FILE__);");
+    
+    /* define dimensions from info in dims array */
+    if (ndims > 0) {
+	cline("");
+	cline("   /* define dimensions */");
+    }
+    for (idim = 0; idim < ndims; idim++) {
+	sprintf(stmnt,
+		"   stat = ncmpi_def_dim(ncid, \"%s\", %s_len, &%s_dim);",
+		dims[idim].name, dims[idim].lname, dims[idim].lname);
+	cline(stmnt);
+	cline("   check_err(stat,\"ncmpi_def_dim\", __func__, __LINE__,__FILE__);");
+    }
+
+    /* define variables from info in vars array */
+    if (nvars > 0) {
+	cline("");
+	cline("   /* define variables */");
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    cline("");
+	    for (idim = 0; idim < vars[ivar].ndims; idim++) {
+		sprintf(stmnt,
+			"   %s_dims[%d] = %s_dim;",
+			vars[ivar].lname,
+			idim,
+			dims[vars[ivar].dims[idim]].lname);
+		cline(stmnt);
+	    }
+	    if (vars[ivar].ndims > 0) {	/* a dimensioned variable */
+		sprintf(stmnt,
+			"   stat = ncmpi_def_var(ncid, \"%s\", %s, RANK_%s, %s_dims, &%s_id);",
+			vars[ivar].name,
+			nctype(vars[ivar].type),
+			vars[ivar].lname,
+			vars[ivar].lname,
+			vars[ivar].lname);
+	    } else {		/* a scalar */
+		sprintf(stmnt,
+			"   stat = ncmpi_def_var(ncid, \"%s\", %s, RANK_%s, 0, &%s_id);",
+			vars[ivar].name,
+			nctype(vars[ivar].type),
+			vars[ivar].lname,
+			vars[ivar].lname);
+	    }
+	    cline(stmnt);
+	    cline("   check_err(stat,\"ncmpi_def_var\", __func__, __LINE__,__FILE__);");
+	}
+    }
+    
+    /* define attributes from info in atts array */
+    if (natts > 0) {
+	cline("");
+	cline("   /* assign attributes */");
+	for (iatt = 0; iatt < natts; iatt++) {
+	    if (atts[iatt].type == NC_CHAR) { /* string */
+		val_string = cstrstr((char *) atts[iatt].val, atts[iatt].len);
+		sprintf(stmnt,
+			"   stat = ncmpi_put_att_text(ncid, %s%s, \"%s\", %lu, %s);",
+			atts[iatt].var == -1 ? "NC_GLOBAL" : vars[atts[iatt].var].lname,
+			atts[iatt].var == -1 ? "" : "_id",
+			atts[iatt].name,
+			(unsigned long) atts[iatt].len,
+			val_string);
+		cline(stmnt);
+		free (val_string);
+	    }
+	    else {			/* vector attribute */
+		for (jatt = 0; jatt < atts[iatt].len ; jatt++) {
+		    val_string = cstring(atts[iatt].type,atts[iatt].val,jatt);
+		    sprintf(stmnt, "   %s_%s[%d] = %s;",
+			    atts[iatt].var == -1 ? "cdf" : vars[atts[iatt].var].lname,
+			    atts[iatt].lname,
+			    jatt, 
+			    val_string);
+		    cline(stmnt);
+		    free (val_string);
+		}
+		
+		sprintf(stmnt,
+			"   stat = ncmpi_put_att_%s(ncid, %s%s, \"%s\", %s, %lu, %s_%s);",
+			ncatype(atts[iatt].type),
+			atts[iatt].var == -1 ? "NC_GLOBAL" : vars[atts[iatt].var].lname,
+			atts[iatt].var == -1 ? "" : "_id",
+			atts[iatt].name,
+			nctype(atts[iatt].type),
+			(unsigned long) atts[iatt].len,
+			atts[iatt].var == -1 ? "cdf" : vars[atts[iatt].var].lname,
+			atts[iatt].lname);
+		cline(stmnt);
+	    }
+	    cline("   check_err(stat,\"ncmpi_put_att_xxx\", __func__, __LINE__,__FILE__);");
+	}
+    }
+    /* here's another place where serial netcdf would insert a call to
+     * setfill(NOFILL), but that's our only supported behavior, so skip */
+    cline("");
+    cline("   /* leave define mode */");
+    cline("   stat = ncmpi_enddef (ncid);");
+    cline("   check_err(stat,\"ncmpi_enddef\", __func__, __LINE__,__FILE__);");
+}
+
+
+/* return Fortran type name for netCDF type, given type code */
+static const char *
+ncftype(
+     nc_type type)		/* netCDF type code */
+{
+    switch (type) {
+
+      case NC_BYTE:
+	return "integer";
+      case NC_CHAR:
+	return "character";
+      case NC_SHORT:
+	return "integer";
+      case NC_INT:
+#ifdef MSDOS
+	return "integer*4";
+#else
+	return "integer";
+#endif
+      case NC_FLOAT:
+	return "real";
+#ifdef _CRAY
+      case NC_DOUBLE:
+	return "real";		/* we don't support CRAY 128-bit doubles */
+#else
+      case NC_DOUBLE:
+	return "double precision";
+#endif
+      default:
+	derror("ncftype: bad type code");
+	return 0;
+
+    }
+}
+
+
+/* return Fortran type suffix for netCDF type, given type code */
+const char *
+nfstype(
+     nc_type type)		/* netCDF type code */
+{
+    switch (type) {
+      case NC_BYTE:
+	return "int1";
+      case NC_CHAR:
+	return "text";
+      case NC_SHORT:
+	return "int2";
+      case NC_INT:
+	return "int";
+      case NC_FLOAT:
+	return "real";
+      case NC_DOUBLE:
+	return "double";
+      default:
+	derror("nfstype: bad type code");
+	return 0;
+
+    }
+}
+
+
+/* Return Fortran function suffix for netCDF type, given type code.
+ * This should correspond to the Fortran type name in ncftype().
+ */
+const char *
+nfftype(
+     nc_type type)		/* netCDF type code */
+{
+    switch (type) {
+      case NC_BYTE:
+	return "int";
+      case NC_CHAR:
+	return "text";
+      case NC_SHORT:
+	return "int";
+      case NC_INT:
+	return "int";
+      case NC_FLOAT:
+	return "real";
+#ifdef _CRAY
+      case NC_DOUBLE:
+	return "real";		/* we don't support CRAY 128-bit doubles */
+#else
+      case NC_DOUBLE:
+	return "double";
+#endif
+      default:
+	derror("nfstype: bad type code");
+	return 0;
+
+    }
+}
+
+
+/* return FORTRAN name for netCDF type, given type code */
+static const char *
+ftypename(
+     nc_type type)			/* netCDF type code */
+{
+    switch (type) {
+      case NC_BYTE:
+	return "NF_INT1";
+      case NC_CHAR:
+	return "NF_CHAR";
+      case NC_SHORT:
+	return "NF_INT2";
+      case NC_INT:
+	return "NF_INT";
+      case NC_FLOAT:
+	return "NF_REAL";
+      case NC_DOUBLE:
+	return "NF_DOUBLE";
+      default:
+	derror("ftypename: bad type code");
+	return 0;
+    }
+}
+
+
+/*
+ * Generate FORTRAN code for creating netCDF from in-memory structure.
+ */
+static void
+gen_fortran(
+     const char *filename)
+{
+    int idim, ivar, iatt, jatt, itype, maxdims;
+    int vector_atts;
+    char *val_string;
+    char stmnt[FORT_MAX_STMNT];
+    char s2[NC_MAX_NAME + 10];
+    char *sp;
+    /* Need how many netCDF types there are, because we create an array
+     * for each type of attribute. */
+    int ntypes = 6;		/* number of netCDF types, NC_BYTE, ... */
+    nc_type types[6];		/* at least ntypes */
+    MPI_Offset max_atts[NC_DOUBLE + 1];
+
+    types[0] = NC_BYTE;
+    types[1] = NC_CHAR;
+    types[2] = NC_SHORT;
+    types[3] = NC_INT;
+    types[4] = NC_FLOAT;
+    types[5] = NC_DOUBLE;
+
+    fline("program fgennc");
+
+    fline("include 'pnetcdf.inc'");
+
+    /* create necessary declarations */
+    fline("* error status return");
+    fline("integer  iret");
+    fline("* netCDF id");
+    fline("integer  ncid");
+    if (nofill_flag) {
+	    fline(" * to save old fill mode before changing it temporarily");
+	    fline ("integer oldmode");
+    }
+
+    if (ndims > 0) {
+	fline("* dimension ids");
+	for (idim = 0; idim < ndims; idim++) {
+	    sprintf(stmnt, "integer  %s_dim", dims[idim].lname);
+	    fline(stmnt);
+	}
+
+	fline("* dimension lengths");
+	for (idim = 0; idim < ndims; idim++) {
+	    sprintf(stmnt, "integer  %s_len", dims[idim].lname);
+	    fline(stmnt);
+	}
+	for (idim = 0; idim < ndims; idim++) {
+	    if (dims[idim].size == NC_UNLIMITED) {
+		sprintf(stmnt, "parameter (%s_len = NFMPI_UNLIMITED)",
+			dims[idim].lname);
+	    } else {
+		sprintf(stmnt, "parameter (%s_len = %lu)",
+			dims[idim].lname,
+			(unsigned long) dims[idim].size);
+	    }
+	    fline(stmnt);
+	}
+	
+    }
+
+    maxdims = 0;		/* most dimensions of any variable */
+    for (ivar = 0; ivar < nvars; ivar++)
+      if (vars[ivar].ndims > maxdims)
+	maxdims = vars[ivar].ndims;
+
+    if (nvars > 0) {
+	fline("* variable ids");
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    sprintf(stmnt, "integer  %s_id", vars[ivar].lname);
+	    fline(stmnt);
+	}
+
+	fline("* rank (number of dimensions) for each variable");
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    sprintf(stmnt, "integer  %s_rank", vars[ivar].lname);
+	    fline(stmnt);
+	}
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    sprintf(stmnt, "parameter (%s_rank = %d)", vars[ivar].lname,
+		    vars[ivar].ndims);
+	    fline(stmnt);
+	}
+	
+	fline("* variable shapes");
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    if (vars[ivar].ndims > 0) {
+		sprintf(stmnt, "integer  %s_dims(%s_rank)",
+			vars[ivar].lname, vars[ivar].lname);
+		fline(stmnt);
+	    }
+	}
+    }
+
+    /* declarations for variables to be initialized */
+    if (nvars > 0) {		/* we have variables */
+	fline("* data variables");
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    struct vars *v = &vars[ivar];
+	    /* Generate declarations here for non-record data variables only.
+	       Record variables are declared in separate subroutine later,
+               when we know how big they are. */
+	    if (v->ndims > 0 && v->dims[0] == rec_dim) {
+		continue;
+	    }
+	    /* Make declarations for non-text variables only;
+	       for text variables, just include string in nfmpi_put_var call */
+	    if (v->type == NC_CHAR) {
+                continue;
+            }
+	    if (v->ndims == 0) { /* scalar */
+		sprintf(stmnt, "%s  %s", ncftype(v->type),
+			v->lname);
+	    } else {
+		sprintf(stmnt, "%s  %s(", ncftype(v->type),
+			v->lname);
+		/* reverse dimensions for FORTRAN */
+		for (idim = v->ndims-1; idim >= 0; idim--) {
+		    sprintf(s2, "%s_len, ",
+			    dims[v->dims[idim]].lname);
+		    strcat(stmnt, s2);
+		}
+		sp = strrchr(stmnt, ',');
+		if(sp != NULL) {
+		    *sp = '\0';
+		}
+		strcat(stmnt, ")");
+	    }
+	    fline(stmnt);
+	}
+    }
+
+    /* determine what attribute vectors needed */
+    for (itype = 0; itype < ntypes; itype++)
+        max_atts[(int)types[itype]] = 0;
+
+    vector_atts = 0;
+    for (iatt = 0; iatt < natts; iatt++) {
+	if (atts[iatt].len > max_atts[(int) atts[iatt].type]) {
+	    max_atts[(int)atts[iatt].type] = atts[iatt].len;
+	    vector_atts = 1;
+	}
+    }
+    if (vector_atts) {
+	fline("* attribute vectors");
+	for (itype = 0; itype < ntypes; itype++) {
+	    if (types[itype] != NC_CHAR && max_atts[(int)types[itype]] > 0) {
+		sprintf(stmnt, "%s  %sval(%lu)", ncftype(types[itype]),
+			nfstype(types[itype]),
+			(unsigned long) max_atts[(int)types[itype]]);
+		fline(stmnt);
+	    }
+	}
+    }
+
+    /* create netCDF file, uses NC_CLOBBER mode */
+    fline("* enter define mode");
+    if (giantfile_flag) {
+	    sprintf(stmnt, "iret = nfmpi_create(\'%s\', OR(NF_CLOBBER|NF_64BIT_OFFSET), ncid)", filename);
+    } else if (giantvar_flag) {
+	    sprintf(stmnt, "iret = nfmpi_create(\'%s\', OR(NF_CLOBBER|NF_64BIT_DATA), ncid)", filename); 
+    } else {
+	    sprintf(stmnt, "iret = nfmpi_create(\'%s\', NF_CLOBBER, ncid)", filename);
+    }
+    fline(stmnt);
+    fline("call check_err(iret,\"nfmpi_create\", __func__, __LINE__,__FILE__)");
+    
+    /* define dimensions from info in dims array */
+    if (ndims > 0)
+        fline("* define dimensions");
+    for (idim = 0; idim < ndims; idim++) {
+	if (dims[idim].size == NC_UNLIMITED)
+            sprintf(stmnt, "iret = nfmpi_def_dim(ncid, \'%s\', NFMPI_UNLIMITED, %s_dim)",
+                    dims[idim].name, dims[idim].lname);
+	else
+            sprintf(stmnt, "iret = nfmpi_def_dim(ncid, \'%s\', %lu, %s_dim)",
+                    dims[idim].name, (unsigned long) dims[idim].size,
+			dims[idim].lname);
+	fline(stmnt);
+	fline("call check_err(iret,\"nfmpi_def_dim\", __func__, __LINE__,__FILE__)");
+    }
+	  
+    /* define variables from info in vars array */
+    if (nvars > 0) {
+	fline("* define variables");
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    for (idim = 0; idim < vars[ivar].ndims; idim++) {
+		sprintf(stmnt, "%s_dims(%d) = %s_dim",
+			vars[ivar].lname,
+			vars[ivar].ndims - idim, /* reverse dimensions */
+			dims[vars[ivar].dims[idim]].lname);
+		fline(stmnt);
+	    }
+	    if (vars[ivar].ndims > 0) {	/* a dimensioned variable */
+		sprintf(stmnt, 
+			"iret = nfmpi_def_var(ncid, \'%s\', %s, %s_rank, %s_dims, %s_id)",
+			vars[ivar].name,
+			ftypename(vars[ivar].type),
+			vars[ivar].lname,
+			vars[ivar].lname,
+			vars[ivar].lname);
+	    } else {		/* a scalar */
+		sprintf(stmnt, 
+			"iret = nfmpi_def_var(ncid, \'%s\', %s, %s_rank, 0, %s_id)",
+			vars[ivar].name,
+			ftypename(vars[ivar].type),
+			vars[ivar].lname,
+			vars[ivar].lname);
+	    }
+	    fline(stmnt);
+	    fline("call check_err(iret,\"nfmpi_def_var\", __func__, __LINE__,__FILE__)");
+	}
+    }
+
+    /* define attributes from info in atts array */
+    if (natts > 0) {
+	fline("* assign attributes");
+	for (iatt = 0; iatt < natts; iatt++) {
+	    if (atts[iatt].type == NC_CHAR) { /* string */
+		val_string = fstrstr((char *) atts[iatt].val, atts[iatt].len);
+		sprintf(stmnt, 
+			"iret = nfmpi_put_att_text(ncid, %s%s, \'%s\', %lu, %s)",
+			atts[iatt].var == -1 ? "NF_GLOBAL" : vars[atts[iatt].var].lname,
+			atts[iatt].var == -1 ? "" : "_id",
+			atts[iatt].name,
+			(unsigned long) atts[iatt].len,
+			val_string);
+		fline(stmnt);
+		fline("call check_err(iret,\"nfmpi_put_att_text\", __func__, __LINE__,__FILE__)");
+		free(val_string);
+	    } else {
+		for (jatt = 0; jatt < atts[iatt].len ; jatt++) {
+		    val_string = fstring(atts[iatt].type,atts[iatt].val,jatt);
+		    sprintf(stmnt, "%sval(%d) = %s",
+			    nfstype(atts[iatt].type),
+			    jatt+1, 
+			    val_string);
+		    fline(stmnt);
+		    free (val_string);
+		}
+	    
+		sprintf(stmnt,
+			"iret = nfmpi_put_att_%s(ncid, %s%s, \'%s\', %s, %lu, %sval)",
+			nfftype(atts[iatt].type),
+			atts[iatt].var == -1 ? "NCGLOBAL" : vars[atts[iatt].var].lname,
+			atts[iatt].var == -1 ? "" : "_id",
+			atts[iatt].name,
+			ftypename(atts[iatt].type),
+			(unsigned long) atts[iatt].len,
+			nfstype(atts[iatt].type));
+		fline(stmnt);
+		fline("call check_err(iret,\"nfmpi_put_att_xxx\", __func__, __LINE__,__FILE__)");
+	    }
+	}
+    }
+    /* skip the call to nfmpi_set_fill until we implement it */
+    fline("* leave define mode");
+    fline("iret = nfmpi_enddef(ncid)");
+    fline("call check_err(iret,\"nfmpi_enddef\", __func__, __LINE__,__FILE__)");
+}
+
+
+/*
+ * Output a C statement.
+ */
+void
+cline(
+     const char *stmnt)
+{
+    FILE *cout = stdout;
+    
+    fputs(stmnt, cout);
+    fputs("\n", cout);
+}
+
+/*
+ * From a long line FORTRAN statment, generates the necessary FORTRAN
+ * lines with continuation characters in column 6.  If stmnt starts with "*",
+ * it is treated as a one-line comment.  Statement labels are *not* handled,
+ * but since we don't generate any labels, we don't care.
+ */
+void
+fline(
+     const char *stmnt)
+{
+    FILE *fout = stdout;
+    int len = (int) strlen(stmnt);
+    int line = 0;
+    static char cont[] = {	/* continuation characters */
+	' ', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+	'+', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+	'+', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
+    
+    if(stmnt[0] == '*') {
+	fputs(stmnt, fout);
+	fputs("\n", fout);
+	return;
+    }
+
+    while (len > 0) {
+	if (line >= FORT_MAX_LINES)
+	  derror("FORTRAN statement too long: %s",stmnt);
+	(void) fprintf(fout, "     %c", cont[line++]);
+	(void) fprintf(fout, "%.66s\n", stmnt);
+	len -= 66;
+	if (len > 0)
+	  stmnt += 66;
+    }
+}
+
+
+/* return C name for netCDF type, given type code */
+const char *
+nctype(
+     nc_type type)			/* netCDF type code */
+{
+    switch (type) {
+      case NC_BYTE:    return "NC_BYTE";
+      case NC_CHAR:    return "NC_CHAR";
+      case NC_SHORT:   return "NC_SHORT";
+      case NC_INT:     return "NC_INT";
+      case NC_FLOAT:   return "NC_FLOAT";
+      case NC_DOUBLE:  return "NC_DOUBLE";
+      case NC_UBYTE:   return "NC_UBYTE";
+      case NC_USHORT:  return "NC_USHORT";
+      case NC_UINT:    return "NC_UINT";
+      case NC_INT64:   return "NC_INT64";
+      case NC_UINT64:  return "NC_UINT64";
+      default:
+	derror("nctype: bad type code");
+	return 0;
+    }
+}
+
+
+/*
+ * Return C type name for netCDF type, given type code.
+ */
+const char *
+ncctype(
+     nc_type type)			/* netCDF type code */
+{
+    switch (type) {
+      case NC_BYTE:
+	return "signed char";
+      case NC_CHAR:
+	return "char";
+      case NC_SHORT:
+	return "short";
+      case NC_INT:
+	return "int";
+      case NC_FLOAT:
+	return "float";
+      case NC_DOUBLE:
+	return "double";
+      case NC_UBYTE:
+	return "unsigned char";
+      case NC_USHORT:
+	return "unsigned short";
+      case NC_UINT:
+	return "unsigned int";
+      case NC_INT64:
+	return "long long";
+      case NC_UINT64:
+	return "unsigned long long";
+      default:
+	derror("ncctype: bad type code");
+	return 0;
+    }
+}
+
+
+
+/*
+ * Return C type name for netCDF type suffix, given type code.
+ */
+const char *
+ncstype(
+     nc_type type)			/* netCDF type code */
+{
+    switch (type) {
+      case NC_BYTE:
+	return "schar";
+      case NC_CHAR:
+	return "text";
+      case NC_SHORT:
+	return "short";
+      case NC_INT:
+	return "int";
+      case NC_FLOAT:
+	return "float";
+      case NC_DOUBLE:
+	return "double";
+      case NC_UBYTE:
+	return "uchar";
+      case NC_USHORT:
+	return "ushort";
+      case NC_UINT:
+	return "uint";
+      case NC_INT64:
+	return "longlong";
+      case NC_UINT64:
+	return "ulonglong";
+      default:
+	derror("ncstype: bad type code");
+	return 0;
+    }
+}
+
+
+/*
+ * Return C type name for netCDF attribute container type, given type code.
+ */
+const char *
+ncatype(
+     nc_type type)			/* netCDF type code */
+{
+    switch (type) {
+      case NC_BYTE:
+	return "int";		/* avoids choosing between uchar and schar */
+      case NC_CHAR:
+	return "text";
+      case NC_SHORT:
+	return "short";
+      case NC_INT:
+	return "int";
+      case NC_FLOAT:
+	return "float";
+      case NC_DOUBLE:
+	return "double";
+      case NC_UBYTE: return "uchar";
+      case NC_USHORT: return "ushort";
+      case NC_UINT: return "uint";
+      case NC_INT64: return "ulonglong";
+      case NC_UINT64: return "longlong";
+      default:
+	derror("ncatype: bad type code");
+	return 0;
+    }
+}
+
+
+/* return internal size for values of specified netCDF type */
+MPI_Offset
+nctypesize(
+     nc_type type)			/* netCDF type code */
+{
+    switch (type) {
+      case NC_BYTE:
+	return sizeof(char);
+      case NC_CHAR:
+	return sizeof(char);
+      case NC_SHORT:
+	return sizeof(short);
+      case NC_INT:
+	return sizeof(int);
+      case NC_FLOAT:
+	return sizeof(float);
+      case NC_DOUBLE:
+	return sizeof(double);
+      case NC_UBYTE:
+	return sizeof(unsigned char);
+      case NC_USHORT:
+	return sizeof(unsigned short);
+      case NC_UINT:
+	return sizeof(unsigned int);
+      case NC_INT64:
+	return sizeof(long long);
+      case NC_UINT64:
+	return sizeof(unsigned long long);
+      default:
+	derror("nctypesize: bad type code");
+	return 0;
+    }
+}
+
+
+/*
+ * Given a netcdf numeric type, a pointer to a vector of values of that
+ * type, and the index of the vector element desired, returns a pointer
+ * to a malloced string representing the value in FORTRAN.  Since this
+ * may be used in a DATA statement, it must not include non-constant
+ * expressions, such as "char(26)".
+ */
+char *
+fstring(
+     nc_type type,		/* netCDF type code */
+     void *valp,		/* pointer to vector of values */
+     int num)			/* element of vector desired */
+{
+    static char *cp;
+    signed char *schp;
+    short *shortp;
+    int *intp;
+    float *floatp;
+    double *doublep;
+
+    switch (type) {
+      case NC_BYTE:
+	cp = (char *) emalloc (10);
+	schp = (signed char *)valp;
+        sprintf(cp,"%d", schp[num]);
+	return cp;
+
+      case NC_SHORT:
+	cp = (char *) emalloc (10);
+	shortp = (short *)valp;
+	(void) sprintf(cp,"%d",* (shortp + num));
+	return cp;
+
+      case NC_INT:
+	cp = (char *) emalloc (20);
+	intp = (int *)valp;
+	(void) sprintf(cp,"%d",* (intp + num));
+	return cp;
+
+      case NC_FLOAT:
+	cp = (char *) emalloc (20);
+	floatp = (float *)valp;
+	(void) sprintf(cp,"%.8g",* (floatp + num));
+	return cp;
+
+      case NC_DOUBLE:
+	cp = (char *) emalloc (25);
+	doublep = (double *)valp;
+	(void) sprintf(cp,"%.16g",* (doublep + num));
+	expe2d(cp);	/* change 'e' to 'd' in exponent */
+	return cp;
+
+      default:
+	derror("fstring: bad type code");
+	return 0;
+    }
+}
+
+
+/*
+ * Given a pointer to a counted string, returns a pointer to a malloced string
+ * representing the string as a C constant.
+ */
+char *
+cstrstr(
+     const char *valp,		/* pointer to vector of characters*/
+     MPI_Offset len)		/* number of characters in valp */
+{
+    static char *sp;
+    char *cp;
+    char *istr, *istr0;		/* for null-terminated copy */
+    int ii;
+    
+    if(4*len+3 != (unsigned)(4*len+3)) {
+	derror("too much character data!");
+	exit(9);
+    }
+    sp = cp = (char *) emalloc(4*len+3);
+
+    if(len == 1 && *valp == 0) { /* empty string */
+	strcpy(sp,"\"\"");
+	return sp;
+    }
+
+    istr0 = istr = (char *) emalloc(len + 1);
+    for(ii = 0; ii < len; ii++) {
+	istr[ii] = valp[ii];
+    }
+    istr[len] = '\0';
+
+    *cp++ = '"';
+    for(ii = 0; ii < len; ii++) {
+	switch (*istr) {
+	case '\0': *cp++ = '\\'; *cp++ = '0'; *cp++ = '0'; *cp++ = '0'; break;
+	case '\b': *cp++ = '\\'; *cp++ = 'b'; break;
+	case '\f': *cp++ = '\\'; *cp++ = 'f'; break;
+	case '\n': *cp++ = '\\'; *cp++ = 'n'; break;
+	case '\r': *cp++ = '\\'; *cp++ = 'r'; break;
+	case '\t': *cp++ = '\\'; *cp++ = 't'; break;
+	case '\v': *cp++ = '\\'; *cp++ = 'v'; break;
+	case '\\': *cp++ = '\\'; *cp++ = '\\'; break;
+	case '\"': *cp++ = '\\'; *cp++ = '\"'; break;
+	default:
+	    if (!isprint(*istr)) {
+		static char octs[] = "01234567";
+		int rem = ((unsigned char)*istr)%64;
+		*cp++ = '\\';
+		*cp++ = octs[((unsigned char)*istr)/64]; /* to get, e.g. '\177' */
+		*cp++ = octs[rem/8];
+		*cp++ = octs[rem%8];
+	    } else {
+		*cp++ = *istr;
+	    }
+	    break;
+	}
+	istr++;
+    }
+    *cp++ = '"';
+    *cp = '\0';
+    free(istr0);
+    return sp;
+}
+
+
+/* Given a pointer to a counted string (not necessarily
+ * null-terminated), returns a pointer to a malloced string representing
+ * the string as a FORTRAN string expression.  For example, the string
+ * "don't" would yield the FORTRAN string "'don''t'", and the string
+ * "ab\ncd" would yield "'ab'//char(10)//'cd'".  The common
+ * interpretation of "\"-escaped characters is non-standard, so the
+ * generated Fortran may require adjustment in compilers that don't
+ * recognize "\" as anything special in a character context.  */
+char *
+fstrstr(
+     const char *str,			/* pointer to vector of characters */
+     MPI_Offset ilen)			/* number of characters in istr */
+{
+    static char *ostr;
+    char *cp, tstr[12];
+    int was_print = 0;		/* true if last character was printable */
+    char *istr, *istr0;		/* for null-terminated copy */
+    int ii;
+
+    if(12*ilen != (MPI_Offset)(12*ilen)) {
+	derror("too much character data!");
+	exit(9);
+    }
+    istr0 = istr = (char *) emalloc(ilen + 1);
+    for(ii = 0; ii < ilen; ii++) {
+	istr[ii] = str[ii];
+    }
+    istr[ilen] = '\0';
+    
+    if (*istr == '\0') {	/* empty string input, not legal in FORTRAN */
+	ostr = (char*) emalloc(strlen("char(0)") + 1);
+	strcpy(ostr, "char(0)");
+	free(istr0);
+	return ostr;
+    }
+    ostr = cp = (char *) emalloc(12*ilen);
+    *ostr = '\0';
+    if (isprint(*istr)) {	/* handle first character in input */
+	*cp++ = '\'';
+	switch (*istr) {
+	case '\'':
+	    *cp++ = '\'';
+	    *cp++ = '\'';
+	    break;
+	case '\\':
+	    *cp++ = '\\';
+	    *cp++ = '\\';
+	    break;
+	default:
+	    *cp++ = *istr;
+	    break;
+	}
+	*cp = '\0';
+	was_print = 1;
+    } else {
+	sprintf(tstr, "char(%d)", (unsigned char)*istr);
+	strcat(cp, tstr);
+	cp += strlen(tstr);
+	was_print = 0;
+    }
+    istr++;
+
+    for(ii = 1; ii < ilen; ii++) { /* handle subsequent characters in input */
+	if (isprint(*istr)) {
+	    if (! was_print) {
+		strcat(cp, "//'");
+		cp += 3;
+	    }
+	    switch (*istr) {
+	    case '\'':
+		*cp++ = '\'';
+		*cp++ = '\'';
+		break;
+	    case '\\':
+		*cp++ = '\\';
+		*cp++ = '\\';
+		break;
+	    default:
+		*cp++ = *istr;
+		break;
+	    }
+	    *cp = '\0';
+	    was_print = 1;
+	} else {
+	    if (was_print) {
+		*cp++ = '\'';
+		*cp = '\0';
+	    }
+	    sprintf(tstr, "//char(%d)", (unsigned char)*istr);
+	    strcat(cp, tstr);
+	    cp += strlen(tstr);
+	    was_print = 0;
+	}
+	istr++;
+    }
+    if (was_print)
+      *cp++ = '\'';
+    *cp = '\0';
+    free(istr0);
+    return ostr;
+}
+
+
+static void
+cl_netcdf(void)
+{
+    int stat = ncmpi_close(ncid);
+    check_err(stat, "ncmpi_close", __func__, __LINE__, __FILE__);
+}
+
+
+static void
+cl_c(void)
+{
+    cline("   stat = ncmpi_close(ncid);");
+    cline("   check_err(stat,\"ncmpi_close\", __func__, __LINE__,__FILE__);");
+    cline("   MPI_Finalize();");
+#ifndef vms
+    cline("   return 0;");
+#else
+    cline("   return 1;");
+#endif
+    cline("}");
+}
+
+/* Returns true if dimension used in at least one record variable,
+  otherwise false.  This is an inefficient algorithm, but we don't call
+  it very often ... */
+static int
+used_in_rec_var(
+    int idim			/* id of dimension */
+    ) {
+    int ivar;
+    
+    for (ivar = 0; ivar < nvars; ivar++) {
+	if (vars[ivar].ndims > 0 && vars[ivar].dims[0] == rec_dim) {
+	    int jdim;
+	    for (jdim = 0; jdim < vars[ivar].ndims; jdim++) {
+		if (vars[ivar].dims[jdim] == idim)
+		    return 1;
+	    }
+	}
+    }
+    return 0;
+}
+
+
+/* Return name for Fortran fill constant of specified type */
+static const char *
+f_fill_name(
+    nc_type type
+    )
+{
+    switch(type) {
+    case NC_BYTE:
+	return "NF_FILL_BYTE";
+    case NC_CHAR:
+	return "NF_FILL_CHAR";
+    case NC_SHORT:
+	return "NF_FILL_SHORT";
+    case NC_INT:
+	return "NF_FILL_INT";
+    case NC_FLOAT:
+	return "NF_FILL_FLOAT";
+    case NC_DOUBLE:
+	return "NF_FILL_DOUBLE";
+    default:
+	derror("f_fill_name: bad type code");
+    }
+    return 0;
+}
+
+
+/* Generate Fortran for cleaning up and closing file */
+static void
+cl_fortran(void)
+{
+    int ivar;
+	    int idim;
+    char stmnt[FORT_MAX_STMNT];
+    char s2[FORT_MAX_STMNT];
+    char*sp;
+    int have_rec_var = 0;
+    
+    /* do we have any record variables? */
+    for (ivar = 0; ivar < nvars; ivar++) {
+	struct vars *v = &vars[ivar];
+        if (v->ndims > 0 && v->dims[0] == rec_dim) {
+	    have_rec_var = 1;
+            break;
+        }
+    }        
+
+    if (have_rec_var) {
+	fline(" ");
+	fline("* Write record variables");
+        sprintf(stmnt, "call writerecs(ncid,");
+        /* generate parameter list for subroutine to write record vars */
+        for (ivar = 0; ivar < nvars; ivar++) {
+            struct vars *v = &vars[ivar];
+            /* if a record variable, include id in parameter list */
+            if (v->ndims > 0 && v->dims[0] == rec_dim) {
+                sprintf(s2, "%s_id,", v->lname);
+                strcat(stmnt, s2);
+            }
+        }        
+        sp = strrchr(stmnt, ',');
+        if(sp != NULL) {
+            *sp = '\0';
+        }
+        strcat(stmnt, ")");
+        fline(stmnt);
+    }
+    
+    fline(" ");
+    fline("iret = nfmpi_close(ncid)");
+    fline("call check_err(iret,\"nfmpi_close\", __func__, __LINE__,__FILE__)");
+    fline("end");
+
+    fline(" ");
+
+    if (have_rec_var) {
+        sprintf(stmnt, "subroutine writerecs(ncid,");
+        for (ivar = 0; ivar < nvars; ivar++) {
+            struct vars *v = &vars[ivar];
+            if (v->ndims > 0 && v->dims[0] == rec_dim) {
+                sprintf(s2, "%s_id,", v->lname);
+                strcat(stmnt, s2);
+            }
+        }        
+        sp = strrchr(stmnt, ',');
+        if(sp != NULL) {
+            *sp = '\0';
+        }
+        strcat(stmnt, ")");
+        fline(stmnt);
+	fline(" ");
+        fline("* netCDF id");
+        fline("integer  ncid");
+
+	fline("* variable ids");
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    struct vars *v = &vars[ivar];
+            if (v->ndims > 0 && v->dims[0] == rec_dim) {
+                sprintf(stmnt, "integer  %s_id", v->lname);
+                fline(stmnt);
+            }
+	}
+
+	fline(" ");
+        fline("include 'pnetcdf.inc'");
+
+        /* create necessary declarations */
+        fline("* error status return");
+        fline("integer  iret");
+
+        /* generate integer/parameter declarations for all dimensions
+          used in record variables, except record dimension. */
+        fline(" ");
+        fline("* netCDF dimension sizes for dimensions used with record variables");
+        for (idim = 0; idim < ndims; idim++) {
+            /* if used in a record variable and not record dimension */
+            if (used_in_rec_var(idim) && dims[idim].size != NC_UNLIMITED) {
+                sprintf(stmnt, "integer  %s_len", dims[idim].lname);
+                fline(stmnt);
+                sprintf(stmnt, "parameter (%s_len = %lu)",
+                        dims[idim].lname, (unsigned long) dims[idim].size);
+                fline(stmnt);
+            }
+        }
+
+	fline(" ");
+	fline("* rank (number of dimensions) for each variable");
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    struct vars *v = &vars[ivar];
+            if (v->ndims > 0 && v->dims[0] == rec_dim) {
+                sprintf(stmnt, "integer  %s_rank", v->lname);
+                fline(stmnt);
+            }
+	}
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    struct vars *v = &vars[ivar];
+            if (v->ndims > 0 && v->dims[0] == rec_dim) {
+                sprintf(stmnt, "parameter (%s_rank = %d)", v->lname,
+                        v->ndims);
+                fline(stmnt);
+            }
+	}
+
+	fline("* starts and counts for array sections of record variables");
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    struct vars *v = &vars[ivar];
+	    if (v->ndims > 0 && v->dims[0] == rec_dim) {
+		sprintf(stmnt,
+			"integer  %s_start(%s_rank), %s_count(%s_rank)",
+			v->lname, v->lname, v->lname, v->lname);
+		fline(stmnt);
+	    }
+	}
+        
+	fline(" ");
+	fline("* data variables");
+        
+        for (ivar = 0; ivar < nvars; ivar++) {
+            struct vars *v = &vars[ivar];
+            if (v->ndims > 0 && v->dims[0] == rec_dim) {
+                fline(" ");
+                sprintf(stmnt, "integer  %s_nr", v->lname);
+                fline(stmnt);
+                if (v->nrecs > 0) {
+                    sprintf(stmnt, "parameter (%s_nr = %lu)",
+                            v->lname, (unsigned long) v->nrecs);
+                } else {
+                    sprintf(stmnt, "parameter (%s_nr = 1)",
+                            v->lname);
+                }
+                fline(stmnt);
+		if (v->type != NC_CHAR) {
+		    char *sp;
+		    sprintf(stmnt, "%s  %s(", ncftype(v->type),
+			    v->lname);
+		    /* reverse dimensions for FORTRAN */
+		    for (idim = v->ndims-1; idim >= 0; idim--) {
+			if(v->dims[idim] == rec_dim) {
+			    sprintf(s2, "%s_nr, ", v->lname);
+			} else {
+			    sprintf(s2, "%s_len, ",
+				    dims[v->dims[idim]].lname);
+			}
+			strcat(stmnt, s2);
+		    }
+		    sp = strrchr(stmnt, ',');
+		    if(sp != NULL) {
+			*sp = '\0';
+		    }
+		    strcat(stmnt, ")");
+		    fline(stmnt);
+		}
+            }
+        }
+
+        fline(" ");
+
+        /* Emit DATA statements after declarations, because f2c on Linux can't
+          handle interspersing them */
+        for (ivar = 0; ivar < nvars; ivar++) {
+            struct vars *v = &vars[ivar];
+
+            if (v->ndims > 0 && v->dims[0] == rec_dim && v->type != NC_CHAR) {
+                if (v->has_data) {
+                    fline(v->data_stmnt);
+                } else {		/* generate data statement for FILL record */
+                    MPI_Offset rec_len = 1;
+                    for (idim = 1; idim < v->ndims; idim++) {
+                        rec_len *= dims[v->dims[idim]].size;
+                    }
+                    sprintf(stmnt,"data %s /%lu * %s/", v->lname,
+			(unsigned long) rec_len,
+                            f_fill_name(v->type));		
+                    fline(stmnt);
+                }
+            }
+        }
+	fline(" ");
+	for (ivar = 0; ivar < nvars; ivar++) {
+	    struct vars *v = &vars[ivar];
+	    /* if a record variable, declare starts and counts */
+	    if (v->ndims > 0 && v->dims[0] == rec_dim) {
+		if (!v->has_data)
+		    continue;
+		sprintf(stmnt, "* store %s", v->name);
+		fline(stmnt);
+
+		for (idim = 0; idim < v->ndims; idim++) {
+		    sprintf(stmnt, "%s_start(%d) = 1", v->lname, idim+1);
+		    fline(stmnt);
+		}
+		for (idim = v->ndims-1; idim > 0; idim--) {
+		    sprintf(stmnt, "%s_count(%d) = %s_len", v->lname,
+			    v->ndims - idim, dims[v->dims[idim]].lname);
+		    fline(stmnt);
+		}
+                sprintf(stmnt, "%s_count(%d) = %s_nr", v->lname,
+                        v->ndims, v->lname);
+		fline(stmnt);
+		
+		if (v->type != NC_CHAR) {
+		    sprintf(stmnt,
+			    "iret = nfmpi_put_vara_%s_all(ncid, %s_id, %s_start, %s_count, %s)",
+			    nfftype(v->type), v->lname, v->lname, v->lname, v->lname);
+		} else {
+		    sprintf(stmnt,
+			    "iret = nfmpi_put_vara_%s_all(ncid, %s_id, %s_start, %s_count, %s)",
+			    nfftype(v->type), v->lname, v->lname, v->lname,
+			    v->data_stmnt);
+		}
+		
+		fline(stmnt);
+		fline("call check_err(iret,\"nfmpi_put_vara_xxx\", __func__, __LINE__,__FILE__)");
+	    }
+	}
+
+        fline(" ");
+
+        fline("end");
+
+        fline(" ");
+    }
+
+    fline("subroutine check_err(iret, nfmpi_func, calling_func, lineno, calling_file)");
+    fline("integer iret");
+    fline("character*80 nfmpi_func");
+    fline("character*80 calling_func");
+    fline("character*80 calling_file");
+    fline("integer lineno");
+    fline("include 'pnetcdf.inc'");
+    fline("if (iret .ne. NF_NOERR) then");
+    fline("print *, \"ncmpigen error when calling \",trim(nfmpi_func),\" in \",trim(ncmpi_func),\"() at line \",lineno, \" of \",trim(calling_file),\": \", nfmpi_strerror(iret)");
+    fline("stop");
+    fline("endif");
+    fline("end");
+}
+
+
+/* invoke netcdf calls (or generate C or Fortran code) to create netcdf
+ * from in-memory structure. */
+void
+define_netcdf(
+     char *netcdfname)
+{
+    char *filename;		/* output file name */
+    
+    if (netcdf_name) {		/* name given on command line */
+	filename = netcdf_name;
+    } else {			/* construct name from CDL name */
+	filename = (char *) emalloc(strlen(netcdfname) + 5);
+	(void) strcpy(filename,netcdfname);
+	if (netcdf_flag == -1)
+	  (void) strcat(filename,".cdf"); /* old, deprecated extension */
+	else
+	  (void) strcat(filename,".nc"); /* new, favored extension */
+    }
+    if (netcdf_flag)
+      gen_netcdf(filename);	/* create netcdf */
+    if (c_flag)			/* create C code to create netcdf */
+      gen_c(filename);
+    if (fortran_flag)		/* create Fortran code to create netcdf */
+      gen_fortran(filename);
+    free(filename);
+}
+
+
+void
+close_netcdf(void)
+{
+    if (netcdf_flag)
+      cl_netcdf();		/* close netcdf */
+    if (c_flag)			/* create C code to close netcdf */
+      cl_c();
+    if (fortran_flag)		/* create Fortran code to close netcdf */
+      cl_fortran();
+}
+
+
+void
+check_err(int stat, const char *ncmpi_func, const char *calling_func, int lineno, const char *calling_file) {
+    if (stat != NC_NOERR) {
+	fprintf(stderr, "ncmpigen error when calling %s in %s() at line %d of %s: %s\n", ncmpi_func, calling_func, lineno, calling_file, ncmpi_strerror(stat));
+	derror_count++;
+    }
+}
+
+/*
+ * For logging error conditions.
+ */
+#ifndef NO_STDARG
+void
+derror(const char *fmt, ...)
+#else
+/*VARARGS1*/
+void
+derror(fmt, va_alist)
+     const char *fmt ;		/* error-message printf-style format */
+     va_dcl			/* variable number of error args, if any */
+#endif /* !NO_STDARG */
+{
+    va_list args ;
+
+
+    if (lineno == 1)
+      (void) fprintf(stderr,"%s: %s: ", progname, cdlname);
+    else  
+      (void) fprintf(stderr,"%s: %s line %d: ", progname, cdlname, lineno);
+
+#ifndef NO_STDARG
+    va_start(args ,fmt) ;
+#else
+    va_start(args) ;
+#endif /* !NO_STDARG */
+
+    (void) vfprintf(stderr,fmt,args) ;
+    va_end(args) ;
+
+    (void) fputc('\n',stderr) ;
+    (void) fflush(stderr);	/* to ensure log files are current */
+    derror_count++;
+}
+
+
+void *
+emalloc (			/* check return from malloc */
+	size_t size)
+{
+    void   *p;
+
+    p = (void *) malloc (size);
+    if (p == 0) {
+	derror ("out of memory\n");
+	exit(3);
+    }
+    return p;
+}
+
+void *
+ecalloc (			/* check return from calloc */
+	size_t size)
+{
+    void   *p;
+
+    p = (void *) calloc (size, 1);
+    if (p == 0) {
+	derror ("out of memory\n");
+	exit(3);
+    }
+    return p;
+}
+
+void *
+erealloc (		/* check return from realloc */
+     void *ptr,
+     size_t size)			/* if 0, this is really a free */
+{
+    void *p;
+
+    p = (void *) realloc (ptr, size);
+
+    if (p == 0 && size != 0) {
+ 	derror ("out of memory");
+	exit(3);
+    }
+    return p;
+}
+
+
+/*
+ * For generated Fortran, change 'e' to 'd' in exponent of double precision
+ * constants.
+ */
+void
+expe2d(
+    char *cp)			/* string containing double constant */
+{
+    char *expchar = strrchr(cp,'e');
+    if (expchar) {
+	*expchar = 'd';
+    }
+}
+
+
+
+/* Returns non-zero if n is a power of 2, 0 otherwise */
+static 
+int
+pow2(
+     int n)
+{
+  int m = n;
+  int p = 1;
+
+  while (m > 0) {
+    m /= 2;
+    p *= 2;
+  }
+  return p == 2*n;
+}
+
+
+/*
+ * Grow an integer array as necessary.
+ *
+ * Assumption: nar never incremented by more than 1 from last call.
+ *
+ * Makes sure an array is within a factor of 2 of the size needed.
+ *
+ * Make sure *arpp points to enough space to hold nar integers.  If not big
+ * enough, malloc more space, copy over existing stuff, free old.  When
+ * called for first time, *arpp assumed to be uninitialized.
+ */
+void
+grow_iarray(
+     int nar,			/* array must be at least this big */
+     int **arpp)		/* address of start of int array */
+{
+  if (nar == 0) {
+    *arpp = (int *) emalloc(1 * sizeof(int));
+    return;
+  }
+  if (! pow2(nar))		/* return unless nar is a power of two */
+    return;
+  *arpp = (int *) erealloc(*arpp, 2 * nar * sizeof(int));
+}
+
+
+/*
+ * Grow an array of variables as necessary.
+ *
+ * Assumption: nar never incremented by more than 1 from last call.
+ *
+ * Makes sure array is within a factor of 2 of the size needed.
+ *
+ * Make sure *arpp points to enough space to hold nar variables.  If not big
+ * enough, malloc more space, copy over existing stuff, free old.  When
+ * called for first time, *arpp assumed to be uninitialized.
+ */
+void
+grow_varray(
+     int nar,			/* array must be at least this big */
+     struct vars **arpp)	/* address of start of var array */
+{
+  if (nar == 0) {
+    *arpp = (struct vars *) emalloc(1 * sizeof(struct vars));
+    return;
+  }
+  if (! pow2(nar))		/* return unless nar is a power of two */
+    return;
+  *arpp = (struct vars *) erealloc(*arpp, 2 * nar * sizeof(struct vars));
+}
+
+
+/*
+ * Grow an array of dimensions as necessary.
+ *
+ * Assumption: nar never incremented by more than 1 from last call.
+ *
+ * Makes sure array is within a factor of 2 of the size needed.
+ *
+ * Make sure *arpp points to enough space to hold nar dimensions.  If not big
+ * enough, malloc more space, copy over existing stuff, free old.  When
+ * called for first time, *arpp assumed to be uninitialized.
+ */
+void
+grow_darray(
+     int nar,			/* array must be at least this big */
+     struct dims **arpp)	/* address of start of var array */
+{
+  if (nar == 0) {
+    *arpp = (struct dims *) emalloc(1 * sizeof(struct dims));
+    return;
+  }
+  if (! pow2(nar))		/* return unless nar is a power of two */
+    return;
+  *arpp = (struct dims *) erealloc(*arpp, 2 * nar * sizeof(struct dims));
+}
+
+
+/*
+ * Grow an array of attributes as necessary.
+ *
+ * Assumption: nar never incremented by more than 1 from last call.
+ *
+ * Makes sure array is within a factor of 2 of the size needed.
+ *
+ * Make sure *arpp points to enough space to hold nar attributes.  If not big
+ * enough, malloc more space, copy over existing stuff, free old.  When
+ * called for first time, *arpp assumed to be uninitialized.
+ */
+void
+grow_aarray(
+     int nar,			/* array must be at least this big */
+     struct atts **arpp)	/* address of start of var array */
+{
+  if (nar == 0) {
+    *arpp = (struct atts *) emalloc(1 * sizeof(struct atts));
+    return;
+  }
+  if (! pow2(nar))		/* return unless nar is a power of two */
+    return;
+  *arpp = (struct atts *) erealloc(*arpp, 2 * nar * sizeof(struct atts));
+}
+
+
+/*
+ * Replace dashes and dots in name so it can be used in C and
+ * Fortran without causing syntax errors.  Here we just replace each "-"
+ * in a name with "_dash_" and each "." with "_dot_", though any
+ * similar replacement that doesn't clash with existing names would
+ * work.
+ */
+extern char*
+decodify (
+    const char *name)
+{
+    int count=0;		/* number of minus signs in name */
+    char *newname;
+    const char *cp = name;
+    char *sp;
+
+    while(*cp != '\0') {
+	switch (*cp) {
+	case '-':
+	    count += strlen("_dash_") - 1;
+	    break;
+	case '.':
+	    count += strlen("_dot_") - 1;
+	    break;
+	case '@':
+	    count += strlen("_at_") - 1;
+	    break;
+	case '#':
+	    count += strlen("_hash_") - 1;
+	    break;
+	case '[':
+	    count += strlen("_lbr_") - 1;
+	    break;
+	case ']':
+	    count += strlen("_rbr_") - 1;
+	    break;
+	default:
+	    break;
+	}
+	cp++;
+    }
+    newname = (char *) ecalloc(strlen(name) + count + 1);
+    cp = name;
+    sp = newname;
+    while(*cp != '\0') {
+	switch (*cp) {
+	case '-':
+	    strcat(sp, "_dash_");
+	    sp += strlen("_dash_");
+	    break;
+	case '.':
+	    strcat(sp, "_dot_");
+	    sp += strlen("_dot_");
+	    break;
+	case '@':
+	    strcat(sp, "_at_");
+	    sp += strlen("_at_");
+	    break;
+	case '#':
+	    strcat(sp, "_hash_");
+	    sp += strlen("_hash_");
+	    break;
+	case '[':
+	    strcat(sp, "_lbr_");
+	    sp += strlen("_lbr_");
+	    break;
+	case ']':
+	    strcat(sp, "_rbr_");
+	    sp += strlen("_rbr_");
+	    break;
+	default:
+	    *sp++ = *cp;
+	    break;
+	}
+	cp++;
+    }
+    *sp = '\0';
+    return newname;
+}
+
+/*
+ * Replace escaped chars in CDL representation of name such as
+ * 'abc\:def\ gh\\i' with unescaped version, such as 'abc:def gh\i'.
+ */
+void
+deescapify (char *name)
+{
+    const char *cp = name;
+    char *sp;
+    size_t len = strlen(name);
+    char *newname;
+
+    if(strchr(name, '\\') == NULL)
+        return;
+
+    newname = (char *) emalloc(len + 1);
+    cp = name;
+    sp = newname;
+    while(*cp != '\0') { /* delete '\' chars, except change '\\' to '\' */
+        switch (*cp) {
+        case '\\':
+            if(*(cp+1) == '\\') {
+                *sp++ = '\\';
+                cp++;
+            }
+            break;
+        default:
+            *sp++ = *cp;
+            break;
+        }
+        cp++;
+    }
+    *sp = '\0';
+    /* assert(strlen(newname) <= strlen(name)); */
+    strncpy(name, newname, len);
+    free(newname);
+    return;
+}
+
diff --git a/src/utils/ncmpigen/genlib.h b/src/utils/ncmpigen/genlib.h
new file mode 100644
index 0000000..1d10e3a
--- /dev/null
+++ b/src/utils/ncmpigen/genlib.h
@@ -0,0 +1,98 @@
+#ifndef NC_GENLIB_H
+#define NC_GENLIB_H
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+#include <stdlib.h>
+#include <stdio.h>  /* FILE */
+#include <limits.h>
+
+extern const char *progname;	/* for error messages */
+extern const char *cdlname;	/* for error messages */
+
+#define FORT_MAX_LINES	20	/* max lines in FORTRAN statement */
+#define	FORT_MAX_STMNT	66*FORT_MAX_LINES /* max chars in FORTRAN statement */
+#define C_MAX_STMNT	FORT_MAX_STMNT /* until we fix to break up C lines */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void cline ( const char* stmnt );
+extern void fline ( const char* stmnt );
+extern const char* nctype ( nc_type  type );
+extern const char* ncctype ( nc_type  type );
+extern const char* ncstype ( nc_type  type );
+extern const char* ncatype ( nc_type  type );
+extern const char* nfstype ( nc_type  type );
+extern const char* nfftype ( nc_type  type );
+extern char* fstring ( nc_type  type, void* valp, int num );
+extern char* cstrstr ( const char* valp, MPI_Offset len );
+extern char* fstrstr ( const char* str, MPI_Offset ilen );
+extern MPI_Offset nctypesize( nc_type type );
+
+extern void	derror ( const char *fmt, ... )
+#ifdef _GNUC_
+	__attribute__ ((format (printf, 1, 2)))
+#endif
+;
+extern void	check_err(int stat, const char *ncmpi_func, const char *calling_func, int lineno, const char *calling_file);
+extern void	*emalloc ( size_t size );
+extern void	*ecalloc ( size_t size );
+extern void	*erealloc ( void *ptr, size_t size );
+extern void	expe2d ( char *ptr );
+extern void	grow_iarray ( int narray, int **array );
+extern void	grow_varray ( int narray, struct vars **array );
+extern void	grow_darray ( int narray, struct dims **array );
+extern void	grow_aarray ( int narray, struct atts **array );
+extern char*	decodify (const char *name);
+extern void     deescapify (char *name);
+
+extern int put_variable ( void* rec_start );
+
+/* initializes netcdf counts (e.g. nvars), defined in init.c */
+extern void init_netcdf ( void );
+
+/* generates all define mode stuff, defined in genlib.c */
+extern void define_netcdf(char *netcdfname);
+
+/* generates variable puts, defined in load.c */
+extern void load_netcdf ( void* rec_start );
+
+/* generates close, defined in close.c */
+extern void close_netcdf ( void );
+
+/* defined in escapes.c */
+extern void expand_escapes ( char* termstring, char* yytext, int yyleng );
+
+/* to get fill value for various types, defined in getfill.c */
+extern void nc_getfill ( nc_type  type, union generic* gval );
+
+/* to put fill value for various types, defined in getfill.c */
+extern void nc_putfill ( nc_type  type, void* val, union generic* gval );
+
+/* fills a generic array with a value, defined in getfill.c */
+extern void nc_fill ( nc_type  type, MPI_Offset num, void* datp,
+	union generic fill_val );
+
+/* reset symbol table to empty, defined in ncmpigen.y */
+extern void clearout(void);
+
+extern int ncmpiwrap(void);
+extern int ncmpiget_lineno(void);
+extern FILE *ncmpiget_in(void);
+extern FILE *ncmpiget_out(void);
+extern char *ncmpiget_text(void);
+extern void ncmpiset_lineno(int  line_number);
+extern void ncmpiset_in(FILE *in_str);
+extern void ncmpiset_out (FILE *out_str);
+extern int ncmpiget_debug(void);
+extern void ncmpiset_debug(int  bdebug);
+extern int ncmpilex_destroy(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*!NC_GENLIB_H*/
diff --git a/src/utils/ncmpigen/getfill.c b/src/utils/ncmpigen/getfill.c
new file mode 100644
index 0000000..437d137
--- /dev/null
+++ b/src/utils/ncmpigen/getfill.c
@@ -0,0 +1,151 @@
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+
+#include <pnetcdf.h>
+#include "generic.h"
+#include "ncmpigen.h"
+#include "genlib.h"
+
+
+/*
+ * Given netCDF type, return a default fill_value appropriate for
+ * that type.
+ */
+void
+nc_getfill(
+     nc_type type,
+     union generic *gval)
+{
+    switch(type) {
+      case NC_CHAR:
+	gval->charv = NC_FILL_CHAR;
+	return;
+      case NC_BYTE:
+	gval->charv = NC_FILL_BYTE;
+	return;
+      case NC_SHORT:
+	gval->shortv = NC_FILL_SHORT;
+	return;
+      case NC_INT:
+	gval->intv = NC_FILL_INT;
+	return;
+      case NC_FLOAT:
+	gval->floatv = NC_FILL_FLOAT;
+	return;
+      case NC_DOUBLE:
+	gval->doublev = NC_FILL_DOUBLE;
+	return;
+      case NC_UBYTE:
+	gval->ubytev = NC_FILL_UBYTE;
+	return;
+      case NC_USHORT:
+	gval->ushortv = NC_FILL_USHORT;
+	return;
+      case NC_UINT:
+	gval->uintv = NC_FILL_UINT;
+	return;
+      case NC_INT64:
+	gval->int64v = NC_FILL_INT64;
+	return;
+      case NC_UINT64:
+	gval->uint64v = NC_FILL_UINT64;
+	return;
+      default:
+	derror("nc_getfill: unrecognized type");
+    }
+}
+
+
+void
+nc_fill(
+     nc_type type,		/* netcdf type code  */
+     MPI_Offset num,		/* number of values to fill */
+     void *datp,		/* where to start filling */
+     union generic fill_val)	/* value to use */
+{
+    char *char_valp=NULL;	/* pointers used to accumulate data values */
+    short *short_valp=NULL;
+    int *long_valp=NULL;
+    float *float_valp=NULL;
+    double *double_valp=NULL;
+
+    switch (type) {
+      case NC_CHAR:
+      case NC_BYTE:
+	char_valp = (char *) datp;
+	break;
+      case NC_SHORT:
+	short_valp = (short *) datp;
+	break;
+      case NC_INT:
+	long_valp = (int *) datp;
+	break;
+      case NC_FLOAT:
+	float_valp = (float *) datp;
+	break;
+      case NC_DOUBLE:
+	double_valp = (double *) datp;
+	break;
+      default:
+	derror("nc_fill: unrecognized type");
+	break;
+    }
+    while (num--) {
+	switch (type) {
+	  case NC_CHAR:
+	  case NC_BYTE:
+	    *char_valp++ = fill_val.charv;
+	    break;
+	  case NC_SHORT:
+	    *short_valp++ = fill_val.shortv;
+	    break;
+	  case NC_INT:
+	    *long_valp++ = fill_val.intv;
+	    break;
+	  case NC_FLOAT:
+	    *float_valp++ = fill_val.floatv;
+	    break;
+	  case NC_DOUBLE:
+	    *double_valp++ = fill_val.doublev;
+	    break;
+	  default:
+	    derror("nc_fill: unrecognized type");
+	    break;
+	}
+    }
+}
+
+
+/*
+ * Given netCDF type, put a value of that type into a fill_value
+ */
+void
+nc_putfill(
+     nc_type type,
+     void *val,			/* value of type to be put */
+     union generic *gval)	/* where the value is to be put */
+{
+    switch(type) {
+      case NC_CHAR:
+      case NC_BYTE:
+	gval->charv = *(char *)val;
+	return;
+      case NC_SHORT:
+	gval->shortv = *(short *)val;
+	return;
+      case NC_INT:
+	gval->intv = *(int *)val;
+	return;
+      case NC_FLOAT:
+	gval->floatv = *(float *)val;
+	return;
+      case NC_DOUBLE:
+	gval->doublev = *(double *)val;
+	return;
+      default:
+	derror("nc_putfill: unrecognized type");
+    }
+}
diff --git a/src/utils/ncmpigen/init.c b/src/utils/ncmpigen/init.c
new file mode 100644
index 0000000..e51620b
--- /dev/null
+++ b/src/utils/ncmpigen/init.c
@@ -0,0 +1,43 @@
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+
+#include <stdio.h>
+#include <pnetcdf.h>
+#include "generic.h"
+#include "ncmpigen.h"
+#include "genlib.h"
+
+extern int netcdf_flag;
+extern int c_flag;
+extern int fortran_flag;
+
+struct dims *dims;		/* table of netcdf dimensions */
+
+int ncid;			/* handle for netCDF */
+int ndims;			/* number of dimensions declared for netcdf */
+int nvars;			/* number of variables declared for netcdf */
+int natts;			/* number of attributes */
+int nvdims;			/* number of dimensions for variables */
+int dimnum;			/* dimension number index for variables */
+int varnum;			/* variable number index for attributes */
+int valnum;			/* value number index for attributes */
+int rec_dim;			/* number of the unlimited dimension, if any */
+MPI_Offset var_len;			/* variable length (product of dimensions) */
+MPI_Offset rec_len;			/* number of elements for a record of data */
+MPI_Offset var_size;		/* size of each element of variable */
+
+struct vars *vars;		/* a malloc'ed list */
+
+struct atts *atts;		/* table of variable and global attributes */
+
+void
+init_netcdf(void) {			/* initialize global counts, flags */
+    
+    clearout();			/* reset symbol table to empty */
+    ndims = 0;
+    nvars = 0;
+    rec_dim = -1;		/* means no unlimited dimension (yet) */
+}
diff --git a/src/utils/ncmpigen/load.c b/src/utils/ncmpigen/load.c
new file mode 100644
index 0000000..e7c8e14
--- /dev/null
+++ b/src/utils/ncmpigen/load.c
@@ -0,0 +1,835 @@
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Id: load.c 2243 2015-12-19 01:12:41Z wkliao $
+ *********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <pnetcdf.h>
+#include "generic.h"
+#include "ncmpigen.h"
+#include "genlib.h"
+
+extern int netcdf_flag;
+extern int c_flag;
+extern int fortran_flag;
+
+#define fpr    (void) fprintf
+
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
+
+/*
+ * Remove trailing zeros (after decimal point) but not trailing decimal
+ * point from ss, a string representation of a floating-point number that
+ * might include an exponent part.
+ */
+static void
+tztrim(
+    char *ss			/* returned string representing dd */
+    )
+{
+    char *cp, *ep;
+    
+    cp = ss;
+    if (*cp == '-')
+      cp++;
+    while(isdigit((int)*cp) || *cp == '.')
+      cp++;
+    if (*--cp == '.')
+      return;
+    ep = cp+1;
+    while (*cp == '0')
+      cp--;
+    cp++;
+    if (cp == ep)
+      return;
+    while (*ep)
+      *cp++ = *ep++;
+    *cp = '\0';
+    return;
+}
+
+
+/* generate C to put netCDF record from in-memory data */
+static void
+gen_load_c(
+    void *rec_start
+    )
+{
+    int  idim, ival;
+    char *val_string;
+    char *charvalp = NULL;
+    short *shortvalp = NULL;
+    int *intvalp = NULL;
+    float *floatvalp = NULL;
+    double *doublevalp = NULL;
+    unsigned char *ubytevalp = NULL;
+    unsigned short *ushortvalp = NULL;
+    unsigned int *uintvalp = NULL;
+    long long *int64valp = NULL;
+    unsigned long long *uint64valp = NULL;
+    char stmnt[C_MAX_STMNT];
+    MPI_Offset stmnt_len;
+    char s2[C_MAX_STMNT];
+
+    if (!vars[varnum].has_data)
+	return;
+
+    cline("");
+    sprintf(stmnt, "   {\t\t\t/* store %s */", vars[varnum].name);
+    cline(stmnt);
+
+    if (vars[varnum].ndims > 0) {
+	if (vars[varnum].dims[0] == rec_dim) {
+	    sprintf(stmnt, "    static MPI_Offset %s_start[RANK_%s];",
+		    vars[varnum].lname, vars[varnum].lname);
+	    cline(stmnt);
+
+	    sprintf(stmnt, "    static MPI_Offset %s_count[RANK_%s];",
+		    vars[varnum].lname, vars[varnum].lname);
+	    cline(stmnt);
+	}
+	
+	/* load variable with data values using static initialization */
+	sprintf(stmnt, "    static %s %s[] = {",
+		ncctype(vars[varnum].type),
+		vars[varnum].lname);
+	
+	stmnt_len = strlen(stmnt);
+	switch (vars[varnum].type) {
+	  case NC_CHAR:
+	    val_string = cstrstr((char *) rec_start, var_len);
+	    sprintf(s2, "%s", val_string);
+	    strncat(stmnt, s2, C_MAX_STMNT - strlen(stmnt) );
+	    free(val_string);
+	    break;
+	  default:
+	    switch (vars[varnum].type) {
+	      case NC_BYTE:
+		charvalp = (char *) rec_start;
+		break;
+	      case NC_SHORT:
+		shortvalp = (short *) rec_start;
+		break;
+	      case NC_INT:
+		intvalp = (int *) rec_start;
+		break;
+	      case NC_FLOAT:
+		floatvalp = (float *) rec_start;
+		break;
+	      case NC_DOUBLE:
+		doublevalp = (double *) rec_start;
+		break;
+	      case NC_UBYTE:
+		ubytevalp = (unsigned char *) rec_start;
+		break;
+	      case NC_USHORT:
+		ushortvalp = (unsigned short *) rec_start;
+		break;
+	      case NC_UINT:
+		uintvalp = (unsigned int *) rec_start;
+		break;
+	      case NC_INT64:
+		int64valp = (long long *) rec_start;
+		break;
+	      case NC_UINT64:
+		uint64valp = (unsigned long long *) rec_start;
+		break;
+	      default:
+		derror("Unhandled type %d\n", vars[varnum].type);
+		break;
+	    }
+            for (ival = 0; ival < var_len-1; ival++) {
+		switch (vars[varnum].type) {
+		  case NC_BYTE:
+			sprintf(s2, "%d, ", *charvalp++);
+		    break;
+		  case NC_SHORT:
+			sprintf(s2, "%d, ", *shortvalp++);
+		    break;
+		  case NC_INT:
+			sprintf(s2, "%ld, ", (long)*intvalp++);
+		    break;
+		  case NC_FLOAT:
+			sprintf(s2, "%.8g, ", *floatvalp++);
+		    break;
+		  case NC_DOUBLE:
+			sprintf(s2, "%#.16g", *doublevalp++);
+			tztrim(s2);
+			strcat(s2, ", ");
+		    break;
+		  case NC_UBYTE:
+			sprintf(s2, "%hhu, ", (unsigned char)*ubytevalp++);
+		    break;
+		  case NC_USHORT:
+			sprintf(s2, "%hu, ", (unsigned short)*ushortvalp++);
+		    break;
+		  case NC_UINT:
+			sprintf(s2, "%u, ", (unsigned int)*uintvalp++);
+		    break;
+		  case NC_INT64:
+			sprintf(s2, "%lld, ", (long long)*int64valp++);
+		    break;
+		  case NC_UINT64:
+			sprintf(s2, "%llu, ", (unsigned long long)*uint64valp++);
+		    break;
+		  default:
+		    derror("Unhandled type %d\n", vars[varnum].type);
+		    break;
+
+		}
+		stmnt_len += strlen(s2);
+		if (stmnt_len < C_MAX_STMNT)
+		  strcat(stmnt, s2);
+		else {
+		    cline(stmnt);
+		    strcpy(stmnt,s2);
+		    stmnt_len = strlen(stmnt);
+		}
+	    }
+	    for (;ival < var_len; ival++) {
+		switch (vars[varnum].type) {
+		  case NC_BYTE:
+			sprintf(s2, "%d", *charvalp);
+		    break;
+		  case NC_SHORT:
+			sprintf(s2, "%d", *shortvalp);
+		    break;
+		  case NC_INT:
+			sprintf(s2, "%ld", (long)*intvalp);
+		    break;
+		  case NC_FLOAT:
+			sprintf(s2, "%.8g", *floatvalp);
+		    break;
+		  case NC_DOUBLE:
+			sprintf(s2, "%#.16g", *doublevalp++);
+			tztrim(s2);
+		    break;
+		  case NC_UBYTE:
+			sprintf(s2, "%hhu, ", (unsigned char)*ubytevalp++);
+		    break;
+		  case NC_USHORT:
+			sprintf(s2, "%hu, ", (unsigned short)*ushortvalp++);
+		    break;
+		  case NC_UINT:
+			sprintf(s2, "%u, ", (unsigned int)*uintvalp++);
+		    break;
+		  case NC_INT64:
+			sprintf(s2, "%lld, ", (long long)*int64valp++);
+		    break;
+		  case NC_UINT64:
+			sprintf(s2, "%llu, ", (unsigned long long)*uint64valp++);
+		    break;
+		  default:
+		    derror("Unhandled type %d\n", vars[varnum].type);
+		    break;
+		}
+		stmnt_len += strlen(s2);
+		if (stmnt_len < C_MAX_STMNT)
+		  strcat(stmnt, s2);
+		else {
+		    cline(stmnt);
+		    strcpy(stmnt,s2);
+		    stmnt_len = strlen(stmnt);
+		}
+	    }
+	    break;
+	}
+	strcat(stmnt,"};");
+	cline(stmnt);
+
+	if (vars[varnum].dims[0] == rec_dim) {
+	    sprintf(stmnt,
+		    "    %s_len = %lu;			/* number of records of %s data */",
+		    dims[rec_dim].lname,
+		    (unsigned long)vars[varnum].nrecs, /* number of recs for this variable */
+		    vars[varnum].name);
+	    cline(stmnt);
+	    
+	    for (idim = 0; idim < vars[varnum].ndims; idim++) {
+		sprintf(stmnt, "    %s_start[%d] = 0;",
+			vars[varnum].lname,
+			idim);
+		cline(stmnt);
+	    }
+
+	    for (idim = 0; idim < vars[varnum].ndims; idim++) {
+		sprintf(stmnt, "    %s_count[%d] = %s_len;",
+			vars[varnum].lname,
+			idim,
+			dims[vars[varnum].dims[idim]].lname);
+		cline(stmnt);
+	    }
+	}
+	
+	if (vars[varnum].dims[0] == rec_dim) {
+	    sprintf(stmnt,
+		    "    stat = ncmpi_put_vara_%s_all(ncid, %s_id, %s_start, %s_count, %s);",
+		    ncstype(vars[varnum].type),
+		    vars[varnum].lname,
+		    vars[varnum].lname,
+		    vars[varnum].lname,
+		    vars[varnum].lname);
+	     cline(stmnt);
+	} else {		/* non-record variables */
+	    cline("  ncmpi_begin_indep_data(ncid);");
+	    sprintf(stmnt,
+		    "    stat = ncmpi_put_var_%s(ncid, %s_id, %s);",
+		    ncstype(vars[varnum].type),
+		    vars[varnum].lname,
+		    vars[varnum].lname);
+	    cline(stmnt);
+	    cline("  ncmpi_end_indep_data(ncid);");
+	}
+    } else {			/* scalar variables */
+	/* load variable with data values using static initialization */
+	sprintf(stmnt, "    static %s %s = ",
+		ncctype(vars[varnum].type),
+		vars[varnum].lname);
+	
+	switch (vars[varnum].type) {
+	  case NC_CHAR:
+	    val_string = cstrstr((char *) rec_start, var_len);
+	    val_string[strlen(val_string)-1] = '\0';
+	    sprintf(s2, "'%s'", &val_string[1]);
+	    free(val_string);
+	    break;
+	  case NC_BYTE:
+	    charvalp = (char *) rec_start;
+	    sprintf(s2, "%d", *charvalp);
+	    break;
+	  case NC_SHORT:
+	    shortvalp = (short *) rec_start;
+	    sprintf(s2, "%d", *shortvalp);
+	    break;
+	  case NC_INT:
+	    intvalp = (int *) rec_start;
+	    sprintf(s2, "%ld", (long)*intvalp);
+	    break;
+	  case NC_FLOAT:
+	    floatvalp = (float *) rec_start;
+	    sprintf(s2, "%.8g", *floatvalp);
+	    break;
+	  case NC_DOUBLE:
+	    doublevalp = (double *) rec_start;
+	    sprintf(s2, "%#.16g", *doublevalp++);
+	    tztrim(s2);
+	    break;
+	  case NC_UBYTE:
+	    ubytevalp = (unsigned char *) rec_start;
+	    sprintf(s2, "%hhu", (unsigned char)*ubytevalp);
+	    break;
+	  case NC_USHORT:
+	    ushortvalp = (unsigned short *) rec_start;
+	    sprintf(s2, "%hu", (unsigned short)*ushortvalp);
+	    break;
+	  case NC_UINT:
+	    uintvalp = (unsigned int *) rec_start;
+	    sprintf(s2, "%u", (unsigned int)*uintvalp);
+	    break;
+	  case NC_INT64:
+	    int64valp = (long long *) rec_start;
+	    sprintf(s2, "%lld", (long long)*int64valp);
+	    break;
+	  case NC_UINT64:
+	    uint64valp = (unsigned long long *) rec_start;
+	    sprintf(s2, "%llu", (unsigned long long)*uint64valp);
+	    break;
+	  default:
+	    derror("Unhandled type %d\n", vars[varnum].type);
+	    break;
+	}
+	strncat(stmnt, s2, C_MAX_STMNT - strlen(stmnt) );
+	strcat(stmnt,";");
+	cline(stmnt);
+	cline("  ncmpi_begin_indep_data(ncid);");
+	sprintf(stmnt,
+		"    stat = ncmpi_put_var_%s(ncid, %s_id, &%s);",
+		ncstype(vars[varnum].type),
+		vars[varnum].lname,
+		vars[varnum].lname);
+	cline(stmnt);
+	cline("  ncmpi_end_indep_data(ncid);");
+    }
+    cline("    check_err(stat,__LINE__,__FILE__);");
+    cline("   }");
+}
+    
+
+/*
+ * Add to a partial Fortran statement, checking if it's too long.  If it is too
+ * long, output the first part of it as a single statement with continuation
+ * characters and start a new (probably invalid) statement with the remainder.
+ * This will cause a Fortran compiler error, but at least all the information
+ * will be available.
+ */
+static void
+fstrcat(
+    char *s,			/* source string of stement being built */
+    const char *t,		/* string to be appended to source */
+    MPI_Offset *slenp			/* pointer to length of source string */
+    )
+{
+    *slenp += strlen(t);
+    if (*slenp >= FORT_MAX_STMNT) {
+	derror("FORTRAN statement too long: %s",s);
+	fline(s);
+	strcpy(s, t);
+	*slenp = strlen(s);
+    } else {
+	strcat(s, t);
+    }
+}
+
+/*
+ * Create Fortran data statement to initialize numeric variable with
+ * values.
+ */
+static void
+f_var_init(
+    int varnum,			/* which variable */
+    void *rec_start		/* start of data */
+    )
+{
+    char *val_string;
+    char *charvalp;
+    short *shortvalp;
+    int *intvalp;
+    float *floatvalp;
+    double *doublevalp;
+    unsigned char *ubytevalp;
+    unsigned short *ushortvalp;
+    unsigned int *uintvalp;
+    long long *int64valp;
+    unsigned long long *uint64valp;
+    char stmnt[FORT_MAX_STMNT];
+    MPI_Offset stmnt_len;
+    char s2[FORT_MAX_STMNT];
+    int ival;
+    
+    /* load variable with data values  */
+    sprintf(stmnt, "data %s /",vars[varnum].lname);
+    stmnt_len = strlen(stmnt);
+    switch (vars[varnum].type) {
+    case NC_BYTE:
+	charvalp = (char *) rec_start;
+	for (ival = 0; ival < var_len-1; ival++) {
+	    val_string = fstring(NC_BYTE,(void *)charvalp++,0);
+	    sprintf(s2, "%s, ", val_string);
+	    fstrcat(stmnt, s2, &stmnt_len);
+	    free(val_string);
+	}
+	val_string = fstring(NC_BYTE,(void *)charvalp++,0);
+	fstrcat(stmnt, val_string, &stmnt_len);
+	free(val_string);
+	break;
+    case NC_SHORT:
+	shortvalp = (short *) rec_start;
+	for (ival = 0; ival < var_len-1; ival++) {
+	    sprintf(s2, "%d, ", *shortvalp++);
+	    fstrcat(stmnt, s2, &stmnt_len);
+	}
+	sprintf(s2, "%d", *shortvalp);
+	fstrcat(stmnt, s2, &stmnt_len);
+	break;
+    case NC_INT:
+	intvalp = (int *) rec_start;
+	for (ival = 0; ival < var_len-1; ival++) {
+	    sprintf(s2, "%ld, ", (long)*intvalp++);
+	    fstrcat(stmnt, s2, &stmnt_len);
+	}
+	sprintf(s2, "%ld", (long)*intvalp);
+	fstrcat(stmnt, s2, &stmnt_len);
+	break;
+    case NC_FLOAT:
+	floatvalp = (float *) rec_start;
+	for (ival = 0; ival < var_len-1; ival++) {
+	    sprintf(s2, "%.8g, ", *floatvalp++);
+	    fstrcat(stmnt, s2, &stmnt_len);
+	}
+	sprintf(s2, "%.8g", *floatvalp);
+	fstrcat(stmnt, s2, &stmnt_len);
+	break;
+    case NC_DOUBLE:
+	doublevalp = (double *) rec_start;
+	for (ival = 0; ival < var_len-1; ival++) {
+	    sprintf(s2, "%#.16g", *doublevalp++);
+	    tztrim(s2);
+	    expe2d(s2);	/* change 'e' to 'd' in exponent */
+	    fstrcat(s2, ", ", &stmnt_len);
+	    fstrcat(stmnt, s2, &stmnt_len);
+	}
+	sprintf(s2, "%#.16g", *doublevalp++);
+	tztrim(s2);
+	expe2d(s2);
+	fstrcat(stmnt, s2, &stmnt_len);
+	break;
+    case NC_UBYTE:
+	ubytevalp = (unsigned char *) rec_start;
+	for (ival = 0; ival < var_len-1; ival++) {
+	    sprintf(s2, "%hhu, ", (unsigned char)*ubytevalp++);
+	    fstrcat(stmnt, s2, &stmnt_len);
+	}
+	sprintf(s2, "%hhu", (unsigned char)*ubytevalp);
+	fstrcat(stmnt, s2, &stmnt_len);
+	break;
+    case NC_USHORT:
+	ushortvalp = (unsigned short *) rec_start;
+	for (ival = 0; ival < var_len-1; ival++) {
+	    sprintf(s2, "%hu, ", (unsigned short)*ushortvalp++);
+	    fstrcat(stmnt, s2, &stmnt_len);
+	}
+	sprintf(s2, "%hu", (unsigned short)*ushortvalp);
+	fstrcat(stmnt, s2, &stmnt_len);
+	break;
+    case NC_UINT:
+	uintvalp = (unsigned int *) rec_start;
+	for (ival = 0; ival < var_len-1; ival++) {
+	    sprintf(s2, "%u, ", (unsigned int)*uintvalp++);
+	    fstrcat(stmnt, s2, &stmnt_len);
+	}
+	sprintf(s2, "%u", (unsigned int)*uintvalp);
+	fstrcat(stmnt, s2, &stmnt_len);
+	break;
+    case NC_INT64:
+	int64valp = (long long *) rec_start;
+	for (ival = 0; ival < var_len-1; ival++) {
+	    sprintf(s2, "%lld, ", (long long)*int64valp++);
+	    fstrcat(stmnt, s2, &stmnt_len);
+	}
+	sprintf(s2, "%lld", (long long)*int64valp);
+	fstrcat(stmnt, s2, &stmnt_len);
+	break;
+    case NC_UINT64:
+	uint64valp = (unsigned long long *) rec_start;
+	for (ival = 0; ival < var_len-1; ival++) {
+	    sprintf(s2, "%llu, ", (unsigned long long)*uint64valp++);
+	    fstrcat(stmnt, s2, &stmnt_len);
+	}
+	sprintf(s2, "%llu", (unsigned long long)*uint64valp);
+	fstrcat(stmnt, s2, &stmnt_len);
+	break;
+    default:
+	derror("fstrstr: bad type");
+	break;
+    }
+    fstrcat(stmnt, "/", &stmnt_len);
+
+    /* For record variables, store data statement for later use;
+      otherwise, just print it. */
+    if (vars[varnum].ndims > 0 && vars[varnum].dims[0] == rec_dim) {
+	char *dup_stmnt = (char*) emalloc(strlen(stmnt)+1);
+	strcpy(dup_stmnt, stmnt); /* ULTRIX missing strdup */
+	vars[varnum].data_stmnt = dup_stmnt;
+    } else {
+	fline(stmnt);
+    }
+}
+
+
+/* make Fortran to put record */
+static void
+gen_load_fortran(
+    void *rec_start
+    )
+{
+    char stmnt[FORT_MAX_STMNT];
+    struct vars *v = &vars[varnum];
+
+    if (!v->has_data)
+	return;
+
+    if (v->ndims == 0 || v->dims[0] != rec_dim) {
+	sprintf(stmnt, "* store %s", v->name);
+	fline(stmnt);
+    }
+
+    /* generate code to initialize variable with values found in CDL input */
+    if (v->type != NC_CHAR) {
+	f_var_init(varnum, (char*)rec_start);
+    } else {
+	v->data_stmnt = (char*) fstrstr((char*)rec_start, valnum);
+    }
+    
+    if (v->ndims >0 && v->dims[0] == rec_dim) {
+	return;
+    }
+    if (v->type != NC_CHAR) {
+	sprintf(stmnt, "iret = nf_put_var_%s(ncid, %s_id, %s)",
+		nfftype(v->type), v->lname, v->lname);
+    } else {
+	char *char_expr = (char*) fstrstr((char*)rec_start, valnum);
+	sprintf(stmnt, "iret = nf_put_var_%s(ncid, %s_id, %s)",
+		nfftype(v->type), v->lname, char_expr);
+	free(char_expr);
+    }
+    
+    fline(stmnt);
+    fline("call check_err(iret)");
+}
+
+
+/* invoke netcdf calls (or generate C or Fortran code) to load netcdf variable
+ * from in-memory data.  Assumes following global variables set from yacc
+ * parser:
+ * int varnum        - number of variable to be loaded.
+ * struct vars[varnum] - structure containing info on variable, specifically
+ *                     name, type, ndims, dims, fill_value, has_data
+ * int rec_dim       - id of record dimension, or -1 if none
+ * struct dims[]     - structure containing name and size of dimensions.
+ */
+int
+put_variable(void *rec_start)	/* points to data to be loaded  */
+{
+    if (netcdf_flag)
+      load_netcdf(rec_start);	/* put variable values */
+    if (c_flag)			/* create C code to put values */
+      gen_load_c(rec_start);
+    if (fortran_flag)		/* create Fortran code to put values */
+      gen_load_fortran(rec_start);
+
+    return 0;
+}
+
+
+/* write out variable's data from in-memory structure */
+void
+load_netcdf(void *rec_start)
+{
+    int i, idim;
+    int stat = NC_NOERR;
+    MPI_Offset start[NC_MAX_VAR_DIMS];
+    MPI_Offset count[NC_MAX_VAR_DIMS];
+    char *charvalp = NULL;
+    short *shortvalp = NULL;
+    int *intvalp = NULL;
+    float *floatvalp = NULL;
+    double *doublevalp = NULL;
+    unsigned char *ubytevalp = NULL;
+    unsigned short *ushortvalp = NULL;
+    unsigned int *uintvalp = NULL;
+    long long *int64valp = NULL;
+    unsigned long long *uint64valp = NULL;
+    MPI_Offset total_size;
+
+    /* load values into variable */
+
+    switch (vars[varnum].type) {
+      case NC_CHAR:
+      case NC_BYTE:
+	charvalp = (char *) rec_start;
+	break;
+      case NC_SHORT:
+	shortvalp = (short *) rec_start;
+	break;
+      case NC_INT:
+	intvalp = (int *) rec_start;
+	break;
+      case NC_FLOAT:
+	floatvalp = (float *) rec_start;
+	break;
+      case NC_DOUBLE:
+	doublevalp = (double *) rec_start;
+	break;
+      case NC_UBYTE:
+	ubytevalp = (unsigned char *) rec_start;
+	break;
+      case NC_USHORT:
+	ushortvalp = (unsigned short *) rec_start;
+	break;
+      case NC_UINT:
+	uintvalp = (unsigned int *) rec_start;
+	break;
+      case NC_INT64:
+	int64valp = (long long *) rec_start;
+	break;
+      case NC_UINT64:
+	uint64valp = (unsigned long long *) rec_start;
+	break;
+      default:
+	derror("Unhandled type %d\n", vars[varnum].type);
+	break;
+    }
+    if (vars[varnum].ndims > 0) {
+	/* initialize start to upper left corner (0,0,0,...) */
+	start[0] = 0;
+	if (vars[varnum].dims[0] == rec_dim) {
+	    count[0] = vars[varnum].nrecs;
+	}
+	else {
+	    count[0] = dims[vars[varnum].dims[0]].size;
+	}
+    }
+
+    for (idim = 1; idim < vars[varnum].ndims; idim++) {
+	start[idim] = 0;
+	count[idim] = dims[vars[varnum].dims[idim]].size;
+    }
+
+    total_size = nctypesize(vars[varnum].type);
+    for (idim=0; idim<vars[varnum].ndims; idim++)
+        total_size *= count[idim];
+
+    /* If the total put size is more than 2GB, then put one subarray at a time.
+     * Here the subarray is from 1, 2, ... ndims, except 0.
+     * This is not a perfect solution. To be improved.
+     */
+    if (total_size > INT_MAX) {
+        MPI_Offset nchunks=count[0];
+        MPI_Offset subarray_nelems=1;
+        for (idim=1; idim<vars[varnum].ndims; idim++)
+            subarray_nelems *= count[idim];
+
+        count[0] = 1;
+        switch (vars[varnum].type) {
+            case NC_BYTE:
+                 for (i=0; i<nchunks; i++) {
+                     start[0] = i;
+                     stat = ncmpi_put_vara_schar_all(ncid, varnum, start, count, (signed char *)charvalp);
+                     check_err(stat, "ncmpi_put_vara_schar_all", __func__, __LINE__, __FILE__);
+                     charvalp += subarray_nelems;
+                 }
+                 break;
+            case NC_CHAR:
+                 for (i=0; i<nchunks; i++) {
+                     start[0] = i;
+                     stat = ncmpi_put_vara_text_all(ncid, varnum, start, count, charvalp);
+                     check_err(stat, "ncmpi_put_vara_text_all", __func__, __LINE__, __FILE__);
+                     charvalp += subarray_nelems;
+                 }
+                 break;
+            case NC_SHORT:
+                 for (i=0; i<nchunks; i++) {
+                     start[0] = i;
+                     stat = ncmpi_put_vara_short_all(ncid, varnum, start, count, shortvalp);
+                     check_err(stat, "ncmpi_put_vara_short_all", __func__, __LINE__, __FILE__);
+                     shortvalp += subarray_nelems;
+                 }
+                 break;
+            case NC_INT:
+                 for (i=0; i<nchunks; i++) {
+                     start[0] = i;
+                     stat = ncmpi_put_vara_int_all(ncid, varnum, start, count, intvalp);
+                     check_err(stat, "ncmpi_put_vara_int_all", __func__, __LINE__, __FILE__);
+                     intvalp += subarray_nelems;
+                 }
+                 break;
+            case NC_FLOAT:
+                 for (i=0; i<nchunks; i++) {
+                     start[0] = i;
+                     stat = ncmpi_put_vara_float_all(ncid, varnum, start, count, floatvalp);
+                     check_err(stat, "ncmpi_put_vara_float_all", __func__, __LINE__, __FILE__);
+                     floatvalp += subarray_nelems;
+                 }
+                 break;
+            case NC_DOUBLE:
+                 for (i=0; i<nchunks; i++) {
+                     start[0] = i;
+                     stat = ncmpi_put_vara_double_all(ncid, varnum, start, count, doublevalp);
+                     check_err(stat, "ncmpi_put_vara_double_all", __func__, __LINE__, __FILE__);
+                     doublevalp += subarray_nelems;
+                 }
+                 break;
+            case NC_UBYTE:
+                 for (i=0; i<nchunks; i++) {
+                     start[0] = i;
+                     stat = ncmpi_put_vara_uchar_all(ncid, varnum, start, count, ubytevalp);
+                     check_err(stat, "ncmpi_put_vara_uchar_all", __func__, __LINE__, __FILE__);
+                     ubytevalp += subarray_nelems;
+                 }
+                 break;
+            case NC_USHORT:
+                 for (i=0; i<nchunks; i++) {
+                     start[0] = i;
+                     stat = ncmpi_put_vara_ushort_all(ncid, varnum, start, count, ushortvalp);
+                     check_err(stat, "ncmpi_put_vara_ushort_all", __func__, __LINE__, __FILE__);
+                     ushortvalp += subarray_nelems;
+                 }
+                 break;
+            case NC_UINT:
+                 for (i=0; i<nchunks; i++) {
+                     start[0] = i;
+                     stat = ncmpi_put_vara_uint_all(ncid, varnum, start, count, uintvalp);
+                     check_err(stat, "ncmpi_put_vara_uint_all", __func__, __LINE__, __FILE__);
+                     uintvalp += subarray_nelems;
+                 }
+                 break;
+            case NC_INT64:
+                 for (i=0; i<nchunks; i++) {
+                     start[0] = i;
+                     stat = ncmpi_put_vara_longlong_all(ncid, varnum, start, count, int64valp);
+                     check_err(stat, "ncmpi_put_vara_longlong_all", __func__, __LINE__, __FILE__);
+                     int64valp += subarray_nelems;
+                 }
+                 break;
+            case NC_UINT64:
+                 for (i=0; i<nchunks; i++) {
+                     start[0] = i;
+                     stat = ncmpi_put_vara_ulonglong_all(ncid, varnum, start, count, uint64valp);
+                     check_err(stat, "ncmpi_put_vara_ulonglong_all", __func__, __LINE__, __FILE__);
+                     uint64valp += subarray_nelems;
+                 }
+                 break;
+            default:
+                     derror("Unhandled type %d\n", vars[varnum].type);
+                     break;
+        }
+    }
+    else {
+        switch (vars[varnum].type) {
+            case NC_BYTE:
+                stat = ncmpi_put_vara_schar_all(ncid, varnum, start, count, (signed char *)charvalp);
+                check_err(stat, "ncmpi_put_vara_schar_all", __func__, __LINE__, __FILE__);
+                break;
+            case NC_CHAR:
+                stat = ncmpi_put_vara_text_all(ncid, varnum, start, count, charvalp);
+                check_err(stat, "ncmpi_put_vara_text_all", __func__, __LINE__, __FILE__);
+                break;
+            case NC_SHORT:
+                stat = ncmpi_put_vara_short_all(ncid, varnum, start, count, shortvalp);
+                check_err(stat, "ncmpi_put_vara_short_all", __func__, __LINE__, __FILE__);
+                break;
+            case NC_INT:
+                stat = ncmpi_put_vara_int_all(ncid, varnum, start, count, intvalp);
+                check_err(stat, "ncmpi_put_vara_int_all", __func__, __LINE__, __FILE__);
+                break;
+            case NC_FLOAT:
+                stat = ncmpi_put_vara_float_all(ncid, varnum, start, count, floatvalp);
+                check_err(stat, "ncmpi_put_vara_float_all", __func__, __LINE__, __FILE__);
+                break;
+            case NC_DOUBLE:
+                stat = ncmpi_put_vara_double_all(ncid, varnum, start, count, doublevalp);
+                check_err(stat, "ncmpi_put_vara_double_all", __func__, __LINE__, __FILE__);
+                break;
+            case NC_UBYTE:
+                stat = ncmpi_put_vara_uchar_all(ncid, varnum, start, count, ubytevalp);
+                check_err(stat, "ncmpi_put_vara_uchar_all", __func__, __LINE__, __FILE__);
+                break;
+            case NC_USHORT:
+                stat = ncmpi_put_vara_ushort_all(ncid, varnum, start, count, ushortvalp);
+                check_err(stat, "ncmpi_put_vara_ushort_all", __func__, __LINE__, __FILE__);
+                break;
+            case NC_UINT:
+                stat = ncmpi_put_vara_uint_all(ncid, varnum, start, count, uintvalp);
+                check_err(stat, "ncmpi_put_vara_uint_all", __func__, __LINE__, __FILE__);
+                break;
+            case NC_INT64:
+                stat = ncmpi_put_vara_longlong_all(ncid, varnum, start, count, int64valp);
+                check_err(stat, "ncmpi_put_vara_longlong_all", __func__, __LINE__, __FILE__);
+                break;
+            case NC_UINT64:
+                stat = ncmpi_put_vara_ulonglong_all(ncid, varnum, start, count, uint64valp);
+                check_err(stat, "ncmpi_put_vara_ulonglong_all", __func__, __LINE__, __FILE__);
+                break;
+            default:
+                derror("Unhandled type %d\n", vars[varnum].type);
+                break;
+        }
+    }
+}
diff --git a/src/utils/ncmpigen/main.c b/src/utils/ncmpigen/main.c
new file mode 100644
index 0000000..00e96d8
--- /dev/null
+++ b/src/utils/ncmpigen/main.c
@@ -0,0 +1,223 @@
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+
+#if HAVE_CONFIG_H
+# include <ncconfig.h>
+#endif
+
+#include <stdio.h>		/* has getopt() under VMS */
+#include <string.h>
+
+#ifdef __hpux
+#include <locale.h>  /* setlocale() */
+#endif
+    
+#include <pnetcdf.h>
+
+#include <unistd.h>
+
+#include "generic.h"
+#include "ncmpigen.h"
+#include "genlib.h"
+
+extern int	ncmpiparse(void);
+
+const char *progname;			/* for error messages */
+const char *cdlname;
+
+int c_flag;
+int fortran_flag;
+int netcdf_flag;
+int giantfile_flag;
+int giantvar_flag;
+int nofill_flag;
+char *netcdf_name = NULL;	/* name of output netCDF file to write */
+
+extern FILE *ncmpiin;
+
+static const char* ubasename ( const char* av0 );
+static void usage ( void );
+int main ( int argc, char** argv );
+
+
+/* strip off leading path */
+static const char *
+ubasename(
+	const char *av0)
+{
+	const char *logident ;
+#ifdef VMS
+#define SEP	']'
+#endif
+#ifdef MSDOS
+#define SEP	'\\'
+#endif
+#ifndef SEP
+#define SEP	'/'
+#endif
+	if ((logident = strrchr(av0, SEP)) == NULL)
+		logident = av0 ;
+	else
+	    logident++ ;
+	return logident ;
+}
+
+
+static void usage(void)
+{
+    derror("Usage: %s [ -b ] [ -c ] [ -f ] [ -v version ] [ -x ] [ -o outfile]  [ file ... ]",
+	   progname);
+    derror("PnetCDF library version %s", ncmpi_inq_libvers());
+}
+
+
+int
+main(int argc, char *argv[])
+{
+    extern int optind;
+    extern int opterr;
+    extern char *optarg;
+    int c;
+    int ret;
+    FILE *fp;
+
+    MPI_Init(&argc, &argv);
+
+#ifdef __hpux
+    setlocale(LC_CTYPE,"");
+#endif
+    
+#ifdef MDEBUG
+    malloc_debug(2) ;	/* helps find malloc/free errors on Sun */
+#endif /* MDEBUG */
+
+    opterr = 1;			/* print error message if bad option */
+    progname = ubasename(argv[0]);
+    cdlname = "-";
+
+    c_flag = 0;
+    fortran_flag = 0;
+    netcdf_flag = 0;
+    giantfile_flag = 0;
+    giantvar_flag = 0;
+    nofill_flag = 0;
+
+#if 0
+#if _CRAYMPP && 0
+    /* initialize CRAY MPP parallel-I/O library */
+    (void) par_io_init(32, 32);
+#endif
+#endif
+
+    while ((c = getopt(argc, argv, "bcfl:no:v:x")) != EOF)
+      switch(c) {
+	case 'c':		/* for c output. old version of '-lc' */
+	  c_flag = 1;
+	  break;
+	case 'f':		/* for fortran output. old version of '-lf' */
+	  fortran_flag = 1;
+	  break;
+	case 'b':		/* for binary netcdf output, ".nc" extension */
+	  netcdf_flag = 1;
+	  break;
+	case 'l':               /* specify language, instead of -c or -f */
+	  {
+               char *lang_name = (char *) emalloc(strlen(optarg)+1);
+               if (! lang_name) {
+                   derror ("%s: out of memory", progname);
+                   return(1);
+               }
+               (void)strcpy(lang_name, optarg);
+               if (strcmp(lang_name, "c") == 0 || strcmp(lang_name, "C") == 0) {
+                   c_flag = 1;
+               }
+               else if (strcmp(lang_name, "f77") == 0 || 
+                        strcmp(lang_name, "fortran77") == 0 ||
+                        strcmp(lang_name, "Fortran77") == 0) {
+                   fortran_flag = 1;
+               } else {     /* Fortran90, Java, C++, Perl, Python, Ruby, ... */
+                   derror("%s: output language %s not implemented", 
+                          progname, lang_name);
+                   return(1);
+               }
+           }
+	  break;
+	case 'n':		/* old version of -b, uses ".cdf" extension */
+	  netcdf_flag = -1;
+	  break;
+	case 'o':		/* to explicitly specify output name */
+	  netcdf_flag = 1;
+	  netcdf_name = (char *) emalloc(strlen(optarg)+1);
+	  if (! netcdf_name) {
+	      derror ("%s: out of memory", progname);
+	      return(1);
+	  }
+	  (void)strcpy(netcdf_name,optarg);
+	  break;
+	case 'x':     /* set nofill mode to speed up creation fo large files */
+	  nofill_flag = 1;
+	  break;
+	case 'v':     /* for creating 64-bit offet files, specify version 2 */
+	  {
+		  char *version_name = (char *)emalloc(strlen(optarg)+1);
+		  if (! version_name) {
+			  derror ("%s: out of memory", progname);
+			  return (1);
+		  }
+		  (void)strcpy(version_name, optarg);
+		  /* the default version is version 1, with 32-bit offsets */
+		  if (strcmp(version_name, "1") == 0 ||
+				  strcmp(version_name, "classic") == 0) {
+			  giantfile_flag = 0;
+		  }
+		  /* the 64-bit offset version (2) should only be used if
+		   * actually needed */
+		  else if (strcmp(version_name, "2") == 0 || 
+				  strcmp(version_name, "64-bit-offset") == 0) {
+			  giantfile_flag = 1;
+		  } else if (strcmp(version_name, "5") == 0 ||
+				  strcmp(version_name, 
+					  "64-bit-variables") == 0) {
+			  giantvar_flag = 1;
+		  }
+	  }
+	  break;
+	case '?':
+	  usage();
+	  return(8);
+      }
+
+    if (fortran_flag && c_flag) {
+	derror("Only one of -c or -f may be specified");
+	return(8);
+    }
+    if (fortran_flag) {
+	    derror("Generating Fortran interface currently not supported yet");
+            return(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc > 1) {
+	derror ("%s: only one input file argument permitted",progname);
+	return(6);
+    }
+
+    fp = stdin;
+    if (argc > 0 && strcmp(argv[0], "-") != 0) {
+	if ((fp = fopen(argv[0], "r")) == NULL) {
+	    derror ("can't open file %s for reading: ", argv[0]);
+	    perror("");
+	    return(7);
+	}
+	cdlname = argv[0];
+    }
+    ncmpiin = fp;
+    ret = ncmpiparse(); 
+    MPI_Finalize();
+    return ret;
+}
diff --git a/src/utils/ncmpigen/ncmpigen.1 b/src/utils/ncmpigen/ncmpigen.1
new file mode 100644
index 0000000..094a956
--- /dev/null
+++ b/src/utils/ncmpigen/ncmpigen.1
@@ -0,0 +1,373 @@
+.\" $Header$
+.nr yr \n(yr+1900
+.af mo 01
+.af dy 01
+.TH NCMPIGEN 1 2013-11-17 "Printed: \n(yr-\n(mo-\n(dy" "UTILITIES"
+.SH NAME
+ncmpigen \- From a CDL file generate a netCDF file, a C program, or a Fortran
+program
+.SH SYNOPSIS
+.HP
+ncmpigen
+.nh
+\%[-b]
+\%[-c]
+\%[-f]
+\%[-n]
+\%[-o \fInetcdf_filename\fP]
+\%[-v \fIfile_format\fP]
+\%\fIinput_file\fP
+.hy
+.ft
+.SH DESCRIPTION
+\fBncmpigen\fP generates either a netCDF file, or C or Fortran source code to
+create a netCDF file.  The input to \fBncmpigen\fP is a description of a netCDF
+file in a small language known as CDL (network Common Data form Language),
+described below.
+If no options are specified in invoking \fBncmpigen\fP, it merely checks the
+syntax of the input CDL file, producing error messages for
+any violations of CDL syntax.  Other options can be used to create the
+corresponding netCDF file, to generate a C program that uses the netCDF C
+interface to create the netCDF file, or to generate a Fortran program that
+uses the netCDF Fortran interface to create the same netCDF file.
+.LP
+\fBncmpigen\fP may be used with the companion program \fBncmpidump\fP to perform
+some simple operations on netCDF files.  For example, to rename a dimension
+in a netCDF file, use \fBncmpidump\fP to get a CDL version of the netCDF file,
+edit the CDL file to change the name of the dimensions, and use \fBncmpigen\fP
+to generate the corresponding netCDF file from the edited CDL file.
+.SH OPTIONS
+.IP "\fB-b\fP"
+Create a (binary) netCDF file.  If the \fB-o\fP option is absent, a default
+file name will be constructed from the netCDF name (specified after the
+\fBnetcdf\fP keyword in the input) by appending the `.nc' extension.  If a
+file already exists with the specified name, it will be overwritten.
+.IP "\fB-c\fP"
+Generate
+.B C
+source code that will create a netCDF file
+matching the netCDF specification.  The C source code is written to
+standard output.
+.IP "\fB-f\fP"
+Generate
+.B Fortran
+source code that will create a netCDF file
+matching the netCDF specification.  The Fortran source code is written
+to standard output.
+.IP "\fB-o\fP \fRnetcdf_file\fP"
+Name for the binary netCDF file created.  If this option is specified, it implies
+the "\fB-b\fP" option.  (This option is necessary because netCDF files
+cannot be written directly to standard output, since standard output is not
+seekable.)
+.IP "\fB-n\fP"
+Like \fB-b\fP option, except creates netCDF file with the obsolete `.cdf'
+extension instead of the `.nc' extension, in the absence of an output
+filename specified by the \fB-o\fP option.  This option is only supported
+for backward compatibility.
+.IP "\fB-v\fP \fRfile_format\fP"
+File format of the output netCDF file. The value of \fRfile_format\fP can
+be:
+1 or classic for CDF-1 format.
+2 or 64-bit-offset is CDF-2.
+5 or 64-bit-variable for CDF-5.
+The default (if this option is not given) is CDF-1, the classic format.
+.SH EXAMPLES
+.LP
+Check the syntax of the CDL file `\fBfoo.cdl\fP':
+.RS
+.HP
+ncmpigen foo.cdl
+.RE
+.LP
+From the CDL file `\fBfoo.cdl\fP', generate an equivalent binary netCDF file
+named `\fBx.nc\fP':
+.RS
+.HP
+ncmpigen -o x.nc foo.cdl
+.RE
+.LP
+From the CDL file `\fBfoo.cdl\fP', generate a C program containing the
+netCDF function invocations necessary to create an equivalent binary netCDF
+file named `\fBx.nc\fP':
+.RS
+.HP
+ncmpigen -c -o x.nc foo.cdl
+.RE
+.LP
+.SH USAGE
+.SS "CDL Syntax Summary"
+.LP
+Below is an example of CDL syntax, describing a netCDF file with several
+named dimensions (lat, lon, and time), variables (Z, t, p, rh, lat, lon,
+time), variable attributes (units, long_name, valid_range, _FillValue), and
+some data.  CDL keywords are in boldface.  (This example is intended to
+illustrate the syntax; a real CDL file would have a more complete set of
+attributes so that the data would be more completely self-describing.)
+
+.RS
+.nf
+\fBnetcdf\fP foo {  // an example netCDF specification in CDL
+
+\fBdimensions\fP:
+	lat = 10, lon = 5, time = \fBunlimited\fP ;
+
+\fBvariables\fP:
+	\fBlong\fP    lat(lat), lon(lon), time(time);
+	\fBfloat\fP   Z(time,lat,lon), t(time,lat,lon);
+	\fBdouble\fP  p(time,lat,lon);
+	\fBlong\fP    rh(time,lat,lon);
+
+	// variable attributes
+	lat:long_name = "latitude";
+	lat:units = "degrees_north";
+	lon:long_name = "longitude";
+	lon:units = "degrees_east";
+	time:units = "seconds since 1992-1-1 00:00:00";
+	Z:units = "geopotential meters";
+	Z:valid_range = 0., 5000.;
+	p:_FillValue = -9999.;
+	rh:_FillValue = -1;
+
+\fBdata\fP:
+	lat   = 0, 10, 20, 30, 40, 50, 60, 70, 80, 90;
+	lon   = -140, -118, -96, -84, -52;
+}
+.fi
+.RE
+.LP
+All CDL statements are terminated by a semicolon.  Spaces, tabs,
+and newlines can be used freely for readability.
+Comments may follow the characters `//' on any line.
+.LP
+A CDL description consists of three optional parts: \fIdimensions\fP,
+\fIvariables\fP, and \fIdata\fP, beginning with the keyword
+.BR dimensions: ,
+.BR variables: ,
+and
+.BR data ,
+respectively.
+The variable part may contain \fIvariable
+declarations\fP and \fIattribute assignments\fP.
+.LP
+A netCDF \fIdimension\fP is used to define the shape of one or more of the
+multidimensional variables contained in the netCDF file.  A netCDF
+dimension has a name and a size.  At most one dimension in a netCDF file
+can have the \fBunlimited\fP size, which means a variable using this
+dimension can grow to any length (like a record number in a file).
+.LP
+A \fIvariable\fP represents a multidimensional array of values of the
+same type.  A variable has a name, a data type, and a shape described
+by its list of dimensions.  Each variable may also have associated
+\fIattributes\fP (see below) as well as data values.  The name, data
+type, and shape of a variable are specified by its declaration in the
+\fIvariable\fP section of a CDL description.  A variable may have the same
+name as a dimension; by convention such a variable is one-dimensional
+and contains coordinates of the dimension it names.  Dimensions need
+not have corresponding variables.
+.LP
+A netCDF \fIattribute\fP contains information about a netCDF variable or
+about the whole netCDF dataset.  Attributes are used
+to specify such properties as units, special values, maximum and
+minimum valid values, scaling factors, offsets, and parameters.  Attribute
+information is represented by single values or arrays of values.  For
+example, "units" is an attribute represented by a character array such
+as "celsius".  An attribute has an associated variable, a name,
+a data type, a length, and a value.  In contrast to variables that are
+intended for data, attributes are intended for metadata (data about
+data).
+.LP
+In CDL, an attribute is designated by a variable and attribute name,
+separated by `:'.  It is possible to assign \fIglobal\fP attributes
+not associated with any variable to the netCDF as a whole by using
+`:' before the attribute name.  The data type of an attribute in CDL
+is derived from the type of the value assigned to it.  The length of
+an attribute is the number of data values assigned to it, or the
+number of characters in the character string assigned to it.  Multiple
+values are assigned to non-character attributes by separating the
+values with commas.  All values assigned to an attribute must be of
+the same type.
+.LP
+The names for CDL dimensions, variables, and attributes must begin with an
+alphabetic character or `_', and subsequent characters may be alphanumeric
+or `_' or `-'.
+.LP
+The optional \fIdata\fP section of a CDL specification is where
+netCDF variables may be initialized.  The syntax of an initialization
+is simple: a variable name, an equals sign, and a
+comma-delimited list of constants (possibly separated by spaces, tabs
+and newlines) terminated with a semicolon.  For multi-dimensional
+arrays, the last dimension varies fastest.  Thus row-order rather than
+column order is used for matrices.  If fewer values are supplied than
+are needed to fill a variable, it is extended with a type-dependent
+`fill value', which can be overridden by supplying a value for a
+distinguished variable attribute named `_FillValue'.  The
+types of constants need not match the type declared for a variable;
+coercions are done to convert integers to floating point, for example.
+The constant `_' can be used to designate the fill value for a variable.
+.SS "Primitive Data Types"
+.LP
+.RS
+.nf
+\fBchar\fP	characters
+\fBbyte\fP	8-bit data
+\fBshort\fP	16-bit signed integers
+\fBlong\fP	32-bit signed integers
+\fBint\fP	(synonymous with \fBlong\fP)
+\fBfloat\fP	IEEE single precision floating point (32 bits)
+\fBreal\fP	(synonymous with \fBfloat\fP)
+\fBdouble\fP	IEEE double precision floating point (64 bits)
+.fi
+.RE
+.LP
+Except for the added data-type \fBbyte\fP and the lack of
+\fBunsigned\fP,
+CDL supports the same primitive data types as C.
+The names for the primitive data types are reserved words in CDL,
+so the names of variables, dimensions, and attributes must not be
+type names.  In declarations, type names may be specified
+in either upper or lower case.
+.LP
+Bytes differ from characters in that they are intended to hold a full eight
+bits of data, and the zero byte has no special significance, as it
+does for character data.
+\fBncmpigen\fP converts \fBbyte\fP declarations to \fBchar\fP
+declarations in the output C code and to the nonstandard \fBBYTE\fP
+declaration in output Fortran code.
+.LP
+Shorts can hold values between -32768 and 32767.
+\fBncmpigen\fP converts \fBshort\fP declarations to \fBshort\fP
+declarations in the output C code and to the nonstandard \fBINTEGER*2\fP
+declaration in output Fortran code.
+.LP
+Longs can hold values between -2147483648 and 2147483647.
+\fBncmpigen\fP converts \fBlong\fP declarations to \fBlong\fP
+declarations in the output C code and to \fBINTEGER\fP
+declarations in output Fortran code.  \fBint\fP and \fBinteger\fP are
+accepted as synonyms for \fBlong\fP in CDL declarations.
+Now that there are platforms with 64-bit representations for C longs, it may
+be better to use the \fBint\fP synonym to avoid confusion.
+.LP
+Floats can hold values between about -3.4+38 and 3.4+38.  Their
+external representation is as 32-bit IEEE normalized single-precision
+floating point numbers.  \fBncmpigen\fP converts \fBfloat\fP
+declarations to \fBfloat\fP declarations in the output C code and to
+\fBREAL\fP declarations in output Fortran code.  \fBreal\fP is accepted
+as a synonym for \fBfloat\fP in CDL declarations.
+.LP
+Doubles can hold values between about -1.7+308 and 1.7+308.  Their
+external representation is as 64-bit IEEE standard normalized
+double-precision floating point numbers.  \fBncmpigen\fP converts
+\fBdouble\fP declarations to \fBdouble\fP declarations in the output C
+code and to \fBDOUBLE PRECISION\fP declarations in output Fortran
+code.
+.LP
+.SS "CDL Constants"
+.LP
+Constants assigned to attributes or variables may be of any of the
+basic netCDF types.  The syntax for constants is similar to C syntax,
+except that type suffixes must be appended to shorts and floats to
+distinguish them from longs and doubles.
+.LP
+A \fIbyte\fP constant is represented by a single character or multiple
+character escape sequence enclosed in single quotes.  For example,
+.RS
+.nf
+ 'a'		// ASCII `a'
+ '\\0'		// a zero byte
+ '\\n'		// ASCII newline character
+ '\\33'		// ASCII escape character (33 octal)
+ '\\x2b'	// ASCII plus (2b hex)
+ '\\377'	// 377 octal = 255 decimal, non-ASCII
+.fi
+.RE
+.LP
+Character constants are enclosed in double quotes.  A character array
+may be represented as a string enclosed in double quotes.  The usual C
+string escape conventions are honored.  For example
+.RS
+.nf
+"a"		// ASCII `a'
+"Two\\nlines\\n"	// a 10-character string with two embedded newlines
+"a bell:\\007"	// a string containing an ASCII bell
+.fi
+.RE
+Note that the netCDF character array "a" would fit in a one-element
+variable, since no terminating NULL character is assumed.  However, a zero
+byte in a character array is interpreted as the end of the significant
+characters by the \fBncmpidump\fP program, following the C convention.
+Therefore, a NULL byte should not be embedded in a character string unless
+at the end: use the \fIbyte\fP data type instead for byte arrays that
+contain the zero byte.  NetCDF and CDL have no string type, but only
+fixed-length character arrays, which may be multi-dimensional.
+.LP
+\fIshort\fP integer constants are intended for representing 16-bit
+signed quantities.  The form of a \fIshort\fP constant is an integer
+constant with an `s' or `S' appended.  If a \fIshort\fP constant
+begins with `0', it is interpreted as octal, except that if it begins with
+`0x', it is interpreted as a hexadecimal constant.  For example:
+.RS
+.nf
+-2s	// a short -2
+0123s	// octal
+0x7ffs  //hexadecimal
+.fi
+.RE
+.LP
+\fILong\fP integer constants are intended for representing 32-bit signed
+quantities.  The form of a \fIlong\fP constant is an ordinary integer
+constant, although it is acceptable to append an optional `l' or
+`L'.  If a \fIlong\fP constant begins with `0', it is interpreted as
+octal, except that if it begins with `0x', it is interpreted as a hexadecimal
+constant.  Examples of valid \fIlong\fP constants include:
+.RS
+.nf
+-2
+1234567890L
+0123		// octal
+0x7ff		// hexadecimal
+.fi
+.RE
+.LP
+Floating point constants of type \fIfloat\fP are appropriate for representing
+floating point data with about seven significant digits of precision. 
+The form of a \fIfloat\fP constant is the same as a C floating point
+constant with an `f' or `F' appended.  For example the following
+are all acceptable \fIfloat\fP constants:
+.RS
+.nf
+-2.0f
+3.14159265358979f	// will be truncated to less precision
+1.f
+.1f
+.fi
+.RE
+.LP
+Floating point constants of type \fIdouble\fP are appropriate for
+representing floating point data with about sixteen significant digits
+of precision.  The form of a \fIdouble\fP constant is the same as a C
+floating point constant.  An optional `d' or `D' may be appended.
+For example the following are all acceptable \fIdouble\fP constants:
+.RS
+.nf
+-2.0
+3.141592653589793
+1.0e-20
+1.d
+.fi
+.RE
+.SH DATE
+$Date: 2014-04-16 13:38:34 -0500 (Wed, 16 Apr 2014) $
+.SH BUGS
+.LP
+The programs generated by \fBncmpigen\fP when using the \fB-c\fP or \fB-f\fP
+use initialization statements to store data in variables, and will fail to
+produce compilable programs if you try to use them for large datasets, since
+the resulting statements may exceed the line length or number of
+continuation statements permitted by the compiler.
+.LP
+The CDL syntax makes it easy to assign what looks like an array of
+variable-length strings to a netCDF variable, but the strings will simply be
+concatenated into a single array of characters, since netCDF cannot
+represent an array of variable-length strings in one netCDF variable.
+.LP
+NetCDF and CDL do not yet support a type corresponding to a 64-bit integer.
diff --git a/src/utils/ncmpigen/ncmpigen.h b/src/utils/ncmpigen/ncmpigen.h
new file mode 100644
index 0000000..a5d0af9
--- /dev/null
+++ b/src/utils/ncmpigen/ncmpigen.h
@@ -0,0 +1,57 @@
+#ifndef NC_NCGEN_H
+#define NC_NCGEN_H
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Header$
+ *********************************************************************/
+
+#define MAX_NC_ATTSIZE    20000	/* max size of attribute (for ncmpigen) */
+#define MAXTRST		  5000	/* max size of string value (for ncmpigen) */
+
+#include <stdlib.h>  /* size_t */
+#include "generic.h"
+
+extern int ncid;		/* handle for netCDF */
+extern int ndims;		/* number of dimensions declared for netcdf */
+extern int nvars;		/* number of variables declared for netcdf */
+extern int natts;		/* number of attributes */
+extern int nvdims;		/* number of dimensions for variables */
+extern int dimnum;		/* dimension number index for variables */
+extern int varnum;		/* variable number index for attributes */
+extern int valnum;		/* number of values specified for variable */
+extern int rec_dim;		/* number of the unlimited dimension, if any */
+extern MPI_Offset rec_len;		/* number of elements for a record of data */
+extern MPI_Offset var_len;		/* variable length (product of dimensions) */
+extern MPI_Offset var_size;		/* size of each element of variable */
+
+extern struct dims {
+    MPI_Offset size;
+    char *name;
+    char *lname;		/* with no "-" characters, for C and Fortran */
+} *dims;			/* table of dimensions */
+
+extern struct vars {
+    char *name;
+    nc_type type;
+    int ndims;
+    int *dims;			/* array of dimension ids */
+    union generic fill_value;	/* set to value of _FillValue attribute */
+    int has_data;		/* 1 if data specified, 0 otherwise */
+    MPI_Offset nrecs;		/* for record variables, number of records
+				 * of data in CDL */
+    char *data_stmnt;		/* for record variables, to avoid
+				 * two passes with -f option */
+    char *lname;		/* with no "-" characters, for C and Fortran */
+} *vars;			/* table of variables */
+
+
+extern struct atts {
+    int var;			/* number of variable for this attribute */
+    char *name;
+    nc_type type;
+    MPI_Offset len;
+    void *val;
+    char *lname;		/* with no "-" characters, for C and Fortran */
+} *atts;			/* table of variable and global attributes */
+#endif /*!NC_NCGEN_H*/
diff --git a/src/utils/ncmpigen/ncmpigen.l b/src/utils/ncmpigen/ncmpigen.l
new file mode 100644
index 0000000..914390c
--- /dev/null
+++ b/src/utils/ncmpigen/ncmpigen.l
@@ -0,0 +1,216 @@
+%{
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Id: ncmpigen.l 2034 2015-05-29 18:52:08Z wkliao $
+ *********************************************************************/
+
+/* lex specification for tokens for ncmpigen */
+
+/* Fill value used by ncdump from version 2.4 and later.  Should match
+   definition of FILL_STRING in ../ncdump/vardata.h */
+#define FILL_STRING "_"
+#define XDR_INT_MIN (-2147483647-1)
+#define XDR_INT_MAX 2147483647
+#define XDR_INT64_MIN  (-9223372036854775807LL-1)
+#define XDR_INT64_MAX  (9223372036854775807LL)
+
+char errstr[100];		/* for short error messages */
+
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>   /* errno */
+#include "genlib.h"
+#include "ncmpigentab.h"
+
+#define YY_BREAK                /* defining as nothing eliminates unreachable
+				   statement warnings from flex output, 
+                                   but make sure every action ends with
+                                   "return" or "break"! */
+
+%}
+
+%p 6000
+
+escaped		\\.
+nonquotes	([^"\\]|{escaped})*
+exp		([eE][+-]?[0-9]+)
+%%
+\/\/.*		        { /* comment */ 
+                          break;
+                        }
+
+\"{nonquotes}\"		{
+			 if(yyleng > MAXTRST) {
+				yyerror("string too long, truncated\n");
+			        yytext[MAXTRST-1] = '\0';
+			 }
+			 expand_escapes(termstring,(char *)yytext,yyleng);
+		 	 return (TERMSTRING);
+		        }
+
+float|FLOAT|real|REAL	{return (FLOAT_K);}
+char|CHAR		{return (CHAR_K);}
+byte|BYTE		{return (BYTE_K);}
+short|SHORT		{return (SHORT_K);}
+long|LONG|int|INT|integer|INTEGER	{return (INT_K);}
+double|DOUBLE		{return (DOUBLE_K);}
+ubyte|UBYTE		{return (UBYTE_K);}
+ushort|USHORT		{return (USHORT_K);}
+uint|UINT		{return (UINT_K);}
+int64|INT64		{return (INT64_K);}
+uint64|UINT64		{return (UINT64_K);}
+unlimited|UNLIMITED	{int_val = -1;
+			 return (NC_UNLIMITED_K);}
+
+dimensions:|DIMENSIONS:	{return (DIMENSIONS);}
+variables:|VARIABLES:	{return (VARIABLES);}
+data:|DATA:		{return (DATA);}
+(netcdf|NETCDF|netCDF)[ \t]+[^\{]+	{
+		char *s = (char*)yytext+strlen("netcdf");
+		char *t = (char*)yytext+yyleng-1;
+		while (isspace(*s))
+			s++;
+		while (isspace(*t))
+			t--;
+		t++;
+                if (t-s+1 < 1) {
+                        yyerror("netCDF name required");
+                        return (DATA); /* generate syntax error */
+                }
+		netcdfname = (char *) emalloc(t-s+1);
+		(void) strncpy(netcdfname, s, t-s);
+		netcdfname[t-s] = '\0';
+		return (NETCDF);
+		}
+DoubleInf|NaN|-?Infinity { /* missing value (pre-2.4 backward compatibility) */
+                if (yytext[0] == '-') {
+		    double_val = -NC_FILL_DOUBLE;
+                } else {
+		    double_val = NC_FILL_DOUBLE;
+                }
+		return (DOUBLE_CONST);
+		}
+FloatInf|-?Inff	{ /* missing value (pre-2.4 backward compatibility) */
+                if (yytext[0] == '-') {
+		    float_val = -NC_FILL_FLOAT;
+                } else {
+		    float_val = NC_FILL_FLOAT;
+                }
+		return (FLOAT_CONST);
+		}
+[A-Za-z_][A-Z.@#\[\]a-z_0-9+-]*	{
+                if (STREQ((char *)yytext, FILL_STRING))
+		        return (FILLVALUE);
+		if ((yylval = lookup((char *)yytext)) == NULL) {
+			yylval = install((char *)yytext);
+		}
+		return (IDENT);
+		}
+
+\n		{
+		lineno++ ;
+                break;
+		}
+
+[+-]?[0-9]*[0-9][Bb]  {
+                int ii;
+		if (sscanf((char*)yytext, "%d", &ii) != 1) {
+		    sprintf(errstr,"bad byte constant: %s",(char*)yytext);
+		    yyerror(errstr);
+		}
+                byte_val = ii;
+		if (ii != (int)byte_val) {
+		    sprintf(errstr,"byte constant out of range (-128,127): %s",(char*)yytext);
+		    yyerror(errstr);
+		}
+		return (BYTE_CONST);
+                }
+
+[+-]?[0-9]*\.[0-9]*{exp}?[LlDd]?|[+-]?[0-9]*{exp}[LlDd]? {
+		if (sscanf((char*)yytext, "%le", &double_val) != 1) {
+		    sprintf(errstr,"bad long or double constant: %s",(char*)yytext);
+		    yyerror(errstr);
+		}
+                return (DOUBLE_CONST);
+                }
+[+-]?[0-9]*\.[0-9]*{exp}?[Ff]|[+-]?[0-9]*{exp}[Ff] {
+		if (sscanf((char*)yytext, "%e", &float_val) != 1) {
+		    sprintf(errstr,"bad float constant: %s",(char*)yytext);
+		    yyerror(errstr);
+		}
+                return (FLOAT_CONST);
+                }
+[+-]?[0-9]+[sS]|0[xX][0-9a-fA-F]+[sS] {
+		if (sscanf((char*)yytext, "%hd", &short_val) != 1) {
+		    sprintf(errstr,"bad short constant: %s",(char*)yytext);
+		    yyerror(errstr);
+		}
+		return (SHORT_CONST);
+	        }
+[+-]?([1-9][0-9]*|0)[lL]? {
+    		char *ptr;
+                errno = 0;
+		double_val = strtod((char*)yytext, &ptr);
+		if (errno != 0 && double_val == 0.0) {
+		    sprintf(errstr,"bad numerical constant: %s",(char*)yytext);
+		    yyerror(errstr);
+		}
+                if (double_val < XDR_INT_MIN ||double_val > XDR_INT_MAX) {
+                    return DOUBLE_CONST;
+                } else {
+                    int_val = (int) double_val;
+                    return INT_CONST;
+                }
+	        }
+0[xX]?[0-9a-fA-F]+[lL]? {
+    		char *ptr;
+                long long_val;
+                errno = 0;
+		long_val = strtol((char*)yytext, &ptr, 0);
+		if (errno != 0) {
+		    sprintf(errstr,"bad long constant: %s",(char*)yytext);
+		    yyerror(errstr);
+		}
+                if (long_val < XDR_INT_MIN || long_val > XDR_INT_MAX) {
+                    double_val = (double) long_val;
+                    return DOUBLE_CONST;
+                } else {
+                    int_val = (int) long_val;
+                    return INT_CONST;
+                }
+	        }
+\'[^\\]\'       {
+	        (void) sscanf((char*)&yytext[1],"%c",&byte_val);
+		return (BYTE_CONST);
+                }
+\'\\[0-7][0-7]?[0-7]?\'  {
+		byte_val = (char) strtol((char*)&yytext[2], (char **) 0, 8);
+		return (BYTE_CONST);
+                }
+\'\\[xX][0-9a-fA-F][0-9a-fA-F]?\'  {
+		byte_val = (char) strtol((char*)&yytext[3], (char **) 0, 16);
+		return (BYTE_CONST);
+                }
+\'\\.\'		{
+	       switch ((char)yytext[2]) {
+	          case 'a': byte_val = '\007'; break; /* not everyone under-
+						       * stands '\a' yet */
+     	          case 'b': byte_val = '\b'; break;
+		  case 'f': byte_val = '\f'; break;
+		  case 'n': byte_val = '\n'; break;
+		  case 'r': byte_val = '\r'; break;
+		  case 't': byte_val = '\t'; break;
+		  case 'v': byte_val = '\v'; break;
+		  case '\\': byte_val = '\\'; break;
+		  case '?': byte_val = '\177'; break;
+		  case '\'': byte_val = '\''; break;
+		  default: byte_val = (char)yytext[2];
+	           }
+		return (BYTE_CONST);
+                }
+
+[ \t\f]+	{ /* whitespace */ 
+		  break;        
+		}
+.		return (yytext[0]) ;
diff --git a/src/utils/ncmpigen/ncmpigen.y b/src/utils/ncmpigen/ncmpigen.y
new file mode 100644
index 0000000..600ea79
--- /dev/null
+++ b/src/utils/ncmpigen/ncmpigen.y
@@ -0,0 +1,1317 @@
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Id: ncmpigen.y 2238 2015-12-18 18:20:25Z wkliao $
+ *********************************************************************/
+
+/* yacc source for "ncmpigen", a netCDL parser and netCDF generator */
+
+%{
+#ifdef sccs
+static char SccsId[] = "$Id: ncmpigen.y 2238 2015-12-18 18:20:25Z wkliao $";
+#endif
+
+#include        <string.h>
+#include	<stdlib.h>
+#include	<stddef.h>  /* ptrdiff_t */
+#include	<pnetcdf.h>
+#include 	"generic.h"
+#include        "ncmpigen.h"
+#include	"genlib.h"	/* for grow_darray() et al */
+
+typedef struct Symbol {		/* symbol table entry */
+	char    	*name;
+	struct Symbol   *next;
+	unsigned	is_dim : 1;	/* appears as netCDF dimension */
+	unsigned	is_var : 1;	/* appears as netCDF variable */
+	unsigned	is_att : 1;	/* appears as netCDF attribute */
+	int             dnum;	        /* handle as a dimension */
+	int             vnum;	        /* handle as a variable */
+	} *YYSTYPE1;
+
+/* True if string a equals string b*/
+#define	STREQ(a, b)	(*(a) == *(b) && strcmp((a), (b)) == 0)
+#define NC_UNSPECIFIED ((nc_type)0)	/* unspecified (as yet) type */
+
+#define YYSTYPE YYSTYPE1
+YYSTYPE symlist;		/* symbol table: linked list */
+
+extern int derror_count;	/* counts errors in netcdf definition */
+extern int lineno;		/* line number for error messages */
+
+static int not_a_string;	/* whether last constant read was a string */
+static char termstring[MAXTRST]; /* last terminal string read */
+static double double_val;	/* last double value read */
+static float float_val;		/* last float value read */
+static int int_val;		/* last int value read */
+static short short_val;		/* last short value read */
+static char char_val;		/* last char value read */
+static signed char byte_val;	/* last byte value read */
+static unsigned char ubyte_val;		/* last byte value read */
+static unsigned short ushort_val;	/* last byte value read */
+static unsigned int uint_val;		/* last byte value read */
+static long long int64_val;		/* last byte value read */
+static unsigned long long uint64_val;	/* last byte value read */
+
+static nc_type type_code;	/* holds declared type for variables */
+static nc_type atype_code;	/* holds derived type for attributes */
+static char *netcdfname;	/* to construct netcdf file name */
+static void *att_space;		/* pointer to block for attribute values */
+static nc_type valtype;		/* type code for list of attribute values  */
+
+static char *char_valp;		/* pointers used to accumulate data values */
+static signed char *byte_valp;
+static short *short_valp;
+static int *int_valp;
+static float *float_valp;
+static double *double_valp;
+static unsigned char *ubyte_valp;
+static unsigned short *ushort_valp;
+static unsigned int *uint_valp;
+static long long *int64_valp;
+static unsigned long long *uint64_valp;
+
+static void *rec_cur;		/* pointer to where next data value goes */
+static void *rec_start;		/* start of space for data */
+
+/* Forward declarations */
+void defatt(void);
+void equalatt(void);
+
+#ifdef YYLEX_PARAM
+int yylex(YYLEX_PARAM);
+#else
+int yylex(void);
+#endif
+
+#ifdef vms
+void yyerror(char*);
+#else
+int yyerror(char*);
+#endif
+%}
+
+/* DECLARATIONS */
+
+%token
+	NC_UNLIMITED_K /* keyword for unbounded record dimension */
+	BYTE_K	    /* keyword for byte datatype */
+	CHAR_K	    /* keyword for char datatype */
+	SHORT_K	    /* keyword for short datatype */
+	INT_K	    /* keyword for int datatype */
+	FLOAT_K	    /* keyword for float datatype */
+	DOUBLE_K    /* keyword for double datatype */
+	UBYTE_K     /* keyword for unsigned char datatype */
+	USHORT_K    /* keyword for unsigned short datatype */
+	UINT_K      /* keyword for unsigned int datatype */
+	INT64_K     /* keyword for long long datatype */
+	UINT64_K    /* keyword for unsigned long long datatype */
+	IDENT	    /* name for a dimension, variable, or attribute */
+	TERMSTRING  /* terminal string */
+	BYTE_CONST  /* byte constant */
+	CHAR_CONST  /* char constant */
+	SHORT_CONST /* short constant */
+	INT_CONST   /* int constant */
+	FLOAT_CONST /* float constant */
+	DOUBLE_CONST /* double constant */
+	UBYTE_CONST  /* unsigned char constant */
+	USHORT_CONST /* unsigned short constant */
+	UINT_CONST   /* unsigned int constant */
+	INT64_CONST  /* long long constant */
+	UINT64_CONST /* unsigned long long constant */
+	DIMENSIONS  /* keyword starting dimensions section, if any */
+	VARIABLES   /* keyword starting variables section, if any */
+	NETCDF      /* keyword declaring netcdf name */
+	DATA        /* keyword starting data section, if any */
+        FILLVALUE   /* fill value, from _FillValue attribute or default */
+
+%start	ncdesc /* start symbol for grammar */
+
+%%
+
+/* RULES */
+
+ncdesc:	NETCDF
+		'{'
+		   { init_netcdf(); }
+                dimsection	/* dimension declarations */
+                vasection	/* variable and attribute declarations */
+		   {
+		       if (derror_count == 0)
+			 define_netcdf(netcdfname);
+		       if (derror_count > 0)
+			   exit(6);
+		   }
+		datasection     /* data, variables loaded as encountered */
+                '}'
+		   {
+		       if (derror_count == 0)
+			 close_netcdf();
+		   }
+		;
+dimsection:     /* empty */
+		| DIMENSIONS dimdecls
+		;
+dimdecls:       dimdecline ';'
+		| dimdecls dimdecline ';'
+		;
+dimdecline:     dimdecl
+                | dimdecline ',' dimdecl
+                ;
+dimdecl:        dimd '=' INT_CONST
+		   { if (int_val <= 0)
+			 derror("dimension length must be positive");
+		     dims[ndims].size = int_val;
+		     ndims++;
+		   }
+                | dimd '=' DOUBLE_CONST
+                   { /* for rare case where 2^31 < dimsize < 2^32 */
+		       if (double_val <= 0)
+			 derror("dimension length must be positive");
+		       if (double_val > 4294967295.0)
+			 derror("dimension too large");
+		       if (double_val - (MPI_Offset) double_val > 0)
+			 derror("dimension length must be an integer");
+		       dims[ndims].size = (MPI_Offset) double_val;
+		       ndims++;
+                   }
+                | dimd '=' NC_UNLIMITED_K
+		   {  if (rec_dim != -1)
+			 derror("only one NC_UNLIMITED dimension allowed");
+		     rec_dim = ndims; /* the unlimited (record) dimension */
+		     dims[ndims].size = NC_UNLIMITED;
+		     ndims++;
+		   }
+                ;
+dimd:           dim
+		   { 
+		    if ($1->is_dim == 1) {
+		        derror( "duplicate dimension declaration for %s",
+		                $1->name);
+		     }
+	             $1->is_dim = 1;
+		     $1->dnum = ndims;
+		     /* make sure dims array will hold dimensions */
+		     grow_darray(ndims,  /* must hold ndims+1 dims */
+				 &dims); /* grow as needed */
+		     dims[ndims].name = (char *) emalloc(strlen($1->name)+1);
+		     (void) strcpy(dims[ndims].name, $1->name);
+		     /* name for use in generated Fortran and C variables */
+		     dims[ndims].lname = decodify($1->name);
+		   }
+                ;
+dim:		IDENT
+		;
+vasection:      /* empty */
+		| VARIABLES vadecls
+		| gattdecls
+		;
+vadecls:        vadecl ';'
+                | vadecls vadecl ';'
+                ;
+vadecl:         vardecl | attdecl | gattdecl
+                ;
+gattdecls:      gattdecl ';'
+                | gattdecls gattdecl ';'
+                ;
+vardecl:        type varlist
+                ;
+type:             BYTE_K  { type_code = NC_BYTE; }
+		| CHAR_K  { type_code = NC_CHAR; }
+		| SHORT_K { type_code = NC_SHORT; }
+		| INT_K   { type_code = NC_INT; }
+		| FLOAT_K { type_code = NC_FLOAT; }
+		| DOUBLE_K{ type_code = NC_DOUBLE; }
+ 		| UBYTE_K { type_code = NC_UBYTE; }
+ 		| USHORT_K{ type_code = NC_USHORT; }
+ 		| UINT_K  { type_code = NC_UINT; }
+ 		| INT64_K { type_code = NC_INT64; }
+ 		| UINT64_K{ type_code = NC_UINT64; }
+		;
+varlist:        varspec
+                | varlist ',' varspec
+                ;
+varspec:        var
+		   {
+		    static struct vars dummyvar;
+
+		    dummyvar.name = "dummy";
+		    dummyvar.type = NC_DOUBLE;
+		    dummyvar.ndims = 0;
+		    dummyvar.dims = 0;
+		    dummyvar.fill_value.doublev = NC_FILL_DOUBLE;
+		    dummyvar.has_data = 0;
+
+		    nvdims = 0;
+		    /* make sure variable not re-declared */
+		    if ($1->is_var == 1) {
+		       derror( "duplicate variable declaration for %s",
+		               $1->name);
+		    }
+	            $1->is_var = 1;
+		    $1->vnum = nvars;
+		    /* make sure vars array will hold variables */
+		    grow_varray(nvars,  /* must hold nvars+1 vars */
+				&vars); /* grow as needed */
+		    vars[nvars] = dummyvar; /* to make Purify happy */
+		    vars[nvars].name = (char *) emalloc(strlen($1->name)+1);
+		    (void) strcpy(vars[nvars].name, $1->name);
+		    /* name for use in generated Fortran and C variables */
+		    vars[nvars].lname = decodify($1->name);
+		    vars[nvars].type = type_code;
+		    /* set default fill value.  You can override this with
+		     * the variable attribute "_FillValue". */
+		    nc_getfill(type_code, &vars[nvars].fill_value);
+		    vars[nvars].has_data = 0; /* has no data (yet) */
+		   }
+		dimspec
+		   {
+		    vars[nvars].ndims = nvdims;
+		    nvars++;
+		   }
+		;
+var:            IDENT
+                ;
+dimspec:	/* empty */
+		| '(' dimlist ')'
+		;
+dimlist:        vdim
+                | dimlist ',' vdim
+                ;
+vdim:		dim
+		   {
+		    if (nvdims >= NC_MAX_VAR_DIMS) {
+		       derror("%s has too many dimensions",vars[nvars].name);
+		    }
+		    if ($1->is_dim == 1)
+		       dimnum = $1->dnum;
+		    else {
+		       derror( "%s is not declared as a dimension",
+			       $1->name);
+	               dimnum = ndims;
+		    }
+		    if (rec_dim != -1 && dimnum == rec_dim && nvdims != 0) {
+		       derror("unlimited dimension must be first");
+		    }
+		    grow_iarray(nvdims, /* must hold nvdims+1 ints */
+				&vars[nvars].dims); /* grow as needed */
+		    vars[nvars].dims[nvdims] = dimnum;
+                    nvdims++;
+		   }
+		;
+attdecl:        att
+		   {
+                   defatt();
+		   }
+		'=' attvallist
+		   {
+                   equalatt();
+		   }
+                ;
+gattdecl:       gatt
+		   {
+                   defatt();
+		   }
+		'=' attvallist
+		   {
+                   equalatt();
+		   }
+                ;
+
+att:            avar ':' attr
+
+gatt:           ':' attr
+		   {
+		    varnum = NC_GLOBAL;  /* handle of "global" attribute */
+		   }
+                ;
+
+avar:           var
+		   { if ($1->is_var == 1)
+		       varnum = $1->vnum;
+		    else {
+		      derror("%s not declared as a variable, fatal error",
+			     $1->name);
+		      YYABORT;
+		      }
+		   }
+		;
+attr:		IDENT
+		   {
+		       /* make sure atts array will hold attributes */
+		       grow_aarray(natts,  /* must hold natts+1 atts */
+				   &atts); /* grow as needed */
+		       atts[natts].name = (char *) emalloc(strlen($1->name)+1);
+		       (void) strcpy(atts[natts].name,$1->name);
+		       /* name for use in generated Fortran and C variables */
+		       atts[natts].lname = decodify($1->name);
+		   }
+		;
+attvallist:     aconst
+                | attvallist ',' aconst
+                ;
+aconst:		attconst
+		   {
+		    if (valtype == NC_UNSPECIFIED)
+		      valtype = atype_code;
+		    if (valtype != atype_code)
+		      derror("values for attribute must be all of same type");
+		   }
+		;
+
+attconst:      CHAR_CONST
+                   {
+		       atype_code = NC_CHAR;
+		       *char_valp++ = char_val;
+		       valnum++;
+		   }
+	       | TERMSTRING
+		   {
+		       atype_code = NC_CHAR;
+		       {
+			   /* don't null-terminate attribute strings */
+			   MPI_Offset len = strlen(termstring);
+			   if (len == 0) /* need null if that's only value */
+			       len = 1;
+			   (void)strncpy(char_valp,termstring,len);
+			   valnum += len;
+			   char_valp += len;
+		       }
+		   }
+                | BYTE_CONST
+                   {
+		       atype_code = NC_BYTE;
+		       *byte_valp++ = byte_val;
+		       valnum++;
+		   }
+                | SHORT_CONST
+                   {
+		       atype_code = NC_SHORT;
+		       *short_valp++ = short_val;
+		       valnum++;
+		   }
+                | INT_CONST
+                   {
+		       atype_code = NC_INT;
+		       *int_valp++ = int_val;
+		       valnum++;
+		   }
+                | FLOAT_CONST
+                   {
+		       atype_code = NC_FLOAT;
+		       *float_valp++ = float_val;
+		       valnum++;
+		   }
+                | DOUBLE_CONST
+                   {
+		       atype_code = NC_DOUBLE;
+		       *double_valp++ = double_val;
+		       valnum++;
+		   }
+                | UBYTE_CONST
+                   {
+		       atype_code = NC_UBYTE;
+		       *ubyte_valp++ = ubyte_val;
+		       valnum++;
+		   }
+                | USHORT_CONST
+                   {
+		       atype_code = NC_USHORT;
+		       *ushort_valp++ = ushort_val;
+		       valnum++;
+		   }
+                | UINT_CONST
+                   {
+		       atype_code = NC_UINT;
+		       *uint_valp++ = uint_val;
+		       valnum++;
+		   }
+                | INT64_CONST
+                   {
+		       atype_code = NC_INT64;
+		       *int64_valp++ = int64_val;
+		       valnum++;
+		   }
+                | UINT64_CONST
+                   {
+		       atype_code = NC_UINT64;
+		       *uint64_valp++ = uint64_val;
+		       valnum++;
+		   }
+                ;
+
+datasection:    /* empty */
+		| DATA datadecls
+		| DATA
+		;
+
+datadecls:      datadecl ';'
+                | datadecls datadecl ';'
+                ;
+datadecl:       avar
+		   {
+		       valtype = vars[varnum].type; /* variable type */
+		       valnum = 0;	/* values accumulated for variable */
+		       vars[varnum].has_data = 1;
+		       /* compute dimensions product */
+		       var_size = nctypesize(valtype);
+		       if (vars[varnum].ndims == 0) { /* scalar */
+			   var_len = 1;
+		       } else if (vars[varnum].dims[0] == rec_dim) {
+			   var_len = 1; /* one record for unlimited vars */
+		       } else {
+			   var_len = dims[vars[varnum].dims[0]].size;
+		       }
+		       for(dimnum = 1; dimnum < vars[varnum].ndims; dimnum++)
+			 var_len = var_len*dims[vars[varnum].dims[dimnum]].size;
+		       /* allocate memory for variable data */
+		       if (var_len*var_size != (MPI_Offset)(var_len*var_size)) {
+			   derror("variable %s too large for memory",
+				  vars[varnum].name);
+			   exit(9);
+		       }
+		       rec_len = var_len;
+		       rec_start = malloc ((MPI_Offset)(rec_len*var_size));
+		       if (rec_start == 0) {
+			   derror ("out of memory\n");
+			   exit(3);
+		       }
+		       rec_cur = rec_start;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   char_valp = (char *) rec_start;
+			   break;
+			 case NC_BYTE:
+			   byte_valp = (signed char *) rec_start;
+			   break;
+			 case NC_SHORT:
+			   short_valp = (short *) rec_start;
+			   break;
+			 case NC_INT:
+			   int_valp = (int *) rec_start;
+			   break;
+			 case NC_FLOAT:
+			   float_valp = (float *) rec_start;
+			   break;
+			 case NC_DOUBLE:
+			   double_valp = (double *) rec_start;
+			   break;
+			 case NC_UBYTE:
+			   ubyte_valp = (unsigned char *) rec_start;
+			   break;
+			 case NC_USHORT:
+			   ushort_valp = (unsigned short *) rec_start;
+			   break;
+			 case NC_UINT:
+			   uint_valp = (unsigned int *) rec_start;
+			   break;
+			 case NC_INT64:
+			   int64_valp = (long long *) rec_start;
+			   break;
+			 case NC_UINT64:
+			   uint64_valp = (unsigned long long *) rec_start;
+			   break;
+			 default: break;
+		       }
+		 }
+		'=' constlist
+                   {
+		       if (valnum < var_len) { /* leftovers */
+			   nc_fill(valtype,
+				    var_len - valnum,
+				    rec_cur,
+				    vars[varnum].fill_value);
+		       }
+		       /* put out var_len values */
+		       /* vars[varnum].nrecs = valnum / rec_len; */
+		       vars[varnum].nrecs = var_len / rec_len;
+		       if (derror_count == 0)
+			   put_variable(rec_start);
+		       free ((char *) rec_start);
+		 }
+                ;
+constlist:      dconst
+                | constlist ',' dconst
+                ;
+dconst:
+                   {
+		       if(valnum >= var_len) {
+			   if (vars[varnum].dims[0] != rec_dim) { /* not recvar */
+			       derror("too many values for this variable, %d >= %d",
+				      valnum, var_len);
+			       exit (4);
+			   } else { /* a record variable, so grow data
+				      container and increment var_len by
+				      multiple of record size */
+			       ptrdiff_t rec_inc = (char *)rec_cur
+				   - (char *)rec_start;
+			       var_len = rec_len * (1 + valnum / rec_len);
+			       rec_start = erealloc(rec_start, var_len*var_size);
+			       rec_cur = (char *)rec_start + rec_inc;
+			       char_valp = (char *) rec_cur;
+			       byte_valp = (signed char *) rec_cur;
+			       short_valp = (short *) rec_cur;
+			       int_valp = (int *) rec_cur;
+			       float_valp = (float *) rec_cur;
+			       double_valp = (double *) rec_cur;
+			       ubyte_valp = (unsigned char *) rec_cur;
+			       ushort_valp = (unsigned short *) rec_cur;
+			       uint_valp = (unsigned int *) rec_cur;
+			       int64_valp = (long long *) rec_cur;
+			       uint64_valp = (unsigned long long *) rec_cur;
+			   }
+		       }
+		       not_a_string = 1;
+                   }
+                const
+		   {
+		       if (not_a_string) {
+			   switch (valtype) {
+			     case NC_CHAR:
+			       rec_cur = (void *) char_valp;
+			       break;
+			     case NC_BYTE:
+			       rec_cur = (void *) byte_valp;
+			       break;
+			     case NC_SHORT:
+			       rec_cur = (void *) short_valp;
+			       break;
+			     case NC_INT:
+			       rec_cur = (void *) int_valp;
+			       break;
+			     case NC_FLOAT:
+			       rec_cur = (void *) float_valp;
+			       break;
+			     case NC_DOUBLE:
+			       rec_cur = (void *) double_valp;
+			       break;
+			     case NC_UBYTE:
+			       rec_cur = (void *) ubyte_valp;
+			       break;
+			     case NC_USHORT:
+			       rec_cur = (void *) ushort_valp;
+			       break;
+			     case NC_UINT:
+			       rec_cur = (void *) uint_valp;
+			       break;
+			     case NC_INT64:
+			       rec_cur = (void *) int64_valp;
+			       break;
+			     case NC_UINT64:
+			       rec_cur = (void *) uint64_valp;
+			       break;
+			     default: break;
+			   }
+		       }
+		   }
+;
+
+const:         CHAR_CONST
+                   {
+		       atype_code = NC_CHAR;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = char_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = char_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = char_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = char_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = char_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = char_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = char_val;
+			   break; 
+			 case NC_USHORT:
+			   *ushort_valp++ = char_val;
+			   break; 
+			 case NC_UINT:
+			   *uint_valp++ = char_val;
+			   break; 
+			 case NC_INT64:
+			   *int64_valp++ = char_val;
+			   break; 
+			 case NC_UINT64:
+			   *uint64_valp++ = char_val;
+			   break; 
+			 default: break;
+		       }
+		       valnum++;
+		   }
+	       | TERMSTRING
+		   {
+		       not_a_string = 0;
+		       atype_code = NC_CHAR;
+		       {
+			   MPI_Offset len = strlen(termstring);
+
+			   if(valnum + len > var_len) {
+			       if (vars[varnum].dims[0] != rec_dim) {
+				   derror("too many values for this variable, %d>%d", 
+					  valnum+len, var_len);
+				   exit (5);
+			       } else {/* a record variable so grow it */
+				   ptrdiff_t rec_inc = (char *)rec_cur
+				       - (char *)rec_start;
+				   var_len += rec_len * (len + valnum - var_len)/rec_len;
+				   rec_start = erealloc(rec_start, var_len*var_size);
+				   rec_cur = (char *)rec_start + rec_inc;
+				   char_valp = (char *) rec_cur;
+			       }
+			   }
+			   switch (valtype) {
+			     case NC_CHAR:
+			       {
+				   int ld;
+				   MPI_Offset i, sl;
+				   (void)strncpy(char_valp,termstring,len);
+				   ld = vars[varnum].ndims-1;
+				   if (ld > 0) {/* null-fill to size of last dim */
+				       sl = dims[vars[varnum].dims[ld]].size;
+				       for (i =len;i<sl;i++)
+					   char_valp[i] = '\0';
+				       if (sl < len)
+					   sl = len;
+				       valnum += sl;
+				       char_valp += sl;
+				   } else { /* scalar or 1D strings */
+				       valnum += len;
+				       char_valp += len;
+				   }
+				   rec_cur = (void *) char_valp;
+			       }
+			       break;
+			     case NC_BYTE:
+			     case NC_SHORT:
+			     case NC_INT:
+			     case NC_FLOAT:
+			     case NC_DOUBLE:
+			       derror("string value invalid for %s variable",
+				      nctype(valtype));
+			       break;
+			     default: break;
+			   }
+		       }
+		   }
+                | BYTE_CONST
+                   {
+		       atype_code = NC_BYTE;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = byte_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = byte_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = byte_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = byte_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = byte_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = byte_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = byte_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = byte_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = byte_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = byte_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = byte_val;
+			   break;
+			 default: break;
+		       }
+		       valnum++;
+		   }
+                | SHORT_CONST
+                   {
+		       atype_code = NC_SHORT;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = short_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = short_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = short_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = short_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = short_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = short_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = short_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = short_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = short_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = short_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = short_val;
+			   break;
+			 default: break;			
+		       }
+		       valnum++;
+		   }
+                | INT_CONST
+                   {
+		       atype_code = NC_INT;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = int_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = int_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = int_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = int_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = int_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = int_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = int_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = int_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = int_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = int_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = int_val;
+			   break;
+			 default: break;
+		       }
+		       valnum++;
+		   }
+                | FLOAT_CONST
+                   {
+		       atype_code = NC_FLOAT;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = float_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = float_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = float_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = float_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = float_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = float_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = float_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = float_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = float_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = float_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = float_val;
+			   break;
+			 default: break;
+		       }
+		       valnum++;
+		   }
+                | DOUBLE_CONST
+                   {
+		       atype_code = NC_DOUBLE;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = double_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = double_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = double_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = double_val;
+			   break;
+			 case NC_FLOAT:
+			   if (double_val == NC_FILL_DOUBLE)
+			     *float_valp++ = NC_FILL_FLOAT;
+			   else
+			     *float_valp++ = double_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = double_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = double_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = double_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = double_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = double_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = double_val;
+			   break;
+			 default: break;
+		       }
+		       valnum++;
+		   }
+                | UBYTE_CONST
+                   {
+		       atype_code = NC_UBYTE;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = ubyte_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = ubyte_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = ubyte_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = ubyte_val;
+			   break;
+			 case NC_FLOAT:
+			     *float_valp++ = ubyte_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = ubyte_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = ubyte_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = ubyte_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = ubyte_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = ubyte_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = ubyte_val;
+			   break;
+			 default: 
+			   derror("Unhandled type %d\n", valtype);
+			   break;
+		       }
+		       valnum++;
+		   }
+                | USHORT_CONST
+                   {
+		       atype_code = NC_USHORT;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = ushort_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = ushort_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = ushort_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = ushort_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = ushort_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = ushort_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = ushort_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = ushort_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = ushort_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = ushort_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = ushort_val;
+			   break;
+			 default: 
+			   derror("Unhandled type %d\n", valtype);
+			   break;
+		       }
+		       valnum++;
+		   }
+                | UINT_CONST
+                   {
+		       atype_code = NC_UINT;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = uint_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = uint_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = uint_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = uint_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = uint_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = uint_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = uint_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = uint_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = uint_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = uint_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = uint_val;
+			   break;
+			 default: 
+			   derror("Unhandled type %d\n", valtype);
+			   break;
+		       }
+		       valnum++;
+		   }
+                | INT64_CONST
+                   {
+		       atype_code = NC_INT64;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = int64_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = int64_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = int64_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = int64_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = int64_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = int64_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = int64_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = int64_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = int64_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = int64_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = int64_val;
+			   break;
+			 default: 
+			   derror("Unhandled type %d\n", valtype);
+			   break;
+		       }
+		       valnum++;
+		   }
+                | UINT64_CONST
+                   {
+		       atype_code = NC_UINT64;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = uint64_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = uint64_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = uint64_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = uint64_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = uint64_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = uint64_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = uint64_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = uint64_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = uint64_val;
+ 			   break;
+ 			 case NC_INT64:
+ 			   *int64_valp++ = uint64_val;
+ 			   break;
+ 			 case NC_UINT64:
+ 			   *uint64_valp++ = uint64_val;
+ 			   break;
+ 			 default: 
+ 			   derror("Unhandled type %d\n", valtype);
+ 			   break;
+ 		       }
+ 		       valnum++;
+ 		   }
+                | FILLVALUE
+                   {
+		       /* store fill_value */
+		       switch (valtype) {
+		       case NC_CHAR:
+			   nc_fill(valtype, 1, (void *)char_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_BYTE:
+			   nc_fill(valtype, 1, (void *)byte_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_SHORT:
+			   nc_fill(valtype, 1, (void *)short_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_INT:
+			   nc_fill(valtype, 1, (void *)int_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_FLOAT:
+			   nc_fill(valtype, 1, (void *)float_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_DOUBLE:
+			   nc_fill(valtype, 1, (void *)double_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_UBYTE:
+			   nc_fill(valtype, 1, (void *)ubyte_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_USHORT:
+			   nc_fill(valtype, 1, (void *)ushort_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_UINT:
+			   nc_fill(valtype, 1, (void *)uint_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_INT64:
+			   nc_fill(valtype, 1, (void *)int64_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_UINT64:
+			   nc_fill(valtype, 1, (void *)uint64_valp++,
+				   vars[varnum].fill_value);
+			   break;
+			default: break;
+		       }
+		       valnum++;
+		   }
+                ;
+
+/* END OF RULES */
+
+%%
+
+/* HELPER PROGRAMS */
+void defatt(void)
+{
+    valnum = 0;
+    valtype = NC_UNSPECIFIED;
+    /* get a large block for attributes, realloc later */
+    att_space = emalloc(MAX_NC_ATTSIZE);
+    /* make all kinds of pointers point to it */
+    char_valp = (char *) att_space;
+    byte_valp = (signed char *) att_space;
+    short_valp = (short *) att_space;
+    int_valp = (int *) att_space;
+    float_valp = (float *) att_space;
+    double_valp = (double *) att_space;
+    ubyte_valp = (unsigned char *) att_space;
+    ushort_valp = (unsigned short *) att_space;
+     uint_valp = (unsigned int *) att_space;
+     int64_valp = (long long *) att_space;
+     uint64_valp = (unsigned long long *) att_space;
+}
+
+void equalatt(void)
+{
+    /* check if duplicate attribute for this var */
+    int i;
+    for(i=0; i<natts; i++) { /* expensive */
+        if(atts[i].var == varnum &&
+           STREQ(atts[i].name,atts[natts].name)) {
+            derror("duplicate attribute %s:%s",
+                   vars[varnum].name,atts[natts].name);
+        }
+    }
+    atts[natts].var = varnum ;
+    atts[natts].type = valtype;
+    atts[natts].len = valnum;
+    /* shrink space down to what was really needed */
+    att_space = erealloc(att_space, valnum*nctypesize(valtype));
+    atts[natts].val = att_space;
+    if (STREQ(atts[natts].name, _FillValue) &&
+        atts[natts].var != NC_GLOBAL) {
+        nc_putfill(atts[natts].type,atts[natts].val,
+                   &vars[atts[natts].var].fill_value);
+        if(atts[natts].type != vars[atts[natts].var].type) {
+            derror("variable %s: %s type mismatch",
+                   vars[atts[natts].var].name, _FillValue);
+        }
+    }
+    natts++;
+}
+/* PROGRAMS */
+
+#ifdef vms
+void
+#else
+int
+#endif
+yyerror(	/* called for yacc syntax error */
+     char *s)
+{
+	derror(s);
+#ifndef vms
+	return -1;
+#endif
+}
+
+/* undefine yywrap macro, in case we are using bison instead of yacc */
+#ifdef ncmpiwrap
+#undef ncmpiwrap
+#endif
+
+int
+ncmpiwrap(void)			/* returns 1 on EOF if no more input */
+{
+    return  1;
+}
+
+
+/* Symbol table operations for ncmpigen tool */
+
+/* Find CDL name in symbol table (linear search).  Note, this has a
+ * side-effect: it handles escape characters in the name, deleting
+ * single escape characters from the CDL name, before looking it up.
+ */
+YYSTYPE lookup(char *sname)
+{
+    YYSTYPE sp;
+    deescapify(sname);		/* delete escape chars from names,
+				 * e.g. 'ab\:cd\ ef' becomes 
+				 * 'ab:cd ef' */
+    for (sp = symlist; sp != (YYSTYPE) 0; sp = sp -> next)
+	if (STREQ(sp -> name, sname)) {
+	    return sp;
+	}
+    return 0;			/* 0 ==> not found */
+}
+
+YYSTYPE install(  /* install sname in symbol table */
+	const char *sname)
+{
+    YYSTYPE sp;
+
+    sp = (YYSTYPE) emalloc (sizeof (struct Symbol));
+    sp -> name = (char *) emalloc (strlen (sname) + 1);/* +1 for '\0' */
+    (void) strcpy (sp -> name, sname);
+    sp -> next = symlist;	/* put at front of list */
+    sp -> is_dim = 0;
+    sp -> is_var = 0;
+    sp -> is_att = 0;
+    symlist = sp;
+    return sp;
+}
+
+void
+clearout(void)	/* reset symbol table to empty */
+{
+    YYSTYPE sp, tp;
+    for (sp = symlist; sp != (YYSTYPE) 0;) {
+	tp = sp -> next;
+	free (sp -> name);
+	free ((char *) sp);
+	sp = tp;
+    }
+    symlist = 0;
+}
+
+/* get lexical input routine generated by lex  */
+
+/* Keep compile quiet */
+#define YY_NO_UNPUT
+#define YY_NO_INPUT
+
+#include "ncmpigenyy.c"
diff --git a/src/utils/ncmpigen/ncmpigentab.c b/src/utils/ncmpigen/ncmpigentab.c
new file mode 100644
index 0000000..2892264
--- /dev/null
+++ b/src/utils/ncmpigen/ncmpigentab.c
@@ -0,0 +1,1919 @@
+#ifndef lint
+static const char yysccsid[] = "@(#)yaccpar	1.9 (Berkeley) 02/21/93";
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define YYPATCH 20070509
+
+#define YYEMPTY (-1)
+#define yyclearin    (yychar = YYEMPTY)
+#define yyerrok      (yyerrflag = 0)
+#define YYRECOVERING (yyerrflag != 0)
+
+extern int yyparse(void);
+
+static int yygrowstack(void);
+#define yyparse ncmpiparse
+#define yylex ncmpilex
+#define yyerror ncmpierror
+#define yychar ncmpichar
+#define yyval ncmpival
+#define yylval ncmpilval
+#define yydebug ncmpidebug
+#define yynerrs ncmpinerrs
+#define yyerrflag ncmpierrflag
+#define yyss ncmpiss
+#define yyssp ncmpissp
+#define yyvs ncmpivs
+#define yyvsp ncmpivsp
+#define yylhs ncmpilhs
+#define yylen ncmpilen
+#define yydefred ncmpidefred
+#define yydgoto ncmpidgoto
+#define yysindex ncmpisindex
+#define yyrindex ncmpirindex
+#define yygindex ncmpigindex
+#define yytable ncmpitable
+#define yycheck ncmpicheck
+#define yyname ncmpiname
+#define yyrule ncmpirule
+#define YYPREFIX "ncmpi"
+#line 10 "./ncmpigen.y"
+#ifdef sccs
+static char SccsId[] = "$Id: ncmpigentab.c 2242 2015-12-19 00:37:52Z wkliao $";
+#endif
+
+#include        <string.h>
+#include	<stdlib.h>
+#include	<stddef.h>  /* ptrdiff_t */
+#include	<pnetcdf.h>
+#include 	"generic.h"
+#include        "ncmpigen.h"
+#include	"genlib.h"	/* for grow_darray() et al */
+
+typedef struct Symbol {		/* symbol table entry */
+	char    	*name;
+	struct Symbol   *next;
+	unsigned	is_dim : 1;	/* appears as netCDF dimension */
+	unsigned	is_var : 1;	/* appears as netCDF variable */
+	unsigned	is_att : 1;	/* appears as netCDF attribute */
+	int             dnum;	        /* handle as a dimension */
+	int             vnum;	        /* handle as a variable */
+	} *YYSTYPE1;
+
+/* True if string a equals string b*/
+#define	STREQ(a, b)	(*(a) == *(b) && strcmp((a), (b)) == 0)
+#define NC_UNSPECIFIED ((nc_type)0)	/* unspecified (as yet) type */
+
+#define YYSTYPE YYSTYPE1
+YYSTYPE symlist;		/* symbol table: linked list */
+
+extern int derror_count;	/* counts errors in netcdf definition */
+extern int lineno;		/* line number for error messages */
+
+static int not_a_string;	/* whether last constant read was a string */
+static char termstring[MAXTRST]; /* last terminal string read */
+static double double_val;	/* last double value read */
+static float float_val;		/* last float value read */
+static int int_val;		/* last int value read */
+static short short_val;		/* last short value read */
+static char char_val;		/* last char value read */
+static signed char byte_val;	/* last byte value read */
+static unsigned char ubyte_val;		/* last byte value read */
+static unsigned short ushort_val;	/* last byte value read */
+static unsigned int uint_val;		/* last byte value read */
+static long long int64_val;		/* last byte value read */
+static unsigned long long uint64_val;	/* last byte value read */
+
+static nc_type type_code;	/* holds declared type for variables */
+static nc_type atype_code;	/* holds derived type for attributes */
+static char *netcdfname;	/* to construct netcdf file name */
+static void *att_space;		/* pointer to block for attribute values */
+static nc_type valtype;		/* type code for list of attribute values  */
+
+static char *char_valp;		/* pointers used to accumulate data values */
+static signed char *byte_valp;
+static short *short_valp;
+static int *int_valp;
+static float *float_valp;
+static double *double_valp;
+static unsigned char *ubyte_valp;
+static unsigned short *ushort_valp;
+static unsigned int *uint_valp;
+static long long *int64_valp;
+static unsigned long long *uint64_valp;
+
+static void *rec_cur;		/* pointer to where next data value goes */
+static void *rec_start;		/* start of space for data */
+
+/* Forward declarations */
+void defatt(void);
+void equalatt(void);
+
+#ifdef YYLEX_PARAM
+int yylex(YYLEX_PARAM);
+#else
+int yylex(void);
+#endif
+
+#ifdef vms
+void yyerror(char*);
+#else
+int yyerror(char*);
+#endif
+#line 130 "y.tab.c"
+#define NC_UNLIMITED_K 257
+#define BYTE_K 258
+#define CHAR_K 259
+#define SHORT_K 260
+#define INT_K 261
+#define FLOAT_K 262
+#define DOUBLE_K 263
+#define UBYTE_K 264
+#define USHORT_K 265
+#define UINT_K 266
+#define INT64_K 267
+#define UINT64_K 268
+#define IDENT 269
+#define TERMSTRING 270
+#define BYTE_CONST 271
+#define CHAR_CONST 272
+#define SHORT_CONST 273
+#define INT_CONST 274
+#define FLOAT_CONST 275
+#define DOUBLE_CONST 276
+#define UBYTE_CONST 277
+#define USHORT_CONST 278
+#define UINT_CONST 279
+#define INT64_CONST 280
+#define UINT64_CONST 281
+#define DIMENSIONS 282
+#define VARIABLES 283
+#define NETCDF 284
+#define DATA 285
+#define FILLVALUE 286
+#define YYERRCODE 256
+short ncmpilhs[] = {                                        -1,
+    2,    5,    0,    1,    1,    6,    6,    7,    7,    8,
+    8,    8,    9,   10,    3,    3,    3,   11,   11,   13,
+   13,   13,   12,   12,   14,   17,   17,   17,   17,   17,
+   17,   17,   17,   17,   17,   17,   18,   18,   22,   19,
+   20,   21,   21,   23,   23,   24,   26,   15,   29,   16,
+   25,   28,   30,   31,   27,   27,   32,   33,   33,   33,
+   33,   33,   33,   33,   33,   33,   33,   33,   33,    4,
+    4,    4,   34,   34,   36,   35,   37,   37,   40,   38,
+   39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+   39,   39,   39,
+};
+short ncmpilen[] = {                                         2,
+    0,    0,    8,    0,    2,    2,    3,    1,    3,    3,
+    3,    3,    1,    1,    0,    2,    1,    2,    3,    1,
+    1,    1,    2,    3,    2,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    3,    0,    3,
+    1,    0,    3,    1,    3,    1,    0,    4,    0,    4,
+    3,    2,    1,    1,    1,    3,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    0,
+    2,    1,    2,    3,    0,    4,    1,    3,    0,    2,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,
+};
+short ncmpidefred[] = {                                      0,
+    0,    0,    1,    0,    0,    0,   14,    0,    0,    8,
+    0,   13,    0,    0,    2,    0,    0,   49,    0,    6,
+    0,    0,   26,   27,   28,   29,   30,   31,   32,   33,
+   34,   35,   36,   41,    0,    0,   20,   21,   22,    0,
+   53,   47,    0,   54,   52,    0,    0,   23,    0,    7,
+    9,   12,   10,   11,    0,   18,    0,   37,   39,    0,
+    0,    0,    0,   24,    0,   19,    0,    0,    0,   51,
+   75,    0,    0,    3,   59,   60,   58,   61,   62,   63,
+   64,   65,   66,   67,   68,   69,    0,   55,   57,   38,
+    0,   40,    0,    0,    0,   73,    0,   46,    0,   44,
+   79,   74,   56,    0,   43,    0,   77,    0,   45,   79,
+   82,   83,   81,   84,   85,   86,   87,   88,   89,   90,
+   91,   92,   93,   80,   78,
+};
+short ncmpidgoto[] = {                                       2,
+    6,    4,   15,   63,   46,    8,    9,   10,   11,   12,
+   35,   16,   36,   37,   38,   39,   40,   57,   58,   41,
+   92,   68,   99,  100,   42,   60,   87,   18,   49,   43,
+   45,   88,   89,   72,   73,   94,  106,  107,  124,  108,
+};
+short ncmpisindex[] = {                                   -253,
+  -90,    0,    0, -246, -215,  -54,    0, -215,  -35,    0,
+   -6,    0,  -56, -213,    0,   -1,    1,    0,  -22,    0,
+ -215, -249,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,  -56,    2,    0,    0,    0, -211,
+    0,    0,    4,    0,    0, -226,    5,    0,    8,    0,
+    0,    0,    0,    0,    6,    0,   19,    0,    0,    9,
+ -213, -211,  -59,    0, -228,    0, -211,   31, -228,    0,
+    0, -211,   13,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,   29,    0,    0,    0,
+ -215,    0,   29,   14,   15,    0, -228,    0,   -9,    0,
+    0,    0,    0, -215,    0,   32,    0, -260,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,
+};
+short ncmpirindex[] = {                                      0,
+    0,    0,    0,  -58,    0, -122,    0,  -57,    0,    0,
+    0,    0,    0,    0,    0, -120,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0, -119,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,  -48,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,   20,    0,    0,    0,
+    0,  -47,    0,    0,    0,    0,    0,  -21,    0,    0,
+    0,  -45,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,   22,    0,    0,    0,
+    0,    0,    1,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,   24,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,
+};
+short ncmpigindex[] = {                                      0,
+    0,    0,    0,    0,    0,    0,   74,   63,    0,  -63,
+    0,    0,   50,    0,    0,   23,    0,    0,   21,  -33,
+    0,    0,    0,  -18,    0,    0,   18,    0,    0,  -32,
+   28,   -7,    0,    0,   25,    0,    0,  -19,    0,    0,
+};
+#define YYTABLESIZE 229
+short ncmpitable[] = {                                       4,
+    5,   14,   15,   14,   17,   16,   59,   52,   21,  111,
+  112,  113,  114,  115,  116,  117,  118,  119,  120,  121,
+  122,   21,   42,   20,   53,  123,   54,   98,   17,   71,
+    1,  105,    3,   59,  104,    5,   50,   42,   47,   71,
+   98,   75,   76,   77,   78,   79,   80,   81,   82,   83,
+   84,   85,   86,    7,   22,   44,   14,   34,   62,   48,
+   56,   61,   67,   64,   66,   74,    4,    5,   65,   69,
+   91,   96,   97,  102,  101,  110,   70,   72,   25,   71,
+   50,   19,   76,   51,   55,  109,   93,   90,   70,  103,
+  125,    0,    0,    0,    0,    0,   95,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,   15,    0,   17,   16,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   23,   24,   25,   26,   27,   28,   29,   30,   31,
+   32,   33,   34,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    4,    5,    4,    5,   13,
+};
+short ncmpicheck[] = {                                      58,
+   58,   58,  125,   58,  125,  125,   40,  257,   44,  270,
+  271,  272,  273,  274,  275,  276,  277,  278,  279,  280,
+  281,   44,   44,   59,  274,  286,  276,   91,    6,   62,
+  284,   41,  123,   67,   44,  282,   59,   59,   16,   72,
+  104,  270,  271,  272,  273,  274,  275,  276,  277,  278,
+  279,  280,  281,  269,   61,  269,   58,  269,  285,   59,
+   59,   58,   44,   59,   59,  125,  125,  125,   61,   61,
+   40,   59,   44,   59,   61,   44,  125,  125,   59,  125,
+   59,    8,   59,   21,   35,  104,   69,   67,   61,   97,
+  110,   -1,   -1,   -1,   -1,   -1,   72,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,  285,   -1,  285,  285,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,  258,  259,  260,  261,  262,  263,  264,  265,  266,
+  267,  268,  269,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,  283,  283,  285,  285,  283,
+};
+#define YYFINAL 2
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 286
+#if YYDEBUG
+char *ncmpiname[] = {
+"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,"'('","')'",0,0,"','",0,0,0,0,0,0,0,0,0,0,0,0,0,"':'","';'",0,"'='",
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+"NC_UNLIMITED_K","BYTE_K","CHAR_K","SHORT_K","INT_K","FLOAT_K","DOUBLE_K",
+"UBYTE_K","USHORT_K","UINT_K","INT64_K","UINT64_K","IDENT","TERMSTRING",
+"BYTE_CONST","CHAR_CONST","SHORT_CONST","INT_CONST","FLOAT_CONST",
+"DOUBLE_CONST","UBYTE_CONST","USHORT_CONST","UINT_CONST","INT64_CONST",
+"UINT64_CONST","DIMENSIONS","VARIABLES","NETCDF","DATA","FILLVALUE",
+};
+char *ncmpirule[] = {
+"$accept : ncdesc",
+"$$1 :",
+"$$2 :",
+"ncdesc : NETCDF '{' $$1 dimsection vasection $$2 datasection '}'",
+"dimsection :",
+"dimsection : DIMENSIONS dimdecls",
+"dimdecls : dimdecline ';'",
+"dimdecls : dimdecls dimdecline ';'",
+"dimdecline : dimdecl",
+"dimdecline : dimdecline ',' dimdecl",
+"dimdecl : dimd '=' INT_CONST",
+"dimdecl : dimd '=' DOUBLE_CONST",
+"dimdecl : dimd '=' NC_UNLIMITED_K",
+"dimd : dim",
+"dim : IDENT",
+"vasection :",
+"vasection : VARIABLES vadecls",
+"vasection : gattdecls",
+"vadecls : vadecl ';'",
+"vadecls : vadecls vadecl ';'",
+"vadecl : vardecl",
+"vadecl : attdecl",
+"vadecl : gattdecl",
+"gattdecls : gattdecl ';'",
+"gattdecls : gattdecls gattdecl ';'",
+"vardecl : type varlist",
+"type : BYTE_K",
+"type : CHAR_K",
+"type : SHORT_K",
+"type : INT_K",
+"type : FLOAT_K",
+"type : DOUBLE_K",
+"type : UBYTE_K",
+"type : USHORT_K",
+"type : UINT_K",
+"type : INT64_K",
+"type : UINT64_K",
+"varlist : varspec",
+"varlist : varlist ',' varspec",
+"$$3 :",
+"varspec : var $$3 dimspec",
+"var : IDENT",
+"dimspec :",
+"dimspec : '(' dimlist ')'",
+"dimlist : vdim",
+"dimlist : dimlist ',' vdim",
+"vdim : dim",
+"$$4 :",
+"attdecl : att $$4 '=' attvallist",
+"$$5 :",
+"gattdecl : gatt $$5 '=' attvallist",
+"att : avar ':' attr",
+"gatt : ':' attr",
+"avar : var",
+"attr : IDENT",
+"attvallist : aconst",
+"attvallist : attvallist ',' aconst",
+"aconst : attconst",
+"attconst : CHAR_CONST",
+"attconst : TERMSTRING",
+"attconst : BYTE_CONST",
+"attconst : SHORT_CONST",
+"attconst : INT_CONST",
+"attconst : FLOAT_CONST",
+"attconst : DOUBLE_CONST",
+"attconst : UBYTE_CONST",
+"attconst : USHORT_CONST",
+"attconst : UINT_CONST",
+"attconst : INT64_CONST",
+"attconst : UINT64_CONST",
+"datasection :",
+"datasection : DATA datadecls",
+"datasection : DATA",
+"datadecls : datadecl ';'",
+"datadecls : datadecls datadecl ';'",
+"$$6 :",
+"datadecl : avar $$6 '=' constlist",
+"constlist : dconst",
+"constlist : constlist ',' dconst",
+"$$7 :",
+"dconst : $$7 const",
+"const : CHAR_CONST",
+"const : TERMSTRING",
+"const : BYTE_CONST",
+"const : SHORT_CONST",
+"const : INT_CONST",
+"const : FLOAT_CONST",
+"const : DOUBLE_CONST",
+"const : UBYTE_CONST",
+"const : USHORT_CONST",
+"const : UINT_CONST",
+"const : INT64_CONST",
+"const : UINT64_CONST",
+"const : FILLVALUE",
+};
+#endif
+#ifndef YYSTYPE
+typedef int YYSTYPE;
+#endif
+#if YYDEBUG
+#include <stdio.h>
+#endif
+
+/* define the initial stack-sizes */
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH  YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 10000
+#define YYMAXDEPTH  10000
+#endif
+#endif
+
+#define YYINITSTACKSIZE 500
+
+int      yydebug;
+int      yynerrs;
+int      yyerrflag;
+int      yychar;
+short   *yyssp;
+YYSTYPE *yyvsp;
+YYSTYPE  yyval;
+YYSTYPE  yylval;
+
+/* variables for the parser stack */
+static short   *yyss;
+static short   *yysslim;
+static YYSTYPE *yyvs;
+static int      yystacksize;
+#line 1185 "./ncmpigen.y"
+
+/* HELPER PROGRAMS */
+void defatt(void)
+{
+    valnum = 0;
+    valtype = NC_UNSPECIFIED;
+    /* get a large block for attributes, realloc later */
+    att_space = emalloc(MAX_NC_ATTSIZE);
+    /* make all kinds of pointers point to it */
+    char_valp = (char *) att_space;
+    byte_valp = (signed char *) att_space;
+    short_valp = (short *) att_space;
+    int_valp = (int *) att_space;
+    float_valp = (float *) att_space;
+    double_valp = (double *) att_space;
+    ubyte_valp = (unsigned char *) att_space;
+    ushort_valp = (unsigned short *) att_space;
+     uint_valp = (unsigned int *) att_space;
+     int64_valp = (long long *) att_space;
+     uint64_valp = (unsigned long long *) att_space;
+}
+
+void equalatt(void)
+{
+    /* check if duplicate attribute for this var */
+    int i;
+    for(i=0; i<natts; i++) { /* expensive */
+        if(atts[i].var == varnum &&
+           STREQ(atts[i].name,atts[natts].name)) {
+            derror("duplicate attribute %s:%s",
+                   vars[varnum].name,atts[natts].name);
+        }
+    }
+    atts[natts].var = varnum ;
+    atts[natts].type = valtype;
+    atts[natts].len = valnum;
+    /* shrink space down to what was really needed */
+    att_space = erealloc(att_space, valnum*nctypesize(valtype));
+    atts[natts].val = att_space;
+    if (STREQ(atts[natts].name, _FillValue) &&
+        atts[natts].var != NC_GLOBAL) {
+        nc_putfill(atts[natts].type,atts[natts].val,
+                   &vars[atts[natts].var].fill_value);
+        if(atts[natts].type != vars[atts[natts].var].type) {
+            derror("variable %s: %s type mismatch",
+                   vars[atts[natts].var].name, _FillValue);
+        }
+    }
+    natts++;
+}
+/* PROGRAMS */
+
+#ifdef vms
+void
+#else
+int
+#endif
+yyerror(	/* called for yacc syntax error */
+     char *s)
+{
+	derror(s);
+#ifndef vms
+	return -1;
+#endif
+}
+
+/* undefine yywrap macro, in case we are using bison instead of yacc */
+#ifdef ncmpiwrap
+#undef ncmpiwrap
+#endif
+
+int
+ncmpiwrap(void)			/* returns 1 on EOF if no more input */
+{
+    return  1;
+}
+
+
+/* Symbol table operations for ncmpigen tool */
+
+/* Find CDL name in symbol table (linear search).  Note, this has a
+ * side-effect: it handles escape characters in the name, deleting
+ * single escape characters from the CDL name, before looking it up.
+ */
+YYSTYPE lookup(char *sname)
+{
+    YYSTYPE sp;
+    deescapify(sname);		/* delete escape chars from names,
+				 * e.g. 'ab\:cd\ ef' becomes 
+				 * 'ab:cd ef' */
+    for (sp = symlist; sp != (YYSTYPE) 0; sp = sp -> next)
+	if (STREQ(sp -> name, sname)) {
+	    return sp;
+	}
+    return 0;			/* 0 ==> not found */
+}
+
+YYSTYPE install(  /* install sname in symbol table */
+	const char *sname)
+{
+    YYSTYPE sp;
+
+    sp = (YYSTYPE) emalloc (sizeof (struct Symbol));
+    sp -> name = (char *) emalloc (strlen (sname) + 1);/* +1 for '\0' */
+    (void) strcpy (sp -> name, sname);
+    sp -> next = symlist;	/* put at front of list */
+    sp -> is_dim = 0;
+    sp -> is_var = 0;
+    sp -> is_att = 0;
+    symlist = sp;
+    return sp;
+}
+
+void
+clearout(void)	/* reset symbol table to empty */
+{
+    YYSTYPE sp, tp;
+    for (sp = symlist; sp != (YYSTYPE) 0;) {
+	tp = sp -> next;
+	free (sp -> name);
+	free ((char *) sp);
+	sp = tp;
+    }
+    symlist = 0;
+}
+
+/* get lexical input routine generated by lex  */
+
+/* Keep compile quiet */
+#define YY_NO_UNPUT
+#define YY_NO_INPUT
+
+#include "ncmpigenyy.c"
+#line 581 "y.tab.c"
+/* allocate initial stack or double stack size, up to YYMAXDEPTH */
+static int yygrowstack(void)
+{
+    int newsize, i;
+    short *newss;
+    YYSTYPE *newvs;
+
+    if ((newsize = yystacksize) == 0)
+        newsize = YYINITSTACKSIZE;
+    else if (newsize >= YYMAXDEPTH)
+        return -1;
+    else if ((newsize *= 2) > YYMAXDEPTH)
+        newsize = YYMAXDEPTH;
+
+    i = yyssp - yyss;
+    newss = (yyss != 0)
+          ? (short *)realloc(yyss, newsize * sizeof(*newss))
+          : (short *)malloc(newsize * sizeof(*newss));
+    if (newss == 0)
+        return -1;
+
+    yyss  = newss;
+    yyssp = newss + i;
+    newvs = (yyvs != 0)
+          ? (YYSTYPE *)realloc(yyvs, newsize * sizeof(*newvs))
+          : (YYSTYPE *)malloc(newsize * sizeof(*newvs));
+    if (newvs == 0)
+        return -1;
+
+    yyvs = newvs;
+    yyvsp = newvs + i;
+    yystacksize = newsize;
+    yysslim = yyss + newsize - 1;
+    return 0;
+}
+
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+int
+yyparse(void)
+{
+    register int yym, yyn, yystate;
+#if YYDEBUG
+    register const char *yys;
+
+    if ((yys = getenv("YYDEBUG")) != 0)
+    {
+        yyn = *yys;
+        if (yyn >= '0' && yyn <= '9')
+            yydebug = yyn - '0';
+    }
+#endif
+
+    yynerrs = 0;
+    yyerrflag = 0;
+    yychar = YYEMPTY;
+
+    if (yyss == NULL && yygrowstack()) goto yyoverflow;
+    yyssp = yyss;
+    yyvsp = yyvs;
+    *yyssp = yystate = 0;
+
+yyloop:
+    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
+    if (yychar < 0)
+    {
+        if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+        if (yydebug)
+        {
+            yys = 0;
+            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+            if (!yys) yys = "illegal-symbol";
+            printf("%sdebug: state %d, reading %d (%s)\n",
+                    YYPREFIX, yystate, yychar, yys);
+        }
+#endif
+    }
+    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+    {
+#if YYDEBUG
+        if (yydebug)
+            printf("%sdebug: state %d, shifting to state %d\n",
+                    YYPREFIX, yystate, yytable[yyn]);
+#endif
+        if (yyssp >= yysslim && yygrowstack())
+        {
+            goto yyoverflow;
+        }
+        *++yyssp = yystate = yytable[yyn];
+        *++yyvsp = yylval;
+        yychar = YYEMPTY;
+        if (yyerrflag > 0)  --yyerrflag;
+        goto yyloop;
+    }
+    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+    {
+        yyn = yytable[yyn];
+        goto yyreduce;
+    }
+    if (yyerrflag) goto yyinrecovery;
+
+    yyerror("syntax error");
+
+#ifdef lint
+    goto yyerrlab;
+#endif
+
+yyerrlab:
+    ++yynerrs;
+
+yyinrecovery:
+    if (yyerrflag < 3)
+    {
+        yyerrflag = 3;
+        for (;;)
+        {
+            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
+                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+            {
+#if YYDEBUG
+                if (yydebug)
+                    printf("%sdebug: state %d, error recovery shifting\
+ to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
+#endif
+                if (yyssp >= yysslim && yygrowstack())
+                {
+                    goto yyoverflow;
+                }
+                *++yyssp = yystate = yytable[yyn];
+                *++yyvsp = yylval;
+                goto yyloop;
+            }
+            else
+            {
+#if YYDEBUG
+                if (yydebug)
+                    printf("%sdebug: error recovery discarding state %d\n",
+                            YYPREFIX, *yyssp);
+#endif
+                if (yyssp <= yyss) goto yyabort;
+                --yyssp;
+                --yyvsp;
+            }
+        }
+    }
+    else
+    {
+        if (yychar == 0) goto yyabort;
+#if YYDEBUG
+        if (yydebug)
+        {
+            yys = 0;
+            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+            if (!yys) yys = "illegal-symbol";
+            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
+                    YYPREFIX, yystate, yychar, yys);
+        }
+#endif
+        yychar = YYEMPTY;
+        goto yyloop;
+    }
+
+yyreduce:
+#if YYDEBUG
+    if (yydebug)
+        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
+                YYPREFIX, yystate, yyn, yyrule[yyn]);
+#endif
+    yym = yylen[yyn];
+    if (yym)
+        yyval = yyvsp[1-yym];
+    else
+        memset(&yyval, 0, sizeof yyval);
+    switch (yyn)
+    {
+case 1:
+#line 136 "./ncmpigen.y"
+{ init_netcdf(); }
+break;
+case 2:
+#line 139 "./ncmpigen.y"
+{
+		       if (derror_count == 0)
+			 define_netcdf(netcdfname);
+		       if (derror_count > 0)
+			   exit(6);
+		   }
+break;
+case 3:
+#line 147 "./ncmpigen.y"
+{
+		       if (derror_count == 0)
+			 close_netcdf();
+		   }
+break;
+case 10:
+#line 162 "./ncmpigen.y"
+{ if (int_val <= 0)
+			 derror("dimension length must be positive");
+		     dims[ndims].size = int_val;
+		     ndims++;
+		   }
+break;
+case 11:
+#line 168 "./ncmpigen.y"
+{ /* for rare case where 2^31 < dimsize < 2^32 */
+		       if (double_val <= 0)
+			 derror("dimension length must be positive");
+		       if (double_val > 4294967295.0)
+			 derror("dimension too large");
+		       if (double_val - (MPI_Offset) double_val > 0)
+			 derror("dimension length must be an integer");
+		       dims[ndims].size = (MPI_Offset) double_val;
+		       ndims++;
+                   }
+break;
+case 12:
+#line 179 "./ncmpigen.y"
+{  if (rec_dim != -1)
+			 derror("only one NC_UNLIMITED dimension allowed");
+		     rec_dim = ndims; /* the unlimited (record) dimension */
+		     dims[ndims].size = NC_UNLIMITED;
+		     ndims++;
+		   }
+break;
+case 13:
+#line 187 "./ncmpigen.y"
+{ 
+		    if (yyvsp[0]->is_dim == 1) {
+		        derror( "duplicate dimension declaration for %s",
+		                yyvsp[0]->name);
+		     }
+	             yyvsp[0]->is_dim = 1;
+		     yyvsp[0]->dnum = ndims;
+		     /* make sure dims array will hold dimensions */
+		     grow_darray(ndims,  /* must hold ndims+1 dims */
+				 &dims); /* grow as needed */
+		     dims[ndims].name = (char *) emalloc(strlen(yyvsp[0]->name)+1);
+		     (void) strcpy(dims[ndims].name, yyvsp[0]->name);
+		     /* name for use in generated Fortran and C variables */
+		     dims[ndims].lname = decodify(yyvsp[0]->name);
+		   }
+break;
+case 26:
+#line 219 "./ncmpigen.y"
+{ type_code = NC_BYTE; }
+break;
+case 27:
+#line 220 "./ncmpigen.y"
+{ type_code = NC_CHAR; }
+break;
+case 28:
+#line 221 "./ncmpigen.y"
+{ type_code = NC_SHORT; }
+break;
+case 29:
+#line 222 "./ncmpigen.y"
+{ type_code = NC_INT; }
+break;
+case 30:
+#line 223 "./ncmpigen.y"
+{ type_code = NC_FLOAT; }
+break;
+case 31:
+#line 224 "./ncmpigen.y"
+{ type_code = NC_DOUBLE; }
+break;
+case 32:
+#line 225 "./ncmpigen.y"
+{ type_code = NC_UBYTE; }
+break;
+case 33:
+#line 226 "./ncmpigen.y"
+{ type_code = NC_USHORT; }
+break;
+case 34:
+#line 227 "./ncmpigen.y"
+{ type_code = NC_UINT; }
+break;
+case 35:
+#line 228 "./ncmpigen.y"
+{ type_code = NC_INT64; }
+break;
+case 36:
+#line 229 "./ncmpigen.y"
+{ type_code = NC_UINT64; }
+break;
+case 39:
+#line 235 "./ncmpigen.y"
+{
+		    static struct vars dummyvar;
+
+		    dummyvar.name = "dummy";
+		    dummyvar.type = NC_DOUBLE;
+		    dummyvar.ndims = 0;
+		    dummyvar.dims = 0;
+		    dummyvar.fill_value.doublev = NC_FILL_DOUBLE;
+		    dummyvar.has_data = 0;
+
+		    nvdims = 0;
+		    /* make sure variable not re-declared */
+		    if (yyvsp[0]->is_var == 1) {
+		       derror( "duplicate variable declaration for %s",
+		               yyvsp[0]->name);
+		    }
+	            yyvsp[0]->is_var = 1;
+		    yyvsp[0]->vnum = nvars;
+		    /* make sure vars array will hold variables */
+		    grow_varray(nvars,  /* must hold nvars+1 vars */
+				&vars); /* grow as needed */
+		    vars[nvars] = dummyvar; /* to make Purify happy */
+		    vars[nvars].name = (char *) emalloc(strlen(yyvsp[0]->name)+1);
+		    (void) strcpy(vars[nvars].name, yyvsp[0]->name);
+		    /* name for use in generated Fortran and C variables */
+		    vars[nvars].lname = decodify(yyvsp[0]->name);
+		    vars[nvars].type = type_code;
+		    /* set default fill value.  You can override this with
+		     * the variable attribute "_FillValue". */
+		    nc_getfill(type_code, &vars[nvars].fill_value);
+		    vars[nvars].has_data = 0; /* has no data (yet) */
+		   }
+break;
+case 40:
+#line 268 "./ncmpigen.y"
+{
+		    vars[nvars].ndims = nvdims;
+		    nvars++;
+		   }
+break;
+case 46:
+#line 282 "./ncmpigen.y"
+{
+		    if (nvdims >= NC_MAX_VAR_DIMS) {
+		       derror("%s has too many dimensions",vars[nvars].name);
+		    }
+		    if (yyvsp[0]->is_dim == 1)
+		       dimnum = yyvsp[0]->dnum;
+		    else {
+		       derror( "%s is not declared as a dimension",
+			       yyvsp[0]->name);
+	               dimnum = ndims;
+		    }
+		    if (rec_dim != -1 && dimnum == rec_dim && nvdims != 0) {
+		       derror("unlimited dimension must be first");
+		    }
+		    grow_iarray(nvdims, /* must hold nvdims+1 ints */
+				&vars[nvars].dims); /* grow as needed */
+		    vars[nvars].dims[nvdims] = dimnum;
+                    nvdims++;
+		   }
+break;
+case 47:
+#line 303 "./ncmpigen.y"
+{
+                   defatt();
+		   }
+break;
+case 48:
+#line 307 "./ncmpigen.y"
+{
+                   equalatt();
+		   }
+break;
+case 49:
+#line 312 "./ncmpigen.y"
+{
+                   defatt();
+		   }
+break;
+case 50:
+#line 316 "./ncmpigen.y"
+{
+                   equalatt();
+		   }
+break;
+case 52:
+#line 324 "./ncmpigen.y"
+{
+		    varnum = NC_GLOBAL;  /* handle of "global" attribute */
+		   }
+break;
+case 53:
+#line 330 "./ncmpigen.y"
+{ if (yyvsp[0]->is_var == 1)
+		       varnum = yyvsp[0]->vnum;
+		    else {
+		      derror("%s not declared as a variable, fatal error",
+			     yyvsp[0]->name);
+		      YYABORT;
+		      }
+		   }
+break;
+case 54:
+#line 340 "./ncmpigen.y"
+{
+		       /* make sure atts array will hold attributes */
+		       grow_aarray(natts,  /* must hold natts+1 atts */
+				   &atts); /* grow as needed */
+		       atts[natts].name = (char *) emalloc(strlen(yyvsp[0]->name)+1);
+		       (void) strcpy(atts[natts].name,yyvsp[0]->name);
+		       /* name for use in generated Fortran and C variables */
+		       atts[natts].lname = decodify(yyvsp[0]->name);
+		   }
+break;
+case 57:
+#line 354 "./ncmpigen.y"
+{
+		    if (valtype == NC_UNSPECIFIED)
+		      valtype = atype_code;
+		    if (valtype != atype_code)
+		      derror("values for attribute must be all of same type");
+		   }
+break;
+case 58:
+#line 363 "./ncmpigen.y"
+{
+		       atype_code = NC_CHAR;
+		       *char_valp++ = char_val;
+		       valnum++;
+		   }
+break;
+case 59:
+#line 369 "./ncmpigen.y"
+{
+		       atype_code = NC_CHAR;
+		       {
+			   /* don't null-terminate attribute strings */
+			   MPI_Offset len = strlen(termstring);
+			   if (len == 0) /* need null if that's only value */
+			       len = 1;
+			   (void)strncpy(char_valp,termstring,len);
+			   valnum += len;
+			   char_valp += len;
+		       }
+		   }
+break;
+case 60:
+#line 382 "./ncmpigen.y"
+{
+		       atype_code = NC_BYTE;
+		       *byte_valp++ = byte_val;
+		       valnum++;
+		   }
+break;
+case 61:
+#line 388 "./ncmpigen.y"
+{
+		       atype_code = NC_SHORT;
+		       *short_valp++ = short_val;
+		       valnum++;
+		   }
+break;
+case 62:
+#line 394 "./ncmpigen.y"
+{
+		       atype_code = NC_INT;
+		       *int_valp++ = int_val;
+		       valnum++;
+		   }
+break;
+case 63:
+#line 400 "./ncmpigen.y"
+{
+		       atype_code = NC_FLOAT;
+		       *float_valp++ = float_val;
+		       valnum++;
+		   }
+break;
+case 64:
+#line 406 "./ncmpigen.y"
+{
+		       atype_code = NC_DOUBLE;
+		       *double_valp++ = double_val;
+		       valnum++;
+		   }
+break;
+case 65:
+#line 412 "./ncmpigen.y"
+{
+		       atype_code = NC_UBYTE;
+		       *ubyte_valp++ = ubyte_val;
+		       valnum++;
+		   }
+break;
+case 66:
+#line 418 "./ncmpigen.y"
+{
+		       atype_code = NC_USHORT;
+		       *ushort_valp++ = ushort_val;
+		       valnum++;
+		   }
+break;
+case 67:
+#line 424 "./ncmpigen.y"
+{
+		       atype_code = NC_UINT;
+		       *uint_valp++ = uint_val;
+		       valnum++;
+		   }
+break;
+case 68:
+#line 430 "./ncmpigen.y"
+{
+		       atype_code = NC_INT64;
+		       *int64_valp++ = int64_val;
+		       valnum++;
+		   }
+break;
+case 69:
+#line 436 "./ncmpigen.y"
+{
+		       atype_code = NC_UINT64;
+		       *uint64_valp++ = uint64_val;
+		       valnum++;
+		   }
+break;
+case 75:
+#line 452 "./ncmpigen.y"
+{
+		       valtype = vars[varnum].type; /* variable type */
+		       valnum = 0;	/* values accumulated for variable */
+		       vars[varnum].has_data = 1;
+		       /* compute dimensions product */
+		       var_size = nctypesize(valtype);
+		       if (vars[varnum].ndims == 0) { /* scalar */
+			   var_len = 1;
+		       } else if (vars[varnum].dims[0] == rec_dim) {
+			   var_len = 1; /* one record for unlimited vars */
+		       } else {
+			   var_len = dims[vars[varnum].dims[0]].size;
+		       }
+		       for(dimnum = 1; dimnum < vars[varnum].ndims; dimnum++)
+			 var_len = var_len*dims[vars[varnum].dims[dimnum]].size;
+		       /* allocate memory for variable data */
+		       if (var_len*var_size != (MPI_Offset)(var_len*var_size)) {
+			   derror("variable %s too large for memory",
+				  vars[varnum].name);
+			   exit(9);
+		       }
+		       rec_len = var_len;
+		       rec_start = malloc ((MPI_Offset)(rec_len*var_size));
+		       if (rec_start == 0) {
+			   derror ("out of memory\n");
+			   exit(3);
+		       }
+		       rec_cur = rec_start;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   char_valp = (char *) rec_start;
+			   break;
+			 case NC_BYTE:
+			   byte_valp = (signed char *) rec_start;
+			   break;
+			 case NC_SHORT:
+			   short_valp = (short *) rec_start;
+			   break;
+			 case NC_INT:
+			   int_valp = (int *) rec_start;
+			   break;
+			 case NC_FLOAT:
+			   float_valp = (float *) rec_start;
+			   break;
+			 case NC_DOUBLE:
+			   double_valp = (double *) rec_start;
+			   break;
+			 case NC_UBYTE:
+			   ubyte_valp = (unsigned char *) rec_start;
+			   break;
+			 case NC_USHORT:
+			   ushort_valp = (unsigned short *) rec_start;
+			   break;
+			 case NC_UINT:
+			   uint_valp = (unsigned int *) rec_start;
+			   break;
+			 case NC_INT64:
+			   int64_valp = (long long *) rec_start;
+			   break;
+			 case NC_UINT64:
+			   uint64_valp = (unsigned long long *) rec_start;
+			   break;
+			 default: break;
+		       }
+		 }
+break;
+case 76:
+#line 518 "./ncmpigen.y"
+{
+		       if (valnum < var_len) { /* leftovers */
+			   nc_fill(valtype,
+				    var_len - valnum,
+				    rec_cur,
+				    vars[varnum].fill_value);
+		       }
+		       /* put out var_len values */
+		       /* vars[varnum].nrecs = valnum / rec_len; */
+		       vars[varnum].nrecs = var_len / rec_len;
+		       if (derror_count == 0)
+			   put_variable(rec_start);
+		       free ((char *) rec_start);
+		 }
+break;
+case 79:
+#line 537 "./ncmpigen.y"
+{
+		       if(valnum >= var_len) {
+			   if (vars[varnum].dims[0] != rec_dim) { /* not recvar */
+			       derror("too many values for this variable, %d >= %d",
+				      valnum, var_len);
+			       exit (4);
+			   } else { /* a record variable, so grow data
+				      container and increment var_len by
+				      multiple of record size */
+			       ptrdiff_t rec_inc = (char *)rec_cur
+				   - (char *)rec_start;
+			       var_len = rec_len * (1 + valnum / rec_len);
+			       rec_start = erealloc(rec_start, var_len*var_size);
+			       rec_cur = (char *)rec_start + rec_inc;
+			       char_valp = (char *) rec_cur;
+			       byte_valp = (signed char *) rec_cur;
+			       short_valp = (short *) rec_cur;
+			       int_valp = (int *) rec_cur;
+			       float_valp = (float *) rec_cur;
+			       double_valp = (double *) rec_cur;
+			       ubyte_valp = (unsigned char *) rec_cur;
+			       ushort_valp = (unsigned short *) rec_cur;
+			       uint_valp = (unsigned int *) rec_cur;
+			       int64_valp = (long long *) rec_cur;
+			       uint64_valp = (unsigned long long *) rec_cur;
+			   }
+		       }
+		       not_a_string = 1;
+                   }
+break;
+case 80:
+#line 567 "./ncmpigen.y"
+{
+		       if (not_a_string) {
+			   switch (valtype) {
+			     case NC_CHAR:
+			       rec_cur = (void *) char_valp;
+			       break;
+			     case NC_BYTE:
+			       rec_cur = (void *) byte_valp;
+			       break;
+			     case NC_SHORT:
+			       rec_cur = (void *) short_valp;
+			       break;
+			     case NC_INT:
+			       rec_cur = (void *) int_valp;
+			       break;
+			     case NC_FLOAT:
+			       rec_cur = (void *) float_valp;
+			       break;
+			     case NC_DOUBLE:
+			       rec_cur = (void *) double_valp;
+			       break;
+			     case NC_UBYTE:
+			       rec_cur = (void *) ubyte_valp;
+			       break;
+			     case NC_USHORT:
+			       rec_cur = (void *) ushort_valp;
+			       break;
+			     case NC_UINT:
+			       rec_cur = (void *) uint_valp;
+			       break;
+			     case NC_INT64:
+			       rec_cur = (void *) int64_valp;
+			       break;
+			     case NC_UINT64:
+			       rec_cur = (void *) uint64_valp;
+			       break;
+			     default: break;
+			   }
+		       }
+		   }
+break;
+case 81:
+#line 610 "./ncmpigen.y"
+{
+		       atype_code = NC_CHAR;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = char_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = char_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = char_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = char_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = char_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = char_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = char_val;
+			   break; 
+			 case NC_USHORT:
+			   *ushort_valp++ = char_val;
+			   break; 
+			 case NC_UINT:
+			   *uint_valp++ = char_val;
+			   break; 
+			 case NC_INT64:
+			   *int64_valp++ = char_val;
+			   break; 
+			 case NC_UINT64:
+			   *uint64_valp++ = char_val;
+			   break; 
+			 default: break;
+		       }
+		       valnum++;
+		   }
+break;
+case 82:
+#line 651 "./ncmpigen.y"
+{
+		       not_a_string = 0;
+		       atype_code = NC_CHAR;
+		       {
+			   MPI_Offset len = strlen(termstring);
+
+			   if(valnum + len > var_len) {
+			       if (vars[varnum].dims[0] != rec_dim) {
+				   derror("too many values for this variable, %d>%d", 
+					  valnum+len, var_len);
+				   exit (5);
+			       } else {/* a record variable so grow it */
+				   ptrdiff_t rec_inc = (char *)rec_cur
+				       - (char *)rec_start;
+				   var_len += rec_len * (len + valnum - var_len)/rec_len;
+				   rec_start = erealloc(rec_start, var_len*var_size);
+				   rec_cur = (char *)rec_start + rec_inc;
+				   char_valp = (char *) rec_cur;
+			       }
+			   }
+			   switch (valtype) {
+			     case NC_CHAR:
+			       {
+				   int ld;
+				   MPI_Offset i, sl;
+				   (void)strncpy(char_valp,termstring,len);
+				   ld = vars[varnum].ndims-1;
+				   if (ld > 0) {/* null-fill to size of last dim */
+				       sl = dims[vars[varnum].dims[ld]].size;
+				       for (i =len;i<sl;i++)
+					   char_valp[i] = '\0';
+				       if (sl < len)
+					   sl = len;
+				       valnum += sl;
+				       char_valp += sl;
+				   } else { /* scalar or 1D strings */
+				       valnum += len;
+				       char_valp += len;
+				   }
+				   rec_cur = (void *) char_valp;
+			       }
+			       break;
+			     case NC_BYTE:
+			     case NC_SHORT:
+			     case NC_INT:
+			     case NC_FLOAT:
+			     case NC_DOUBLE:
+			       derror("string value invalid for %s variable",
+				      nctype(valtype));
+			       break;
+			     default: break;
+			   }
+		       }
+		   }
+break;
+case 83:
+#line 706 "./ncmpigen.y"
+{
+		       atype_code = NC_BYTE;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = byte_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = byte_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = byte_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = byte_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = byte_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = byte_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = byte_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = byte_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = byte_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = byte_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = byte_val;
+			   break;
+			 default: break;
+		       }
+		       valnum++;
+		   }
+break;
+case 84:
+#line 747 "./ncmpigen.y"
+{
+		       atype_code = NC_SHORT;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = short_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = short_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = short_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = short_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = short_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = short_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = short_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = short_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = short_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = short_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = short_val;
+			   break;
+			 default: break;			
+		       }
+		       valnum++;
+		   }
+break;
+case 85:
+#line 788 "./ncmpigen.y"
+{
+		       atype_code = NC_INT;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = int_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = int_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = int_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = int_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = int_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = int_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = int_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = int_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = int_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = int_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = int_val;
+			   break;
+			 default: break;
+		       }
+		       valnum++;
+		   }
+break;
+case 86:
+#line 829 "./ncmpigen.y"
+{
+		       atype_code = NC_FLOAT;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = float_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = float_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = float_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = float_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = float_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = float_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = float_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = float_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = float_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = float_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = float_val;
+			   break;
+			 default: break;
+		       }
+		       valnum++;
+		   }
+break;
+case 87:
+#line 870 "./ncmpigen.y"
+{
+		       atype_code = NC_DOUBLE;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = double_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = double_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = double_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = double_val;
+			   break;
+			 case NC_FLOAT:
+			   if (double_val == NC_FILL_DOUBLE)
+			     *float_valp++ = NC_FILL_FLOAT;
+			   else
+			     *float_valp++ = double_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = double_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = double_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = double_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = double_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = double_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = double_val;
+			   break;
+			 default: break;
+		       }
+		       valnum++;
+		   }
+break;
+case 88:
+#line 914 "./ncmpigen.y"
+{
+		       atype_code = NC_UBYTE;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = ubyte_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = ubyte_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = ubyte_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = ubyte_val;
+			   break;
+			 case NC_FLOAT:
+			     *float_valp++ = ubyte_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = ubyte_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = ubyte_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = ubyte_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = ubyte_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = ubyte_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = ubyte_val;
+			   break;
+			 default: 
+			   derror("Unhandled type %d\n", valtype);
+			   break;
+		       }
+		       valnum++;
+		   }
+break;
+case 89:
+#line 957 "./ncmpigen.y"
+{
+		       atype_code = NC_USHORT;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = ushort_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = ushort_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = ushort_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = ushort_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = ushort_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = ushort_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = ushort_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = ushort_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = ushort_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = ushort_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = ushort_val;
+			   break;
+			 default: 
+			   derror("Unhandled type %d\n", valtype);
+			   break;
+		       }
+		       valnum++;
+		   }
+break;
+case 90:
+#line 1000 "./ncmpigen.y"
+{
+		       atype_code = NC_UINT;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = uint_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = uint_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = uint_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = uint_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = uint_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = uint_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = uint_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = uint_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = uint_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = uint_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = uint_val;
+			   break;
+			 default: 
+			   derror("Unhandled type %d\n", valtype);
+			   break;
+		       }
+		       valnum++;
+		   }
+break;
+case 91:
+#line 1043 "./ncmpigen.y"
+{
+		       atype_code = NC_INT64;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = int64_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = int64_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = int64_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = int64_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = int64_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = int64_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = int64_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = int64_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = int64_val;
+			   break;
+			 case NC_INT64:
+			   *int64_valp++ = int64_val;
+			   break;
+			 case NC_UINT64:
+			   *uint64_valp++ = int64_val;
+			   break;
+			 default: 
+			   derror("Unhandled type %d\n", valtype);
+			   break;
+		       }
+		       valnum++;
+		   }
+break;
+case 92:
+#line 1086 "./ncmpigen.y"
+{
+		       atype_code = NC_UINT64;
+		       switch (valtype) {
+			 case NC_CHAR:
+			   *char_valp++ = uint64_val;
+			   break;
+			 case NC_BYTE:
+			   *byte_valp++ = uint64_val;
+			   break;
+			 case NC_SHORT:
+			   *short_valp++ = uint64_val;
+			   break;
+			 case NC_INT:
+			   *int_valp++ = uint64_val;
+			   break;
+			 case NC_FLOAT:
+			   *float_valp++ = uint64_val;
+			   break;
+			 case NC_DOUBLE:
+			   *double_valp++ = uint64_val;
+			   break;
+			 case NC_UBYTE:
+			   *ubyte_valp++ = uint64_val;
+			   break;
+			 case NC_USHORT:
+			   *ushort_valp++ = uint64_val;
+			   break;
+			 case NC_UINT:
+			   *uint_valp++ = uint64_val;
+ 			   break;
+ 			 case NC_INT64:
+ 			   *int64_valp++ = uint64_val;
+ 			   break;
+ 			 case NC_UINT64:
+ 			   *uint64_valp++ = uint64_val;
+ 			   break;
+ 			 default: 
+ 			   derror("Unhandled type %d\n", valtype);
+ 			   break;
+ 		       }
+ 		       valnum++;
+ 		   }
+break;
+case 93:
+#line 1129 "./ncmpigen.y"
+{
+		       /* store fill_value */
+		       switch (valtype) {
+		       case NC_CHAR:
+			   nc_fill(valtype, 1, (void *)char_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_BYTE:
+			   nc_fill(valtype, 1, (void *)byte_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_SHORT:
+			   nc_fill(valtype, 1, (void *)short_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_INT:
+			   nc_fill(valtype, 1, (void *)int_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_FLOAT:
+			   nc_fill(valtype, 1, (void *)float_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_DOUBLE:
+			   nc_fill(valtype, 1, (void *)double_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_UBYTE:
+			   nc_fill(valtype, 1, (void *)ubyte_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_USHORT:
+			   nc_fill(valtype, 1, (void *)ushort_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_UINT:
+			   nc_fill(valtype, 1, (void *)uint_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_INT64:
+			   nc_fill(valtype, 1, (void *)int64_valp++,
+				   vars[varnum].fill_value);
+			   break;
+		       case NC_UINT64:
+			   nc_fill(valtype, 1, (void *)uint64_valp++,
+				   vars[varnum].fill_value);
+			   break;
+			default: break;
+		       }
+		       valnum++;
+		   }
+break;
+#line 1860 "y.tab.c"
+    }
+    yyssp -= yym;
+    yystate = *yyssp;
+    yyvsp -= yym;
+    yym = yylhs[yyn];
+    if (yystate == 0 && yym == 0)
+    {
+#if YYDEBUG
+        if (yydebug)
+            printf("%sdebug: after reduction, shifting from state 0 to\
+ state %d\n", YYPREFIX, YYFINAL);
+#endif
+        yystate = YYFINAL;
+        *++yyssp = YYFINAL;
+        *++yyvsp = yyval;
+        if (yychar < 0)
+        {
+            if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+            if (yydebug)
+            {
+                yys = 0;
+                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+                if (!yys) yys = "illegal-symbol";
+                printf("%sdebug: state %d, reading %d (%s)\n",
+                        YYPREFIX, YYFINAL, yychar, yys);
+            }
+#endif
+        }
+        if (yychar == 0) goto yyaccept;
+        goto yyloop;
+    }
+    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+        yystate = yytable[yyn];
+    else
+        yystate = yydgoto[yym];
+#if YYDEBUG
+    if (yydebug)
+        printf("%sdebug: after reduction, shifting from state %d \
+to state %d\n", YYPREFIX, *yyssp, yystate);
+#endif
+    if (yyssp >= yysslim && yygrowstack())
+    {
+        goto yyoverflow;
+    }
+    *++yyssp = yystate;
+    *++yyvsp = yyval;
+    goto yyloop;
+
+yyoverflow:
+    yyerror("yacc stack overflow");
+
+yyabort:
+    return (1);
+
+yyaccept:
+    return (0);
+}
+
diff --git a/src/utils/ncmpigen/ncmpigentab.h b/src/utils/ncmpigen/ncmpigentab.h
new file mode 100644
index 0000000..d728a0c
--- /dev/null
+++ b/src/utils/ncmpigen/ncmpigentab.h
@@ -0,0 +1,30 @@
+#define NC_UNLIMITED_K 257
+#define BYTE_K 258
+#define CHAR_K 259
+#define SHORT_K 260
+#define INT_K 261
+#define FLOAT_K 262
+#define DOUBLE_K 263
+#define UBYTE_K 264
+#define USHORT_K 265
+#define UINT_K 266
+#define INT64_K 267
+#define UINT64_K 268
+#define IDENT 269
+#define TERMSTRING 270
+#define BYTE_CONST 271
+#define CHAR_CONST 272
+#define SHORT_CONST 273
+#define INT_CONST 274
+#define FLOAT_CONST 275
+#define DOUBLE_CONST 276
+#define UBYTE_CONST 277
+#define USHORT_CONST 278
+#define UINT_CONST 279
+#define INT64_CONST 280
+#define UINT64_CONST 281
+#define DIMENSIONS 282
+#define VARIABLES 283
+#define NETCDF 284
+#define DATA 285
+#define FILLVALUE 286
diff --git a/src/utils/ncmpigen/ncmpigenyy.c b/src/utils/ncmpigen/ncmpigenyy.c
new file mode 100644
index 0000000..3558068
--- /dev/null
+++ b/src/utils/ncmpigen/ncmpigenyy.c
@@ -0,0 +1,2294 @@
+
+#line 3 "lex.ncmpi.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer ncmpi_create_buffer
+#define yy_delete_buffer ncmpi_delete_buffer
+#define yy_flex_debug ncmpi_flex_debug
+#define yy_init_buffer ncmpi_init_buffer
+#define yy_flush_buffer ncmpi_flush_buffer
+#define yy_load_buffer_state ncmpi_load_buffer_state
+#define yy_switch_to_buffer ncmpi_switch_to_buffer
+#define yyin ncmpiin
+#define yyleng ncmpileng
+#define yylex ncmpilex
+#define yylineno ncmpilineno
+#define yyout ncmpiout
+#define yyrestart ncmpirestart
+#define yytext ncmpitext
+#define yywrap ncmpiwrap
+#define yyalloc ncmpialloc
+#define yyrealloc ncmpirealloc
+#define yyfree ncmpifree
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE ncmpirestart(ncmpiin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int ncmpileng;
+
+extern FILE *ncmpiin, *ncmpiout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    #define YY_LESS_LINENO(n)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up ncmpitext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up ncmpitext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via ncmpirestart()), so that the user can continue scanning by
+	 * just pointing ncmpiin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when ncmpitext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int ncmpileng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow ncmpiwrap()'s to do buffer switches
+ * instead of setting up a fresh ncmpiin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void ncmpirestart (FILE *input_file  );
+void ncmpi_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE ncmpi_create_buffer (FILE *file,int size  );
+void ncmpi_delete_buffer (YY_BUFFER_STATE b  );
+void ncmpi_flush_buffer (YY_BUFFER_STATE b  );
+void ncmpipush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void ncmpipop_buffer_state (void );
+
+static void ncmpiensure_buffer_stack (void );
+static void ncmpi_load_buffer_state (void );
+static void ncmpi_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER ncmpi_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE ncmpi_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE ncmpi_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE ncmpi_scan_bytes (yyconst char *bytes,int len  );
+
+void *ncmpialloc (yy_size_t  );
+void *ncmpirealloc (void *,yy_size_t  );
+void ncmpifree (void *  );
+
+#define yy_new_buffer ncmpi_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        ncmpiensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            ncmpi_create_buffer(ncmpiin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        ncmpiensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            ncmpi_create_buffer(ncmpiin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+typedef unsigned char YY_CHAR;
+
+FILE *ncmpiin = (FILE *) 0, *ncmpiout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int ncmpilineno;
+
+int ncmpilineno = 1;
+
+extern char *ncmpitext;
+#define yytext_ptr ncmpitext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up ncmpitext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	ncmpileng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 35
+#define YY_END_OF_BUFFER 36
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[277] =
+    {   0,
+        0,    0,   36,   34,   33,   22,   34,   34,   34,   34,
+       24,   34,   27,   27,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,   33,    0,
+        2,    0,    0,    0,   24,   27,   27,    0,    0,   24,
+       24,    0,   25,    1,   28,   28,   23,   28,   27,   26,
+        0,   27,   23,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+
+       21,   21,   29,    0,    0,    0,    0,    0,   24,    0,
+        0,   24,    1,   28,   24,   28,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,    7,   21,   21,   21,
+       19,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,    7,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   32,   30,    0,    0,   24,    0,
+       24,   25,   24,    5,    4,   21,   21,   21,   21,   21,
+       21,   21,   21,   20,   21,    7,   21,    3,   21,   21,
+       11,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   11,   21,   21,   21,   30,    0,
+
+       31,    0,   20,    0,   17,   21,   21,   21,   21,   12,
+       21,   21,   21,    6,    9,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21,   21,   21,    0,   21,
+        8,   21,   21,   21,   21,   21,   13,   21,   10,   21,
+       21,   21,   21,   21,    0,   21,   21,   21,   21,    0,
+       21,   21,   21,   21,   21,    0,   21,   21,   18,   18,
+       21,   21,   21,   21,   21,   19,   21,   14,   21,   21,
+       21,   21,   16,   21,   15,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    4,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    5,    6,    1,    1,    1,    7,    1,
+        1,    1,    8,    1,    9,   10,   11,   12,   13,   13,
+       13,   14,   13,   15,   13,   16,   16,   17,    1,    1,
+        1,    1,    1,    6,   18,   19,   20,   21,   22,   23,
+       24,   25,   26,   27,   27,   28,   29,   30,   31,   27,
+       27,   32,   33,   34,   35,   36,   27,   37,   38,   27,
+        6,   39,    6,    1,   27,    1,   40,   41,   42,   43,
+
+       44,   45,   46,   47,   48,   27,   27,   49,   50,   51,
+       52,   27,   27,   53,   54,   55,   56,   57,   27,   37,
+       58,   27,   59,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[60] =
+    {   0,
+        1,    1,    2,    1,    1,    3,    4,    3,    3,    3,
+        1,    5,    5,    5,    5,    5,    1,    5,    5,    5,
+        5,    5,    5,    3,    3,    3,    3,    6,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    1,    5,
+        5,    5,    5,    5,    5,    3,    3,    3,    6,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    7
+    } ;
+
+static yyconst flex_int16_t yy_base[287] =
+    {   0,
+        0,    0,  514,  515,   58,  515,   56,  474,   53,   88,
+      121,  501,  161,  206,    0,  473,  485,   53,   73,   42,
+       42,  478,   52,  486,  482,   87,  488,  447,  457,   59,
+      454,  451,  449,  456,  455,  451,   67,  457,   74,   85,
+      515,  493,  488,  113,    0,  139,    0,  228,  443,    0,
+      515,  249,  515,    0,  110,   45,   81,  258,  515,  515,
+        0,    0,  515,    0,  459,  474,  457,  461,  454,  432,
+      217,  296,  456,  434,  451,  439,  453,  448,  451,  462,
+      448,  440,  447,  448,  450,  442,  418,  432,  416,  420,
+      413,  416,  412,  415,  393,  401,  385,  362,  368,  369,
+
+      369,  361,  515,  406,  178,  405,   91,  263,  334,  366,
+      268,  372,    0,  515,  293,  113,  388,  377,  390,  385,
+      387,  364,    0,    0,  386,  363,  101,   32,  378,  381,
+        0,  371,  366,  363,  362,  368,  361,  365,  346,  336,
+      342,  337,  339,  338,   68,  330,  119,  326,  321,  318,
+      317,  323,  318,  321,  515,  515,  239,  361,  515,  100,
+      129,  158,  515,    0,    0,  350,  336,  337,  315,  329,
+      306,  346,  335,    0,  307,    0,  335,    0,  320,  331,
+      337,  322,  312,  325,  323,  286,  286,  279,  319,  286,
+      310,  287,  274,  284,  312,  276,  272,  283,  515,  315,
+
+      515,  313,  515,  267,  515,  282,  291,  262,  279,    0,
+      282,  255,  277,    0,    0,  285,  272,  263,  277,  241,
+      250,  249,  269,  246,  276,  241,  233,  246,  237,  243,
+        0,  242,  208,  224,  194,  246,    0,  211,    0,  210,
+      187,  174,  171,  175,  168,  186,  163,  168,  154,  209,
+      187,  186,  148,  155,  153,  138,  165,  143,    0,  185,
+      151,  136,  117,  120,  106,  515,  125,    0,  139,   77,
+      112,  105,  515,   79,  515,  515,  421,  428,  433,  439,
+      446,  449,   59,  452,  454,  459
+    } ;
+
+static yyconst flex_int16_t yy_def[287] =
+    {   0,
+      276,    1,  276,  276,  276,  276,  277,  278,  276,  276,
+      276,  276,  276,  276,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  276,  277,
+      276,  277,  276,  280,   11,   14,   14,  276,  276,   11,
+      276,  276,  276,  281,   13,  282,  282,  282,  276,  276,
+      283,   14,  276,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+
+      279,  279,  276,  276,  276,  284,   46,  276,  276,  276,
+      276,  276,  281,  276,   58,  283,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  276,  276,  276,  285,  276,  276,
+      282,  282,  276,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  276,  276,
+
+      276,  276,  276,  276,  276,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  276,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  276,  279,  279,  279,  279,  286,
+      279,  279,  279,  279,  279,  276,  279,  279,  286,  286,
+      279,  279,  279,  279,  279,  276,  279,  279,  279,  279,
+      279,  279,  276,  279,  276,    0,  276,  276,  276,  276,
+      276,  276,  276,  276,  276,  276
+    } ;
+
+static yyconst flex_int16_t yy_nxt[575] =
+    {   0,
+        4,    5,    6,    5,    7,    4,    8,    9,   10,   11,
+       12,   13,   14,   14,   14,   14,    4,   15,   16,   17,
+       18,   19,   20,   15,   15,   21,   15,   22,   15,   23,
+       15,   24,   25,   15,   26,   27,   15,   15,    4,   15,
+       28,   29,   30,   19,   31,   15,   15,   32,   33,   15,
+       34,   15,   35,   36,   15,   37,   38,   15,    4,   39,
+       41,   39,   45,  116,   46,   47,   47,   47,   47,   73,
+       67,   75,  114,   78,   48,   39,  174,   39,   68,  175,
+       71,   71,  189,   69,   72,   72,   72,   72,   72,   41,
+       74,   79,   76,  114,   42,  275,   48,   45,   89,   46,
+
+       47,   47,   47,   47,   70,   82,   90,   98,  114,   48,
+       91,  190,   83,   49,   99,  172,   84,  100,  276,   85,
+      101,  275,  173,   42,  105,  105,  105,  105,  273,  114,
+      274,   48,   50,   50,   50,   50,   50,  114,  191,  276,
+      114,   51,   52,   53,  203,   60,  276,  204,   51,  106,
+      107,  107,  107,  107,  107,  273,  114,  272,  114,  271,
+      192,  114,  268,   51,   52,   53,   60,  270,  269,   51,
+       45,  268,   55,   55,   55,   55,   55,  114,   56,   57,
+       56,   56,   58,   56,  156,  114,  260,  131,   59,  157,
+      157,  157,  157,   60,  267,  266,  265,   61,  264,  263,
+
+       56,   57,   56,   56,   58,   56,  114,  262,  261,   59,
+      260,  131,  174,  258,   60,   45,  257,   62,   62,   62,
+       62,   62,  256,  255,   63,  254,  176,   48,   72,   72,
+       72,   72,   72,   59,  253,  108,  108,  252,   60,  109,
+      109,  109,  109,  109,  251,  199,   63,  250,  249,   48,
+      200,  200,  200,  200,   59,  176,  111,  111,  248,   60,
+      112,  112,  112,  112,  112,  108,  108,  247,  246,  115,
+      115,  115,  115,  115,  109,  109,  109,  109,  109,  112,
+      112,  112,  112,  112,  245,  114,  244,  239,  243,  237,
+      236,  236,  242,  231,  241,  240,  239,  238,  237,  236,
+
+      276,  276,  235,  234,  233,  232,  114,   72,   72,   72,
+       72,   72,  231,  161,  230,  162,  123,  229,  124,  201,
+      163,  199,  228,  123,  227,  226,  225,  215,  214,  224,
+      223,  222,  210,  178,  221,  161,  220,  162,  123,  205,
+      124,  163,  219,  218,  123,  109,  109,  109,  109,  109,
+      217,  216,  215,  214,  159,  213,   53,  212,  211,  210,
+      209,  159,  178,  208,  207,  206,  205,  201,  198,  197,
+      196,  195,  194,  193,  178,  176,  159,  188,   53,  187,
+      186,  185,  159,  112,  112,  112,  112,  112,  165,  164,
+      184,  183,   51,  182,   53,  181,  180,  179,  178,   51,
+
+      177,  176,  171,  170,  169,  168,  167,  166,  165,  164,
+      160,  155,  155,  154,   51,  153,   53,  152,  151,  150,
+       51,   40,   40,   40,   40,   40,   40,   40,   43,   43,
+       43,   43,   43,   43,   43,   64,  149,   64,   64,  104,
+      148,  104,  104,  104,  104,  104,  113,  147,  113,  113,
+      113,  113,  113,   56,   56,  158,  158,  202,  202,  259,
+      259,  259,  259,  259,  259,  146,  145,  144,  143,  142,
+      141,  140,  139,  138,  137,  136,  135,  134,  133,  132,
+      131,  130,  129,  128,  127,  126,  125,  122,  121,  120,
+      119,  118,  117,  110,  103,  276,  102,   97,   96,   95,
+
+       94,   93,   92,   88,   87,   86,   81,   80,   77,   66,
+       65,   54,   44,  276,    3,  276,  276,  276,  276,  276,
+      276,  276,  276,  276,  276,  276,  276,  276,  276,  276,
+      276,  276,  276,  276,  276,  276,  276,  276,  276,  276,
+      276,  276,  276,  276,  276,  276,  276,  276,  276,  276,
+      276,  276,  276,  276,  276,  276,  276,  276,  276,  276,
+      276,  276,  276,  276,  276,  276,  276,  276,  276,  276,
+      276,  276,  276,  276
+    } ;
+
+static yyconst flex_int16_t yy_chk[575] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    5,
+        7,    5,    9,  283,    9,    9,    9,    9,    9,   20,
+       18,   21,   56,   23,    9,   39,  128,   39,   18,  128,
+       19,   19,  145,   18,   19,   19,   19,   19,   19,   40,
+       20,   23,   21,   56,    7,  274,    9,   10,   30,   10,
+
+       10,   10,   10,   10,   18,   26,   30,   37,   57,   10,
+       30,  145,   26,   10,   37,  127,   26,   37,  107,   26,
+       37,  272,  127,   40,   44,   44,   44,   44,  271,   57,
+      270,   10,   11,   11,   11,   11,   11,   55,  147,  107,
+      116,   11,   11,   11,  160,  116,   55,  160,   11,   44,
+       46,   46,   46,   46,   46,  269,  161,  267,   55,  265,
+      147,  116,  264,   11,   11,   11,  116,  263,  262,   11,
+       13,  261,   13,   13,   13,   13,   13,  161,   13,   13,
+       13,   13,   13,   13,  105,  162,  260,  258,   13,  105,
+      105,  105,  105,   13,  257,  256,  255,   13,  254,  253,
+
+       13,   13,   13,   13,   13,   13,  162,  252,  251,   13,
+      250,  249,  248,  247,   13,   14,  246,   14,   14,   14,
+       14,   14,  245,  244,   14,  243,  242,   14,   71,   71,
+       71,   71,   71,   14,  241,   48,   48,  240,   14,   48,
+       48,   48,   48,   48,  238,  157,   14,  236,  235,   14,
+      157,  157,  157,  157,   14,  234,   52,   52,  233,   14,
+       52,   52,   52,   52,   52,   58,   58,  232,  230,   58,
+       58,   58,   58,   58,  108,  108,  108,  108,  108,  111,
+      111,  111,  111,  111,  229,   58,  228,  227,  226,  225,
+      224,  223,  222,  221,  220,  219,  218,  217,  216,  213,
+
+      115,  115,  212,  211,  209,  208,   58,   72,   72,   72,
+       72,   72,  207,  115,  206,  115,   72,  204,   72,  202,
+      115,  200,  198,   72,  197,  196,  195,  194,  193,  192,
+      191,  190,  189,  188,  187,  115,  186,  115,   72,  185,
+       72,  115,  184,  183,   72,  109,  109,  109,  109,  109,
+      182,  181,  180,  179,  109,  177,  109,  175,  173,  172,
+      171,  109,  170,  169,  168,  167,  166,  158,  154,  153,
+      152,  151,  150,  149,  148,  146,  109,  144,  109,  143,
+      142,  141,  109,  112,  112,  112,  112,  112,  140,  139,
+      138,  137,  112,  136,  112,  135,  134,  133,  132,  112,
+
+      130,  129,  126,  125,  122,  121,  120,  119,  118,  117,
+      110,  106,  104,  102,  112,  101,  112,  100,   99,   98,
+      112,  277,  277,  277,  277,  277,  277,  277,  278,  278,
+      278,  278,  278,  278,  278,  279,   97,  279,  279,  280,
+       96,  280,  280,  280,  280,  280,  281,   95,  281,  281,
+      281,  281,  281,  282,  282,  284,  284,  285,  285,  286,
+      286,  286,  286,  286,  286,   94,   93,   92,   91,   90,
+       89,   88,   87,   86,   85,   84,   83,   82,   81,   80,
+       79,   78,   77,   76,   75,   74,   73,   70,   69,   68,
+       67,   66,   65,   49,   43,   42,   38,   36,   35,   34,
+
+       33,   32,   31,   29,   28,   27,   25,   24,   22,   17,
+       16,   12,    8,    3,  276,  276,  276,  276,  276,  276,
+      276,  276,  276,  276,  276,  276,  276,  276,  276,  276,
+      276,  276,  276,  276,  276,  276,  276,  276,  276,  276,
+      276,  276,  276,  276,  276,  276,  276,  276,  276,  276,
+      276,  276,  276,  276,  276,  276,  276,  276,  276,  276,
+      276,  276,  276,  276,  276,  276,  276,  276,  276,  276,
+      276,  276,  276,  276
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int ncmpi_flex_debug;
+int ncmpi_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *ncmpitext;
+#line 1 "./ncmpigen.l"
+#line 2 "./ncmpigen.l"
+/*********************************************************************
+ *   Copyright 1993, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Id: ncmpigenyy.c 2035 2015-05-29 18:58:33Z wkliao $
+ *********************************************************************/
+
+/* lex specification for tokens for ncmpigen */
+
+/* Fill value used by ncdump from version 2.4 and later.  Should match
+   definition of FILL_STRING in ../ncdump/vardata.h */
+#define FILL_STRING "_"
+#define XDR_INT_MIN (-2147483647-1)
+#define XDR_INT_MAX 2147483647
+#define XDR_INT64_MIN  (-9223372036854775807LL-1)
+#define XDR_INT64_MAX  (9223372036854775807LL)
+
+char errstr[100];		/* for short error messages */
+
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>   /* errno */
+#include "genlib.h"
+#include "ncmpigentab.h"
+
+#define YY_BREAK                /* defining as nothing eliminates unreachable
+				   statement warnings from flex output, 
+                                   but make sure every action ends with
+                                   "return" or "break"! */
+
+#line 714 "lex.ncmpi.c"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int ncmpilex_destroy (void );
+
+int ncmpiget_debug (void );
+
+void ncmpiset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE ncmpiget_extra (void );
+
+void ncmpiset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *ncmpiget_in (void );
+
+void ncmpiset_in  (FILE * in_str  );
+
+FILE *ncmpiget_out (void );
+
+void ncmpiset_out  (FILE * out_str  );
+
+int ncmpiget_leng (void );
+
+char *ncmpiget_text (void );
+
+int ncmpiget_lineno (void );
+
+void ncmpiset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int ncmpiwrap (void );
+#else
+extern int ncmpiwrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( ncmpitext, ncmpileng, 1, ncmpiout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		unsigned n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( ncmpiin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( ncmpiin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, ncmpiin))==0 && ferror(ncmpiin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(ncmpiin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int ncmpilex (void);
+
+#define YY_DECL int ncmpilex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after ncmpitext and ncmpileng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 38 "./ncmpigen.l"
+
+#line 898 "lex.ncmpi.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! ncmpiin )
+			ncmpiin = stdin;
+
+		if ( ! ncmpiout )
+			ncmpiout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			ncmpiensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				ncmpi_create_buffer(ncmpiin,YY_BUF_SIZE );
+		}
+
+		ncmpi_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of ncmpitext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 277 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 515 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 39 "./ncmpigen.l"
+{ /* comment */ 
+                          break;
+                        }
+	YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+#line 43 "./ncmpigen.l"
+{
+			 if(ncmpileng > MAXTRST) {
+				yyerror("string too long, truncated\n");
+			        ncmpitext[MAXTRST-1] = '\0';
+			 }
+			 expand_escapes(termstring,(char *)ncmpitext,ncmpileng);
+		 	 return (TERMSTRING);
+		        }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 52 "./ncmpigen.l"
+{return (FLOAT_K);}
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 53 "./ncmpigen.l"
+{return (CHAR_K);}
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 54 "./ncmpigen.l"
+{return (BYTE_K);}
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 55 "./ncmpigen.l"
+{return (SHORT_K);}
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 56 "./ncmpigen.l"
+{return (INT_K);}
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 57 "./ncmpigen.l"
+{return (DOUBLE_K);}
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 58 "./ncmpigen.l"
+{return (UBYTE_K);}
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 59 "./ncmpigen.l"
+{return (USHORT_K);}
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 60 "./ncmpigen.l"
+{return (UINT_K);}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 61 "./ncmpigen.l"
+{return (INT64_K);}
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 62 "./ncmpigen.l"
+{return (UINT64_K);}
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 63 "./ncmpigen.l"
+{int_val = -1;
+			 return (NC_UNLIMITED_K);}
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 66 "./ncmpigen.l"
+{return (DIMENSIONS);}
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 67 "./ncmpigen.l"
+{return (VARIABLES);}
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 68 "./ncmpigen.l"
+{return (DATA);}
+	YY_BREAK
+case 18:
+/* rule 18 can match eol */
+YY_RULE_SETUP
+#line 69 "./ncmpigen.l"
+{
+		char *s = (char*)ncmpitext+strlen("netcdf");
+		char *t = (char*)ncmpitext+ncmpileng-1;
+		while (isspace(*s))
+			s++;
+		while (isspace(*t))
+			t--;
+		t++;
+                if (t-s+1 < 1) {
+                        yyerror("netCDF name required");
+                        return (DATA); /* generate syntax error */
+                }
+		netcdfname = (char *) emalloc(t-s+1);
+		(void) strncpy(netcdfname, s, t-s);
+		netcdfname[t-s] = '\0';
+		return (NETCDF);
+		}
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 86 "./ncmpigen.l"
+{ /* missing value (pre-2.4 backward compatibility) */
+                if (ncmpitext[0] == '-') {
+		    double_val = -NC_FILL_DOUBLE;
+                } else {
+		    double_val = NC_FILL_DOUBLE;
+                }
+		return (DOUBLE_CONST);
+		}
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 94 "./ncmpigen.l"
+{ /* missing value (pre-2.4 backward compatibility) */
+                if (ncmpitext[0] == '-') {
+		    float_val = -NC_FILL_FLOAT;
+                } else {
+		    float_val = NC_FILL_FLOAT;
+                }
+		return (FLOAT_CONST);
+		}
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 102 "./ncmpigen.l"
+{
+                if (STREQ((char *)ncmpitext, FILL_STRING))
+		        return (FILLVALUE);
+		if ((yylval = lookup((char *)ncmpitext)) == NULL) {
+			yylval = install((char *)ncmpitext);
+		}
+		return (IDENT);
+		}
+	YY_BREAK
+case 22:
+/* rule 22 can match eol */
+YY_RULE_SETUP
+#line 111 "./ncmpigen.l"
+{
+		lineno++ ;
+                break;
+		}
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 116 "./ncmpigen.l"
+{
+                int ii;
+		if (sscanf((char*)ncmpitext, "%d", &ii) != 1) {
+		    sprintf(errstr,"bad byte constant: %s",(char*)ncmpitext);
+		    yyerror(errstr);
+		}
+                byte_val = ii;
+		if (ii != (int)byte_val) {
+		    sprintf(errstr,"byte constant out of range (-128,127): %s",(char*)ncmpitext);
+		    yyerror(errstr);
+		}
+		return (BYTE_CONST);
+                }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 130 "./ncmpigen.l"
+{
+		if (sscanf((char*)ncmpitext, "%le", &double_val) != 1) {
+		    sprintf(errstr,"bad long or double constant: %s",(char*)ncmpitext);
+		    yyerror(errstr);
+		}
+                return (DOUBLE_CONST);
+                }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 137 "./ncmpigen.l"
+{
+		if (sscanf((char*)ncmpitext, "%e", &float_val) != 1) {
+		    sprintf(errstr,"bad float constant: %s",(char*)ncmpitext);
+		    yyerror(errstr);
+		}
+                return (FLOAT_CONST);
+                }
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 144 "./ncmpigen.l"
+{
+		if (sscanf((char*)ncmpitext, "%hd", &short_val) != 1) {
+		    sprintf(errstr,"bad short constant: %s",(char*)ncmpitext);
+		    yyerror(errstr);
+		}
+		return (SHORT_CONST);
+	        }
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 151 "./ncmpigen.l"
+{
+    		char *ptr;
+                errno = 0;
+		double_val = strtod((char*)ncmpitext, &ptr);
+		if (errno != 0 && double_val == 0.0) {
+		    sprintf(errstr,"bad numerical constant: %s",(char*)ncmpitext);
+		    yyerror(errstr);
+		}
+                if (double_val < XDR_INT_MIN ||double_val > XDR_INT_MAX) {
+                    return DOUBLE_CONST;
+                } else {
+                    int_val = (int) double_val;
+                    return INT_CONST;
+                }
+	        }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 166 "./ncmpigen.l"
+{
+    		char *ptr;
+                long long_val;
+                errno = 0;
+		long_val = strtol((char*)ncmpitext, &ptr, 0);
+		if (errno != 0) {
+		    sprintf(errstr,"bad long constant: %s",(char*)ncmpitext);
+		    yyerror(errstr);
+		}
+                if (long_val < XDR_INT_MIN || long_val > XDR_INT_MAX) {
+                    double_val = (double) long_val;
+                    return DOUBLE_CONST;
+                } else {
+                    int_val = (int) long_val;
+                    return INT_CONST;
+                }
+	        }
+	YY_BREAK
+case 29:
+/* rule 29 can match eol */
+YY_RULE_SETUP
+#line 183 "./ncmpigen.l"
+{
+	        (void) sscanf((char*)&ncmpitext[1],"%c",&byte_val);
+		return (BYTE_CONST);
+                }
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 187 "./ncmpigen.l"
+{
+		byte_val = (char) strtol((char*)&ncmpitext[2], (char **) 0, 8);
+		return (BYTE_CONST);
+                }
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 191 "./ncmpigen.l"
+{
+		byte_val = (char) strtol((char*)&ncmpitext[3], (char **) 0, 16);
+		return (BYTE_CONST);
+                }
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 195 "./ncmpigen.l"
+{
+	       switch ((char)ncmpitext[2]) {
+	          case 'a': byte_val = '\007'; break; /* not everyone under-
+						       * stands '\a' yet */
+     	          case 'b': byte_val = '\b'; break;
+		  case 'f': byte_val = '\f'; break;
+		  case 'n': byte_val = '\n'; break;
+		  case 'r': byte_val = '\r'; break;
+		  case 't': byte_val = '\t'; break;
+		  case 'v': byte_val = '\v'; break;
+		  case '\\': byte_val = '\\'; break;
+		  case '?': byte_val = '\177'; break;
+		  case '\'': byte_val = '\''; break;
+		  default: byte_val = (char)ncmpitext[2];
+	           }
+		return (BYTE_CONST);
+                }
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 213 "./ncmpigen.l"
+{ /* whitespace */ 
+		  break;        
+		}
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 216 "./ncmpigen.l"
+return (ncmpitext[0]) ;
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 217 "./ncmpigen.l"
+ECHO;
+	YY_BREAK
+#line 1297 "lex.ncmpi.c"
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed ncmpiin at a new source and called
+			 * ncmpilex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = ncmpiin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( ncmpiwrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * ncmpitext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of ncmpilex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					ncmpirealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			ncmpirestart(ncmpiin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) ncmpirealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 277 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 277 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 276);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+	register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+	/* undo effects of setting up ncmpitext */
+	*yy_cp = (yy_hold_char);
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = (yy_n_chars) + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+	(yytext_ptr) = yy_bp;
+	(yy_hold_char) = *yy_cp;
+	(yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					ncmpirestart(ncmpiin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( ncmpiwrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve ncmpitext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void ncmpirestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        ncmpiensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            ncmpi_create_buffer(ncmpiin,YY_BUF_SIZE );
+	}
+
+	ncmpi_init_buffer(YY_CURRENT_BUFFER,input_file );
+	ncmpi_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void ncmpi_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		ncmpipop_buffer_state();
+	 *		ncmpipush_buffer_state(new_buffer);
+     */
+	ncmpiensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	ncmpi_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (ncmpiwrap()) processing, but the only time this flag
+	 * is looked at is after ncmpiwrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void ncmpi_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	ncmpiin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE ncmpi_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) ncmpialloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in ncmpi_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) ncmpialloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in ncmpi_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	ncmpi_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with ncmpi_create_buffer()
+ * 
+ */
+    void ncmpi_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		ncmpifree((void *) b->yy_ch_buf  );
+
+	ncmpifree((void *) b  );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+    
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a ncmpirestart() or at EOF.
+ */
+    static void ncmpi_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	ncmpi_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then ncmpi_init_buffer was _probably_
+     * called from ncmpirestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void ncmpi_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		ncmpi_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void ncmpipush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	ncmpiensure_buffer_stack();
+
+	/* This block is copied from ncmpi_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from ncmpi_switch_to_buffer. */
+	ncmpi_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void ncmpipop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	ncmpi_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		ncmpi_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void ncmpiensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)ncmpialloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in ncmpiensure_buffer_stack()" );
+								  
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)ncmpirealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in ncmpiensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE ncmpi_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) ncmpialloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in ncmpi_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	ncmpi_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to ncmpilex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       ncmpi_scan_bytes() instead.
+ */
+YY_BUFFER_STATE ncmpi_scan_string (yyconst char * yystr )
+{
+    
+	return ncmpi_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to ncmpilex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE ncmpi_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) ncmpialloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in ncmpi_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = ncmpi_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in ncmpi_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up ncmpitext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		ncmpitext[ncmpileng] = (yy_hold_char); \
+		(yy_c_buf_p) = ncmpitext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		ncmpileng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int ncmpiget_lineno  (void)
+{
+        
+    return ncmpilineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *ncmpiget_in  (void)
+{
+        return ncmpiin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *ncmpiget_out  (void)
+{
+        return ncmpiout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int ncmpiget_leng  (void)
+{
+        return ncmpileng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *ncmpiget_text  (void)
+{
+        return ncmpitext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void ncmpiset_lineno (int  line_number )
+{
+    
+    ncmpilineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see ncmpi_switch_to_buffer
+ */
+void ncmpiset_in (FILE *  in_str )
+{
+        ncmpiin = in_str ;
+}
+
+void ncmpiset_out (FILE *  out_str )
+{
+        ncmpiout = out_str ;
+}
+
+int ncmpiget_debug  (void)
+{
+        return ncmpi_flex_debug;
+}
+
+void ncmpiset_debug (int  bdebug )
+{
+        ncmpi_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from ncmpilex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    ncmpiin = stdin;
+    ncmpiout = stdout;
+#else
+    ncmpiin = (FILE *) 0;
+    ncmpiout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * ncmpilex_init()
+     */
+    return 0;
+}
+
+/* ncmpilex_destroy is for both reentrant and non-reentrant scanners. */
+int ncmpilex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		ncmpi_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		ncmpipop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	ncmpifree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * ncmpilex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *ncmpialloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *ncmpirealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void ncmpifree (void * ptr )
+{
+	free( (char *) ptr );	/* see ncmpirealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 217 "./ncmpigen.l"
diff --git a/src/utils/ncmpivalid/Makefile.in b/src/utils/ncmpivalid/Makefile.in
new file mode 100644
index 0000000..cc21cd2
--- /dev/null
+++ b/src/utils/ncmpivalid/Makefile.in
@@ -0,0 +1,65 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2103 2015-09-18 23:34:03Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../../macros.make
+
+# For VPATH build:
+# Add ../../lib into search path because ../../lib/pnetcdf.h is created at the
+# configure time and included by ncmpivalid.c
+# Add $(srcdir)/../../lib into search path because $(srcdir)/../../lib/ncx.h
+# and $(srcdir)/../../lib/macro.h are included by ncmpivalid.c
+INCLUDES	= -I../../lib -I$(srcdir)/../../lib
+
+LDFLAGS        += -L../../lib
+LIBS           := -lpnetcdf $(LIBS) @LCOV_LIB@
+
+C_SOURCES	= ncmpivalid.c
+HEADERS		=
+
+OBJS            = $(C_SOURCES:.c=.o)
+
+PROGRAM		= ncmpivalid
+MANUAL		= ncmpivalid.1
+
+PACKING_LIST	= $(C_SOURCES) $(HEADERS) $(MANUAL) \
+                  Makefile.in depend
+
+GARBAGE		= $(PROGRAM)
+
+all:		$(PROGRAM)
+
+$(PROGRAM):	$(LIBRARY) $(OBJS)
+	$(LINK.c) $(OBJS) $(LDFLAGS) $(LIBS) 
+
+install: $(PROGRAM) $(MANUAL)
+	$(INSTALL) -d -m 755 $(MANDIR)/man1
+	$(INSTALL_DATA) $(srcdir)/$(MANUAL) $(MANDIR)/man1/$(MANUAL)
+
+	$(INSTALL) -d $(BINDIR)
+	$(INSTALL) -m 755 $(PROGRAM) $(BINDIR)/$(PROGRAM)
+
+uninstall:
+	$(RM) -f $(BINDIR)/$(PROGRAM)
+	$(RM) -f $(MANDIR)/man1/$(MANUAL)
+
+$(PROGRAM)_oc : $(C_SOURCES)
+	#setopt primary_language C
+	#load -C $(CPPFLAGS) $(C_SOURCES)
+	#load -C $(LIBS)
+	#setopt program_name $(PROGRAM)
+
+TAGS:		FORCE
+	etags `echo $(PACKING_LIST) | fmt -1 | $(EGREP) '\.c|\.h'
+
+include $(srcdir)/../../../rules.make
+include $(srcdir)/depend
+
+.PHONY: $(LIBRARY)
diff --git a/src/utils/ncmpivalid/depend b/src/utils/ncmpivalid/depend
new file mode 100644
index 0000000..5a9acdb
--- /dev/null
+++ b/src/utils/ncmpivalid/depend
@@ -0,0 +1 @@
+ncmpivalid.o: ncmpivalid.c ../../lib/ncx.h ../../lib/macro.h
diff --git a/src/utils/ncmpivalid/ncmpivalid.1 b/src/utils/ncmpivalid/ncmpivalid.1
new file mode 100644
index 0000000..9b2dba7
--- /dev/null
+++ b/src/utils/ncmpivalid/ncmpivalid.1
@@ -0,0 +1,28 @@
+.\" $Header$
+.nr yr \n(yr+1900
+.af mo 01
+.af dy 01
+.TH NCMPIVALID 1 2013-11-17 "Printed: \n(yr-\n(mo-\n(dy" "UTILITIES"
+.SH NAME
+ncmpivalid \- validates a netCDF file in parallel
+.SH SYNOPSIS
+.ft B
+.HP
+mpiexec -n 4 ncmpivalid
+.nh
+\%\fIfile\fP
+.hy
+.ft
+.SH DESCRIPTION
+\fBncmpivalid\fP checks a netCDF file whether it conforms
+the CDF file format.
+
+.SH "SEE ALSO"
+.LP
+.BR ncmpidump (1),
+.BR pnetcdf (3)
+.SH DATE
+$Date: 2013-11-17 00:21:28 -0600 (Sun, 17 Nov 2013) $
+.LP
+
+
diff --git a/src/utils/ncmpivalid/ncmpivalid.c b/src/utils/ncmpivalid/ncmpivalid.c
new file mode 100644
index 0000000..9fbbf4a
--- /dev/null
+++ b/src/utils/ncmpivalid/ncmpivalid.c
@@ -0,0 +1,870 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: ncmpivalid.c 2299 2016-01-09 06:14:37Z wkliao $ */
+
+#if HAVE_CONFIG_H
+# include <ncconfig.h>
+#endif
+
+#include <assert.h>
+#include <sys/types.h>  /* open() */
+#include <sys/stat.h>   /* open() */
+#include <fcntl.h>      /* open() */
+#include <unistd.h>     /* read() */
+#include <string.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <mpi.h>
+
+#include <ncx.h>
+#include <macro.h>
+
+/*
+ * "magic number" at beginning of file: 0x43444601 (big endian) 
+ */
+static const schar ncmagic[] = {'C', 'D', 'F', 0x01}; 
+
+/* Prototypes for functions used only in this file */
+static int val_get_NCtype(bufferinfo *gbp, NCtype *typep);
+static int val_get_size_t(bufferinfo *gbp, MPI_Offset *sp);
+static int val_get_NC_string(bufferinfo *gbp, NC_string **ncstrpp);
+static int val_get_NC_dim(bufferinfo *gbp, NC_dim **dimpp);
+static int val_get_NC_dimarray(bufferinfo *gbp, NC_dimarray *ncap);
+static int val_get_nc_type(bufferinfo *gbp, nc_type *typep);
+static int val_get_NC_attrV(bufferinfo *gbp, NC_attr *attrp);
+static int val_get_NC_attr(bufferinfo *gbp, NC_attr **attrpp);
+static int val_get_NC_attrarray(bufferinfo *gbp, NC_attrarray *ncap);
+static int val_get_NC_var(bufferinfo *gbp, NC_var **varpp);
+static int val_get_NC_vararray(bufferinfo *gbp, NC_vararray *ncap);
+static int val_get_NC(NC *ncp);
+
+static int val_fetch(bufferinfo *gbp, MPI_Offset fsize);
+static int val_check_buffer(bufferinfo *gbp, MPI_Offset nextread);
+
+
+#define ABORT {printf("Abort: at line=%d func=%s\n", __LINE__,__func__); fflush(stdout); MPI_Abort(MPI_COMM_WORLD, -1);}
+
+/* Begin Of get NC */
+
+/*
+ * Fetch the next header chunk.
+ */
+static int
+val_fetch(bufferinfo *gbp, MPI_Offset fsize) {
+  ssize_t nn = 0;
+  MPI_Offset slack;        /* any leftover data in the buffer */
+  MPI_Aint pos_addr, base_addr;
+
+  assert(gbp->base != NULL);
+  
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(gbp->pos,  &pos_addr);
+    MPI_Get_address(gbp->base, &base_addr);
+#else
+    MPI_Address(gbp->pos,  &pos_addr);
+    MPI_Address(gbp->base, &base_addr);
+#endif
+  slack = gbp->size - (pos_addr - base_addr);
+  /* . if gbp->pos and gbp->base are the same, there is no leftover buffer data
+   *   to worry about.  
+   * In the other extreme, where gbp->size == (gbp->pos - gbp->base), then all
+   * data in the buffer has been consumed */
+  if (slack == gbp->size) slack = 0;
+
+  memset(gbp->base, 0, gbp->size);
+  gbp->pos = gbp->base;
+  gbp->index = 0;
+
+  lseek(gbp->nciop->fd, gbp->offset-slack, SEEK_SET);
+  nn = read(gbp->nciop->fd, gbp->base, gbp->size);
+  if (nn < gbp->size) {
+      printf("Error: Unexpected EOF ");
+      return -1;
+  }
+  gbp->offset += (gbp->size - slack);
+
+  return NC_NOERR;
+}
+
+/*
+ * Ensure that 'nextread' bytes are available.
+ */
+static int
+val_check_buffer(bufferinfo *gbp,
+                 MPI_Offset  nextread)
+{
+    MPI_Aint pos_addr, base_addr;
+
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(gbp->pos,  &pos_addr);
+    MPI_Get_address(gbp->base, &base_addr);
+#else
+    MPI_Address(gbp->pos,  &pos_addr);
+    MPI_Address(gbp->base, &base_addr);
+#endif
+    if (pos_addr + nextread <= base_addr + gbp->size)
+        return NC_NOERR;
+
+    return val_fetch(gbp, MIN(gbp->size, nextread));
+} 
+
+static int
+val_get_NCtype(bufferinfo *gbp, NCtype *typep) {
+  unsigned int type = 0;
+  int status = val_check_buffer(gbp, X_SIZEOF_INT);
+  if (status != NC_NOERR) {
+    printf("NC component type is expected for ");
+    return status;
+  }
+
+  status = ncmpix_get_uint32((const void**)(&gbp->pos), &type);
+  if (status != NC_NOERR)
+    return status;
+  *typep = (NCtype) type;
+  return NC_NOERR;
+}
+
+static int
+val_get_size_t(bufferinfo *gbp, MPI_Offset *sp) {
+  int sizeof_t = (gbp->version == 5) ? 8 : 4; 
+  int status = val_check_buffer(gbp, sizeof_t);
+  if (status != NC_NOERR) {
+    printf("size is expected for ");
+    return status; 
+  }
+  if (gbp->version == 5) {
+      unsigned long long tmp=0;
+      status = ncmpix_get_uint64((const void **)(&gbp->pos), &tmp);
+      *sp = (MPI_Offset)tmp;
+  }
+  else {
+      unsigned int tmp=0;
+      status = ncmpix_get_uint32((const void **)(&gbp->pos), &tmp);
+      *sp = (MPI_Offset)tmp;
+  }
+  return status;
+}
+
+static int
+val_get_NC_string(bufferinfo *gbp, NC_string **ncstrpp) {
+  int status;
+  MPI_Offset  nchars = 0, padding, bufremain, strcount; 
+  NC_string *ncstrp;
+  char *cpos, pad[X_ALIGN-1];
+  MPI_Aint pos_addr, base_addr;
+
+  status = val_get_size_t(gbp, &nchars);
+  if (status != NC_NOERR) {
+    printf("the name string of ");
+    return status;
+  }
+
+  ncstrp = ncmpii_new_NC_string(nchars, NULL);
+  if (ncstrp == NULL)
+    return NC_ENOMEM;
+
+  padding = _RNDUP(X_SIZEOF_CHAR * ncstrp->nchars, X_ALIGN)
+            - X_SIZEOF_CHAR * ncstrp->nchars;
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(gbp->pos,  &pos_addr);
+    MPI_Get_address(gbp->base, &base_addr);
+#else
+    MPI_Address(gbp->pos,  &pos_addr);
+    MPI_Address(gbp->base, &base_addr);
+#endif
+  bufremain = gbp->size - (pos_addr - base_addr);
+  cpos = ncstrp->cp;
+
+  while (nchars > 0) {
+    if (bufremain > 0) {
+      strcount = MIN(bufremain, X_SIZEOF_CHAR * nchars); 
+      (void) memcpy(cpos, gbp->pos, strcount);
+      nchars -= strcount/X_SIZEOF_CHAR;
+      gbp->pos = (void *)((char *)gbp->pos + strcount);
+      cpos += strcount; 
+      bufremain -= strcount;
+    } else {
+      status = val_fetch(gbp, MIN(gbp->size, X_SIZEOF_CHAR * nchars));
+      if(status != NC_NOERR) {
+	printf("fetching the name string of ");
+        ncmpii_free_NC_string(ncstrp);
+        return status;
+      } 
+      bufremain = gbp->size;
+    }
+  }
+
+  memset(pad, 0, X_ALIGN-1);
+  status = val_check_buffer(gbp, padding);
+  if(status != NC_NOERR) {
+    printf("fetching padding for the name string of ");
+    ncmpii_free_NC_string(ncstrp);
+    return status;
+  } 
+  if (memcmp(gbp->pos, pad, padding) != 0) {
+    printf("Error @ [0x%8.8Lx]: \n\tPadding should be 0x00 for the name string alignment of ", (long long unsigned)
+	   (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size));
+    ncmpii_free_NC_string(ncstrp);
+    return NC_EINVAL;
+  }
+  gbp->pos = (void *)((char *)gbp->pos + padding);
+  
+  *ncstrpp = ncstrp;
+  
+  return NC_NOERR;  
+}
+
+static int
+val_get_NC_dim(bufferinfo *gbp, NC_dim **dimpp) {
+  int status;
+  NC_string *ncstrp;
+  NC_dim *dimp;
+
+  status = val_get_NC_string(gbp, &ncstrp);
+  if (status != NC_NOERR) 
+    return status;
+
+  dimp = ncmpii_new_x_NC_dim(ncstrp);
+  if(dimp == NULL)
+    return NC_ENOMEM;
+
+  status = val_get_size_t(gbp, &dimp->size);
+  if(status != NC_NOERR) {
+    printf("\"%s\" - ", ncstrp->cp);
+    ncmpii_free_NC_dim(dimp); /* frees name */
+    return status;
+  }
+
+  *dimpp = dimp;
+
+  return NC_NOERR;
+}
+
+static int
+val_get_NC_dimarray(bufferinfo *gbp, NC_dimarray *ncap) {
+  int status;
+  NCtype type = NC_UNSPECIFIED; 
+  NC_dim **dpp, **end;
+  int dim;
+  MPI_Offset tmp;
+
+  assert(gbp != NULL && gbp->pos != NULL);
+  assert(ncap != NULL);
+  assert(ncap->value == NULL);
+
+  status = val_get_NCtype(gbp, &type);
+  if(status != NC_NOERR) {
+    printf("preamble of ");
+    return status; 
+  }
+
+  status = val_get_size_t(gbp, &tmp);
+  if(status != NC_NOERR) {
+    printf("the length of ");
+    return status;
+  }
+  ncap->ndefined = tmp; /* number of allowable defined variables < 2^32 */
+
+  if(ncap->ndefined == 0) {
+    if (type != NC_DIMENSION && type != NC_UNSPECIFIED) {
+      printf("Error @ [0x%8.8Lx]: \n\tInvalid NC component type, while ",
+	      (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T));
+      printf("NC_DIMENSION or NC_UNSPECIFIED is expected for ");
+      return NC_EINVAL;
+    }
+  } else {
+    if(type != NC_DIMENSION) {
+      printf("Error @ [0x%8.8Lx]: \n\tInvalid NC component type, while ",
+	      (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T));
+      printf("NC_DIMENSION is expected since number of dimensions is %d for ", ncap->ndefined);
+      return NC_EINVAL;
+    }
+
+    ncap->value = (NC_dim **) NCI_Malloc(ncap->ndefined * sizeof(NC_dim *));
+    if(ncap->value == NULL)
+      return NC_ENOMEM;
+    ncap->nalloc = ncap->ndefined;
+
+    dpp = ncap->value;
+    end = &dpp[ncap->ndefined];
+    for( /*NADA*/ dim = 0; dpp < end; dpp++, dim++) {
+      status = val_get_NC_dim(gbp, dpp);
+      if (status != NC_NOERR) {
+	printf("dimension[%d] in ", dim);
+        ncap->ndefined = dpp - ncap->value;
+        ncmpii_free_NC_dimarray(ncap);
+        return status;
+      }
+    }
+  }
+
+  return NC_NOERR;
+}
+
+static int
+val_get_nc_type(bufferinfo *gbp, nc_type *typep) {
+    /* NCtype is 4-byte integer */
+    unsigned int type = 0;
+    int status = val_check_buffer(gbp, 4);
+    if (status != NC_NOERR) return status;
+
+    /* get a 4-byte integer */
+    status = ncmpix_get_uint32((const void**)(&gbp->pos), &type);
+    gbp->index += X_SIZEOF_INT;
+    if (status != NC_NOERR) return status;
+
+  if (   type != NC_BYTE
+      && type != NC_UBYTE
+      && type != NC_CHAR
+      && type != NC_SHORT
+      && type != NC_USHORT
+      && type != NC_INT
+      && type != NC_UINT
+      && type != NC_FLOAT
+      && type != NC_DOUBLE
+      && type != NC_INT64
+      && type != NC_UINT64) {
+    printf("Error @ [0x%8.8Lx]: \n\tUnknown data type for the values of ",
+	   (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - X_SIZEOF_INT));
+    return NC_EINVAL; 
+  }
+ 
+  *typep = (nc_type) type;
+
+  return NC_NOERR;
+}
+
+/*
+ * Get the values of an attribute  
+ */
+static int
+val_get_NC_attrV(bufferinfo *gbp, NC_attr *attrp) {
+    int status;
+    void *value = attrp->xvalue;
+    char pad[X_ALIGN-1]; 
+    MPI_Offset nvalues = attrp->nelems, esz, padding, bufremain, attcount;
+    MPI_Aint pos_addr, base_addr;
+
+    esz = ncmpix_len_nctype(attrp->type);
+    padding = attrp->xsz - esz * nvalues;
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(gbp->pos,  &pos_addr);
+    MPI_Get_address(gbp->base, &base_addr);
+#else
+    MPI_Address(gbp->pos,  &pos_addr);
+    MPI_Address(gbp->base, &base_addr);
+#endif
+    bufremain = gbp->size - (pos_addr - base_addr);
+
+  while (nvalues > 0) {
+    if (bufremain > 0) {
+      attcount = MIN(bufremain, esz * nvalues);
+      (void) memcpy(value, gbp->pos, attcount);
+      nvalues -= attcount/esz;
+      gbp->pos = (void *)((char *)gbp->pos + attcount);
+      value = (void *)((char *)value + attcount);
+      bufremain -= attcount;
+    } else {
+      status = val_fetch(gbp, MIN(gbp->size, esz * nvalues));
+      if(status != NC_NOERR) {
+	printf("fetching the values of ");
+        return status;
+      }
+      bufremain = gbp->size;
+    }
+  }
+ 
+  memset(pad, 0, X_ALIGN-1);
+  if (memcmp(gbp->pos, pad, padding) != 0) {
+    printf("Error @ [0x%8.8Lx]: \n\tPadding should be 0x00 for the values alignment of ",
+           (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size)); 
+    return NC_EINVAL;
+  }
+  gbp->pos = (void *)((char *)gbp->pos + padding);
+
+  return NC_NOERR;
+}
+
+static int
+val_get_NC_attr(bufferinfo *gbp, NC_attr **attrpp) {
+  NC_string *strp;
+  int status;
+  nc_type type; 
+  MPI_Offset nelems;
+  NC_attr *attrp;
+
+  status = val_get_NC_string(gbp, &strp);
+  if(status != NC_NOERR)
+    return status;
+
+  status = val_get_nc_type(gbp, &type);
+  if(status != NC_NOERR) {
+    printf("\"%s\" - ", strp->cp);
+    ncmpii_free_NC_string(strp);
+    return status;
+  }
+
+  status = val_get_size_t(gbp, &nelems); 
+  if(status != NC_NOERR) {
+    printf("the values of \"%s\" - ", strp->cp);
+    ncmpii_free_NC_string(strp);
+    return status;
+  }
+
+  attrp = ncmpii_new_x_NC_attr(strp, type, nelems);
+  if(attrp == NULL) {
+    ncmpii_free_NC_string(strp);
+    return status;
+  }
+
+  status = val_get_NC_attrV(gbp, attrp);
+  if(status != NC_NOERR) {
+    printf("\"%s\" - ", strp->cp);
+    ncmpii_free_NC_attr(attrp); /* frees strp */ 
+    return status;
+  }
+
+  *attrpp = attrp; 
+  
+  return NC_NOERR; 
+}
+
+static int
+val_get_NC_attrarray(bufferinfo *gbp, NC_attrarray *ncap){
+  int status;
+  NCtype type = NC_UNSPECIFIED;
+  NC_attr **app, **end;
+  int att;
+  MPI_Offset tmp;
+
+  assert(gbp != NULL && gbp->pos != NULL);
+  assert(ncap != NULL);
+  assert(ncap->value == NULL);
+
+  status = val_get_NCtype(gbp, &type);
+  if(status != NC_NOERR) {
+    printf("preamble of ");
+    return status; 
+  }
+
+  status = val_get_size_t(gbp, &tmp);
+  if(status != NC_NOERR) {
+    printf("the length of ");
+    return status;
+  }
+  ncap->ndefined = tmp; /* number of allowable defined variables < 2^32 */
+
+  if(ncap->ndefined == 0) {
+    if (type != NC_ATTRIBUTE && type != NC_UNSPECIFIED) {
+      printf("Error @ [0x%8.8Lx]: \n\tInvalid NC component type, while ",
+              (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T));
+      printf("NC_ATTRIBUTE or NC_UNSPECIFIED is expected for "); 
+      return NC_EINVAL;
+    }
+  } else {
+    if(type != NC_ATTRIBUTE) {
+      printf("Error @ [0x%8.8Lx]: \n\tInvalid NC component type, while ",
+              (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T));
+      printf("NC_ATTRIBUTE is expected since number of attributes is %d for ", (int)ncap->ndefined);  
+      return NC_EINVAL;
+    }
+
+    ncap->value = (NC_attr **) NCI_Malloc(ncap->ndefined * sizeof(NC_attr *));
+    if(ncap->value == NULL)
+      return NC_ENOMEM;
+    ncap->nalloc = ncap->ndefined; 
+
+    app = ncap->value;
+    end = &app[ncap->ndefined];
+    for( /*NADA*/ att = 0; app < end; app++, att++) {
+      status = val_get_NC_attr(gbp, app);
+      if (status != NC_NOERR) {
+	printf("attribute[%d] of ", att);
+        ncap->ndefined = app - ncap->value;
+        ncmpii_free_NC_attrarray(ncap);
+        return status;
+      }
+    }
+  }
+  
+  return NC_NOERR;
+}
+
+static int
+val_get_NC_var(bufferinfo *gbp, NC_var **varpp) {
+  NC_string *strp;
+  int status;
+  MPI_Offset ndims, *tmp_dim;
+  size_t dim;
+  NC_var *varp;
+
+  status = val_get_NC_string(gbp, &strp);
+  if(status != NC_NOERR)
+    return status;
+
+  status = val_get_size_t(gbp, &ndims);
+  if(status != NC_NOERR) {
+     printf("the dimid list of \"%s\" - ", strp->cp);
+     ncmpii_free_NC_string(strp); 
+     return status;
+  }
+
+  varp = ncmpii_new_x_NC_var(strp, ndims);
+  if(varp == NULL) {
+    ncmpii_free_NC_string(strp);
+    return NC_ENOMEM;
+  }
+
+  for (dim = 0; dim < ndims; dim++ ) {
+    status = val_check_buffer(gbp, (gbp->version == 5 ? 8 : 4));
+    if(status != NC_NOERR) {
+      printf("the dimid[%d] is expected for \"%s\" - ", (int)dim, strp->cp);
+      ncmpii_free_NC_var(varp);
+      return status;
+    }
+    tmp_dim = (MPI_Offset*) (varp->dimids + dim);
+    if (gbp->version == 5) {
+        unsigned long long tmp=0;
+        status = ncmpix_get_uint64((const void **)(&gbp->pos), &tmp);
+        *tmp_dim = (MPI_Offset)tmp;
+    }
+    else {
+        unsigned int tmp=0;
+        status = ncmpix_get_uint32((const void **)(&gbp->pos), &tmp);
+        *tmp_dim = (MPI_Offset)tmp;
+    }
+    if(status != NC_NOERR) {
+      ncmpii_free_NC_var(varp);
+      return status;
+    }
+  }
+
+  status = val_get_NC_attrarray(gbp, &varp->attrs);
+  if(status != NC_NOERR) {
+    printf("ATTRIBUTE list of \"%s\" - ", strp->cp);
+    ncmpii_free_NC_var(varp);
+    return status;
+  }
+
+  status = val_get_nc_type(gbp, &varp->type);
+  if(status != NC_NOERR) {
+    printf("\"%s\" - ", strp->cp);
+    ncmpii_free_NC_var(varp);
+    return status;
+  } 
+
+  status = val_get_size_t(gbp, &varp->len);
+  if(status != NC_NOERR) {
+    printf("the data of  \"%s\" - ", strp->cp);
+    ncmpii_free_NC_var(varp);
+    return status;
+  }
+
+  status = val_check_buffer(gbp, (gbp->version == 5 ? 8 : 4));
+  if(status != NC_NOERR) {
+    printf("offset is expected for the data of \"%s\" - ", strp->cp);
+    ncmpii_free_NC_var(varp);
+    return status;
+  }
+  if (gbp->version == 1) {
+      unsigned int tmp=0;
+      status = ncmpix_get_uint32((const void **)(&gbp->pos), &tmp);
+      varp->begin = (MPI_Offset)tmp;
+  }
+  else {
+      unsigned long long tmp=0;
+      status = ncmpix_get_uint64((const void **)(&gbp->pos), &tmp);
+      varp->begin = (MPI_Offset)tmp;
+  }
+  if(status != NC_NOERR) {
+    ncmpii_free_NC_var(varp);
+    return status;
+  }
+
+  *varpp = varp;
+  return NC_NOERR;
+}
+
+static int
+val_get_NC_vararray(bufferinfo *gbp, NC_vararray *ncap) {
+  int status;
+  NCtype type = NC_UNSPECIFIED;
+  NC_var **vpp, **end;
+  int var;
+  MPI_Offset tmp;
+
+  assert(gbp != NULL && gbp->pos != NULL);
+  assert(ncap != NULL);
+  assert(ncap->value == NULL); 
+
+  status = val_get_NCtype(gbp, &type);
+  if(status != NC_NOERR) {
+    printf("preamble of ");
+    return status;
+  }
+ 
+  status = val_get_size_t(gbp, &tmp);
+  if(status != NC_NOERR) {
+    printf("the length of ");
+    return status;
+  }
+  ncap->ndefined = tmp; /* number of allowable defined variables < 2^32 */
+ 
+  if(ncap->ndefined == 0) {
+    if (type != NC_VARIABLE && type != NC_UNSPECIFIED) {
+      printf("Error @ [0x%8.8Lx]: \n\tInvalid NC component type, while ",
+              (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T));
+      printf("NC_VARIABLE or NC_UNSPECIFIED is expected for ");
+      return NC_EINVAL;
+    }
+  } else {
+    if(type != NC_VARIABLE) {
+      printf("Error @ [0x%8.8Lx]: \n\tInvalid NC component type, while ",
+              (long long unsigned) (((size_t) gbp->pos - (size_t) gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T));
+      printf("NC_VARIABLE is expected since number of variables is %d for ", ncap->ndefined);        
+      return NC_EINVAL;
+    }
+ 
+    ncap->value = (NC_var **) NCI_Malloc(ncap->ndefined * sizeof(NC_var *));
+    if(ncap->value == NULL)
+      return NC_ENOMEM; 
+    ncap->nalloc = ncap->ndefined;
+
+    vpp = ncap->value;
+    end = &vpp[ncap->ndefined];
+    for( /*NADA*/ var = 0; vpp < end; vpp++, var++) {
+      status = val_get_NC_var(gbp, vpp);
+      if (status != NC_NOERR) {
+        printf("variable[%d] in ", var);
+        ncap->ndefined = vpp - ncap->value;
+        ncmpii_free_NC_vararray(ncap);
+        return status;
+      }
+    }
+  }
+
+  return NC_NOERR;
+}
+
+static int
+val_get_NC(NC *ncp) {
+    int status;
+    bufferinfo getbuf;
+    schar magic[sizeof(ncmagic)];
+    MPI_Offset nrecs = 0;
+    MPI_Aint pos_addr, base_addr;
+
+    assert(ncp != NULL);
+
+    /* Initialize the get buffer that stores the header read from the file */
+    getbuf.nciop = ncp->nciop;
+    getbuf.offset = 0;     /* read from start of the file */
+    getbuf.put_size = 0;   /* amount of writes so far in bytes */
+    getbuf.get_size = 0;   /* amount of reads  so far in bytes */
+
+    /* CDF-5's minimum header size is 4 bytes more than CDF-1 and CDF-2's */
+    getbuf.size = _RNDUP( MAX(MIN_NC_XSZ+4, ncp->chunk), X_ALIGN );
+    if (getbuf.size > NC_DEFAULT_CHUNKSIZE)
+        getbuf.size = NC_DEFAULT_CHUNKSIZE;
+
+    getbuf.pos = getbuf.base = (void *)NCI_Malloc(getbuf.size);
+    getbuf.index = 0;
+
+    /* Fetch the next header chunk. The chunk is 'gbp->size' bytes big */
+    status = val_fetch(&getbuf, sizeof(magic));
+    if (status != NC_NOERR) {
+        printf("magic number (C D F \\001) is expected!\n");
+        return status;
+    }
+  
+    /* First get the file format information, magic */
+    memset(magic, 0, sizeof(magic));
+    status = ncmpix_getn_schar_schar((const void **)(&getbuf.pos),
+                                     sizeof(magic), magic);
+    getbuf.index += sizeof(magic);
+
+    if (memcmp(magic, ncmagic, sizeof(ncmagic)-1) != 0) {
+        printf("Error @ [0x%8.8x]: \n\tUnknow magic number, while (C D F \\001, \\002, or \\005) is expected!\n", (unsigned) 0);
+        NCI_Free(getbuf.base);
+        return NC_ENOTNC;
+    }
+
+    /* check version number in last byte of magic */
+    if (magic[sizeof(ncmagic)-1] == 0x1) {
+        getbuf.version = 1;
+        fSet(ncp->flags, NC_32BIT);
+    } else if (magic[sizeof(ncmagic)-1] == 0x2) {
+        getbuf.version = 2;
+        fSet(ncp->flags, NC_64BIT_OFFSET);
+        if (sizeof(MPI_Offset) != 8) {
+            /* take the easy way out: if we can't support all CDF-2
+             * files, return immediately */
+            NCI_Free(getbuf.base);
+            return NC_ESMALL;
+        }
+    } else if (magic[sizeof(ncmagic)-1] == 0x5) {
+        getbuf.version = 5;
+        fSet(ncp->flags, NC_64BIT_DATA);
+        if (sizeof(MPI_Offset) != 8) {
+            NCI_Free(getbuf.base);
+            return NC_ESMALL;
+        }
+    } else {
+        NCI_Free(getbuf.base);
+        return NC_ENOTNC;
+    }
+
+    /* status = val_check_buffer(&getbuf, X_SIZEOF_SIZE_T); */
+    status = val_check_buffer(&getbuf, (getbuf.version == 1) ? 4 : 8);
+    if (status != NC_NOERR) {
+        printf("number of records is expected!\n");
+        NCI_Free(getbuf.base);
+        return status;
+    }
+
+    /* get numrecs from getbuf into ncp */
+    if (getbuf.version == 5) {
+        unsigned long long tmp=0;
+        status = ncmpix_get_uint64((const void **)(&getbuf.pos), &tmp);
+        nrecs = (MPI_Offset)tmp;
+    }
+    else {
+        unsigned int tmp=0;
+        status = ncmpix_get_uint32((const void **)(&getbuf.pos), &tmp);
+        nrecs = (MPI_Offset)tmp;
+    }
+    if (status != NC_NOERR) {
+        NCI_Free(getbuf.base);
+        return status;
+    }
+
+    if (getbuf.version == 5)
+        getbuf.index += X_SIZEOF_INT64;
+    else
+        getbuf.index += X_SIZEOF_SIZE_T;
+
+    ncp->numrecs = nrecs;
+
+#ifdef HAVE_MPI_GET_ADDRESS
+    MPI_Get_address(getbuf.pos,  &pos_addr);
+    MPI_Get_address(getbuf.base, &base_addr);
+#else
+    MPI_Address(getbuf.pos,  &pos_addr);
+    MPI_Address(getbuf.base, &base_addr);
+#endif
+    assert(pos_addr < base_addr + getbuf.size);
+
+    /* get dim_list from getbuf into ncp */
+    status = val_get_NC_dimarray(&getbuf, &ncp->dims);
+    if (status != NC_NOERR) {
+        printf("DIMENSION list!\n");
+        NCI_Free(getbuf.base);
+        return status;
+    }
+
+    status = val_get_NC_attrarray(&getbuf, &ncp->attrs); 
+    if (status != NC_NOERR) {
+        printf("GLOBAL ATTRIBUTE list!\n");
+        NCI_Free(getbuf.base);
+        return status;
+    }
+
+  status = val_get_NC_vararray(&getbuf, &ncp->vars);
+  if(status != NC_NOERR) {
+    printf("VARIABLE list!\n");
+    NCI_Free(getbuf.base);
+    return status; 
+  }
+
+  ncp->xsz = ncmpii_hdr_len_NC(ncp);
+  status = ncmpii_NC_computeshapes(ncp);
+  NCI_Free(getbuf.base);
+
+  return status;
+}
+
+/* End Of get NC */
+
+int main(int argc, char **argv) {
+
+    char *ncfile;
+    int status;
+    NC *ncp;
+    struct stat ncfilestat;
+
+    MPI_Init(&argc, &argv);
+
+    if (argc != 2) {
+        printf("Usage: %s <ncfile>\n", argv[0]);
+        MPI_Finalize();
+        return 1;
+    } 
+
+    ncfile = argv[1];
+
+    /* open the netCDF file */
+    ncp = ncmpii_new_NC(NULL);
+    if (ncp == NULL) {
+        printf("ncmpii_new_NC(): Not enough memory!\n");
+        ABORT
+    }
+
+    ncp->nciop = ncmpiio_new(ncfile, NC_NOWRITE);
+    if (ncp->nciop == NULL) {
+        ncmpii_free_NC(ncp);
+        printf("ncmpiio_new(): Not enough memory!\n");
+        ABORT
+    }
+
+    if ( (*((int *)&ncp->nciop->fd) = open(ncfile, O_RDONLY)) < 0 ) {
+        printf("Can not open file: %s\n", ncfile);
+        ncmpiio_free(ncp->nciop);
+        ncmpii_free_NC(ncp);
+        ABORT
+    }
+
+    /* read to validate the header */
+    status = val_get_NC(ncp);
+    if (status !=  NC_NOERR) {
+        printf("Error at line %d (%s)\n",__LINE__,ncmpi_strerror(status));
+        close(ncp->nciop->fd);
+        ncmpiio_free(ncp->nciop);
+        ncmpii_free_NC(ncp);
+        ABORT
+    }
+
+    /* check data size */
+    fstat(ncp->nciop->fd, &ncfilestat);
+    if ( ncp->begin_rec + ncp->recsize * ncp->numrecs < ncfilestat.st_size ) {
+        printf("Error: \n\tData size is larger than defined!\n");
+        close(ncp->nciop->fd);
+        ncmpiio_free(ncp->nciop);
+        ncmpii_free_NC(ncp);
+        return 0;  
+    } else if ( ncp->numrecs > 0 &&
+                ncp->begin_rec + ncp->recsize * (ncp->numrecs - 1) > ncfilestat.st_size ) {
+        printf("Error: \n\tData size is less than expected!\n");
+        printf("\tbegin_rec=%lld recsize=%lld numrecs=%lld ncfilestat.st_size=%lld\n",ncp->begin_rec, ncp->recsize, ncp->numrecs, (long long) ncfilestat.st_size);
+        close(ncp->nciop->fd);
+        ncmpiio_free(ncp->nciop);
+        ncmpii_free_NC(ncp);
+        return 0;
+    }
+
+
+  /* close the file */
+
+  close(ncp->nciop->fd);
+  ncmpiio_free(ncp->nciop);
+  ncmpii_free_NC(ncp);
+
+  printf("The netCDF file is validated!\n");
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/src/utils/ncoffsets/Makefile.in b/src/utils/ncoffsets/Makefile.in
new file mode 100644
index 0000000..7d77a0b
--- /dev/null
+++ b/src/utils/ncoffsets/Makefile.in
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2253 2015-12-22 01:45:40Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include ../../../macros.make
+
+C_SOURCES	= ncoffsets.c
+OBJS            = $(C_SOURCES:.c=.o)
+
+PROGRAM		= $(C_SOURCES:.c=)
+MANUAL		= ncoffsets.1
+PACKING_LIST    = $(C_SOURCES) $(MANUAL) Makefile.in
+GARBAGE		= $(PROGRAM)
+
+all: $(PROGRAM)
+
+ncoffsets: ncoffsets.c
+	$(SEQ_CC) -o $@ $<
+
+install: $(PROGRAM) $(MANUAL)
+	$(INSTALL) -d -m 755 $(MANDIR)/man1
+	$(INSTALL_DATA) $(srcdir)/$(MANUAL) $(MANDIR)/man1/$(MANUAL)
+	$(INSTALL) -d $(BINDIR)
+	$(INSTALL) -m 755 $(PROGRAM) $(BINDIR)/$(PROGRAM)
+
+uninstall:
+	$(RM) -f $(BINDIR)/$(PROGRAM)
+	$(RM) -f $(MANDIR)/man1/$(MANUAL)
+
+include $(srcdir)/../../../rules.make
+
diff --git a/src/utils/ncoffsets/ncoffsets.1 b/src/utils/ncoffsets/ncoffsets.1
new file mode 100644
index 0000000..0191668
--- /dev/null
+++ b/src/utils/ncoffsets/ncoffsets.1
@@ -0,0 +1,109 @@
+.\" $Header$
+.nr yr \n(yr+1900
+.af mo 01
+.af dy 01
+.TH PNETCDF_VERSION 1 2014-04-15 "Printed: \n(yr-\n(mo-\n(dy" "UTILITIES"
+.SH NAME
+ncoffsets \- print the starting/ending file offsets for netCDF variables
+.SH SYNOPSIS
+.ft B
+.HP
+ncoffsets
+.nh
+\%[\fB-h\fP] |
+\%[\fB-x\fP] |
+\%[\fB-sgr\fP]
+\%[\fB-v\fP var1[,...]]
+\%\fIfile\fP
+.hy
+.ft
+.SH DESCRIPTION
+\fBncoffsets\fP prints the file offsets information of variables defined in
+a given netCDF file. The ending offsets reported is an exclusive offset, i.e.
+1 byte more than the last byte occupied by the variable. In other words, the
+ending offset is equal to the sum of starting offset and the variable size.
+For record variables, only the offsets of first record are printed. Add
+option \fB-r\fP to print the offsets of all records.
+
+If no argument is given, command usage information is printed.
+.SH OPTIONS
+.IP "\fB-v\fP var1[,...]"
+The output will include data values for the specified variables. One or more
+variables must be specified by name in the comma-delimited list following this
+option.  The list must be a single argument to the command, hence cannot
+contain blanks or other white space characters.  The named variables must be
+valid netCDF variables in the input-file.  The default, without this option is
+to include data values for \fIall\fP variables in the output.
+.IP "\fB-s\fP"
+Print the variable size in bytes. For record variables, only the size of one
+record is printed.
+.IP "\fB-g\fP"
+Print the gap in bytes from the previous variable. For the first defined
+variable, print the gap from the end of file header. For record variables,
+there is no gap between records.
+.IP "\fB-r\fP"
+Output the offset information for all records of the selected record variables.
+Without this option, only the offsets of first record are printed.
+.IP "\fB-x\fP"
+Check all fixed-size variable for file space gaps in between any two
+immediately adjacent variables. It prints "1" on stdout if gaps are found,
+"0" for otherwise. This option disables all other options.
+.IP "\fB-h\fP"
+Print the available command-line options
+
+.SH EXAMPLES
+.LP
+Print the file offset information for all variables in a netCDF file.
+
+% ncoffsets -sg testfile.nc
+.nf
+netcdf test_double.nc {
+//file format: CDF-1
+
+file header:
+	size   = 340 bytes
+	extent = 340 bytes
+
+dimensions:
+	x = 100
+	y = 100
+	z = 100
+	time = UNLIMITED // (100 currently)
+
+fixed-size variables:
+	double square(x, y):
+	       start file offset =         340
+	       end   file offset =       80340
+	       size in bytes     =       80000
+	       gap from prev var =           0
+	double cube(x, y, z):
+	       start file offset =       80340
+	       end   file offset =     8080340
+	       size in bytes     =     8000000
+	       gap from prev var =           0
+
+record variables:
+	double time(time):
+	       start file offset =     8080340    (record 0)
+	       end   file offset =     8081140    (record 0)
+	       size in bytes     =           8    (of one record)
+	       gap from prev var =           0
+	double xytime(time, x, y):
+	       start file offset =     8080348    (record 0)
+	       end   file offset =    16080348    (record 0)
+	       size in bytes     =       80000    (of one record)
+	       gap from prev var =           0
+}
+.LP
+Check if there are gaps in between two adjacent fixed-size variables.
+
+% ncoffsets -x testfile.nc
+0
+.fi
+
+.SH "SEE ALSO"
+.LP
+.BR pnetcdf (3)
+.SH DATE
+$Date: 2016-01-10 14:33:45 -0600 (Sun, 10 Jan 2016) $
+.LP
diff --git a/src/utils/ncoffsets/ncoffsets.c b/src/utils/ncoffsets/ncoffsets.c
new file mode 100644
index 0000000..3eb876b
--- /dev/null
+++ b/src/utils/ncoffsets/ncoffsets.c
@@ -0,0 +1,2099 @@
+/*
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: ncoffsets.c 2302 2016-01-10 20:33:45Z wkliao $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>    /* strcpy() */
+#include <errno.h>     /* errno, strerror() */
+#include <sys/types.h> /* open() */
+#include <sys/stat.h>  /* open() */
+#include <fcntl.h>     /* open() */
+#include <unistd.h>    /* read() */
+#include <assert.h>    /* assert() */
+#include <inttypes.h>  /* check for Endianness */
+
+static int endianness;
+
+#ifndef MIN
+#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
+#endif
+
+static int verbose_debug;
+
+#define DEBUG_RETURN_ERROR(err) {                             \
+    if (verbose_debug)                                        \
+        fprintf(stderr, "Error code %s at line %d of %s\n",   \
+        ncmpii_err_code_name(err),__LINE__,__FILE__);         \
+    return err;                                               \
+}
+#define DEBUG_ASSIGN_ERROR(status, err) {                     \
+    if (verbose_debug)                                        \
+        fprintf(stderr, "Error code %s at line %d of %s\n",   \
+        ncmpii_err_code_name(err),__LINE__,__FILE__);         \
+    status = err;                                             \
+}
+
+#define IS_RECVAR(vp) \
+        ((vp)->shape != NULL ? (*(vp)->shape == NC_UNLIMITED) : 0 )
+
+#define MALLOC_CHECK(ptr) { \
+    if ((ptr) == NULL) { \
+        fprintf(stderr, "Error at line %d: malloc out of memory",__LINE__); \
+        exit(1); \
+    } \
+}
+
+#define NC_NOERR 0
+#define	NC_EINVAL	(-36)	/**< Invalid Argument */
+#define NC_EBADDIM	(-46)	/**< Invalid dimension id or name */
+#define NC_EUNLIMPOS	(-47)	/**< NC_UNLIMITED in the wrong index */
+#define NC_ENOTNC	(-51)	/**< Not a netcdf file */
+#define NC_EVARSIZE     (-62)   /**< One or more variable sizes violate format constraints */
+
+#define NC_UNLIMITED 0L
+
+typedef enum {
+    NC_UNSPECIFIED =  0,
+    NC_DIMENSION   = 10,
+    NC_VARIABLE    = 11,
+    NC_ATTRIBUTE   = 12
+} NCtype;
+
+#define NC_NAT          0       /**< Not A Type */
+#define NC_BYTE         1       /**< signed 1 byte integer */
+#define NC_CHAR         2       /**< ISO/ASCII character */
+#define NC_SHORT        3       /**< signed 2 byte integer */
+#define NC_INT          4       /**< signed 4 byte integer */
+#define NC_LONG         NC_INT
+#define NC_FLOAT        5       /**< single precision floating point number */
+#define NC_DOUBLE       6       /**< double precision floating point number */
+#define NC_UBYTE        7       /**< unsigned 1 byte int */
+#define NC_USHORT       8       /**< unsigned 2-byte int */
+#define NC_UINT         9       /**< unsigned 4-byte int */
+#define NC_INT64        10      /**< signed 8-byte int */
+#define NC_UINT64       11      /**< unsigned 8-byte int */
+
+#define NC_DEFAULT_CHUNKSIZE 1048576
+
+/* sizes of external data types */
+#define X_SIZEOF_CHAR           1
+#define X_SIZEOF_SHORT          2
+#define X_SIZEOF_INT            4
+#define X_SIZEOF_FLOAT          4
+#define X_SIZEOF_DOUBLE         8
+#define X_SIZEOF_UBYTE          1
+#define X_SIZEOF_USHORT         2
+#define X_SIZEOF_UINT           4
+#define X_SIZEOF_LONGLONG       8
+#define X_SIZEOF_ULONGLONG      8
+#define X_SIZEOF_INT64          8
+#define X_SIZEOF_UINT64         8
+
+#define X_UINT_MAX	4294967295U
+
+#define X_ALIGN                 4
+
+/* useful for aligning memory */
+#define _RNDUP(x, unit)  ((((x) + (unit) - 1) / (unit)) * (unit))
+#define M_RND_UNIT       X_SIZEOF_DOUBLE
+#define M_RNDUP(x)       _RNDUP(x, M_RND_UNIT)
+
+#define ncmpix_len_char(nelems)   _RNDUP((nelems), X_ALIGN)
+#define ncmpix_len_short(nelems)  (((nelems) + (nelems)%2)  * X_SIZEOF_SHORT)
+#define ncmpix_len_int(nelems)    ((nelems) * X_SIZEOF_INT)
+#define ncmpix_len_long(nelems)   ((nelems) * X_SIZEOF_LONG)
+#define ncmpix_len_float(nelems)  ((nelems) * X_SIZEOF_FLOAT)
+#define ncmpix_len_double(nelems) ((nelems) * X_SIZEOF_DOUBLE)
+#define ncmpix_len_ubyte(nelems)  _RNDUP((nelems), X_ALIGN)
+#define ncmpix_len_ushort(nelems) (((nelems) + (nelems)%2)  * X_SIZEOF_USHORT)
+#define ncmpix_len_uint(nelems)   ((nelems) * X_SIZEOF_UINT)
+#define ncmpix_len_int64(nelems)  ((nelems) * X_SIZEOF_INT64)
+#define ncmpix_len_uint64(nelems) ((nelems) * X_SIZEOF_UINT64)
+
+typedef int nc_type;
+
+typedef struct {
+    long long  nchars;
+    char      *cp;     /* [nchars+1] one additional char for '\0' */
+} NC_string;
+
+typedef struct {
+    NC_string *name;
+    long long  size;
+} NC_dim;
+
+typedef struct NC_dimarray {
+    int      nalloc;    /* number allocated >= ndefined */
+    int      ndefined;  /* number of defined dimensions */
+    NC_dim **value;
+} NC_dimarray;
+
+typedef struct {
+    long long  xsz;      /* amount of space at xvalue (4-byte aligned) */
+    NC_string *name;     /* name of the attributes */
+    nc_type    type;     /* the discriminant */
+    long long  nelems;   /* number of attribute elements */
+    void      *xvalue;   /* the actual data, in external representation */
+} NC_attr;
+
+typedef struct NC_attrarray {
+    int       nalloc;    /* number allocated >= ndefined */
+    int       ndefined;  /* number of defined attributes */
+    NC_attr **value;
+} NC_attrarray;
+
+typedef struct {
+    int           xsz;    /* byte size of 1 array element */
+    long long    *shape;  /* dim->size of each dim */
+    long long    *dsizes; /* the right to left product of shape */
+    NC_string    *name;   /* name of the variable */
+    int           ndims;  /* number of dimensions */
+    int          *dimids; /* array of dimension IDs */
+    NC_attrarray  attrs;  /* attribute array */
+    nc_type       type;   /* variable's data type */
+    long long     len;    /* this is the "vsize" defined in header format, the
+                             total size in bytes of the array variable.
+                             For record variable, this is the record size */
+    long long     begin;  /* starting file offset of this variable */
+} NC_var;
+
+typedef struct NC_vararray {
+    int      nalloc;      /* number allocated >= ndefined */
+    int      ndefined;    /* number of defined variables */
+    int      num_rec_vars;/* number of defined record variables */
+    NC_var **value;
+} NC_vararray;
+
+typedef struct NC {
+    int           flags;
+    char          path[1024];
+    long long     xsz;      /* external size of this header, <= var[0].begin */
+    long long     begin_var;/* file offset of the first (non-record) var */
+    long long     begin_rec;/* file offset of the first 'record' */
+
+    long long     recsize;  /* length of 'record': sum of single record sizes
+                               of all the record variables */
+    long long     numrecs;  /* number of 'records' allocated */
+    NC_dimarray   dims;     /* dimensions defined */
+    NC_attrarray  attrs;    /* global attributes defined */
+    NC_vararray   vars;     /* variables defined */
+} NC;
+
+typedef struct bufferinfo {
+    int        fd;
+    off_t      offset;   /* current read/write offset in the file */
+    int        version;  /* 1, 2, and 5 for CDF-1, 2, and 5 respectively */
+    void      *base;     /* beginning of read/write buffer */
+    void      *pos;      /* current position in buffer */
+    long long  size;     /* size of the buffer */
+} bufferinfo;
+
+/*
+ * "magic number" at beginning of file: 0x43444601 (big endian)
+ */
+static const char ncmagic1[] = {'C', 'D', 'F', 0x01};
+static const char ncmagic2[] = {'C', 'D', 'F', 0x02};
+static const char ncmagic5[] = {'C', 'D', 'F', 0x05};
+
+const char * ncmpii_err_code_name(int err);
+
+static int is_little_endian(void) {
+    volatile uint32_t i=0x01234567;
+    // return 0 for big endian, 1 for little endian.
+    return (*((uint8_t*)(&i))) == 0x67;
+}
+
+static void
+swap4b(int *val)
+{
+    unsigned int tmp = *val;
+    char *ip = (char*) &tmp;
+    char *op = (char*) val;
+    op[0] = ip[3];
+    op[1] = ip[2];
+    op[2] = ip[1];
+    op[3] = ip[0];
+}
+
+static void
+swap8b(long long *val)
+{
+    unsigned long long tmp = *val;
+    char *ip = (char*) &tmp;
+    char *op = (char*) val;
+    op[0] = ip[7];
+    op[1] = ip[6];
+    op[2] = ip[5];
+    op[3] = ip[4];
+    op[4] = ip[3];
+    op[5] = ip[2];
+    op[6] = ip[1];
+    op[7] = ip[0];
+}
+
+static unsigned long long
+get_uint8(bufferinfo *gbp) {
+    unsigned long long tmp;
+    memcpy(&tmp, gbp->pos, 8);
+    if (endianness) swap8b(&tmp);
+    gbp->pos += 8;
+    return tmp;
+}
+
+static unsigned int
+get_uint4(bufferinfo *gbp) {
+    unsigned int tmp;
+    memcpy(&tmp, gbp->pos, 4);
+    if (endianness) swap4b(&tmp);
+    gbp->pos += 4;
+    return tmp;
+}
+
+static int
+type_size(nc_type type) {
+    switch (type) {
+      case NC_BYTE:   return X_SIZEOF_CHAR;
+      case NC_CHAR:   return X_SIZEOF_CHAR;
+      case NC_SHORT:  return X_SIZEOF_SHORT;
+      case NC_INT:    return X_SIZEOF_INT;
+      case NC_FLOAT:  return X_SIZEOF_FLOAT;
+      case NC_DOUBLE: return X_SIZEOF_DOUBLE;
+      case NC_UBYTE:  return X_SIZEOF_UBYTE;
+      case NC_USHORT: return X_SIZEOF_USHORT;
+      case NC_UINT:   return X_SIZEOF_UINT;
+      case NC_INT64:  return X_SIZEOF_INT64;
+      case NC_UINT64: return X_SIZEOF_UINT64;
+      default: return -1;
+    }
+}
+
+static const char *
+type_name(nc_type type) {
+    switch (type) {
+      case NC_BYTE:   return "byte";
+      case NC_CHAR:   return "char";
+      case NC_SHORT:  return "short";
+      case NC_INT:    return "int";
+      case NC_FLOAT:  return "float";
+      case NC_DOUBLE: return "double";
+      case NC_UBYTE:  return "ubyte";
+      case NC_USHORT: return "ushort";
+      case NC_UINT:   return "uint";
+      case NC_INT64:  return "int64";
+      case NC_UINT64: return "uint64";
+      default: return "bogus";
+    }
+}
+
+static NC_string *
+ncmpii_new_NC_string(long long   slen,
+                     const char *str)
+{
+    /* str may not be NULL terminated */
+    NC_string *ncstrp;
+    size_t sizeof_NC_string = M_RNDUP(sizeof(NC_string));
+    size_t sz = slen + sizeof_NC_string + 1;
+    /* one char more space for NULL terminate char */
+
+    ncstrp = (NC_string *) calloc(sz, sizeof(char));
+    if (ncstrp == NULL) return NULL;
+
+    /* make space occupied by ncstrp->cp part of ncstrp */
+    ncstrp->nchars = slen;
+    ncstrp->cp = (char *)ncstrp + sizeof_NC_string;
+
+    /* in PnetCDF, we want to make name->cp always NULL character terminated */
+    if (str != NULL && *str != '\0') {
+        strncpy(ncstrp->cp, str, slen);
+        ncstrp->cp[slen] = '\0';  /* NULL terminated */
+    }
+
+    return(ncstrp);
+}
+
+static NC_dim *
+ncmpii_elem_NC_dimarray(const NC_dimarray *ncap,
+                        int                dimid)
+{
+    /* returns the dimension ID defined earlier */
+    assert(ncap != NULL);
+
+    if (dimid < 0 || ncap->ndefined == 0 || dimid >= ncap->ndefined)
+        return NULL;
+
+    assert(ncap->value != NULL);
+
+    return ncap->value[dimid];
+}
+
+/*----< ncmpix_len_nctype() >------------------------------------------------*/
+static int
+ncmpix_len_nctype(nc_type type) {
+    switch(type) {
+        case NC_BYTE:
+        case NC_CHAR:
+        case NC_UBYTE:  return X_SIZEOF_CHAR;
+        case NC_SHORT:
+        case NC_USHORT: return X_SIZEOF_SHORT;
+        case NC_INT:
+        case NC_UINT:   return X_SIZEOF_INT;
+        case NC_FLOAT:  return X_SIZEOF_FLOAT;
+        case NC_DOUBLE: return X_SIZEOF_DOUBLE;
+        case NC_INT64:
+        case NC_UINT64: return X_SIZEOF_INT64;
+        default: assert("ncmpix_len_nctype bad type" == 0);
+    }
+    return 0;
+}
+
+static int
+ncmpii_NC_var_shape64(NC                *ncp,
+                      NC_var            *varp,
+                      const NC_dimarray *dims)
+{
+    int i;
+    long long product = 1;
+
+    /* set the size of 1 element */
+    varp->xsz = ncmpix_len_nctype(varp->type);
+
+    if (varp->ndims == 0) goto out;
+
+    /*
+     * use the user supplied dimension indices to determine the shape
+     */
+    for (i=0; i<varp->ndims; i++) {
+        const NC_dim *dimp;
+
+        if (varp->dimids[i] < 0)
+            DEBUG_RETURN_ERROR(NC_EBADDIM);
+
+        if (varp->dimids[i] >= ((dims != NULL) ? dims->ndefined : 1))
+            DEBUG_RETURN_ERROR(NC_EBADDIM);
+
+        /* get the pointer to the dim object */
+        dimp = ncmpii_elem_NC_dimarray(dims, varp->dimids[i]);
+        varp->shape[i] = dimp->size;
+
+        /* check for record variable, only the highest dimension can
+         * be unlimited */
+        if (varp->shape[i] == NC_UNLIMITED && i != 0)
+            DEBUG_RETURN_ERROR(NC_EUNLIMPOS);
+    }
+
+    /*
+     * compute the dsizes, the right to left product of shape
+     */
+    product = 1;
+    if (varp->ndims == 1) {
+        if (varp->shape[0] == NC_UNLIMITED)
+            varp->dsizes[0] = 1;
+        else {
+            varp->dsizes[0] = varp->shape[0];
+            product = varp->shape[0];
+        }
+    }
+    else { /* varp->ndims > 1 */
+        varp->dsizes[varp->ndims-1] = varp->shape[varp->ndims-1];
+        product = varp->shape[varp->ndims-1];
+        for (i=varp->ndims-2; i>=0; i--) {
+            if (varp->shape[i] != NC_UNLIMITED)
+                product *= varp->shape[i];
+            varp->dsizes[i] = product;
+        }
+    }
+
+out :
+    /*
+     * For CDF-1 and CDF-2 formats, the total number of array elements
+     * cannot exceed 2^32, unless this variable is the last fixed-size 
+     * variable, there is no record variable, and the file starting 
+     * offset of this variable is less than 2GiB. 
+     * We will check this in ncmpi_enddef() which calls ncmpii_NC_enddef() 
+     * which calls ncmpii_NC_check_vlens() 
+    if (ncp->flags != 5 && product >= X_UINT_MAX)
+        DEBUG_RETURN_ERROR(NC_EVARSIZE);
+     */
+
+    /*
+     * align variable size to 4 byte boundary, required by all netcdf file
+     * formats
+     */
+    varp->len = product * varp->xsz;
+    if (varp->len % 4 > 0)
+        varp->len += 4 - varp->len % 4; /* round up */
+
+    return NC_NOERR;
+}
+
+/*
+ * Recompute the shapes of all variables
+ * Sets ncp->begin_var to start of first variable.
+ * Sets ncp->begin_rec to start of first record variable.
+ * Returns -1 on error. The only possible error is an reference
+ * to a non existent dimension, which would occur for a corrupt
+ * netcdf file.
+ */
+static int
+ncmpii_NC_computeshapes(NC *ncp)
+{
+    NC_var **vpp = (NC_var **)ncp->vars.value;
+    NC_var *const *const end = &vpp[ncp->vars.ndefined];
+    NC_var *first_var = NULL;       /* first "non-record" var */
+    NC_var *first_rec = NULL;       /* first "record" var */
+    int status;
+
+    ncp->begin_var = ncp->xsz;
+    ncp->begin_rec = ncp->xsz;
+    ncp->recsize = 0;
+
+    if (ncp->vars.ndefined == 0) return NC_NOERR;
+
+    for ( /*NADA*/; vpp < end; vpp++) {
+        /* (*vpp)->len is recomputed from dimensions in ncmpii_NC_var_shape64() */
+        status = ncmpii_NC_var_shape64(ncp, *vpp, &ncp->dims);
+
+        if (status != NC_NOERR) return status ;
+
+        if (IS_RECVAR(*vpp)) {
+            if (first_rec == NULL)
+                first_rec = *vpp;
+            ncp->recsize += (*vpp)->len;
+        }
+        else {
+            if (first_var == NULL)
+            first_var = *vpp;
+            /*
+             * Overwritten each time thru.
+             * Usually overwritten in first_rec != NULL clause.
+             */
+            ncp->begin_rec = (*vpp)->begin + (*vpp)->len;
+        }
+    }
+
+    if (first_rec != NULL) {
+        if (ncp->begin_rec > first_rec->begin)
+            DEBUG_RETURN_ERROR(NC_ENOTNC); /* not a netCDF file or corrupted */
+
+        ncp->begin_rec = first_rec->begin;
+        /*
+         * for special case of exactly one record variable, pack value
+         */
+        if (ncp->recsize == first_rec->len)
+            ncp->recsize = *first_rec->dsizes * first_rec->xsz;
+    }
+
+    if (first_var != NULL)
+        ncp->begin_var = first_var->begin;
+    else
+        ncp->begin_var = ncp->begin_rec;
+
+    if (ncp->begin_var <= 0 ||
+        ncp->xsz > ncp->begin_var ||
+        ncp->begin_rec <= 0 ||
+        ncp->begin_var > ncp->begin_rec)
+        DEBUG_RETURN_ERROR(NC_ENOTNC); /* not a netCDF file or corrupted */
+
+    return NC_NOERR;
+}
+
+/*
+ * To compute how much space will the xdr'd header take
+ */
+
+#define X_SIZEOF_NC_TYPE X_SIZEOF_INT
+#define X_SIZEOF_NCTYPE X_SIZEOF_INT
+
+/*----< hdr_len_NC_name() >--------------------------------------------------*/
+static long long
+hdr_len_NC_name(const NC_string *ncstrp,
+                int              sizeof_t)     /* NON_NEG */
+{
+    /* netCDF file format:
+     * name       = nelems  namestring
+     * nelems     = NON_NEG
+     * namestring = ID1 [IDN ...] padding
+     * ID1        = alphanumeric | '_'
+     * IDN        = alphanumeric | special1 | special2
+     * padding    = <0, 1, 2, or 3 bytes to next 4-byte boundary>
+     * NON_NEG    = <non-negative INT> |  // CDF-1 and CDF-2
+     *              <non-negative INT64>  // CDF-5
+     */
+    long long sz = sizeof_t; /* nelems */
+
+    assert(ncstrp != NULL);
+
+    if (ncstrp->nchars != 0)  /* namestring */
+        sz += _RNDUP(ncstrp->nchars, X_ALIGN);
+
+    return sz;
+}
+
+/*----< hdr_len_NC_dim() >---------------------------------------------------*/
+static long long
+hdr_len_NC_dim(const NC_dim *dimp,
+               int           sizeof_t)     /* NON_NEG */
+{
+    /* netCDF file format:
+     *  ...
+     * dim        = name  dim_length
+     * dim_length = NON_NEG
+     * NON_NEG    = <non-negative INT> |  // CDF-1 and CDF-2
+     *              <non-negative INT64>  // CDF-5
+     */
+    long long sz;
+
+    assert(dimp != NULL);
+
+    sz = hdr_len_NC_name(dimp->name, sizeof_t); /* name */
+    sz += sizeof_t;                             /* dim_length */
+
+    return sz;
+}
+
+/*----< hdr_len_NC_dimarray() >----------------------------------------------*/
+static long long
+hdr_len_NC_dimarray(const NC_dimarray *ncap,
+                    int                sizeof_t)     /* NON_NEG */
+{
+    /* netCDF file format:
+     *  ...
+     * dim_list     = ABSENT | NC_DIMENSION  nelems  [dim ...]
+     * ABSENT       = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *                ZERO  ZERO64  // for CDF-5
+     * ZERO         = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64       = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_DIMENSION = \x00 \x00 \x00 \x0A         // tag for list of dimensions
+     * nelems       = NON_NEG       // number of elements in following sequence
+     * NON_NEG      = <non-negative INT> |        // CDF-1 and CDF-2
+     *                <non-negative INT64>        // CDF-5
+     */
+    int i;
+    long long xlen;
+
+    xlen = X_SIZEOF_NCTYPE;           /* NC_DIMENSION */
+    xlen += sizeof_t;                 /* nelems */
+
+    if (ncap == NULL) /* ABSENT: no dimension is defined */
+        return xlen;
+
+    /* [dim ...] */
+    for (i=0; i<ncap->ndefined; i++)
+        xlen += hdr_len_NC_dim(ncap->value[i], sizeof_t);
+
+    return xlen;
+}
+
+/*----< hdr_len_NC_attr() >--------------------------------------------------*/
+static long long
+hdr_len_NC_attr(const NC_attr *attrp,
+                int            sizeof_t)     /* NON_NEG */
+{
+    /* netCDF file format:
+     *  ...
+     * attr    = name  nc_type  nelems  [values ...]
+     * nc_type = NC_BYTE | NC_CHAR | NC_SHORT | ...
+     * nelems  = NON_NEG       // number of elements in following sequence
+     * values  = bytes | chars | shorts | ints | floats | doubles
+     * bytes   = [BYTE ...]  padding
+     * chars   = [CHAR ...]  padding
+     * shorts  = [SHORT ...]  padding
+     * ints    = [INT ...]
+     * floats  = [FLOAT ...]
+     * doubles = [DOUBLE ...]
+     * padding = <0, 1, 2, or 3 bytes to next 4-byte boundary>
+     * NON_NEG = <non-negative INT> |  // CDF-1 and CDF-2
+     *           <non-negative INT64>  // CDF-5
+     */
+    long long sz;
+
+    assert(attrp != NULL);
+
+    sz  = hdr_len_NC_name(attrp->name, sizeof_t); /* name */
+    sz += X_SIZEOF_NC_TYPE;                       /* nc_type */
+    sz += sizeof_t;                               /* nelems */
+    sz += attrp->xsz;                             /* [values ...] */
+
+    return sz;
+}
+
+/*----< hdr_len_NC_attrarray() >---------------------------------------------*/
+static long long
+hdr_len_NC_attrarray(const NC_attrarray *ncap,
+                     int                 sizeof_t)     /* NON_NEG */
+{
+    /* netCDF file format:
+     *  ...
+     * att_list     = ABSENT | NC_ATTRIBUTE  nelems  [attr ...]
+     * ABSENT       = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *                ZERO  ZERO64  // for CDF-5
+     * ZERO         = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64       = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_ATTRIBUTE = \x00 \x00 \x00 \x0C         // tag for list of attributes
+     * nelems       = NON_NEG       // number of elements in following sequence
+     * NON_NEG      = <non-negative INT> |        // CDF-1 and CDF-2
+     *                <non-negative INT64>        // CDF-5
+     */
+    int i;
+    long long xlen;
+
+    xlen = X_SIZEOF_NCTYPE;        /* NC_ATTRIBUTE */
+    xlen += sizeof_t;              /* nelems */
+
+    if (ncap == NULL) /* ABSENT: no attribute is defined */
+        return xlen;
+
+    for (i=0; i<ncap->ndefined; i++) /* [attr ...] */
+        xlen += hdr_len_NC_attr(ncap->value[i], sizeof_t);
+
+    return xlen;
+}
+
+/*----< hdr_len_NC_var() >---------------------------------------------------*/
+static long long
+hdr_len_NC_var(const NC_var *varp,
+               int           sizeof_off_t, /* OFFSET */
+               int           sizeof_t)     /* NON_NEG */
+{
+    /* netCDF file format:
+     * netcdf_file = header data
+     * header      = magic numrecs dim_list gatt_list var_list
+     *  ...
+     * var         = name nelems [dimid ...] vatt_list nc_type vsize begin
+     * nelems      = NON_NEG
+     * dimid       = NON_NEG
+     * vatt_list   = att_list
+     * nc_type     = NC_BYTE | NC_CHAR | NC_SHORT | ...
+     * vsize       = NON_NEG
+     * begin       = OFFSET        // Variable start location.
+     * OFFSET      = <non-negative INT> |  // CDF-1
+     *               <non-negative INT64>  // CDF-2 and CDF-5
+     * NON_NEG     = <non-negative INT> |  // CDF-1 and CDF-2
+     *               <non-negative INT64>  // CDF-5
+     */
+    long long sz;
+
+    assert(varp != NULL);
+
+    /* for CDF-1, sizeof_off_t == 4 && sizeof_t == 4
+     * for CDF-2, sizeof_off_t == 8 && sizeof_t == 4
+     * for CDF-5, sizeof_off_t == 8 && sizeof_t == 8
+     */
+    sz = hdr_len_NC_name(varp->name, sizeof_t);         /* name */
+    sz += sizeof_t;                                     /* nelems */
+    sz += sizeof_t * varp->ndims;                       /* [dimid ...] */
+    sz += hdr_len_NC_attrarray(&varp->attrs, sizeof_t); /* vatt_list */
+    sz += X_SIZEOF_NC_TYPE;                             /* nc_type */
+    sz += sizeof_t;                                     /* vsize */
+    sz += sizeof_off_t;                                 /* begin */
+
+    return sz;
+}
+
+/*----< hdr_len_NC_vararray() >----------------------------------------------*/
+static long long
+hdr_len_NC_vararray(const NC_vararray *ncap,
+                    int                sizeof_t,     /* NON_NEG */
+                    int                sizeof_off_t) /* OFFSET */
+{
+    /* netCDF file format:
+     * netcdf_file = header  data
+     * header      = magic  numrecs  dim_list  gatt_list  var_list
+     *  ...
+     * var_list    = ABSENT | NC_VARIABLE   nelems  [var ...]
+     * ABSENT      = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *               ZERO  ZERO64  // for CDF-5
+     * ZERO        = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64      = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_VARIABLE = \x00 \x00 \x00 \x0B         // tag for list of variables
+     * nelems      = NON_NEG       // number of elements in following sequence
+     * NON_NEG     = <non-negative INT> |        // CDF-1 and CDF-2
+     *               <non-negative INT64>        // CDF-5
+     */
+    int i;
+    long long xlen;
+
+    xlen = X_SIZEOF_NCTYPE;           /* NC_VARIABLE */
+    xlen += sizeof_t;                 /* nelems */
+
+    if (ncap == NULL) /* ABSENT: no variable is defined */
+        return xlen;
+
+    /* for CDF-1, sizeof_off_t == 4 && sizeof_t == 4
+     * for CDF-2, sizeof_off_t == 8 && sizeof_t == 4
+     * for CDF-5, sizeof_off_t == 8 && sizeof_t == 8
+     */
+    for (i=0; i<ncap->ndefined; i++)  /* [var ...] */
+        xlen += hdr_len_NC_var(ncap->value[i], sizeof_off_t, sizeof_t);
+
+    return xlen;
+}
+
+/*----< ncmpii_hdr_len_NC() >------------------------------------------------*/
+static long long
+ncmpii_hdr_len_NC(const NC *ncp)
+{
+    /* netCDF file format:
+     * netcdf_file = header  data
+     * header      = magic  numrecs  dim_list  gatt_list  var_list
+     *  ...
+     * numrecs     = NON_NEG | STREAMING   // length of record dimension
+     * NON_NEG     = <non-negative INT> |  // CDF-1 and CDF-2
+     *               <non-negative INT64>  // CDF-5
+     */
+
+    int sizeof_t, sizeof_off_t;
+    long long xlen;
+
+    assert(ncp != NULL);
+
+    if (ncp->flags == 5) {        /* CDF-5 */
+        sizeof_t     = X_SIZEOF_INT64; /* 8-byte integer for all integers */
+        sizeof_off_t = X_SIZEOF_INT64; /* 8-byte integer for var begin */
+    }
+    else if (ncp->flags == 2) { /* CDF-2 */
+        sizeof_t     = X_SIZEOF_INT; /* 4-byte integer in CDF-1 */
+        sizeof_off_t = X_SIZEOF_INT64; /* 8-byte integer for var begin */
+    }
+    else { /* CDF-1 */
+        sizeof_t     = X_SIZEOF_INT; /* 4-byte integer in CDF-1 */
+        sizeof_off_t = X_SIZEOF_INT; /* 4-byte integer in CDF-1 */
+    }
+
+    xlen  = sizeof(ncmagic1);                                          /* magic */
+    xlen += sizeof_t;                                                  /* numrecs */
+    xlen += hdr_len_NC_dimarray(&ncp->dims,   sizeof_t);               /* dim_list */
+    xlen += hdr_len_NC_attrarray(&ncp->attrs, sizeof_t);               /* gatt_list */
+    xlen += hdr_len_NC_vararray(&ncp->vars,   sizeof_t, sizeof_off_t); /* var_list */
+
+    return xlen; /* return the header size (not yet aligned) */
+}
+
+static int
+hdr_fetch(bufferinfo *gbp) {
+    int err=NC_NOERR;
+    size_t slack;        /* any leftover data in the buffer */
+
+    assert(gbp->base != NULL);
+
+    slack = gbp->size - (gbp->pos - gbp->base);
+    /* if gbp->pos and gbp->base are the same, there is no leftover buffer
+     * data to worry about.
+     * In the other extreme, where gbp->size == (gbp->pos - gbp->base), then
+     * all data in the buffer has been consumed */
+    if (slack == gbp->size) slack = 0;
+
+    memset(gbp->base, 0, (size_t)gbp->size);
+    gbp->pos = gbp->base;
+
+    lseek(gbp->fd, (gbp->offset)-slack, SEEK_SET);
+    size_t read_amount = read(gbp->fd, gbp->base, gbp->size);
+    if (read_amount == -1) {
+        fprintf(stderr,"ERROR at line %d: read error %s\n",__LINE__,strerror(errno));
+        exit(1);
+    }
+    /* we might have had to backtrack */
+    gbp->offset += (gbp->size - slack);
+
+    return err;
+}
+
+/*----< hdr_check_buffer() >--------------------------------------------------*/
+/* Ensure that 'nextread' bytes are available.  */
+static int
+hdr_check_buffer(bufferinfo *gbp,
+                 size_t      nextread)
+{
+    if (gbp->pos + nextread <= gbp->base + gbp->size)
+        return NC_NOERR;
+
+    /* read the next chunk from file */
+    return hdr_fetch(gbp);
+}
+
+/*----< hdr_get_NCtype() >----------------------------------------------------*/
+static int
+hdr_get_NCtype(bufferinfo *gbp,
+               NCtype     *typep)
+{
+    /* NCtype is 4-byte integer */
+    int status = hdr_check_buffer(gbp, 4);
+    if (status != NC_NOERR) return status;
+
+    /* get a 4-byte integer */
+    *typep = get_uint4(gbp);
+
+    return NC_NOERR;
+}
+
+/*----< hdr_get_nc_type() >---------------------------------------------------*/
+static int
+hdr_get_nc_type(bufferinfo *gbp,
+                nc_type    *typep)
+{
+    /* nc_type is 4-byte integer, X_SIZEOF_INT */
+    int type, status;
+
+    status = hdr_check_buffer(gbp, X_SIZEOF_INT);
+    if (status != NC_NOERR) return status;
+
+    type = get_uint4(gbp);
+
+    if (type != NC_BYTE    &&
+        type != NC_CHAR    &&
+        type != NC_UBYTE   &&
+        type != NC_SHORT   &&
+        type != NC_USHORT  &&
+        type != NC_INT     &&
+        type != NC_UINT    &&
+        type != NC_FLOAT   &&
+        type != NC_DOUBLE  &&
+        type != NC_INT64   &&
+        type != NC_UINT64
+       )
+        DEBUG_RETURN_ERROR(NC_EINVAL);
+
+    *typep = (nc_type) type;
+    return NC_NOERR;
+}
+
+/*----< hdr_get_NC_name() >---------------------------------------------------*/
+static int
+hdr_get_NC_name(bufferinfo  *gbp,
+                NC_string  **ncstrpp)
+{
+    /* netCDF file format:
+     *  ...
+     * name       = nelems  namestring
+     * nelems     = NON_NEG
+     * namestring = ID1 [IDN ...] padding
+     * ID1        = alphanumeric | '_'
+     * IDN        = alphanumeric | special1 | special2
+     * padding    = <0, 1, 2, or 3 bytes to next 4-byte boundary>
+     * NON_NEG    = <non-negative INT> |  // CDF-1 and CDF-2
+     *              <non-negative INT64>  // CDF-5
+     */
+    int status;
+    size_t  nchars, nbytes, padding, bufremain, strcount;
+    NC_string *ncstrp;
+    char *cpos, pad[X_ALIGN-1];
+
+    /* get nelems */
+    if (gbp->version == 5) 
+        nchars = get_uint8(gbp);
+    else
+        nchars = get_uint4(gbp);
+
+    /* Allocate a NC_string structure large enough to hold nchars characters */
+    ncstrp = ncmpii_new_NC_string(nchars, NULL);
+
+    nbytes = nchars;
+    padding = _RNDUP(ncstrp->nchars, X_ALIGN) - ncstrp->nchars;
+    bufremain = gbp->size - (gbp->pos - gbp->base);
+    cpos = ncstrp->cp;
+
+    /* get namestring with padding */
+    while (nbytes > 0) {
+        if (bufremain > 0) {
+            strcount = MIN(bufremain, nbytes);
+            memcpy(cpos, gbp->pos, strcount);
+            nbytes -= strcount;
+            gbp->pos = (void *)((char *)gbp->pos + strcount);
+            cpos += strcount;
+            bufremain -= strcount;
+        } else {
+            status = hdr_fetch(gbp);
+            if (status != NC_NOERR) {
+                free(ncstrp);
+                return status;
+            }
+            bufremain = gbp->size;
+        }
+    }
+
+    /* handle the padding */
+    if (padding > 0) {
+        memset(pad, 0, X_ALIGN-1);
+        if (memcmp(gbp->pos, pad, padding) != 0) {
+            free(ncstrp);
+            DEBUG_RETURN_ERROR(NC_EINVAL);
+        }
+        gbp->pos = (void *)((char *)gbp->pos + padding);
+    }
+
+    *ncstrpp = ncstrp;
+
+    return NC_NOERR;
+}
+
+static NC_dim *
+ncmpii_new_x_NC_dim(NC_string *name)
+{
+    NC_dim *dimp;
+
+    dimp = (NC_dim *) malloc(sizeof(NC_dim));
+    MALLOC_CHECK(dimp)
+
+    dimp->name = name;
+    dimp->size = 0;
+
+    return(dimp);
+}
+
+/*----< hdr_get_NC_dim() >----------------------------------------------------*/
+static int
+hdr_get_NC_dim(bufferinfo  *gbp,
+               NC_dim     **dimpp)
+{
+    /* netCDF file format:
+     *  ...
+     * dim        = name  dim_length
+     * dim_length = NON_NEG
+     * NON_NEG    = <non-negative INT> |  // CDF-1 and CDF-2
+     *              <non-negative INT64>  // CDF-5
+     */
+    int status;
+    NC_string *ncstrp;
+    NC_dim *dimp;
+
+    /* get name */
+    status = hdr_get_NC_name(gbp, &ncstrp);
+    if (status != NC_NOERR) return status;
+
+    dimp = ncmpii_new_x_NC_dim(ncstrp);
+
+    /* get dim_length */
+    if (gbp->version == 5) 
+        dimp->size = get_uint8(gbp);
+    else
+        dimp->size = get_uint4(gbp);
+
+    *dimpp = dimp;
+    return NC_NOERR;
+}
+
+static void
+ncmpii_free_NC_dim(NC_dim *dimp)
+{
+    if (dimp == NULL) return;
+    free(dimp->name);
+    free(dimp);
+}
+
+static void
+ncmpii_free_NC_dimarray(NC_dimarray *ncap)
+{
+    int i;
+
+    assert(ncap != NULL);
+    if (ncap->nalloc == 0) return;
+
+    assert(ncap->value != NULL);
+    for (i=0; i<ncap->ndefined; i++)
+        ncmpii_free_NC_dim(ncap->value[i]);
+
+    free(ncap->value);
+    ncap->value    = NULL;
+    ncap->nalloc   = 0;
+    ncap->ndefined = 0;
+}
+
+
+/*----< hdr_get_NC_dimarray() >-----------------------------------------------*/
+static int
+hdr_get_NC_dimarray(bufferinfo  *gbp,
+                    NC_dimarray *ncap)
+{
+    /* netCDF file format:
+     *  ...
+     * dim_list     = ABSENT | NC_DIMENSION  nelems  [dim ...]
+     * ABSENT       = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *                ZERO  ZERO64  // for CDF-5
+     * ZERO         = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64       = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_DIMENSION = \x00 \x00 \x00 \x0A         // tag for list of dimensions
+     * nelems       = NON_NEG       // number of elements in following sequence
+     * NON_NEG      = <non-negative INT> |        // CDF-1 and CDF-2
+     *                <non-negative INT64>        // CDF-5
+     */
+    int i, status;
+    NCtype type = NC_UNSPECIFIED;
+    size_t ndefined;
+
+    /* get NCtype (NC_DIMENSION) */
+    status = hdr_get_NCtype(gbp, &type);
+    if (status != NC_NOERR) return status;
+
+    /* get nelems */
+    if (gbp->version == 5) 
+        ndefined = get_uint8(gbp);
+    else
+        ndefined = get_uint4(gbp);
+    ncap->ndefined = (int)ndefined;
+
+    if (ndefined == 0) {
+        if (type != NC_DIMENSION && type != NC_UNSPECIFIED)
+            DEBUG_RETURN_ERROR(NC_EINVAL);
+    } else {
+        if (type != NC_DIMENSION) DEBUG_RETURN_ERROR(NC_EINVAL);
+
+        ncap->value = (NC_dim **) malloc(ndefined * sizeof(NC_dim*));
+        MALLOC_CHECK(ncap->value)
+        ncap->nalloc = (int)ndefined;
+
+        for (i=0; i<ndefined; i++) {
+            status = hdr_get_NC_dim(gbp, ncap->value + i);
+            if (status != NC_NOERR) { /* error: fail to get the next dim */
+                ncap->ndefined = i;
+                ncmpii_free_NC_dimarray(ncap);
+                return status;
+            }
+        }
+    }
+
+    return NC_NOERR;
+}
+
+/*----< hdr_get_NC_attrV() >--------------------------------------------------*/
+static int
+hdr_get_NC_attrV(bufferinfo *gbp,
+                 NC_attr    *attrp)
+{
+    /* netCDF file format:
+     *  ...
+     * attr    = name  nc_type  nelems  [values ...]
+     *  ...
+     * values  = bytes | chars | shorts | ints | floats | doubles
+     * bytes   = [BYTE ...]  padding
+     * chars   = [CHAR ...]  padding
+     * shorts  = [SHORT ...]  padding
+     * ints    = [INT ...]
+     * floats  = [FLOAT ...]
+     * doubles = [DOUBLE ...]
+     * padding = <0, 1, 2, or 3 bytes to next 4-byte boundary>
+     */
+    int status;
+    void *value = attrp->xvalue;
+    char pad[X_ALIGN-1];
+    size_t nbytes, padding, bufremain, attcount;
+
+    nbytes = attrp->nelems * ncmpix_len_nctype(attrp->type);
+    padding = attrp->xsz - nbytes;
+    bufremain = gbp->size - (gbp->pos - gbp->base);
+
+    /* get values */
+    while (nbytes > 0) {
+        if (bufremain > 0) {
+            attcount = MIN(bufremain, nbytes);
+            memcpy(value, gbp->pos, (size_t)attcount);
+            nbytes -= attcount;
+            gbp->pos = (void *)((char *)gbp->pos + attcount);
+            value = (void *)((char *)value + attcount);
+            bufremain -= attcount;
+        } else {
+            status = hdr_fetch(gbp);
+            if (status != NC_NOERR) return status;
+            bufremain = gbp->size;
+        }
+    }
+
+    /* handle the padding */
+    if (padding > 0) {
+        memset(pad, 0, X_ALIGN-1);
+        if (memcmp(gbp->pos, pad, (size_t)padding) != 0)
+            DEBUG_RETURN_ERROR(NC_EINVAL);
+        gbp->pos = (void *)((char *)gbp->pos + padding);
+    }
+
+    return NC_NOERR;
+}
+
+static long long
+ncmpix_len_NC_attrV(nc_type    type,
+                    long long  nelems)
+{
+    switch(type) {
+        case NC_BYTE:
+        case NC_CHAR:
+        case NC_UBYTE:  return ncmpix_len_char(nelems);
+        case NC_SHORT:  return ncmpix_len_short(nelems);
+        case NC_USHORT: return ncmpix_len_ushort(nelems);
+        case NC_INT:    return ncmpix_len_int(nelems);
+        case NC_UINT:   return ncmpix_len_uint(nelems);
+        case NC_FLOAT:  return ncmpix_len_float(nelems);
+        case NC_DOUBLE: return ncmpix_len_double(nelems);
+        case NC_INT64:  return ncmpix_len_int64(nelems);
+        case NC_UINT64: return ncmpix_len_uint64(nelems);
+        default: assert("ncmpix_len_NC_attr bad type" == 0);
+    }
+    return 0;
+}
+
+static NC_attr *
+ncmpii_new_x_NC_attr(NC_string  *strp,
+                     nc_type     type,
+                     size_t      nelems)
+{
+    NC_attr *attrp;
+    const long long xsz = ncmpix_len_NC_attrV(type, nelems);
+    size_t sz = M_RNDUP(sizeof(NC_attr));
+
+    assert(!(xsz == 0 && nelems != 0));
+
+    sz += (size_t)xsz;
+
+    attrp = (NC_attr *) malloc(sz);
+    MALLOC_CHECK(attrp)
+
+    attrp->xsz    = xsz;
+    attrp->name   = strp;
+    attrp->type   = type;
+    attrp->nelems = nelems;
+
+    if (xsz != 0)
+        attrp->xvalue = (char *)attrp + M_RNDUP(sizeof(NC_attr));
+    else
+        attrp->xvalue = NULL;
+
+    return(attrp);
+}
+
+static void
+ncmpii_free_NC_attr(NC_attr *attrp)
+{
+    if (attrp == NULL) return;
+    free(attrp->name);
+    free(attrp);
+}
+
+
+/*----< hdr_get_NC_attr() >---------------------------------------------------*/
+static int
+hdr_get_NC_attr(bufferinfo  *gbp,
+                NC_attr    **attrpp)
+{
+    /* netCDF file format:
+     *  ...
+     * attr    = name  nc_type  nelems  [values ...]
+     * nc_type = NC_BYTE | NC_CHAR | NC_SHORT | ...
+     * nelems  = NON_NEG       // number of elements in following sequence
+     * NON_NEG = <non-negative INT> |  // CDF-1 and CDF-2
+     *           <non-negative INT64>  // CDF-5
+     */
+    int status;
+    NC_string *strp;
+    nc_type type;
+    size_t nelems;
+    NC_attr *attrp;
+
+    /* get name */
+    status = hdr_get_NC_name(gbp, &strp);
+    if (status != NC_NOERR) return status;
+
+    /* get nc_type */
+    status = hdr_get_nc_type(gbp, &type);
+    if (status != NC_NOERR) {
+        free(strp);
+        return status;
+    }
+
+    /* get nelems */
+    if (gbp->version == 5) 
+        nelems = get_uint8(gbp);
+    else
+        nelems = get_uint4(gbp);
+
+    /* allocate space for attribute object */
+    attrp = ncmpii_new_x_NC_attr(strp, type, nelems);
+    if (attrp == NULL) {
+        free(strp);
+        return status;
+    }
+
+    /* get [values ...] */
+    status = hdr_get_NC_attrV(gbp, attrp);
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_attr(attrp); /* frees strp */
+        return status;
+    }
+
+    *attrpp = attrp;
+    return NC_NOERR;
+}
+
+static void
+ncmpii_free_NC_attrarray(NC_attrarray *ncap)
+{
+    int i;
+
+    assert(ncap != NULL);
+    if (ncap->nalloc == 0) return;
+    assert(ncap->value != NULL);
+    for (i=0; i<ncap->ndefined; i++)
+        ncmpii_free_NC_attr(ncap->value[i]);
+
+    free(ncap->value);
+    ncap->value    = NULL;
+    ncap->nalloc   = 0;
+    ncap->ndefined = 0;
+}
+/*----< hdr_get_NC_attrarray() >----------------------------------------------*/
+static int
+hdr_get_NC_attrarray(bufferinfo   *gbp,
+                     NC_attrarray *ncap)
+{
+    /* netCDF file format:
+     *  ...
+     * att_list     = ABSENT | NC_ATTRIBUTE  nelems  [attr ...]
+     * ABSENT       = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *                ZERO  ZERO64  // for CDF-5
+     * ZERO         = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64       = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_ATTRIBUTE = \x00 \x00 \x00 \x0C         // tag for list of attributes
+     * nelems       = NON_NEG       // number of elements in following sequence
+     * NON_NEG      = <non-negative INT> |        // CDF-1 and CDF-2
+     *                <non-negative INT64>        // CDF-5
+     */
+    int i, status;
+    NCtype type = NC_UNSPECIFIED;
+    size_t ndefined;
+
+    /* get NCtype (NC_ATTRIBUTE) */
+    status = hdr_get_NCtype(gbp, &type);
+    if (status != NC_NOERR) return status;
+
+    /* get nelems */
+    if (gbp->version == 5) 
+        ndefined = get_uint8(gbp);
+    else
+        ndefined = get_uint4(gbp);
+    ncap->ndefined = (int)ndefined;
+
+    if (ndefined == 0) {
+        if (type != NC_ATTRIBUTE && type != NC_UNSPECIFIED)
+            DEBUG_RETURN_ERROR(NC_EINVAL);
+    } else {
+        if (type != NC_ATTRIBUTE)
+            DEBUG_RETURN_ERROR(NC_EINVAL);
+
+        ncap->value = (NC_attr **)malloc((size_t)ndefined * sizeof(NC_attr*));
+        MALLOC_CHECK(ncap->value)
+        ncap->nalloc = (int)ndefined;
+
+        /* get [attr ...] */
+        for (i=0; i<ndefined; i++) {
+            status = hdr_get_NC_attr(gbp, ncap->value + i);
+            if (status != NC_NOERR) { /* Error: fail to get the next att */
+                ncap->ndefined = i;
+                ncmpii_free_NC_attrarray(ncap);
+                return status;
+            }
+        }
+    }
+
+    return NC_NOERR;
+}
+
+static NC_var *
+ncmpii_new_x_NC_var(NC_string *strp,
+                    int        ndims)
+{
+    NC_var *varp;
+    int shape_space   = M_RNDUP(ndims * 8);
+    int dsizes_space  = M_RNDUP(ndims * 8);
+    int dimids_space  = M_RNDUP(ndims * 4);
+    size_t sizeof_NC_var = M_RNDUP(sizeof(NC_var));
+    size_t sz = sizeof_NC_var + (size_t)(shape_space + dsizes_space + dimids_space);
+
+    varp = (NC_var *) malloc(sz);
+    MALLOC_CHECK(varp)
+
+    memset(varp, 0, sz);
+
+    varp->name = strp;
+    varp->ndims = ndims;
+
+    if (ndims != 0) {
+        varp->shape  = (long long *)((char *)varp + sizeof_NC_var);
+        varp->dsizes = (long long *)((char *)varp->shape  + shape_space);
+        varp->dimids = (int *)      ((char *)varp->dsizes + dsizes_space);
+    }
+
+    varp->xsz = 0;
+    varp->len = 0;
+    varp->begin = 0;
+    return varp;
+}
+
+static void
+ncmpii_free_NC_var(NC_var *varp)
+{
+    if (varp == NULL) return;
+    ncmpii_free_NC_attrarray(&varp->attrs);
+    free(varp->name);
+    free(varp);
+}
+
+/*----< hdr_get_NC_var() >---------------------------------------------------*/
+static int
+hdr_get_NC_var(bufferinfo  *gbp,
+               NC_var     **varpp)
+{
+    /* netCDF file format:
+     * netcdf_file = header data
+     * header      = magic numrecs dim_list gatt_list var_list
+     *  ...
+     * var         = name nelems [dimid ...] vatt_list nc_type vsize begin
+     * nelems      = NON_NEG
+     * dimid       = NON_NEG
+     * vatt_list   = att_list
+     * nc_type     = NC_BYTE | NC_CHAR | NC_SHORT | ...
+     * vsize       = NON_NEG
+     * begin       = OFFSET        // Variable start location.
+     * OFFSET      = <non-negative INT> |  // CDF-1
+     *               <non-negative INT64>  // CDF-2 and CDF-5
+     * NON_NEG     = <non-negative INT> |  // CDF-1 and CDF-2
+     *               <non-negative INT64>  // CDF-5
+     */
+    int status;
+    NC_string *strp;
+    size_t ndims=0, dim;
+    NC_var *varp;
+
+    /* get name */
+    status = hdr_get_NC_name(gbp, &strp);
+    if (status != NC_NOERR) return status;
+
+    /* nelems */
+    if (gbp->version == 5) 
+        ndims = get_uint8(gbp);
+    else
+        ndims = get_uint4(gbp);
+
+    /* allocate space for var object */
+    varp = ncmpii_new_x_NC_var(strp, (int)ndims);
+
+    /* get [dimid ...] */
+    for (dim=0; dim<ndims; dim++) {
+        status = hdr_check_buffer(gbp, (gbp->version == 5 ? 8 : 4));
+        if (status != NC_NOERR) {
+            ncmpii_free_NC_var(varp);
+            return status;
+        }
+        if (gbp->version == 5) 
+            varp->dimids[dim] = get_uint8(gbp);
+        else
+            varp->dimids[dim] = get_uint4(gbp);
+    }
+
+    /* get vatt_list */
+    status = hdr_get_NC_attrarray(gbp, &varp->attrs);
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_var(varp);
+        return status;
+    }
+
+    /* get nc_type */
+    status = hdr_get_nc_type(gbp, &varp->type);
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_var(varp);
+        return status;
+    }
+
+    /* get vsize */
+    if (gbp->version == 5) 
+        varp->len = get_uint8(gbp);
+    else
+        varp->len = get_uint4(gbp);
+
+    /* next element is 'begin' */
+    status = hdr_check_buffer(gbp, (gbp->version == 1 ? 4 : 8));
+    if (status != NC_NOERR) {
+        ncmpii_free_NC_var(varp);
+        return status;
+    }
+
+    /* get begin */
+    if (gbp->version == 1)
+        varp->begin = get_uint4(gbp);
+    else
+        varp->begin = get_uint8(gbp);
+
+    *varpp = varp;
+    return NC_NOERR;
+}
+
+static void
+ncmpii_free_NC_vararray(NC_vararray *ncap)
+{
+    int i;
+
+    assert(ncap != NULL);
+    if (ncap->nalloc == 0) return;
+
+    assert(ncap->value != NULL);
+    for (i=0; i<ncap->ndefined; i++) {
+        if (ncap->value[i] != NULL)
+            ncmpii_free_NC_var(ncap->value[i]);
+    }
+
+    free(ncap->value);
+    ncap->value    = NULL;
+    ncap->nalloc   = 0;
+    ncap->ndefined = 0;
+}
+
+/*----< hdr_get_NC_vararray() >----------------------------------------------*/
+static int
+hdr_get_NC_vararray(bufferinfo  *gbp,
+                    NC_vararray *ncap)
+{
+    /* netCDF file format:
+     * netcdf_file = header  data
+     * header      = magic  numrecs  dim_list  gatt_list  var_list
+     *  ...
+     * var_list    = ABSENT | NC_VARIABLE   nelems  [var ...]
+     * ABSENT      = ZERO  ZERO |  // list is not present for CDF-1 and 2
+     *               ZERO  ZERO64  // for CDF-5
+     * ZERO        = \x00 \x00 \x00 \x00                      // 32-bit zero
+     * ZERO64      = \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00  // 64-bit zero
+     * NC_VARIABLE = \x00 \x00 \x00 \x0B         // tag for list of variables
+     * nelems      = NON_NEG       // number of elements in following sequence
+     * NON_NEG     = <non-negative INT> |        // CDF-1 and CDF-2
+     *               <non-negative INT64>        // CDF-5
+     */
+    int i, status;
+    NCtype type = NC_UNSPECIFIED;
+    size_t ndefined;
+
+    assert(gbp != NULL && gbp->pos != NULL);
+    assert(ncap != NULL);
+    assert(ncap->value == NULL);
+
+    /* get NCtype (NC_VARIABLE) from gbp buffer */
+    status = hdr_get_NCtype(gbp, &type);
+    if (status != NC_NOERR) return status;
+
+    /* get nelems (number of variables) from gbp buffer */
+    if (gbp->version == 5) 
+        ndefined = get_uint8(gbp);
+    else
+        ndefined = get_uint4(gbp);
+    ncap->ndefined = (int)ndefined;
+
+    if (ndefined == 0) { /* no variable defined */
+        if (type != NC_VARIABLE && type != NC_UNSPECIFIED)
+            DEBUG_RETURN_ERROR(NC_EINVAL);
+    } else {
+        if (type != NC_VARIABLE)
+            DEBUG_RETURN_ERROR(NC_EINVAL);
+
+        ncap->value = (NC_var **) malloc((size_t)ndefined * sizeof(NC_var*));
+        MALLOC_CHECK(ncap->value)
+        ncap->nalloc = (int)ndefined;
+
+        /* get [var ...] */
+        for (i=0; i<ndefined; i++) {
+            status = hdr_get_NC_var(gbp, ncap->value + i);
+            if (status != NC_NOERR) { /* Error: fail to get the next var */
+                ncap->ndefined = i;
+                ncmpii_free_NC_vararray(ncap);
+                return status;
+            }
+        }
+    }
+
+    return NC_NOERR;
+}
+
+/*----< ncmpii_hdr_get_NC() >------------------------------------------------*/
+/*  CDF format specification
+ *      netcdf_file  = header  data
+ *      header       = magic  numrecs  dim_list  gatt_list  var_list
+ *      magic        = 'C'  'D'  'F'  VERSION
+ *      VERSION      = \x01 |                      // classic format
+ *                     \x02 |                      // 64-bit offset format
+ *                     \x05                        // 64-bit data format
+ *      numrecs      = NON_NEG | STREAMING         // length of record dimension
+ *      dim_list     = ABSENT | NC_DIMENSION  nelems  [dim ...]
+ *      gatt_list    = att_list                    // global attributes
+ *      att_list     = ABSENT | NC_ATTRIBUTE  nelems  [attr ...]
+ *      var_list     = ABSENT | NC_VARIABLE   nelems  [var ...]
+ */
+static int
+ncmpii_hdr_get_NC(int fd, NC *ncp)
+{
+    int i, status;
+    bufferinfo getbuf;
+    char *magic;
+
+    /* Initialize the get buffer that stores the header read from the file */
+    getbuf.fd     = fd;
+    getbuf.offset = 0;   /* read from start of the file */
+    getbuf.size   = NC_DEFAULT_CHUNKSIZE;
+    getbuf.base   = (void *)malloc((size_t)getbuf.size);
+    MALLOC_CHECK(getbuf.base)
+    getbuf.pos    = getbuf.base;
+
+    /* Fetch the next header chunk. The chunk is 'gbp->size' bytes big */
+    status = hdr_fetch(&getbuf);
+    if (status != NC_NOERR) return status;
+
+    /* processing the header from getbuf, the get buffer */
+
+    /* First get the file format information, magic */
+    magic = getbuf.base;
+    getbuf.pos += 4;
+
+    /* don't need to worry about CDF-1 or CDF-2
+     * if the first bits are not 'CDF'
+     */
+    if (memcmp(magic, ncmagic1, sizeof(ncmagic1)-1) != 0) {
+        DEBUG_ASSIGN_ERROR(status, NC_ENOTNC)
+        goto fn_exit;
+    }
+
+    /* check version number in last byte of magic */
+    if (magic[sizeof(ncmagic1)-1] == 0x1) {
+        getbuf.version = 1;
+        ncp->flags = 1;
+    } else if (magic[sizeof(ncmagic1)-1] == 0x2) {
+        getbuf.version = 2;
+        ncp->flags = 2;
+    } else if (magic[sizeof(ncmagic1)-1] == 0x5) {
+        getbuf.version = 5;
+        ncp->flags = 5;
+    } else {
+        DEBUG_ASSIGN_ERROR(status, NC_ENOTNC); /* not an netCDF file */
+        goto fn_exit;
+    }
+
+    /** Ensure that 'nextread' bytes (numrecs) are available. */
+    status = hdr_check_buffer(&getbuf, (getbuf.version == 5) ? 8 : 4);
+    if(status != NC_NOERR) goto fn_exit;
+
+    /* get numrecs from getbuf into ncp */
+    if (getbuf.version == 5) 
+        ncp->numrecs = get_uint8(&getbuf);
+    else
+        ncp->numrecs = get_uint4(&getbuf);
+
+    /* get dim_list from getbuf into ncp */
+    status = hdr_get_NC_dimarray(&getbuf, &ncp->dims);
+    if (status != NC_NOERR) goto fn_exit;
+
+    /* get gatt_list from getbuf into ncp */
+    status = hdr_get_NC_attrarray(&getbuf, &ncp->attrs);
+    if (status != NC_NOERR) goto fn_exit;
+
+    /* get var_list from getbuf into ncp */
+    status = hdr_get_NC_vararray(&getbuf, &ncp->vars);
+    if (status != NC_NOERR) goto fn_exit;
+
+    /* get the un-aligned size occupied by the file header */
+    ncp->xsz = ncmpii_hdr_len_NC(ncp);
+
+    /* Recompute the shapes of all variables
+     * Sets ncp->begin_var to start of first variable.
+     * Sets ncp->begin_rec to start of first record variable.
+     */
+    status = ncmpii_NC_computeshapes(ncp);
+
+    /* update the total number of record variables */
+    ncp->vars.num_rec_vars = 0;
+    for (i=0; i<ncp->vars.ndefined; i++)
+        ncp->vars.num_rec_vars += IS_RECVAR(ncp->vars.value[i]);
+
+fn_exit:
+    free(getbuf.base);
+    return status;
+}
+
+/*----< ncmpii_free_NC() >----------------------------------------------------*/
+static void
+ncmpii_free_NC(NC *ncp)
+{
+    if (ncp == NULL) return;
+    ncmpii_free_NC_dimarray(&ncp->dims);
+    ncmpii_free_NC_attrarray(&ncp->attrs);
+    ncmpii_free_NC_vararray(&ncp->vars);
+}
+
+const char *
+ncmpi_strerror(int err)
+{
+   switch(err)
+   {
+      case NC_NOERR:
+	 return "No error";
+      case NC_EINVAL:
+	 return "NetCDF: Invalid argument";
+      case NC_EBADDIM:
+	 return "NetCDF: Invalid dimension ID or name";
+      case NC_EUNLIMPOS:
+	 return "NetCDF: NC_UNLIMITED in the wrong index";
+      case NC_ENOTNC:
+	 return "NetCDF: Unknown file format";
+      case NC_EVARSIZE:
+	 return "NetCDF: One or more variable sizes violate format constraints";
+      default:
+         printf("Unknown error code %d\n",err);
+         return "Unknown error code";
+   }
+}
+
+const char *
+ncmpii_err_code_name(int err)
+{
+   switch(err)
+   {
+      case NC_NOERR:     return "NC_NOERR";
+      case NC_EINVAL:    return "NC_EINVAL";
+      case NC_EBADDIM:   return "NC_EBADDIM";
+      case NC_EUNLIMPOS: return "NC_EUNLIMPOS";
+      case NC_ENOTNC:    return "NC_ENOTNC";
+      case NC_EVARSIZE : return "NC_EVARSIZE";
+      default:
+         printf("Unknown error code %d\n",err);
+         return "Unknown error code";
+   }
+}
+
+struct fspec {
+    int nlvars;    /* Number of variables specified with -v
+                    * option on command line */
+    char** lvars;  /* list of variable names specified with -v
+                    * option on command line */
+    NC_var **varp;  /* [nlvars] */
+    int    *varids; /* [nlvars] */
+};
+
+static void
+make_lvars(char *optarg, struct fspec* fspecp)
+{
+    char *cp = optarg;
+    int nvars = 1;
+    char ** cpp;
+
+    /* compute number of variable names in comma-delimited list */
+    fspecp->nlvars = 1;
+    while (*cp++)
+        if (*cp == ',')
+            nvars++;
+
+    fspecp->lvars = (char **) malloc(nvars * sizeof(char*));
+    MALLOC_CHECK(fspecp->lvars)
+
+    cpp = fspecp->lvars;
+    /* copy variable names into list */
+    for (cp = strtok(optarg, ",");
+         cp != NULL;
+         cp = strtok((char *) NULL, ",")) {
+
+        *cpp = (char *) malloc(strlen(cp) + 1);
+        MALLOC_CHECK(*cpp)
+
+        strcpy(*cpp, cp);
+        cpp++;
+    }
+    fspecp->nlvars = nvars;
+    fspecp->varp = (NC_var**) malloc(nvars * sizeof(NC_var*));
+    MALLOC_CHECK(fspecp->varp)
+}
+
+static int
+check_gap_in_fixed_vars(NC *ncp)
+{
+    int i, j;
+    long long size, prev_end;
+    NC_var *varp, *prev;
+
+    /* check only fixed-size variables */
+    for (i=1; i<ncp->vars.ndefined; i++) {
+        varp = ncp->vars.value[i];
+
+        if (IS_RECVAR(varp)) continue;
+
+        /* calculate the size in bytes of this variable */
+        size = type_size(varp->type);
+        if (varp->ndims) size *= varp->dsizes[0];
+
+        /* search for the previous fixed-size variable */
+        prev = NULL;
+        for (j=i-1; j>=0; j--) {
+            if (!IS_RECVAR(ncp->vars.value[j])) {
+                prev = ncp->vars.value[j];
+                break;
+            }
+        }
+        if (prev == NULL) /* first defined fixed-size variable */
+            continue;
+
+        /* not the first fixed-size variable */
+        prev_end = prev->begin;
+        if (prev->ndims == 0)
+            prev_end += type_size(prev->type);
+        else
+            prev_end += type_size(prev->type) * prev->dsizes[0];
+
+        /* check the gap between the begin of this variable from the end of
+         * variable immediately before it */
+        if (varp->begin - prev_end) return 1;
+    }
+    return 0;
+}
+
+static void
+usage(char *cmd)
+{
+    char *help =
+"Usage: %s [-h] | [-x] | [-sgr] [-v var1[,...]] file\n"
+"       [-h]            Print help\n"
+"       [-v var1[,...]] Output for variable(s) <var1>,... only\n"
+"       [-s]            Output variable size. For record variables, output\n"
+"                       the size of one record only\n"
+"       [-g]            Output gap from the previous variable\n"
+"       [-r]            Output offsets for all records\n"
+"       [-x]            Check gaps in fixed-size variables, ouput 1 if gaps\n"
+"                       are found, 0 for otherwise.\n"
+"       file            Input netCDF file name\n"
+"*Parallel netCDF library version 1.7.0\n";
+    fprintf(stderr, help, cmd);
+}
+
+/*----< main() >-------------------------------------------------------------*/
+int main(int argc, char *argv[])
+{
+    extern int optind;
+    char *filename, cmd[256], *env_str;
+    int i, j, err, opt, nvars;
+    int print_var_size=0, print_gap=0, check_gap=0, print_all_rec=0;
+    NC *ncp;
+    struct fspec *fspecp=NULL;
+
+    fspecp = (struct fspec*) calloc(1, sizeof(struct fspec));
+    strcpy(cmd,argv[0]);
+
+    /* get command-line arguments */
+    while ((opt = getopt(argc, argv, "v:sghqxr")) != EOF) {
+        switch(opt) {
+            case 'v': make_lvars (optarg, fspecp);
+                      break;
+            case 's': print_var_size = 1;
+                      break;
+            case 'g': print_gap = 1;
+                      break;
+            case 'r': print_all_rec = 1;
+                      break;
+            case 'x': check_gap = 1;
+                      break;
+            case 'h':
+            default:  usage(cmd);
+                      free(fspecp);
+                      return 0;
+        }
+    }
+    argc -= optind;
+    argv += optind;
+    if (argc != 1) {
+        fprintf(stderr, "%s: missing file name\n", cmd);
+        usage(cmd);
+        if (fspecp->varp != NULL) free(fspecp->varp);
+        for (i=0; i<fspecp->nlvars; i++)
+            free(fspecp->lvars[i]);
+        if (fspecp->lvars != NULL) free(fspecp->lvars);
+        free(fspecp);
+        return 1;
+    }
+    filename = argv[0]; /* required argument */
+
+    verbose_debug = 0;
+    env_str = getenv("PNETCDF_VERBOSE_DEBUG_MODE");
+    if (env_str != NULL && *env_str != '0') verbose_debug = 1;
+
+    /* find Endianness of the running machine */
+    endianness = is_little_endian();
+
+    /* open file */
+    int fd = open(filename, O_RDONLY, 0666);
+    if (fd == -1) {
+        printf("Error: file open %s (%s)\n",filename,strerror(errno));
+        exit(1);
+    }
+
+    ncp = (NC*) calloc(1, sizeof(NC));
+    strcpy(ncp->path, filename);
+
+    /* read the header from file */
+    err = ncmpii_hdr_get_NC(fd, ncp);
+    if (err != NC_NOERR) {
+        fprintf(stderr,"Error: %s\n", ncmpii_err_code_name(err));
+        exit(1);
+    }
+
+    if (check_gap) {
+        int ret = check_gap_in_fixed_vars(ncp);
+        ncmpii_free_NC(ncp);
+        free(ncp);
+        close(fd);
+        printf("%d\n",ret);
+        return 0;
+    }
+
+    /* First check if all selected variables can be found in input file. */
+    if (fspecp->nlvars > 0) {
+        /* print a selected list of variables */
+        fspecp->varids = (int*) malloc(fspecp->nlvars * sizeof(int));
+        MALLOC_CHECK(fspecp->varids)
+        for (i=0; i<fspecp->nlvars; i++) {
+            for (j=0; j<ncp->vars.ndefined; j++) {
+                if (!strcmp(fspecp->lvars[i], ncp->vars.value[j]->name->cp)) {
+                    fspecp->varp[i] = ncp->vars.value[j];
+                    fspecp->varids[i] = j;
+                    break;
+                }
+            }
+            if (j == ncp->vars.ndefined) {
+                printf("Error: variable %s not found\n",fspecp->lvars[i]);
+                return 1;
+            }
+        }
+    }
+
+    /* print file name and format */
+    printf("netcdf %s {\n",filename);
+    printf("// file format: CDF-%d\n",ncp->flags);
+    printf("\n");
+
+    /* print file header size and extent */
+    printf("file header:\n");
+    printf("\tsize   = %lld bytes\n",ncp->xsz);
+    printf("\textent = %lld bytes\n",ncp->begin_var);
+    
+    /* print dimensions */
+    if (ncp->dims.ndefined > 0) printf("\ndimensions:\n");
+    for (i=0; i<ncp->dims.ndefined; i++) {
+        long long size;
+        size = ncp->dims.value[i]->size;
+        printf("\t%s = ",ncp->dims.value[i]->name->cp);
+        if (size == NC_UNLIMITED)
+            printf("UNLIMITED // (%lld currently)\n",ncp->numrecs);
+        else
+            printf("%lld\n",size);
+    }
+
+    if (fspecp->nlvars == 0) { /* print all variables */
+        fspecp = (struct fspec*) malloc(sizeof(struct fspec));
+        MALLOC_CHECK(fspecp)
+        fspecp->varp = (NC_var**) malloc(ncp->vars.ndefined * sizeof(NC_var*));
+        MALLOC_CHECK(fspecp->varp)
+        fspecp->varids = (int*) malloc(ncp->vars.ndefined * sizeof(int));
+        MALLOC_CHECK(fspecp->varids)
+        fspecp->nlvars = ncp->vars.ndefined;
+        fspecp->lvars = NULL;
+        for (i=0; i<ncp->vars.ndefined; i++) {
+            fspecp->varp[i] = ncp->vars.value[i];
+            fspecp->varids[i] = i;
+        }
+    }
+
+    /* find how many variables are record variables */
+    int num_rec_vars = 0;
+    int num_fix_vars = 0;
+    for (i=0; i<fspecp->nlvars; i++) {
+        if (IS_RECVAR(fspecp->varp[i])) num_rec_vars++;
+        else                            num_fix_vars++;
+    }
+
+    int last_fix_varid = -1;
+    for (i=0; i<ncp->vars.ndefined; i++) {
+        if (IS_RECVAR(ncp->vars.value[i])) continue;
+        last_fix_varid = i;
+    }
+
+    int first_rec_varid = -1;
+    for (i=0; i<ncp->vars.ndefined; i++) {
+        if (IS_RECVAR(ncp->vars.value[i])) {
+            first_rec_varid = i;
+            break;
+        }
+    }
+
+    /* print fixed-size variables first */
+    if (num_fix_vars) printf("\nfixed-size variables:\n");
+    for (i=0; i<fspecp->nlvars; i++) {
+        int j, ndims;
+        char type_str[16], str[1024], line[1024];
+        long long size;
+        NC_var *varp = fspecp->varp[i];
+
+        if (IS_RECVAR(varp)) continue;
+
+        /* calculate the size in bytes of this variable */
+        size = type_size(varp->type);
+        if (varp->ndims) size *= varp->dsizes[0];
+
+        line[0]='\0';
+        sprintf(type_str,"%-6s", type_name(varp->type));
+        sprintf(line,"%s", varp->name->cp);
+        ndims = varp->ndims;
+        if (ndims > 0) strcat(line,"(");
+        for (j=0; j<ndims; j++) {
+            NC_dim *dimp = ncp->dims.value[varp->dimids[j]];
+            if (dimp->size == NC_UNLIMITED)
+                size *= ncp->numrecs;
+            sprintf(str, "%s%s", dimp->name->cp, j < ndims-1 ? ", " : ")");
+            strcat(line, str);
+        }
+
+        /* print the data type, variable name, and its dimensions */
+        printf("\t%6s %s:\n", type_str, line);
+
+        /* print the starting and ending file offset of this variable */
+        printf("\t       start file offset =%12lld\n", varp->begin);
+        printf("\t       end   file offset =%12lld\n", varp->begin+size);
+
+        /* print variable size in bytes */
+        if (print_var_size)
+            printf("\t       size in bytes     =%12lld\n", size);
+
+        /* print the gap between the begin of this variable from the end of
+         * variable immediately before it */
+        if (print_gap) {
+            NC_var *prev=NULL;
+            for (j=fspecp->varids[i]-1; j>=0; j--) {
+                /* search for the previous fixed-size variable */
+                if (!IS_RECVAR(ncp->vars.value[j])) {
+                    prev = ncp->vars.value[j];
+                    break;
+                }
+            }
+            if (fspecp->varids[i] == 0 || prev == NULL) {
+                /* first defined fixed-size variable */
+                printf("\t       gap from prev var =%12lld\n",
+                       varp->begin - ncp->xsz);
+            }
+            else {
+                /* not the first fixed-size variable */
+                long long prev_end = prev->begin;
+                if (prev->ndims == 0)
+                    prev_end += type_size(prev->type);
+                else
+                    prev_end += type_size(prev->type) * prev->dsizes[0];
+                printf("\t       gap from prev var =%12lld\n",
+                       varp->begin - prev_end);
+            }
+        }
+    }
+
+    /* print record variables */
+    if (num_rec_vars) printf("\nrecord variables:\n");
+    for (i=0; i<fspecp->nlvars; i++) {
+        int j, ndims;
+        char type_str[16], str[1024], line[1024];
+        long long var_begin, var_end, size, numrecs;
+        NC_var *varp = fspecp->varp[i];
+
+        if (!IS_RECVAR(varp)) continue;
+
+        /* calculate the size in bytes of this variable */
+        size = type_size(varp->type);
+        if (varp->ndims) size *= varp->dsizes[0];
+
+        line[0]='\0';
+        sprintf(type_str,"%-6s", type_name(varp->type));
+        sprintf(line,"%s", varp->name->cp);
+        ndims = varp->ndims;
+        if (ndims > 0) strcat(line,"(");
+        for (j=0; j<ndims; j++) {
+            NC_dim *dimp = ncp->dims.value[varp->dimids[j]];
+            sprintf(str, "%s%s", dimp->name->cp, j < ndims-1 ? ", " : ")");
+            strcat(line, str);
+        }
+
+        /* print the data type, variable name, and its dimensions */
+        printf("\t%6s %s:\n", type_str, line);
+
+        /* print the starting and ending file offset of this variable */
+        numrecs = ncp->numrecs;
+        var_begin = varp->begin;
+        var_end   = varp->begin + size;
+        if (print_all_rec == 0) numrecs = 1;
+        for (j=0; j<numrecs; j++) {
+            char rec_num[32];
+                 if (j % 10 == 1) sprintf(rec_num, "%dst", j);
+            else if (j % 10 == 2) sprintf(rec_num, "%dnd", j);
+            else if (j % 10 == 3) sprintf(rec_num, "%drd", j);
+            else                  sprintf(rec_num, "%dth", j);
+            printf("\t       start file offset =%12lld    (%s record)\n", var_begin,rec_num);
+            printf("\t       end   file offset =%12lld    (%s record)\n", var_end,rec_num);
+            var_begin += ncp->recsize;
+            var_end   += ncp->recsize;
+        }
+
+        /* print variable size in bytes (one record only)
+         *   size *= ncp->numrecs;   (if for all records)
+         */
+        if (print_var_size)
+            printf("\t       size in bytes     =%12lld    (of one record)\n", size);
+
+        /* print the gap between the begin of this variable from the end of
+         * variable immediately before it */
+        if (print_gap) {
+            NC_var *prev=NULL;
+            long long prev_end;
+            for (j=fspecp->varids[i]-1; j>=0; j--) {
+                /* search for the previous record variable */
+                if (IS_RECVAR(ncp->vars.value[j])) {
+                    prev = ncp->vars.value[j];
+                    break;
+                }
+            }
+            if (fspecp->varids[i] == 0 && last_fix_varid == -1) {
+                /* first record variable and no fixed-size variable */
+                printf("\t       gap from prev var =%12lld\n",
+                       varp->begin - ncp->xsz);
+            }
+            else if (fspecp->varids[i] == first_rec_varid) {
+                /* first record variable and there are fixed-size variables */
+                prev = ncp->vars.value[last_fix_varid];
+                prev_end = prev->begin;
+                if (prev->ndims == 0)
+                    prev_end += type_size(prev->type);
+                else
+                    prev_end += type_size(prev->type) * prev->dsizes[0];
+                printf("\t       gap from prev var =%12lld\n",
+                       varp->begin - prev_end);
+            }
+            else {
+                /* not the first record variable */
+                prev_end = prev->begin;
+                if (prev->ndims == 0)
+                    prev_end += type_size(prev->type);
+                else
+                    prev_end += type_size(prev->type) * prev->dsizes[0];
+                printf("\t       gap from prev var =%12lld\n",
+                       varp->begin - prev_end);
+            }
+        }
+    }
+    printf("}\n");
+
+    free(fspecp->varp);
+    if (fspecp->lvars != NULL) {
+        for (i=0; i<fspecp->nlvars; i++)
+            free(fspecp->lvars[i]);
+        free(fspecp->lvars);
+    }
+    free(fspecp->varids);
+    free(fspecp);
+    ncmpii_free_NC(ncp);
+    free(ncp);
+    close(fd);
+
+    return 0;
+}
+
diff --git a/src/utils/pnetcdf_version/Makefile.in b/src/utils/pnetcdf_version/Makefile.in
new file mode 100644
index 0000000..1d6e216
--- /dev/null
+++ b/src/utils/pnetcdf_version/Makefile.in
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2264 2015-12-22 15:42:59Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include ../../../macros.make
+
+DEFS  = -DMPICC="\"$(MPICC)\""   -DCFLAGS="\"$(CFLAGS)\""
+DEFS += -DCONFIGURE_ARGS_CLEAN="\"@CONFIGURE_ARGS_CLEAN@\""
+DEFS += -DPNETCDF_VERSION="\"@PNETCDF_VERSION@\""
+DEFS += -DPNETCDF_RELEASE_DATE="\"@PNETCDF_RELEASE_DATE@\""
+
+ifeq (@has_mpicxx@, yes)
+DEFS += -DMPICXX="\"$(MPICXX)\"" -DCXXFLAGS="\"$(CXXFLAGS)\""
+endif
+
+ifeq (@has_fortran@, yes)
+DEFS += -DMPIF77="\"$(MPIF77)\"" -DF77FLAGS="\"$(F77FLAGS)\""
+DEFS += -DMPIF90="\"$(MPIF90)\"" -DF90FLAGS="\"$(F90FLAGS)\""
+endif
+
+C_SOURCES	= pnetcdf_version.c
+
+PROGRAM		= pnetcdf_version
+MANUAL		= pnetcdf_version.1
+
+PACKING_LIST    = $(C_SOURCES) $(MANUAL) \
+                  Makefile.in depend
+
+GARBAGE		= $(PROGRAM)
+
+all: $(PROGRAM)
+
+pnetcdf_version: pnetcdf_version.c
+	$(SEQ_CC) $(DEFS) -o $@ $<
+
+install: $(PROGRAM) $(MANUAL)
+	$(INSTALL) -d -m 755 $(MANDIR)/man1
+	$(INSTALL_DATA) $(srcdir)/$(MANUAL) $(MANDIR)/man1/$(MANUAL)
+	$(INSTALL) -d $(BINDIR)
+	$(INSTALL) -m 755 $(PROGRAM) $(BINDIR)/$(PROGRAM)
+
+uninstall:
+	$(RM) -f $(BINDIR)/$(PROGRAM)
+	$(RM) -f $(MANDIR)/man1/$(MANUAL)
+
+include $(srcdir)/../../../rules.make
+include $(srcdir)/depend
+
+.PHONY: $(LIBRARY)
diff --git a/src/utils/pnetcdf_version/depend b/src/utils/pnetcdf_version/depend
new file mode 100644
index 0000000..568a29a
--- /dev/null
+++ b/src/utils/pnetcdf_version/depend
@@ -0,0 +1 @@
+pnetcdf_version.o: pnetcdf_version.c
diff --git a/src/utils/pnetcdf_version/pnetcdf_version.1 b/src/utils/pnetcdf_version/pnetcdf_version.1
new file mode 100644
index 0000000..35463d9
--- /dev/null
+++ b/src/utils/pnetcdf_version/pnetcdf_version.1
@@ -0,0 +1,61 @@
+.\" $Header$
+.nr yr \n(yr+1900
+.af mo 01
+.af dy 01
+.TH PNETCDF_VERSION 1 2014-04-15 "Printed: \n(yr-\n(mo-\n(dy" "UTILITIES"
+.SH NAME
+pnetcdf_version \- print the version information of PnetCDF library
+.SH SYNOPSIS
+.ft B
+.HP
+pnetcdf_version
+.nh
+
+\%[-v]
+\%[-d]
+\%[-c]
+\%[-b]
+\%[-h]
+.hy
+.ft
+.SH DESCRIPTION
+\fBpnetcdf_version\fP prints the version information of PnetCDF library and
+the configure command line used to build the library
+
+If no argument is given, all information is printed.
+.SH OPTIONS
+.IP "\fB-v\fP"
+Version number of this PnetCDF release.
+.IP "\fB-d\fP"
+Release date.
+.IP "\fB-c\fP"
+Configure command-line arguments used to build this PnetCDF
+.IP "\fB-b\fP"
+MPI compilers used to build this PnetCDF library
+.IP "\fB-h\fP"
+Print the available command-line options of pnetcdf_version
+
+.SH EXAMPLES
+.LP
+Print all information about the PnetCDF library by running the command with no options.
+
+% pnetcdf_version
+.sp
+.nf
+PnetCDF Version:    	1.4.2.pre1
+PnetCDF Release date:	15 Apr 2014
+PnetCDF configure: 	--with-mpi=/usr/local/bin
+MPICC:  /usr/local/bin/mpicc -g -O2
+MPICXX: /usr/local/bin/mpicxx -g -O2
+MPIF77: /usr/local/bin/mpif77 -g -O2
+MPIF90: /usr/local/bin/mpif90 -g -O2
+.fi
+
+.SH "SEE ALSO"
+.LP
+.BR pnetcdf (3)
+.SH DATE
+$Date: 2014-07-11 13:07:40 -0500 (Fri, 11 Jul 2014) $
+.LP
+
+
diff --git a/src/utils/pnetcdf_version/pnetcdf_version.c b/src/utils/pnetcdf_version/pnetcdf_version.c
new file mode 100644
index 0000000..bfae58b
--- /dev/null
+++ b/src/utils/pnetcdf_version/pnetcdf_version.c
@@ -0,0 +1,107 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: pnetcdf_version.c 2264 2015-12-22 15:42:59Z wkliao $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h> /* getopt */
+
+typedef enum {
+    Version_number = 0,
+    Date           = 1, 
+    Patches        = 2,
+    Configure_args = 3,
+    Compilers      = 4,
+    LastField
+} fields;
+
+/*
+ *   pnetcdf_version - Report on the PnetCDF version
+ */
+
+/*---< usage() >-------------------------------------------------------------*/
+static void usage(char *argv0) {
+    char *help =
+        "Usage: %s [switches]\n"
+        "       -v  : version number\n"
+        "       -d  : release date\n"
+        "       -c  : configure arguments used to build PnetCDF\n"
+        "       -b  : MPI compilers used\n"
+        "       -h  : print this help (available command-line options)\n";
+    fprintf(stderr, help, argv0);
+    exit(-1);
+}
+
+/*----< main() >-------------------------------------------------------------*/
+int main( int argc, char *argv[] )
+{
+           int     opt;
+
+    int i, flags[10];
+
+    if (argc <= 1) {
+        /* Show all values */
+        for (i=0; i<LastField; i++) flags[i] = 1;
+    }
+    else {
+        /* Show only requested values */
+        for (i=0; i<LastField; i++) flags[i] = 0;
+    }
+
+    while ( (opt=getopt(argc,argv,"vdcbh"))!= EOF) {
+        switch (opt) {
+            case 'v': flags[Version_number] = 1;
+                      break;
+            case 'd': flags[Date] = 1;
+                      break;
+            case 'c': flags[Configure_args] = 1;
+                      break;
+            case 'b': flags[Compilers] = 1;
+                      break;
+            case 'h':
+            default: usage(argv[0]);
+                      break;
+        }
+    }
+
+    /* Print out the information, one item per line */
+    if (flags[Version_number]) {
+        printf( "PnetCDF Version:    \t%s\n", PNETCDF_VERSION);
+    }
+    if (flags[Date]) {
+        printf( "PnetCDF Release date:\t%s\n", PNETCDF_RELEASE_DATE);
+    }
+    if (flags[Configure_args]) {
+        printf( "PnetCDF configure: \t%s\n", CONFIGURE_ARGS_CLEAN);
+    }
+    if (flags[Compilers]) {
+        if (strcmp(CFLAGS, ""))
+            printf( "MPICC:  %s %s\n", MPICC, CFLAGS);
+        else
+            printf( "MPICC:  %s\n", MPICC);
+#ifdef MPICXX
+        if (strcmp(CXXFLAGS, ""))
+            printf( "MPICXX: %s %s\n", MPICXX, CXXFLAGS);
+        else
+            printf( "MPICXX: %s\n", MPICXX);
+#endif
+#ifdef MPIF77
+        if (strcmp(F77FLAGS, ""))
+            printf( "MPIF77: %s %s\n", MPIF77, F77FLAGS);
+        else
+            printf( "MPIF77: %s\n", MPIF77);
+#endif
+#ifdef MPIF90
+        if (strcmp(F90FLAGS, ""))
+            printf( "MPIF90: %s %s\n", MPIF90, F90FLAGS);
+        else
+            printf( "MPIF90: %s\n", MPIF90);
+#endif
+    }
+
+    return 0;
+}
+
diff --git a/stamp-h.in b/stamp-h.in
new file mode 100644
index 0000000..9788f70
--- /dev/null
+++ b/stamp-h.in
@@ -0,0 +1 @@
+timestamp
diff --git a/test/C/Makefile.in b/test/C/Makefile.in
new file mode 100644
index 0000000..3501c82
--- /dev/null
+++ b/test/C/Makefile.in
@@ -0,0 +1,76 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2259 2015-12-22 04:51:01Z wkliao $
+#
+# @configure_input@
+
+srcdir	= @srcdir@
+VPATH	= @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I../../src/lib -I$(srcdir)/../common
+LDFLAGS  := $(LDFLAGS) -L../common
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
+ifeq (@PNC_DEBUG@, yes)
+CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
+endif
+
+SRCS    = pres_temp_4D_wr.c \
+          pres_temp_4D_rd.c
+
+OBJS    = $(SRCS:.c=.o)
+PROGS   = $(SRCS:.c=)
+
+GARBAGE      = $(PROGS) *.nc
+PACKING_LIST = $(SRCS) Makefile.in
+
+all: $(PROGS)
+
+$(OBJS): $(srcdir)/../common/testutils.h 
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+pres_temp_4D_wr.o: pres_temp_4D_wr.c 
+
+pres_temp_4D_wr: pres_temp_4D_wr.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+pres_temp_4D_rd.o: pres_temp_4D_rd.c 
+
+pres_temp_4D_rd: pres_temp_4D_rd.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+check testing verbose_testing: $(PROGS)
+	@for i in $(PROGS); do ( \
+	$(TEST_SEQRUN) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+TEST_MPIRUN_2  = $(subst NP,2,$(TEST_MPIRUN))
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+
+ptest2: $(PROGS)
+	@for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_2) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest4: $(PROGS)
+	@for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_4) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest: ptest4
+
+ptests: ptest2 ptest4
+
+ptest6 ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+
+$(LIBRARY): ;
+
diff --git a/test/C/pres_temp_4D_rd.c b/test/C/pres_temp_4D_rd.c
new file mode 100644
index 0000000..315417f
--- /dev/null
+++ b/test/C/pres_temp_4D_rd.c
@@ -0,0 +1,205 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: pres_temp_4D_rd.c 2133 2015-09-26 19:16:01Z wkliao $ */
+
+/*
+   This is an example which reads some 4D pressure and
+   temperatures. The data file read by this program is produced by the
+   companion program pres_temp_4D_wr.c. It is intended to illustrate
+   the use of the netCDF C API.
+
+   This program is part of the netCDF tutorial:
+   http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-tutorial
+
+   Full documentation of the netCDF C API can be found at:
+   http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c
+
+   $Id: pres_temp_4D_rd.c 2133 2015-09-26 19:16:01Z wkliao $
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <pnetcdf.h>
+#include <mpi.h>
+#include <testutils.h>
+
+/* This is the name of the data file we will read. */
+#define FILE_NAME "pres_temp_4D.nc"
+
+/* We are reading 4D data, a 2 x 6 x 12 lvl-lat-lon grid, with 2
+   timesteps of data. */
+#define NDIMS 4
+#define NLAT 6
+#define NLON 12
+#define LAT_NAME "latitude"
+#define LON_NAME "longitude"
+#define NREC 2
+#define REC_NAME "time"
+#define LVL_NAME "level"
+#define NLVL 4
+
+/* Names of things. */
+#define PRES_NAME "pressure"
+#define TEMP_NAME "temperature"
+#define UNITS "units"
+#define DEGREES_EAST "degrees_east"
+#define DEGREES_NORTH "degrees_north"
+
+/* These are used to calculate the values we expect to find. */
+#define SAMPLE_PRESSURE 900
+#define SAMPLE_TEMP 9.0
+#define START_LAT 25.0
+#define START_LON -125.0
+
+/* For the units attributes. */
+#define UNITS "units"
+#define PRES_UNITS "hPa"
+#define TEMP_UNITS "celsius"
+#define LAT_UNITS "degrees_north"
+#define LON_UNITS "degrees_east"
+#define MAX_ATT_LEN 80
+
+/* Handle errors by printing an error message and exiting with a
+ * non-zero status. */
+#define CHECK_ERR { \
+    if (err != NC_NOERR) { \
+        nerrs++; \
+        printf("Error: %s a5 line %d (%s)\n", __FILE__,__LINE__,ncmpi_strerror(err)); } }
+
+
+int
+main(int argc, char **argv)
+{
+   int rank, nprocs, ncid, pres_varid, temp_varid;
+   int lat_varid, lon_varid;
+
+   /* The start and count arrays will tell the netCDF library where to
+      read our data. */
+   MPI_Offset start[NDIMS], count[NDIMS];
+
+   /* Program variables to hold the data we will read. We will only
+      need enough space to hold one timestep of data; one record. */
+   float pres_in[NLVL][NLAT][NLON];
+   float temp_in[NLVL][NLAT][NLON];
+
+   /* These program variables hold the latitudes and longitudes. */
+   float lats[NLAT], lons[NLON];
+
+   /* Loop indexes. */
+   int lvl, lat, lon, rec, i = 0;
+   
+   /* Error handling. */
+   int err, nerrs=0;
+
+   char *filename = FILE_NAME;
+
+   MPI_Init(&argc, &argv);
+   MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+   if (argc > 2) {
+       if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+       MPI_Finalize();
+       return 0;
+   }
+   if (argc == 2) filename = argv[1];
+
+   if (rank == 0) {
+       char cmd_str[256];
+       sprintf(cmd_str, "*** TESTING C   %s for reading file", argv[0]);
+       printf("%-66s ------ ", cmd_str);
+   }
+
+   /* Open the file. */
+   err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid);
+   CHECK_ERR
+
+   /* Get the varids of the latitude and longitude coordinate
+    * variables. */
+   err = ncmpi_inq_varid(ncid, LAT_NAME, &lat_varid);
+   CHECK_ERR
+   err = ncmpi_inq_varid(ncid, LON_NAME, &lon_varid);
+   CHECK_ERR
+
+   /* Read the coordinate variable data. */
+   err = ncmpi_get_var_float_all(ncid, lat_varid, &lats[0]);
+   CHECK_ERR
+   err = ncmpi_get_var_float_all(ncid, lon_varid, &lons[0]);
+   CHECK_ERR
+
+   /* Check the coordinate variable data. */
+   for (lat = 0; lat < NLAT; lat++)
+      if (lats[lat] != START_LAT + 5.*lat)
+	 return 2;
+   for (lon = 0; lon < NLON; lon++)
+      if (lons[lon] != START_LON + 5.*lon)
+	 return 2;
+
+   /* Get the varids of the pressure and temperature netCDF
+    * variables. */
+   err = ncmpi_inq_varid(ncid, PRES_NAME, &pres_varid);
+   CHECK_ERR
+   err = ncmpi_inq_varid(ncid, TEMP_NAME, &temp_varid);
+   CHECK_ERR
+
+   /* Read the data. Since we know the contents of the file we know
+    * that the data arrays in this program are the correct size to
+    * hold one timestep. */
+   count[0] = 1;
+   count[1] = NLVL/nprocs;
+   count[2] = NLAT;
+   count[3] = NLON;
+   start[1] = 0;
+   start[2] = 0;
+   start[3] = 0;
+
+   /* Read and check one record at a time. */
+   for (rec = 0; rec < NREC; rec++)
+   {
+      start[0] = rec;
+      err = ncmpi_get_vara_float_all(ncid, pres_varid, start, 
+				      count, &pres_in[0][0][0]);
+      CHECK_ERR
+      err = ncmpi_get_vara_float_all(ncid, temp_varid, start,
+				      count, &temp_in[0][0][0]);
+      CHECK_ERR
+
+      /* Check the data. */
+      i = 0;
+      for (lvl = 0; lvl < NLVL/nprocs; lvl++)
+	 for (lat = 0; lat < NLAT; lat++)
+	    for (lon = 0; lon < NLON; lon++)
+	    {
+	       if (pres_in[lvl][lat][lon] != SAMPLE_PRESSURE + i) 
+		  return 2;
+	       if (temp_in[lvl][lat][lon] != SAMPLE_TEMP + i) 
+		  return 2;
+	       i++;
+	    }
+
+   } /* next record */
+
+   /* Close the file. */
+   err = ncmpi_close(ncid);
+   CHECK_ERR
+
+    /* check if there is any malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+   MPI_Finalize();
+   return 0;
+}
diff --git a/test/C/pres_temp_4D_wr.c b/test/C/pres_temp_4D_wr.c
new file mode 100644
index 0000000..325692a
--- /dev/null
+++ b/test/C/pres_temp_4D_wr.c
@@ -0,0 +1,262 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: pres_temp_4D_wr.c 2133 2015-09-26 19:16:01Z wkliao $ */
+
+
+/*
+   This is an example program which writes some 4D pressure and
+   temperatures. It is intended to illustrate the use of the netCDF
+   C API. The companion program pres_temp_4D_rd.c shows how
+   to read the netCDF data file created by this program.
+   
+   This program is part of the netCDF tutorial:
+   http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-tutorial
+   
+   Full documentation of the netCDF C API can be found at:
+   http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c
+
+   $Id: pres_temp_4D_wr.c 2133 2015-09-26 19:16:01Z wkliao $
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <pnetcdf.h>
+#include <mpi.h>
+#include <testutils.h>
+
+/* This is the name of the data file we will create. */
+#define FILE_NAME "pres_temp_4D.nc"
+
+/* We are writing 4D data, a 2 x 6 x 12 lvl-lat-lon grid, with 2
+   timesteps of data. */
+#define NDIMS 4
+#define NLAT 6
+#define NLON 12
+#define LAT_NAME "latitude"
+#define LON_NAME "longitude"
+#define NREC 2
+#define REC_NAME "time"
+#define LVL_NAME "level"
+#define NLVL 4
+
+/* Names of things. */
+#define PRES_NAME "pressure"
+#define TEMP_NAME "temperature"
+#define UNITS "units"
+#define DEGREES_EAST "degrees_east"
+#define DEGREES_NORTH "degrees_north"
+
+/* These are used to construct some example data. */
+#define SAMPLE_PRESSURE 900
+#define SAMPLE_TEMP 9.0
+#define START_LAT 25.0
+#define START_LON -125.0
+
+/* For the units attributes. */
+#define UNITS "units"
+#define PRES_UNITS "hPa"
+#define TEMP_UNITS "celsius"
+#define LAT_UNITS "degrees_north"
+#define LON_UNITS "degrees_east"
+#define MAX_ATT_LEN 80
+
+/* Handle errors by printing an error message and exiting with a
+ * non-zero status. */
+#define ERR(e) {printf("Error: %s\n", nc_strerror(e)); return 2;}
+
+#define CHECK_ERR { \
+    if (err != NC_NOERR) { \
+        nerrs++; \
+        printf("Error: %s at line %d: %s\n", __FILE__,__LINE__,ncmpi_strerror(err)); \
+    } \
+}
+
+
+int
+main(int argc, char ** argv)
+{
+   /* IDs for the netCDF file, dimensions, and variables. */
+   int nprocs, rank, nerrs=0;
+   int ncid;
+   int lon_dimid, lat_dimid, lvl_dimid, rec_dimid;
+   int lat_varid, lon_varid, pres_varid, temp_varid;
+   int dimids[NDIMS];
+
+   /* The start and count arrays will tell the netCDF library where to
+      write our data. */
+   MPI_Offset start[NDIMS], count[NDIMS];
+
+   /* Program variables to hold the data we will write out. We will only
+      need enough space to hold one timestep of data; one record. */
+   float pres_out[NLVL][NLAT][NLON];
+   float temp_out[NLVL][NLAT][NLON];
+
+   /* These program variables hold the latitudes and longitudes. */
+   float lats[NLAT], lons[NLON];
+
+   /* Loop indexes. */
+   int lvl, lat, lon, rec, i = 0;
+   
+   /* Error handling. */
+   int err;
+
+   char *filename=FILE_NAME;
+
+   MPI_Init(&argc, &argv);
+   MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+   if (argc > 2) {
+       if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+       MPI_Finalize();
+       return 0;
+   }
+   if (argc == 2) filename = argv[1];
+
+   if (rank == 0) {
+       char cmd_str[256];
+       sprintf(cmd_str, "*** TESTING C   %s for writing file", argv[0]);
+       printf("%-66s ------ ", cmd_str);
+   }
+
+   /* Create some pretend data. If this wasn't an example program, we
+    * would have some real data to write, for example, model
+    * output. */
+   for (lat = 0; lat < NLAT; lat++)
+      lats[lat] = START_LAT + 5.*lat;
+   for (lon = 0; lon < NLON; lon++)
+      lons[lon] = START_LON + 5.*lon;
+   
+   for (lvl = 0; lvl < NLVL; lvl++)
+      for (lat = 0; lat < NLAT; lat++)
+	 for (lon = 0; lon < NLON; lon++)
+	 {
+	    pres_out[lvl][lat][lon] = SAMPLE_PRESSURE + i;
+	    temp_out[lvl][lat][lon] = SAMPLE_TEMP + i++;
+	 }
+
+   /* Create the file. */
+   err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, MPI_INFO_NULL, &ncid);
+
+   CHECK_ERR
+
+   /* Define the dimensions. The record dimension is defined to have
+    * unlimited length - it can grow as needed. In this example it is
+    * the time dimension.*/
+   err = ncmpi_def_dim(ncid, LVL_NAME, NLVL, &lvl_dimid);
+   CHECK_ERR
+   err = ncmpi_def_dim(ncid, LAT_NAME, NLAT, &lat_dimid);
+   CHECK_ERR
+   err = ncmpi_def_dim(ncid, LON_NAME, NLON, &lon_dimid);
+   CHECK_ERR
+   err = ncmpi_def_dim(ncid, REC_NAME, NC_UNLIMITED, &rec_dimid);
+   CHECK_ERR
+
+   /* Define the coordinate variables. We will only define coordinate
+      variables for lat and lon.  Ordinarily we would need to provide
+      an array of dimension IDs for each variable's dimensions, but
+      since coordinate variables only have one dimension, we can
+      simply provide the address of that dimension ID (&lat_dimid) and
+      similarly for (&lon_dimid). */
+   err = ncmpi_def_var(ncid, LAT_NAME, NC_FLOAT, 1, &lat_dimid, &lat_varid);
+   CHECK_ERR
+   err = ncmpi_def_var(ncid, LON_NAME, NC_FLOAT, 1, &lon_dimid, &lon_varid);
+   CHECK_ERR
+
+   /* Assign units attributes to coordinate variables. */
+   err = ncmpi_put_att_text(ncid, lat_varid, UNITS, 
+				 strlen(DEGREES_NORTH), DEGREES_NORTH);
+   CHECK_ERR
+   err = ncmpi_put_att_text(ncid, lon_varid, UNITS, 
+				 strlen(DEGREES_EAST), DEGREES_EAST);
+   CHECK_ERR
+
+   /* The dimids array is used to pass the dimids of the dimensions of
+      the netCDF variables. Both of the netCDF variables we are
+      creating share the same four dimensions. In C, the
+      unlimited dimension must come first on the list of dimids. */
+   dimids[0] = rec_dimid;
+   dimids[1] = lvl_dimid;
+   dimids[2] = lat_dimid;
+   dimids[3] = lon_dimid;
+
+   /* Define the netCDF variables for the pressure and temperature
+    * data. */
+   err = ncmpi_def_var(ncid, PRES_NAME, NC_FLOAT, NDIMS, dimids, &pres_varid);
+   CHECK_ERR
+   err = ncmpi_def_var(ncid, TEMP_NAME, NC_FLOAT, NDIMS, dimids, &temp_varid);
+   CHECK_ERR
+
+   /* Assign units attributes to the netCDF variables. */
+   err = ncmpi_put_att_text(ncid, pres_varid, UNITS, 
+				 strlen(PRES_UNITS), PRES_UNITS);
+   CHECK_ERR
+   err = ncmpi_put_att_text(ncid, temp_varid, UNITS, 
+				 strlen(TEMP_UNITS), TEMP_UNITS);
+   CHECK_ERR
+
+   /* End define mode. */
+   err = ncmpi_enddef(ncid);
+   CHECK_ERR
+
+   err = ncmpi_begin_indep_data(ncid);
+   /* Write the coordinate variable data. This will put the latitudes
+      and longitudes of our data grid into the netCDF file. */
+   err = ncmpi_put_var_float(ncid, lat_varid, &lats[0]);
+   CHECK_ERR
+   err = ncmpi_put_var_float(ncid, lon_varid, &lons[0]);
+   CHECK_ERR
+   err = ncmpi_end_indep_data(ncid);
+   CHECK_ERR
+
+   /* These settings tell netcdf to write one timestep of data. (The
+     setting of start[0] inside the loop below tells netCDF which
+                    &data[0][0][0]);
+     timestep to write.) */
+   count[0] = 1;
+   count[1] = NLVL/nprocs;
+   count[2] = NLAT;
+   count[3] = NLON;
+   start[1] = 0;
+   start[2] = 0;
+   start[3] = 0;
+
+   /* Write the pretend data. This will write our surface pressure and
+      surface temperature data. The arrays only hold one timestep worth
+      of data. We will just rewrite the same data for each timestep. In
+      a real application, the data would change between timesteps. */
+
+   for (rec = 0; rec < NREC; rec++)
+   {
+      start[0] = rec;
+      err = ncmpi_put_vara_float_all(ncid, pres_varid, start, count, &pres_out[0][0][0]);
+      CHECK_ERR
+      err = ncmpi_put_vara_float_all(ncid, temp_varid, start, count, &temp_out[0][0][0]);
+      CHECK_ERR
+   }
+
+   /* Close the file. */
+   err = ncmpi_close(ncid);
+   CHECK_ERR
+   
+    /* check if there is any malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+
+    return 0;
+}
diff --git a/test/CXX/Makefile.in b/test/CXX/Makefile.in
new file mode 100644
index 0000000..beadd0e
--- /dev/null
+++ b/test/CXX/Makefile.in
@@ -0,0 +1,79 @@
+#
+# Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+#
+# @configure_input@
+
+srcdir	= @srcdir@
+VPATH	= @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I../../src/lib -I../../src/libcxx -I$(srcdir)/../common
+LDFLAGS  := $(LDFLAGS) -L../common
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
+ifeq (@PNC_DEBUG@, yes)
+CXXCPPFLAGS := $(CXXCPPFLAGS) -DPNC_DEBUG
+endif
+
+SRCS    = nctst.cpp \
+          test_classic.cpp
+
+OBJS    = $(SRCS:.cpp=.o)
+PROGS   = $(SRCS:.cpp=)
+
+GARBAGE      = $(PROGS) *.nc
+PACKING_LIST = $(SRCS) Makefile.in
+
+all: $(PROGS)
+
+$(OBJS): $(srcdir)/../common/testutils.h
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+nctst.o: nctst.cpp 
+
+nctst: nctst.o $(LIBRARY) $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+test_classic.o: test_classic.cpp 
+
+test_classic: test_classic.o $(LIBRARY)
+	$(LINK.cxx) $< $(LDFLAGS) $(LIBS)
+
+check testing verbose_testing: $(PROGS)
+	$(TEST_SEQRUN) ./nctst        $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./test_classic $(TEST_OUTDIR)/testfile.nc
+
+TEST_MPIRUN_2  = $(subst NP,2,$(TEST_MPIRUN))
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+TEST_MPIRUN_6  = $(subst NP,6,$(TEST_MPIRUN))
+
+ptest4: $(PROGS)
+	@for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_4) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest2: $(PROGS)
+	@for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_2) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest6: $(PROGS)
+	@for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_6) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest: ptest4
+ptests: ptest2 ptest4 ptest6
+ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+
+$(LIBRARY): ;
+
diff --git a/test/CXX/nctst.cpp b/test/CXX/nctst.cpp
new file mode 100644
index 0000000..1b9dcd7
--- /dev/null
+++ b/test/CXX/nctst.cpp
@@ -0,0 +1,560 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: nctst.cpp 2208 2015-11-29 00:52:26Z wkliao $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <iostream>
+using namespace std;
+
+#include <string.h>
+#include <pnetcdf>
+#include <testutils.h>
+
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+const char LAT[] = "lat";
+const char LON[] = "lon";
+const char FRTIME[] = "frtime";
+const char TIMELEN1[] = "timelen";
+const char P_NAME[] = "P";
+const char PRES_MAX_WIND[] = "pressure at maximum wind";
+const char LONG_NAME[] = "long_name";
+const char UNITS[] = "units";
+const char VALID_RANGE[] = "valid_range";
+const char FILL_VALUE[] = "_FillValue";
+const char DEGREES_NORTH[] = "degrees_north";
+const char LONGITUDE[] = "longitude";
+const char LATITUDE[] = "latitude";
+const char HECTOPASCALS[] = "hectopascals";
+const char DEGREES_EAST[] = "degrees_east";
+const char HOURS[] = "hours";
+const char FORECAST_TIME[] = "forecast time";
+const char REFERENCE_TIME[] = "reference time";
+const char REFTIME[] = "reftime";
+const char TEXT_TIME[] = "text_time";
+const char SCALARV[] = "scalarv";
+const char SCALAR_ATT[] = "scalar_att";
+const int SCALAR_VALUE = 1;
+const char HISTORY[] = "history";
+const char TITLE[] = "title";
+const char HISTORY_STR[] = "created by Unidata LDM from NPS broadcast";
+const char TITLE_STR[] = "NMC Global Product Set: Pressure at Maximum Wind";
+
+const int NC_ERR = 2;
+const int NLATS = 4;
+const int NLONS = 3;
+const int NFRTIMES = 2;
+const int TIMESTRINGLEN = 20;
+const MPI_Offset NRANGES = 2;
+
+// These are data values written out by the gen() function, and read
+// in again and checked by the read() function.
+static float range[] = {0., 1500.};
+static float lats[NLATS] = {-90, -87.5, -85, -82.5};
+static float lons[NLONS] = {-180, -175, -170};
+static int frtimes[NFRTIMES] = {12, 18};
+static const char* s = "1992-3-21 12:00";
+static float fill_value = -9999.0;
+static float P_data[NFRTIMES][NLATS][NLONS] = {
+   {{950, 951, 952}, {953, 954, 955}, {956, 957, 958}, {959, 960, 961}},
+   {{962, 963, 964}, {965, 966, 967}, {968, 969, 970}, {971, 972, 973}}
+};
+
+
+// Check a string attribute to make sure it has the correct value.
+int 
+check_string_att(NcmpiAtt &att, const char *theName, const char *value)
+{
+   if (att.isNull() || att.getName().compare(theName) != 0 || 
+       att.getType() != ncmpiChar || att.getAttLength() != (long)strlen(value))
+      return NC_ERR;
+
+   char *value_in = (char*)malloc(strlen(value)+1);
+   att.getValues(value_in);
+   if (strncmp(value_in, value, strlen(value)))
+      return NC_ERR;
+   free(value_in);
+
+   return 0;
+}
+
+// Check the units and long_name attributes of a var to make sure they
+// are what is expected.
+int
+check_u_ln_atts(NcmpiVar &var, const char *units, const char *long_name)
+{
+   NcmpiVarAtt att = var.getAtt(UNITS);
+   if (check_string_att(att, UNITS, units))
+      return NC_ERR;
+
+   att = var.getAtt(LONG_NAME);
+   if (check_string_att(att, LONG_NAME, long_name))
+      return NC_ERR;
+
+   return 0;
+}
+
+// This reads the netCDF file created by gen() and ensures that
+// everything is there as expected.
+int read(const MPI_Comm        &comm,
+         const char            *path,
+         NcmpiFile::FileFormat  format)
+{
+    try {
+        // open the file
+        NcmpiFile nc(comm, path, NcmpiFile::read); 
+
+        // Check the format.
+        if (nc.getFormat() != format) {
+            cout << "unexpected file format"<<endl;
+            throw NcmpiException("read Error ",__FILE__,__LINE__);
+        }
+
+        // Check the number of dimensions.
+        int ndims = nc.getDimCount();
+        if (ndims != 4 && ndims != 6 && ndims != 2) {
+            cout << "nc.getDimCount()="<<ndims<<" != 2, 4, 6"<<endl;
+            throw NcmpiException("read Error ",__FILE__,__LINE__);
+        }
+
+        // Check the global attributes.
+        NcmpiGroupAtt att = nc.getAtt(HISTORY);
+        if (check_string_att(att, HISTORY, HISTORY_STR)) {
+            cout << "global attribute "<<HISTORY_STR<<" != "<<HISTORY<<endl;
+            throw NcmpiException("read Error ",__FILE__,__LINE__);
+        }
+
+        att = nc.getAtt(TITLE);
+        if (check_string_att(att, TITLE, TITLE_STR)) {
+            cout << "global attribute "<<TITLE_STR<<" != "<<TITLE<<endl;
+            throw NcmpiException("read Error ",__FILE__,__LINE__);
+        }
+   
+        // Check the dimensions.
+        NcmpiDim latDim = nc.getDim(LAT);
+        if (latDim.isNull() || latDim.getName().compare(LAT) != 0 || 
+            latDim.getSize() != NLATS || latDim.isUnlimited())
+            throw NcmpiException("read Error: dimension lat ",__FILE__,__LINE__);
+
+        NcmpiDim lonDim = nc.getDim(LON);
+        if (lonDim.isNull() || lonDim.getName().compare(LON) != 0 || 
+            lonDim.getSize() != NLONS || lonDim.isUnlimited())
+            throw NcmpiException("read Error: dimension lon ",__FILE__,__LINE__);
+
+        NcmpiDim frtimeDim = nc.getDim(FRTIME);
+        if (frtimeDim.isNull() || frtimeDim.getName().compare(FRTIME) != 0 || 
+            frtimeDim.getSize() != NFRTIMES || !frtimeDim.isUnlimited())
+            throw NcmpiException("read Error: unlimited dimension frtime ",__FILE__,__LINE__);
+
+        NcmpiDim timeLenDim = nc.getDim(TIMELEN1);
+        if (timeLenDim.isNull() || timeLenDim.getName().compare(TIMELEN1) != 0 || 
+            timeLenDim.getSize() != TIMESTRINGLEN || timeLenDim.isUnlimited())
+            throw NcmpiException("read Error: dimension timeLen ",__FILE__,__LINE__);
+
+        // Check the coordinate variables.
+
+        // Get the latitude.
+        NcmpiVar latVar = nc.getVar(LAT);
+
+        // Check units and long name.
+        if (check_u_ln_atts(latVar, DEGREES_NORTH, LATITUDE))
+            throw NcmpiException("read Error: check_u_ln_atts lat ",__FILE__,__LINE__);
+
+        // Get the longitude.
+        NcmpiVar lonVar = nc.getVar(LON);
+
+        // Check units and long name.
+        if (check_u_ln_atts(lonVar, DEGREES_EAST, LONGITUDE))
+            throw NcmpiException("read Error: check_u_ln_atts lon ",__FILE__,__LINE__);
+
+        // Get the forecast time coordinate variable.
+        NcmpiVar frtimeVar = nc.getVar(FRTIME);
+
+        // Check units and long name.
+        if (check_u_ln_atts(frtimeVar, HOURS, FORECAST_TIME)) {
+            cout << "check_u_ln_atts frtime  err"<<endl;
+            throw NcmpiException("read Error ",__FILE__,__LINE__);
+        }
+
+        // Get the refTime coordinate variable.
+        NcmpiVar refTimeVar = nc.getVar(REFTIME);
+
+        // Check units and long name.
+        if (check_u_ln_atts(refTimeVar, TEXT_TIME, REFERENCE_TIME))
+            throw NcmpiException("read Error: check_u_ln_atts refTime ",__FILE__,__LINE__);
+
+        // Check the data variables.
+        NcmpiVar pVar = nc.getVar(P_NAME);
+
+        // Check units and long name.
+        if (check_u_ln_atts(pVar, HECTOPASCALS, PRES_MAX_WIND))
+            throw NcmpiException("read Error: check_u_ln_atts HECTOPASCALS ",__FILE__,__LINE__);
+
+        // Check the valid range, and check the values.
+        NcmpiVarAtt vatt = pVar.getAtt(VALID_RANGE);
+        if (vatt.isNull() || vatt.getName().compare(VALID_RANGE) != 0 || 
+            vatt.getType() != ncmpiFloat || vatt.getAttLength() != NRANGES)
+            throw NcmpiException("read Error: VALID_RANGE ",__FILE__,__LINE__);
+
+        float range_in[NRANGES];
+        vatt.getValues(range_in);
+        if (range_in[0] != range[0] || range_in[1] != range[1])
+            throw NcmpiException("read Error: range value ",__FILE__,__LINE__);
+
+        // Check the fill value, and check the value.
+        vatt = pVar.getAtt(FILL_VALUE);
+        if (vatt.isNull() || vatt.getName().compare(FILL_VALUE) != 0 || 
+            vatt.getType() != ncmpiFloat || vatt.getAttLength() != 1)
+            throw NcmpiException("read Error: FILL_VALUE ",__FILE__,__LINE__);
+
+        float fill_value_in;
+        vatt.getValues(&fill_value_in);
+        if (fill_value_in != fill_value)
+            throw NcmpiException("Fill value mismatch Error ",__FILE__,__LINE__);
+
+        // Check the data in the pressure variable.
+        float P_data_in[NFRTIMES][NLATS][NLONS];
+        // pVar.getVar(NFRTIMES, NLATS, NLONS, &P_data_in[0][0][0]);
+        pVar.getVar_all(&P_data_in[0][0][0]);
+        for (int f = 0; f < NFRTIMES; f++)
+           for (int la = 0; la < NLATS; la++)
+	      for (int lo = 0; lo < NLONS; lo++)
+	         if (P_data_in[f][la][lo] != P_data[f][la][lo])
+                     throw NcmpiException("read Error: unexpect variable value ",__FILE__,__LINE__);
+
+        // Get the scalar variable.
+        NcmpiVar scalarVar = nc.getVar(SCALARV);
+
+        // Check for the scalar attribute of the scalar variable and check its value.
+        vatt = scalarVar.getAtt(SCALAR_ATT);
+        if (vatt.isNull() || vatt.getName().compare(SCALAR_ATT) != 0 || 
+            vatt.getType() != ncmpiInt || vatt.getAttLength() != 1)
+            throw NcmpiException("read Error: SCALAR_ATT ",__FILE__,__LINE__);
+
+        int value_in;
+        vatt.getValues(&value_in);
+        if (value_in != SCALAR_VALUE)
+            throw NcmpiException("read Error: SCALAR_VALUE ",__FILE__,__LINE__);
+
+        // Check the value of the scalar variable.
+    }
+    catch(NcmpiException& e)
+    {
+      cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+      return -1;
+    }
+
+   return 0;
+}
+
+// Generate a netCDF file
+int gen(const MPI_Comm        &comm,
+        const char            *path,
+        NcmpiFile::FileFormat  format)
+{
+    try {
+        // Create a new file, leave in define mode
+        NcmpiFile nc(comm, path, NcmpiFile::replace, format);
+
+        // Create dimensions
+        NcmpiDim latd     = nc.addDim(LAT, NLATS);
+        NcmpiDim lond     = nc.addDim(LON, NLONS);
+        NcmpiDim frtimed  = nc.addDim(FRTIME); // unlimited dimension
+        NcmpiDim timelend = nc.addDim(TIMELEN1, TIMESTRINGLEN); 
+
+        vector<NcmpiDim> dim3D(3);
+        dim3D[0]=frtimed;
+        dim3D[1]=latd;
+        dim3D[2]=lond;
+
+        // Create variables and their attributes
+        NcmpiVar P = nc.addVar(P_NAME, ncmpiFloat, dim3D);
+        P.putAtt(LONG_NAME,   PRES_MAX_WIND);
+        P.putAtt(UNITS,       HECTOPASCALS);
+        P.putAtt(VALID_RANGE, ncmpiFloat, NRANGES, range);
+        P.putAtt(FILL_VALUE,  ncmpiFloat, fill_value);
+
+        NcmpiVar lat = nc.addVar(LAT, ncmpiFloat, latd);
+        lat.putAtt(LONG_NAME, LATITUDE);
+        lat.putAtt(UNITS, DEGREES_NORTH);
+
+        NcmpiVar lon = nc.addVar(LON, ncmpiFloat, lond);
+        lon.putAtt(LONG_NAME, LONGITUDE);
+        lon.putAtt(UNITS, DEGREES_EAST);
+
+        NcmpiVar frtime = nc.addVar(FRTIME, ncmpiInt, frtimed);
+        frtime.putAtt(LONG_NAME, FORECAST_TIME);
+        frtime.putAtt(UNITS, HOURS);
+
+        NcmpiVar reftime = nc.addVar(REFTIME, ncmpiChar, timelend);
+        reftime.putAtt(LONG_NAME, REFERENCE_TIME);
+        reftime.putAtt(UNITS, TEXT_TIME);
+
+        NcmpiVar scalar = nc.addVar(SCALARV, ncmpiInt);
+        scalar.putAtt(SCALAR_ATT, ncmpiInt, SCALAR_VALUE);
+
+        // Global attributes
+        nc.putAtt(HISTORY, HISTORY_STR);
+        nc.putAtt(TITLE, TITLE_STR);
+
+        // Start writing data, implictly leaves define mode
+
+        lat.putVar_all(lats);
+
+        lon.putVar_all(lons);
+
+        // make sure tailing characters are all '\0'
+        char *str = (char*) calloc(TIMESTRINGLEN, 1);
+        strcpy(str, s);
+        reftime.putVar_all(str);
+        free(str);
+
+        // we write one record at a time
+        vector<MPI_Offset> startp,countp;
+        startp.push_back(0);
+        startp.push_back(0);
+        startp.push_back(0);
+        countp.push_back(1);
+        countp.push_back(NLATS);
+        countp.push_back(NLONS);
+
+        P.putVar_all(startp,countp,&P_data[0][0][0]); // write 1st record
+
+        startp[0] = 1;
+        P.putVar_all(startp,countp,&P_data[1][0][0]); // write 2nd record
+
+        frtime.putVar_all(frtimes);
+
+        // close of nc takes place in destructor
+    }
+    catch(NcmpiException& e)
+    {
+      cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+      return -1;
+    }
+
+    return 0;
+}
+
+/*
+ * Convert pathname of netcdf file into name for CDL, by taking last component
+ * of path and stripping off any extension.  The returned string is in static
+ * storage, so copy it if you need to keep it.
+ */
+static char* 
+cdl_name(const char* path)
+{
+    const char* cp = path + strlen(path);
+    while (*(cp-1) != '/' && cp != path) // assumes UNIX path separator
+	cp--;
+
+    static char np[NC_MAX_NAME];
+    strncpy(&np[0], cp, NC_MAX_NAME);
+
+    char* ep = np + strlen(np);
+    while (*ep != '.' && ep != np)
+	ep--;
+    if (*ep == '.')
+      *ep = '\0';
+    return np;
+}
+
+// A derived class, just like NcmpiFile except knows how to "dump" its
+// dimensions, variables, global attributes, and data in ASCII form.
+class DumpableNcmpiFile : public NcmpiFile
+{
+  public:
+    DumpableNcmpiFile(const MPI_Comm &comm,
+                      const char* path, NcmpiFile::FileMode mode = read)
+	: NcmpiFile(comm, path, mode) {} ;
+    void dumpdims( void );
+    void dumpvars( void );
+    void dumpgatts( void );
+    void dumpdata( void );
+};
+
+void DumpableNcmpiFile::dumpdims( void )
+{
+    multimap<string,NcmpiDim> dimMap = getDims();
+
+    for (multimap<string,NcmpiDim>::iterator iter=dimMap.begin(); iter!=dimMap.end(); ++iter) {
+        NcmpiDim *ptr = &(*iter).second;
+	cout << "\t" << ptr->getName() << " = " ;
+	if (ptr->isUnlimited())
+	  cout << "UNLIMITED" << " ;\t " << "// " << ptr->getSize() <<
+	    " currently\n";
+	else
+	  cout << ptr->getSize() << " ;\n";
+    }
+}
+
+void dumpatts(NcmpiVar& var)
+{
+    std::map<std::string,NcmpiVarAtt> attMap = var.getAtts();
+
+    for (std::map<std::string,NcmpiVarAtt>::iterator iter=attMap.begin(); iter!=attMap.end(); ++iter) {
+        NcmpiAtt *ptr = &(*iter).second;
+	cout << "\t\t" << var.getName() << ":" << ptr->getName() << " = " ;
+        vector<double>  atest(ptr->getAttLength());
+        ptr->getValues(&atest[0]);
+	cout << &atest[0] << " ;" << endl ;
+    }
+}
+
+void DumpableNcmpiFile::dumpvars( void )
+{
+    multimap<string,NcmpiVar> vMap = getVars();
+
+    for (multimap<string,NcmpiVar>::iterator iter=vMap.begin(); iter!=vMap.end(); ++iter) {
+        NcmpiVar *vp = &(*iter).second;
+	cout << "\t" << vp->getType().getName() << " " << vp->getName() ;
+
+	if (vp->getDimCount() > 0) {
+	    cout << "(";
+	    for (int d = 0; d < vp->getDimCount(); d++) {
+		NcmpiDim dim = vp->getDim(d);
+		cout << dim.getName();
+		if (d < vp->getDimCount()-1)
+		  cout << ", ";		  
+	    }
+	    cout << ")";
+	}
+	cout << " ;\n";
+	// now dump each of this variable's attributes
+	dumpatts(*vp);
+    }
+}
+
+void DumpableNcmpiFile::dumpgatts( void )
+{
+    std::multimap<std::string,NcmpiGroupAtt> attMap = getAtts();
+
+    for (std::multimap<std::string,NcmpiGroupAtt>::iterator iter=attMap.begin(); iter!=attMap.end(); ++iter) {
+        NcmpiGroupAtt *ap = &(*iter).second;
+        cout << "\t\t" << ":" << ap->getName() << " = " ;
+        vector<double>  atest(ap->getAttLength());
+        ap->getValues(&atest[0]);
+	cout << &atest[0] << " ;" << endl ;
+    }
+}
+
+void DumpableNcmpiFile::dumpdata( )
+{
+    std::multimap<std::string,NcmpiVar> vMap = getVars();
+
+    for (std::multimap<std::string,NcmpiVar>::iterator iter=vMap.begin(); iter!=vMap.end(); ++iter) {
+        NcmpiVar *vp = &(*iter).second;
+	cout << " " << vp->getName() << " = ";
+
+        MPI_Offset vSize = 1;
+        std::vector<NcmpiDim> dimMap = vp->getDims();
+        for (std::vector<NcmpiDim>::iterator iterD=dimMap.begin(); iterD!=dimMap.end(); ++iterD) {
+            vSize *= iterD->getSize();
+        }
+
+        vector<double> vals(vSize);
+        vp->getVar_all(&vals[0]);
+	cout << &vals[0] << " ;" << endl ;
+    }
+}
+
+void dump(const MPI_Comm &comm, const char* path)
+{
+    DumpableNcmpiFile nc(comm, path);	// default is open in read-only mode
+
+    cout << "netcdf " << cdl_name(path) << " {" << endl <<
+	    "dimensions:" << endl ;
+
+    nc.dumpdims();
+
+    cout << "variables:" << endl;
+
+    nc.dumpvars();
+
+    if (nc.getAttCount() > 0)
+      cout << "// global attributes" << endl ;
+
+    nc.dumpgatts();
+
+    cout << "data:" << endl;
+
+    nc.dumpdata();
+
+    cout << "}" << endl;
+}
+
+/* Test everything for classic, 64-bit offset, an 64-bit data files. */
+#define NUM_FORMATS (3)
+
+int
+main(int argc, char* argv[])	// test new netCDF interface
+{
+   char filename[256];
+   int rank, nprocs, verbose=0;
+
+   MPI_Init(&argc, &argv);
+   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+   MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+   if (argc > 2) {
+       if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+       MPI_Finalize();
+       return 0;
+   }
+   strcpy(filename, "testfile.nc");
+   if (argc == 2) strcpy(filename, argv[1]);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C++ %s for APIs with different netCDF formats ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+   // Set up the format constants.
+   NcmpiFile::FileFormat format[NUM_FORMATS] =
+              {NcmpiFile::classic, NcmpiFile::classic2, NcmpiFile::classic5};
+
+   char format_name[NUM_FORMATS][NC_MAX_NAME] = 
+        {"classic", "classic2", "classic5"};
+
+   int nerrs = 0;
+   for (int i = 0; i < NUM_FORMATS; i++)
+   {
+      if (gen(MPI_COMM_WORLD, filename, format[i]) || 
+	  read(MPI_COMM_WORLD, filename, format[i]))
+      {
+	 if (verbose)
+             cout << "*** FAILURE with format " << format_name[i] << "\n";
+	 nerrs++;
+      }
+      else if (verbose)
+	 cout << "*** SUCCESS with format " << format_name[i] << "\n";
+   }
+
+   if (verbose) cout << "\n*** Total number of failures: " << nerrs << "\n";
+
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+
+   MPI_Finalize();
+   return nerrs;
+}
diff --git a/test/CXX/test_classic.cpp b/test/CXX/test_classic.cpp
new file mode 100644
index 0000000..f9b6b1f
--- /dev/null
+++ b/test/CXX/test_classic.cpp
@@ -0,0 +1,96 @@
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <pnetcdf>
+#include <testutils.h>
+
+using namespace std;
+using namespace PnetCDF;
+using namespace PnetCDF::exceptions;
+
+int main( int argc, char *argv[] )
+{
+   char filename[256];
+   int rank, nerrs=0, verbose=0;
+
+   MPI_Init(&argc, &argv);
+   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+   if (argc > 2) {
+       if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+       MPI_Finalize();
+       return 0;
+   }
+   strcpy(filename, "testfile.nc");
+   if (argc == 2) strcpy(filename, argv[1]);
+
+   if (rank == 0) {
+       char cmd_str[256];
+       sprintf(cmd_str, "*** TESTING C++ %s for creation of classic format file", argv[0]);
+       printf("%-66s ------ ", cmd_str);
+   }
+
+   try
+   {
+      if (verbose) cout << "Test creation of classic format file" << endl;
+      {
+	 NcmpiFile ncFile(MPI_COMM_WORLD, filename, NcmpiFile::replace,
+                          NcmpiFile::classic);
+	 NcmpiDim dim1 = ncFile.addDim("dim1",11);
+	 NcmpiDim dim2 = ncFile.addDim("dim2");
+	 NcmpiDim dim3 = ncFile.addDim("dim3",13);
+
+	 NcmpiVar var_gw  = ncFile.addVar("George_Washington", ncmpiInt, dim1);
+	 // add a 2D record variable
+	 vector<NcmpiDim> dimArray(2);
+	 dimArray[0]=dim2;
+	 dimArray[1]=dim1;
+	 NcmpiVar varA1_3  = ncFile.addVar("varA1_3", ncmpiInt, dimArray);
+
+	 // ncFile.enddef(); is no need in C++ program
+
+         // and inserting some data that needs leaving the define mode
+         if (verbose) cout << "testing the switch to DATA mode..." << endl;
+         int arr[] = {1,2,3,4,5,6,7,8,9,10,11};
+         var_gw.putVar_all(arr);
+      }
+
+      // Now test reading.
+      {
+	 NcmpiFile ncFile(MPI_COMM_WORLD, filename, NcmpiFile::read);
+
+	 if (ncFile.getVarCount() != 2)
+	    throw NcmpiException( "Holy Mother of Pearl!", __FILE__, __LINE__);
+      }
+
+      // and redefinition
+      {
+        NcmpiFile ncFile(MPI_COMM_WORLD, filename, NcmpiFile::write);
+        if (verbose) cout << "testing the switch to DEFINE mode..." << endl;
+        ncFile.putAtt(string("name"),string("value"));
+      }
+
+      if (verbose) cout << "    -----------   passed\n";
+   }
+   catch(NcmpiException& e)
+   {
+      cout << e.what() << " error code=" << e.errorCode() << " Error!\n";
+      nerrs++;
+   }
+
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+   MPI_Finalize();
+   return 0;
+}
diff --git a/test/F90/Makefile.in b/test/F90/Makefile.in
new file mode 100644
index 0000000..7462058
--- /dev/null
+++ b/test/F90/Makefile.in
@@ -0,0 +1,142 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+#
+# @configure_input@
+
+srcdir  = @srcdir@
+VPATH   = @srcdir@
+
+include ../../macros.make
+
+INCLUDES  =
+FPPFLAGS += @FC_MODINC at ../../src/libf90 @FC_MODINC at ../common
+F90FLAGS += @FC_MODOUT at .
+LDFLAGS  := $(LDFLAGS) -L../common
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
+
+F90_SRCS = tst_f90.f90 \
+           tst_io.f90 \
+           f90tst_vars.f90 \
+           tst_types2.f90 \
+           tst_f90_cdf5.f90 \
+           f90tst_vars2.f90 \
+           f90tst_vars3.f90 \
+           f90tst_vars4.f90 \
+           tst_flarge.f90 \
+           f90tst_parallel.f90 \
+           f90tst_parallel2.f90 \
+           f90tst_parallel3.f90 \
+           f90tst_parallel4.f90 \
+           test_intent.f90
+
+PROGS    = $(F90_SRCS:.f90=)
+OBJS     = $(F90_SRCS:.f90=.o)
+
+GARBAGE  = $(PROGS) *.nc *. at FC_MODEXT@
+
+PACKING_LIST = $(F90_SRCS) Makefile.in depend
+
+all: $(PROGS)
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+tst_f90: tst_f90.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+tst_io: tst_io.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+f90tst_vars: f90tst_vars.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+tst_types2: tst_types2.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+tst_f90_cdf5: tst_f90_cdf5.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+f90tst_vars2: f90tst_vars2.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+f90tst_vars3: f90tst_vars3.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+f90tst_vars4: f90tst_vars4.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+tst_flarge: tst_flarge.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+f90tst_parallel: f90tst_parallel.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+f90tst_parallel2: f90tst_parallel2.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+f90tst_parallel3: f90tst_parallel3.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+f90tst_parallel4: f90tst_parallel4.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+test_intent: test_intent.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+testing check verbose_testing: $(PROGS)
+	$(TEST_SEQRUN) ./test_intent  $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_f90      $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./f90tst_vars  $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_types2   $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_f90_cdf5 $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./f90tst_vars2 $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./f90tst_vars3 $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./f90tst_vars4 $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_flarge   $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_io       $(TEST_OUTDIR)
+
+PARALLEL_PROGS = f90tst_parallel f90tst_parallel2 f90tst_parallel3 f90tst_parallel4
+
+TEST_MPIRUN_2   = $(subst NP,2,$(TEST_MPIRUN))
+TEST_MPIRUN_4   = $(subst NP,4,$(TEST_MPIRUN))
+TEST_MPIRUN_8   = $(subst NP,8,$(TEST_MPIRUN))
+TEST_MPIRUN_10  = $(subst NP,10,$(TEST_MPIRUN))
+
+ptest4: $(PARALLEL_PROGS)
+	@for i in $(PARALLEL_PROGS); do ( \
+	$(TEST_MPIRUN_4) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest2: $(PARALLEL_PROGS)
+	@for i in $(PARALLEL_PROGS); do ( \
+	$(TEST_MPIRUN_2) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest8: $(PARALLEL_PROGS)
+	@for i in $(PARALLEL_PROGS); do ( \
+	$(TEST_MPIRUN_8) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest10: $(PARALLEL_PROGS)
+	@for i in $(PARALLEL_PROGS); do ( \
+	$(TEST_MPIRUN_10) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest: ptest4
+ptests: ptest2 ptest4 ptest8 ptest10
+ptest6:
+
+install:
+
+uninstall:
+
+include $(srcdir)/depend
+include $(srcdir)/../../rules.make
+
+$(LIBRARY): ;
+
diff --git a/test/F90/depend b/test/F90/depend
new file mode 100644
index 0000000..d4b6d2c
--- /dev/null
+++ b/test/F90/depend
@@ -0,0 +1,13 @@
+tst_f90.o: tst_f90.f90
+tst_io.o: tst_io.f90
+f90tst_vars.o: f90tst_vars.f90
+tst_types2.o: tst_types2.f90
+tst_f90_cdf5.o: tst_f90_cdf5.f90
+f90tst_vars2.o: f90tst_vars2.f90
+f90tst_vars3.o: f90tst_vars3.f90
+f90tst_vars4.o: f90tst_vars4.f90
+tst_flarge.o: tst_flarge.f90
+f90tst_parallel.o: f90tst_parallel.f90
+f90tst_parallel2.o: f90tst_parallel2.f90
+f90tst_parallel3.o: f90tst_parallel3.f90
+f90tst_parallel4.o: f90tst_parallel4.f90
diff --git a/test/F90/f90tst_parallel.f90 b/test/F90/f90tst_parallel.f90
new file mode 100644
index 0000000..bf838bd
--- /dev/null
+++ b/test/F90/f90tst_parallel.f90
@@ -0,0 +1,169 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: f90tst_parallel.f90 2131 2015-09-25 22:33:12Z wkliao $
+
+!     This program tests PnetCDF parallel I/O functions from fortran 90.
+!
+!     We are writing 2D data, a 6 x 12 grid, on 4 processors. Each
+!     processor will write it's rank to it's quarter of the array. The
+!     result will be (in CDL):
+!
+! netcdf f90tst_parallel {
+! dimensions:
+! 	x = 16 ;
+! 	y = 16 ;
+! variables:
+! 	int data(x, y) ;
+! data:
+! 
+!  data =
+!   0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+!   0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+!   0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+!   0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+!   0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+!   0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+!   0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+!   0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+!   2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+!   2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+!   2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+!   2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+!   2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+!   2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+!   2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+!   2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 ;
+! }
+
+program f90tst_parallel
+  use mpi
+  use pnetcdf
+  implicit none
+  
+  ! This is the name of the data file we will create.
+  character (len = *), parameter :: FILE_NAME = "f90tst_parallel.nc"
+
+  integer, parameter :: MAX_DIMS = 2
+  integer, parameter :: NX = 16, NY = 16
+  integer, parameter :: NUM_PROC = 4
+  integer :: ncid, varid, dimids(MAX_DIMS)
+  integer :: x_dimid, y_dimid
+  integer :: data_out(NY / 2, NX / 2), data_in(NY / 2, NX / 2)
+  integer :: mode_flag
+  integer :: nvars, ngatts, ndims, unlimdimid, file_format
+  integer :: x, y
+  integer :: p, my_rank, err, ierr, get_args
+  integer(KIND=MPI_OFFSET_KIND) :: start(MAX_DIMS), count(MAX_DIMS)
+  integer(KIND=MPI_OFFSET_KIND) :: nx_ll, ny_ll
+  character(LEN=256) filename, cmd, msg
+
+  call MPI_Init(ierr)
+  call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_Comm_size(MPI_COMM_WORLD, p, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      filename = FILE_NAME
+      err = get_args(cmd, filename)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+!  if (p .ne. 4 .AND. my_rank .eq. 0) then
+!     print *, 'Warning: ',trim(cmd),' is design to run on 4 processes.'
+!  endif
+
+  ! Create some pretend data.
+  do x = 1, NX / 2
+     do y = 1, NY / 2
+        data_out(y, x) = my_rank
+     end do
+  end do
+
+  ! Create the netCDF file. 
+  mode_flag = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+  call handle_err(nf90mpi_create(MPI_COMM_WORLD, filename, mode_flag, MPI_INFO_NULL, ncid))
+
+  ! Define the dimensions.
+  nx_ll = NX
+  ny_ll = NY
+  call handle_err(nf90mpi_def_dim(ncid, "x", nx_ll, x_dimid))
+  call handle_err(nf90mpi_def_dim(ncid, "y", ny_ll, y_dimid))
+  dimids =  (/ y_dimid, x_dimid /)
+
+  ! Define the variable. 
+  call handle_err(nf90mpi_def_var(ncid, "data", NF90_INT, dimids, varid))
+
+  call handle_err(nf90mpi_enddef(ncid))
+
+  ! Determine what part of the variable will be written for this
+  ! processor. It's a checkerboard decomposition.
+  count = (/ NX / 2, NY / 2 /)
+  if (my_rank .eq. 0) then
+     start = (/ 1, 1 /)
+  else if (my_rank .eq. 1) then
+     start = (/ NX / 2 + 1, 1 /)
+  else if (my_rank .eq. 2) then
+     start = (/ 1, NY / 2 + 1 /)
+  else if (my_rank .eq. 3) then
+     start = (/ NX / 2 + 1, NY / 2 + 1 /)
+  else
+     start = (/ 1, 1 /)
+     count = 0
+  endif
+
+  ! Write this processor's data.
+  call handle_err(nf90mpi_put_var_all(ncid, varid, data_out, start = start, count = count))
+
+  ! Close the file. 
+  call handle_err(nf90mpi_close(ncid))
+
+  ! Reopen the file.
+  call handle_err(nf90mpi_open(MPI_COMM_WORLD, filename, nf90_nowrite, MPI_INFO_NULL, ncid))
+  
+  ! Check some stuff out.
+  call handle_err(nf90mpi_inquire(ncid, ndims, nvars, ngatts, unlimdimid, file_format))
+  if (ndims /= 2 .or. nvars /= 1 .or. ngatts /= 0 .or. unlimdimid /= -1 .or. &
+       file_format /= nf90_format_cdf5) stop 3
+
+  ! Read this processor's data.
+  call handle_err(nf90mpi_get_var_all(ncid, varid, data_in, start = start, count = count))
+
+  ! Check the data.
+  if (my_rank .LT. 4) then
+     do x = 1, NX / 2
+        do y = 1, NY / 2
+           if (data_in(y, x) .ne. my_rank) stop 4
+        end do
+     end do
+  endif
+
+  ! Close the file.
+  call handle_err(nf90mpi_close(ncid))
+
+  msg = '*** TESTING F90 '//trim(cmd)
+  if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999 call MPI_Finalize(ierr)
+
+
+contains
+!     This subroutine handles errors by printing an error message and
+!     exiting with a non-zero status.
+  subroutine handle_err(errcode)
+    implicit none
+    integer, intent(in) :: errcode
+    
+    if(errcode /= nf90_noerr) then
+       print *, 'Error: ', trim(nf90mpi_strerror(errcode))
+       stop 2
+    endif
+  end subroutine handle_err
+end program f90tst_parallel
+
diff --git a/test/F90/f90tst_parallel2.f90 b/test/F90/f90tst_parallel2.f90
new file mode 100644
index 0000000..1662a43
--- /dev/null
+++ b/test/F90/f90tst_parallel2.f90
@@ -0,0 +1,176 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: f90tst_parallel2.f90 2131 2015-09-25 22:33:12Z wkliao $
+
+!     This program tests PnetCDF parallel I/O functions from fortran 90.
+
+!     We are writing 2D data, a 6 x 12 grid, on 4 processors. We only
+!     have half that amount of input data, because a stride is used so
+!     that only every other value is written to the file. Each
+!     processor will write it's rank to every other value in it's
+!     quarter of the array. The result will be (in CDL):
+!
+! netcdf f90tst_parallel2 {
+! dimensions:
+! 	x = 16 ;
+! 	y = 16 ;
+! variables:
+! 	int data(x, y) ;
+! data:
+
+!  data =
+!   0, _, 0, _, 0, _, 0, _, 1, _, 1, _, 1, _, 1, _,
+!   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+!   0, _, 0, _, 0, _, 0, _, 0, _, 0, _, 0, _, 0, _,
+!   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+!   0, _, 0, _, 0, _, 0, _, 1, _, 1, _, 1, _, 1, _,
+!   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+!   0, _, 0, _, 0, _, 0, _, 0, _, 0, _, 0, _, 0, _,
+!   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+!   2, _, 2, _, 2, _, 2, _, 3, _, 3, _, 3, _, 3, _,
+!   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+!   0, _, 0, _, 0, _, 0, _, 0, _, 0, _, 0, _, 0, _,
+!   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+!   2, _, 2, _, 2, _, 2, _, 3, _, 3, _, 3, _, 3, _,
+!   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+!   0, _, 0, _, 0, _, 0, _, 0, _, 0, _, 0, _, 0, _,
+!   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ ;
+! }
+
+!     $Id: f90tst_parallel2.f90 2131 2015-09-25 22:33:12Z wkliao $
+
+program f90tst_parallel
+  use mpi
+  use pnetcdf
+  implicit none
+  
+  ! This is the name of the data file we will create.
+  character (len = *), parameter :: FILE_NAME = "f90tst_parallel2.nc"
+
+  integer, parameter :: MAX_DIMS = 2
+  integer, parameter :: NX = 16, NY = 16
+  integer, parameter :: NUM_PROC = 4
+  integer :: ncid, varid, dimids(MAX_DIMS)
+  integer :: x_dimid, y_dimid
+  integer :: data_out(NY / 4, NX / 4), data_in(NY / 4, NX / 4)
+  integer :: mode_flag
+  integer :: nvars, ngatts, ndims, unlimdimid, file_format
+  integer :: x, y
+  integer :: p, my_rank, err, ierr, get_args
+  integer(KIND=MPI_OFFSET_KIND) :: start(MAX_DIMS), count(MAX_DIMS), stride(MAX_DIMS)
+  integer(KIND=MPI_OFFSET_KIND) :: nx_ll, ny_ll
+  character(LEN=256) filename, cmd, msg
+
+  call MPI_Init(ierr)
+  call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_Comm_size(MPI_COMM_WORLD, p, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      filename = FILE_NAME
+      err = get_args(cmd, filename)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+!  if (p .ne. 4 .AND. my_rank .eq. 0) then
+!     print *, 'Warning: ',trim(cmd),' is design to run on 4 processes.'
+!  endif
+
+  ! Create some pretend data.
+  do x = 1, NX / 4
+     do y = 1, NY / 4
+        data_out(y, x) = my_rank
+     end do
+  end do
+
+  ! Create the netCDF file. 
+  mode_flag = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+  call handle_err(nf90mpi_create(MPI_COMM_WORLD, filename, mode_flag, MPI_INFO_NULL, ncid))
+
+  ! Define the dimensions.
+  nx_ll = NX
+  ny_ll = NY
+  call handle_err(nf90mpi_def_dim(ncid, "x", nx_ll, x_dimid))
+  call handle_err(nf90mpi_def_dim(ncid, "y", ny_ll, y_dimid))
+  dimids =  (/ y_dimid, x_dimid /)
+
+  ! Define the variable. 
+  call handle_err(nf90mpi_def_var(ncid, "data", NF90_INT, dimids, varid))
+
+  ! With classic model netCDF-4 file, enddef must be called.
+  call handle_err(nf90mpi_enddef(ncid))
+
+  ! Determine what part of the variable will be written for this
+  ! processor. It's a checkerboard decomposition.
+  count = (/ NX / 4, NY / 4 /)
+  stride = (/ 2, 2 /)
+  if (my_rank .eq. 0) then
+     start = (/ 1, 1 /)
+  else if (my_rank .eq. 1) then
+     start = (/ NX / 2 + 1, 1 /)
+  else if (my_rank .eq. 2) then
+     start = (/ 1, NY / 2 + 1 /)
+  else if (my_rank .eq. 3) then
+     start = (/ NX / 2 + 1, NY / 2 + 1 /)
+  else
+     start = (/ 1, 1 /)
+     count = 0
+  endif
+
+  ! Write this processor's data.
+  call handle_err(nf90mpi_put_var_all(ncid, varid, data_out, start = start, &
+       count = count, stride = stride))
+
+  ! Close the file. 
+  call handle_err(nf90mpi_close(ncid))
+
+  ! Reopen the file.
+  call handle_err(nf90mpi_open(MPI_COMM_WORLD, filename, nf90_nowrite, MPI_INFO_NULL, ncid))
+  
+  ! Check some stuff out.
+  call handle_err(nf90mpi_inquire(ncid, ndims, nvars, ngatts, unlimdimid, file_format))
+  if (ndims /= 2 .or. nvars /= 1 .or. ngatts /= 0 .or. unlimdimid /= -1 .or. &
+       file_format /= nf90_format_cdf5) stop 3
+
+  ! Read this processor's data.
+  call handle_err(nf90mpi_get_var_all(ncid, varid, data_in, start = start, count = count, &
+       stride = stride))
+
+  ! Check the data.
+  if (my_rank .LT. 4) then
+     do x = 1, NX / 4
+        do y = 1, NY / 4
+           if (data_in(y, x) .ne. my_rank) stop 4
+        end do
+     end do
+  endif
+
+  ! Close the file. 
+  call handle_err(nf90mpi_close(ncid))
+
+  msg = '*** TESTING F90 '//trim(cmd)//' for strided access'
+  if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999 call MPI_Finalize(ierr)
+
+contains
+!     This subroutine handles errors by printing an error message and
+!     exiting with a non-zero status.
+  subroutine handle_err(errcode)
+    implicit none
+    integer, intent(in) :: errcode
+    
+    if(errcode /= nf90_noerr) then
+       print *, 'Error: ', trim(nf90mpi_strerror(errcode))
+       stop 5
+    endif
+  end subroutine handle_err
+end program f90tst_parallel
+
diff --git a/test/F90/f90tst_parallel3.f90 b/test/F90/f90tst_parallel3.f90
new file mode 100644
index 0000000..efaa595
--- /dev/null
+++ b/test/F90/f90tst_parallel3.f90
@@ -0,0 +1,196 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: f90tst_parallel3.f90 2136 2015-10-07 19:25:34Z wkliao $
+
+!     This program tests PnetCDF parallel I/O from
+!     fortran. It creates a file like this:
+
+! netcdf f90tst_parallel3 {
+! dimensions:
+! 	x = 16 ;
+! 	y = 16 ;
+! variables:
+! 	byte byte__(x, y) ;
+! 	short short_(x, y) ;
+! 	int int__(x, y) ;
+! 	float float_(x, y) ;
+! 	double double(x, y) ;
+! 	int64 int64_(x, y) ;
+
+
+program f90tst_parallel3
+  use mpi
+  use pnetcdf
+  implicit none
+  
+  integer, parameter ::   OneByteInt = selected_int_kind(2), &
+                          TwoByteInt = selected_int_kind(4), &
+                         FourByteInt = selected_int_kind(9), &
+                        EightByteInt = selected_int_kind(18)
+
+  ! This is the name of the data file we will create.
+  character (len = *), parameter :: FILE_NAME = "f90tst_parallel3.nc"
+  integer, parameter :: MAX_DIMS = 2
+  integer, parameter :: NX = 16, NY = 16
+  integer, parameter :: HALF_NX = NX/2, HALF_NY = NY/2
+  integer, parameter :: NUM_PROC = 4
+  integer, parameter :: NUM_VARS = 6
+  integer, parameter :: CACHE_SIZE = 4194304, CACHE_NELEMS = 1013
+  integer, parameter :: CACHE_PREEMPTION = 79
+  character (len = *), parameter :: var_name(NUM_VARS) = &
+       (/ 'byte__', 'short_', 'int___', 'float_', 'double', 'int64_' /)
+  integer :: ncid, varid(NUM_VARS), dimids(MAX_DIMS)
+  integer :: var_type(NUM_VARS) = (/ nf90_byte, nf90_short, nf90_int, &
+       nf90_float, nf90_double, nf90_int64 /)
+  integer :: x_dimid, y_dimid
+  integer(kind=OneByteInt) :: byte_out(HALF_NY, HALF_NX), byte_in(HALF_NY, HALF_NX)
+  integer(kind=TwoByteInt) :: short_out(HALF_NY, HALF_NX), short_in(HALF_NY, HALF_NX)
+  integer :: int_out(HALF_NY, HALF_NX), int_in(HALF_NY, HALF_NX)
+  real :: areal_out(HALF_NY, HALF_NX), areal_in(HALF_NY, HALF_NX)
+  double precision :: double_out(HALF_NY, HALF_NX), double_in(HALF_NY, HALF_NX)
+  integer (kind=EightByteInt) :: int64_out(HALF_NY, HALF_NX), int64_in(HALF_NY, HALF_NX)
+  integer :: nvars, ngatts, ndims, unlimdimid, file_format
+  integer :: x, y, v
+  integer :: p, my_rank, err, ierr, get_args
+  integer(KIND=MPI_OFFSET_KIND) :: start(MAX_DIMS), count(MAX_DIMS)
+  integer :: cmode
+  integer(KIND=MPI_OFFSET_KIND) :: nx_ll, ny_ll
+  character(LEN=256) filename, cmd, msg
+
+  call MPI_Init(ierr)
+  call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_Comm_size(MPI_COMM_WORLD, p, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      filename = FILE_NAME
+      err = get_args(cmd, filename)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+!  if (p .ne. 4 .AND. my_rank .eq. 0) then
+!     print *, 'Warning: ',trim(cmd),' is design to run on 4 processes.'
+!  endif
+
+  ! Create some pretend data.
+  do x = 1, HALF_NX
+     do y = 1, HALF_NY
+        byte_out(y, x) = INT(my_rank,1) * (-1_1)
+        short_out(y, x) = INT(my_rank, TwoByteInt) * (-2_2)
+        int_out(y, x) = my_rank * (-4)
+        areal_out(y, x) = my_rank * 2.5
+        double_out(y, x) = my_rank * (-4.5)
+        int64_out(y, x) = my_rank * 4
+     end do
+  end do
+
+  ! Create the netCDF file. 
+  cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+  call check(nf90mpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, ncid))
+
+  ! Define the dimensions.
+  nx_ll = NX
+  ny_ll = NY
+  call check(nf90mpi_def_dim(ncid, "x", nx_ll, x_dimid))
+  call check(nf90mpi_def_dim(ncid, "y", ny_ll, y_dimid))
+  dimids =  (/ y_dimid, x_dimid /)
+
+  ! Define the variables. 
+  do v = 1, NUM_VARS
+     call check(nf90mpi_def_var(ncid, var_name(v), var_type(v), dimids, varid(v)))
+  end do
+
+  ! This will be the last collective operation.
+  call check(nf90mpi_enddef(ncid))
+
+  ! Determine what part of the variable will be written/read for this
+  ! processor. It's a checkerboard decomposition.
+  count = (/ HALF_NX, HALF_NY /)
+  if (my_rank .eq. 0) then
+     start = (/ 1, 1 /)
+  else if (my_rank .eq. 1) then
+     start = (/ HALF_NX + 1, 1 /)
+  else if (my_rank .eq. 2) then
+     start = (/ 1, HALF_NY + 1 /)
+  else if (my_rank .eq. 3) then
+     start = (/ HALF_NX + 1, HALF_NY + 1 /)
+  else
+     start = (/ 1, 1 /)
+     count = 0
+  endif
+
+  ! Write this processor's data, except for processor zero.
+  if (my_rank .EQ. 0) count = (/ 0, 0 /)
+  call check(nf90mpi_put_var_all(ncid, varid(1), byte_out, start = start, count = count))
+  call check(nf90mpi_put_var_all(ncid, varid(2), short_out, start = start, count = count))
+  call check(nf90mpi_put_var_all(ncid, varid(3), int_out, start = start, count = count))
+  call check(nf90mpi_put_var_all(ncid, varid(4), areal_out, start = start, count = count))
+  call check(nf90mpi_put_var_all(ncid, varid(5), double_out, start = start, count = count))
+  call check(nf90mpi_put_var_all(ncid, varid(6), int64_out, start = start, count = count))
+
+  ! Close the file. 
+  call check(nf90mpi_close(ncid))
+
+  ! Reopen the file.
+  call check(nf90mpi_open(MPI_COMM_WORLD, filename, nf90_nowrite, MPI_INFO_NULL, ncid))
+  
+  ! Check some stuff out.
+  call check(nf90mpi_inquire(ncid, ndims, nvars, ngatts, unlimdimid, file_format))
+  if (ndims /= 2 .or. nvars /= NUM_VARS .or. ngatts /= 0 .or. unlimdimid /= -1 .or. &
+       file_format /= nf90_format_cdf5) stop 2
+
+  ! Read this processor's data.
+  if (my_rank .EQ. 0) count = (/ HALF_NX, HALF_NY /)
+  call check(nf90mpi_get_var_all(ncid, varid(1), byte_in, start = start, count = count))
+  call check(nf90mpi_get_var_all(ncid, varid(2), short_in, start = start, count = count))
+  call check(nf90mpi_get_var_all(ncid, varid(3), int_in, start = start, count = count))
+  call check(nf90mpi_get_var_all(ncid, varid(4), areal_in, start = start, count = count))
+  call check(nf90mpi_get_var_all(ncid, varid(5), double_in, start = start, count = count))
+  call check(nf90mpi_get_var_all(ncid, varid(6), int64_in, start = start, count = count))
+
+  ! Check the data. All the data from the processor zero are fill
+  ! value.
+  if (my_rank .LT. 4) then
+     do x = 1, HALF_NX
+        do y = 1, HALF_NY
+           if (my_rank .NE. 0) then
+              if (byte_in(y, x) .ne. (my_rank * (-1))) stop 13
+              if (short_in(y, x) .ne. (my_rank * (-2))) stop 14
+              if (int_in(y, x) .ne. (my_rank * (-4))) stop 15
+              if (areal_in(y, x) .ne. (my_rank * (2.5))) stop 16
+              if (double_in(y, x) .ne. (my_rank * (-4.5))) stop 17
+              if (int64_in(y, x) .ne. (my_rank * (4))) stop 20
+           endif
+        end do
+     end do
+  endif
+ 
+  ! Close the file. 
+  call check(nf90mpi_close(ncid))
+
+   msg = '*** TESTING F90 '//trim(cmd)
+   if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999 call MPI_Finalize(ierr)
+
+contains
+!     This subroutine handles errors by printing an error message and
+!     exiting with a non-zero status.
+  subroutine check(errcode)
+    implicit none
+    integer, intent(in) :: errcode
+    
+    if(errcode /= nf90_noerr) then
+       print *, 'Error: ', trim(nf90mpi_strerror(errcode))
+       stop 99
+    endif
+  end subroutine check
+end program f90tst_parallel3
+
diff --git a/test/F90/f90tst_parallel4.f90 b/test/F90/f90tst_parallel4.f90
new file mode 100644
index 0000000..8c6a889
--- /dev/null
+++ b/test/F90/f90tst_parallel4.f90
@@ -0,0 +1,105 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+! $Id: f90tst_parallel4.f90 2136 2015-10-07 19:25:34Z wkliao $
+
+! This parallel test was contributed by Jim Edwards at UCAR. Thanks Jim!
+program f90tst
+  use mpi
+  use pnetcdf
+  implicit none
+
+  character (len = *), parameter :: FILE_NAME = "f90tst_nc4_par.nc"
+  integer :: nmode, err, ierr, fh, my_rank, nprocs, i, varid, get_args
+  integer :: dimid(3)
+  integer(KIND=MPI_OFFSET_KIND) :: start(3), count(3)
+  real :: f(3)
+  character(LEN=256) filename, cmd, msg
+
+  call MPI_INIT(ierr)
+  call MPI_COMM_RANK(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      filename = FILE_NAME
+      err = get_args(cmd, filename)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+!  if (nprocs .ne. 8 .AND. my_rank .eq. 0) then
+!     print *, 'Warning: ',trim(cmd),' is design to run on 8 processes.'
+!  endif
+
+  nmode = ior(NF90_CLOBBER,NF90_64BIT_DATA)
+
+  call handle_err(nf90mpi_create(MPI_COMM_WORLD, filename, nmode, MPI_INFO_NULL, fh))
+
+  call handle_err(nf90mpi_def_dim(fh, 'dim1', 6_MPI_OFFSET_KIND, dimid(1)))
+  call handle_err(nf90mpi_def_dim(fh, 'dim2', 4_MPI_OFFSET_KIND, dimid(2)))
+  call handle_err(nf90mpi_def_dim(fh, 'dim3', 1_MPI_OFFSET_KIND, dimid(3)))
+
+
+  call handle_err(nf90mpi_def_var(fh, 'var1', NF90_DOUBLE, dimid, varid))
+  call handle_err(nf90mpi_enddef(fh))
+
+
+  do i=1,3
+     f(i) = my_rank*3+i
+  end do
+
+  count = (/3,1,1/)
+  start(1) = mod(my_rank,2)*3+1
+  start(2) = my_rank/2+1
+  start(3) = 1
+  if (my_rank .GE. 8) then
+      start = 1
+      count = 0
+  endif
+
+  call handle_err(nf90mpi_put_var_all(fh, varid, f,start=start,count=count))
+
+  call handle_err(nf90mpi_close(fh))
+
+  ! Reopen the file and check it.
+  call handle_err(nf90mpi_open(MPI_COMM_WORLD, filename, NF90_NOWRITE, MPI_INFO_NULL, fh))
+
+  call handle_err(nf90mpi_get_var_all(fh, varid, f, start=start, count=count))
+ 
+  if (my_rank .LE. 8) then
+     do i=1,3
+        if (f(i) .ne. my_rank*3+i) then
+           print *, 'Error: unexpected read value ',f(i),' should be ', my_rank*3+i
+           goto 999
+        endif
+     end do
+  endif 
+
+  call handle_err(nf90mpi_close(fh))
+
+  msg = '*** TESTING F90 '//trim(cmd)
+  if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999 call MPI_Finalize(ierr)
+
+contains
+  !     This subroutine handles errors by printing an error message and
+  !     exiting with a non-zero status.
+  subroutine handle_err(errcode)
+    implicit none
+    integer, intent(in) :: errcode
+
+    if(errcode /= nf90_noerr) then
+       print *, 'Error: ', trim(nf90mpi_strerror(errcode))
+       stop 2
+    endif
+  end subroutine handle_err
+
+end program f90tst
+
diff --git a/test/F90/f90tst_vars.f90 b/test/F90/f90tst_vars.f90
new file mode 100644
index 0000000..ca74588
--- /dev/null
+++ b/test/F90/f90tst_vars.f90
@@ -0,0 +1,139 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: f90tst_vars.f90 2131 2015-09-25 22:33:12Z wkliao $
+
+!     This program tests PnetCDF variable functions from fortran 90.
+
+
+program f90tst_vars
+  use mpi
+  use pnetcdf
+  implicit none
+  
+  ! This is the name of the data file we will create.
+  character (len = *), parameter :: FILE_NAME = "f90tst_vars.nc"
+
+  ! We are writing 2D data, a 6 x 12 grid. 
+  integer, parameter :: MAX_DIMS = 2
+  integer, parameter :: NX = 6, NY = 12
+  integer :: data_out(NY, NX), data_in(NY, NX)
+
+  ! We need these ids and other gunk for netcdf.
+  integer :: ncid, varid, dimids(MAX_DIMS)
+  integer :: x_dimid, y_dimid
+  integer :: mode_flag
+  integer :: nvars, ngatts, ndims, unlimdimid, file_format
+  integer :: x, y
+  integer, parameter :: CACHE_SIZE = 1000000
+  integer :: info, err, ierr, get_args
+  integer(KIND=MPI_OFFSET_KIND) :: nx_ll, ny_ll
+  character(LEN=256) filename, cmd, msg
+  integer my_rank, p
+
+  call MPI_Init(ierr)
+  call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_Comm_size(MPI_COMM_WORLD, p, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      filename = FILE_NAME
+      err = get_args(cmd, filename)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+!  if (p .ne. 1 .AND. my_rank .eq. 0) then
+!     print *, 'Warning: ',trim(cmd),' is design to run on 1 process'
+!  endif
+
+  ! Create some pretend data.
+  do x = 1, NX
+     do y = 1, NY
+        data_out(y, x) = (x - 1) * NY + (y - 1)
+     end do
+  end do
+
+  call MPI_Info_create(info, ierr)
+  call MPI_Info_set(info, "nc_header_align_size",      "1024", ierr)
+  call MPI_Info_set(info, "nc_var_align_size",         "512",  ierr)
+  call MPI_Info_set(info, "nc_header_read_chunk_size", "256",  ierr)
+
+  ! Create the netCDF file. 
+  mode_flag = IOR(NF90_CLOBBER, NF90_64BIT_DATA) 
+  call handle_err(nf90mpi_create(MPI_COMM_WORLD, filename, mode_flag, info, ncid))
+  call MPI_Info_free(info, ierr)
+
+  ! Define the dimensions.
+  nx_ll = NX
+  ny_ll = NY
+  call handle_err(nf90mpi_def_dim(ncid, "x", nx_ll, x_dimid))
+  call handle_err(nf90mpi_def_dim(ncid, "y", ny_ll, y_dimid))
+  dimids =  (/ y_dimid, x_dimid /)
+
+  ! Define the variable. 
+  call handle_err(nf90mpi_def_var(ncid, "data", NF90_INT, dimids, varid))
+
+  ! With classic model netCDF-4 file, enddef must be called.
+  call handle_err(nf90mpi_enddef(ncid))
+
+  ! enter independent data mode
+  call handle_err(nf90mpi_begin_indep_data(ncid))
+
+  ! Write the pretend data to the file.
+  call handle_err(nf90mpi_put_var(ncid, varid, data_out))
+
+  ! Close the file. 
+  call handle_err(nf90mpi_close(ncid))
+
+  ! Reopen the file.
+  call handle_err(nf90mpi_open(MPI_COMM_WORLD, filename, nf90_nowrite, MPI_INFO_NULL, ncid))
+  
+  ! Check some stuff out.
+  call handle_err(nf90mpi_inquire(ncid, ndims, nvars, ngatts, unlimdimid, file_format))
+  if (ndims /= 2 .or. nvars /= 1 .or. ngatts /= 0 .or. unlimdimid /= -1 .or. &
+       file_format /= nf90_format_cdf5) then
+       print*,'ndims should be 2 but got ',ndims
+       print*,'nvars should be 1 but got ',nvars
+       print*,'ngatts should be 0 but got ',ngatts
+       print*,'unlimdimid should be -1 but got ',unlimdimid
+       print*,'file_format should be 5 but got ',file_format
+       stop 2
+  endif
+
+  ! Check the data.
+  call handle_err(nf90mpi_get_var_all(ncid, varid, data_in))
+  do x = 1, NX
+     do y = 1, NY
+        if (data_out(y, x) .ne. data_in(y, x)) stop 3
+     end do
+  end do
+
+  ! Close the file. 
+  call handle_err(nf90mpi_close(ncid))
+
+  msg = '*** TESTING F90 '//trim(cmd)//' for def_var API'
+  if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999 call MPI_Finalize(ierr)
+
+contains
+!     This subroutine handles errors by printing an error message and
+!     exiting with a non-zero status.
+  subroutine handle_err(errcode)
+    use pnetcdf
+    implicit none
+    integer, intent(in) :: errcode
+    
+    if(errcode /= nf90_noerr) then
+       print *, 'Error: ', trim(nf90mpi_strerror(errcode))
+       stop 2
+    endif
+  end subroutine handle_err
+end program f90tst_vars
+
diff --git a/test/F90/f90tst_vars2.f90 b/test/F90/f90tst_vars2.f90
new file mode 100644
index 0000000..f53f899
--- /dev/null
+++ b/test/F90/f90tst_vars2.f90
@@ -0,0 +1,194 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: f90tst_vars2.f90 2136 2015-10-07 19:25:34Z wkliao $
+
+!     This program tests PnetCDF variable functions from fortran 90.
+
+program f90tst_vars2
+  use mpi
+  use pnetcdf
+  implicit none
+  
+  ! This is the name of the data file we will create.
+  character (len = *), parameter :: FILE_NAME = "f90tst_vars2.nc"
+
+  ! We are writing 2D data, a 6 x 12 grid. 
+  integer, parameter :: MAX_DIMS = 2
+  integer, parameter :: NX = 6, NY = 12
+  integer :: data_out(NY, NX), data_in(NY, NX)
+  integer :: data_out_1d(NX), data_in_1d(NX)
+
+  ! We need these ids and other gunk for netcdf.
+  integer :: ncid, varid1, varid2, varid3, varid4, varid5, dimids(MAX_DIMS)
+  integer :: x_dimid, y_dimid
+  integer :: nvars, ngatts, ndims, unlimdimid, file_format
+  integer :: x, y
+  integer, parameter :: DEFLATE_LEVEL = 4
+  integer, parameter :: EightByteInt = selected_int_kind(18)
+  integer (kind = EightByteInt) :: TOE_SAN_VALUE = 2147483648_EightByteInt
+  character (len = *), parameter :: VAR1_NAME = "Chon-Ji"
+  character (len = *), parameter :: VAR2_NAME = "Tan-Gun"
+  character (len = *), parameter :: VAR3_NAME = "Toe-San"
+  character (len = *), parameter :: VAR4_NAME = "Won-Hyo"
+  character (len = *), parameter :: VAR5_NAME = "Yul-Guk"
+  integer, parameter :: CACHE_SIZE = 8, CACHE_NELEMS = 571
+  integer, parameter :: CACHE_PREEMPTION = 66
+
+  ! Information read back from the file to check correctness.
+  integer :: varid1_in, varid2_in, varid3_in, varid4_in, varid5_in
+  integer :: xtype_in, ndims_in, natts_in, dimids_in(MAX_DIMS)
+  character (len = nf90_max_name) :: name_in
+  integer (kind = EightByteInt) :: toe_san_in(1)
+  integer :: cmode, err, ierr, get_args
+  integer(KIND=MPI_OFFSET_KIND) :: nx_ll, ny_ll
+  character(LEN=256) filename, cmd, msg
+  integer my_rank, p
+
+  call MPI_Init(ierr)
+  call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_Comm_size(MPI_COMM_WORLD, p, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      filename = FILE_NAME
+      err = get_args(cmd, filename)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+!  if (p .ne. 1 .AND. my_rank .eq. 0) then
+!     print *, 'Warning: ',trim(cmd),' is design to run on 1 process'
+!  endif
+
+  ! Create some pretend data.
+  do x = 1, NX
+     do y = 1, NY
+        data_out(y, x) = (x - 1) * NY + (y - 1)
+     end do
+  end do
+  do x = 1, NX
+        data_out_1d(x) = x
+  end do
+
+  ! Create the netCDF file. 
+  cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+  call check(nf90mpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, ncid))
+
+  ! Define the dimensions.
+  nx_ll = NX
+  ny_ll = NY
+  call check(nf90mpi_def_dim(ncid, "x", nx_ll, x_dimid))
+  call check(nf90mpi_def_dim(ncid, "y", ny_ll, y_dimid))
+  dimids =  (/ y_dimid, x_dimid /)
+
+  ! Define some variables. 
+  call check(nf90mpi_def_var(ncid, VAR1_NAME, NF90_INT, dimids, varid1))
+  call check(nf90mpi_def_var(ncid, VAR2_NAME, NF90_INT, dimids, varid2))
+  call check(nf90mpi_def_var(ncid, VAR3_NAME, NF90_INT64, varid3))
+  call check(nf90mpi_def_var(ncid, VAR4_NAME, NF90_INT, x_dimid, varid4))
+  call check(nf90mpi_def_var(ncid, VAR5_NAME, NF90_INT, dimids, varid5))
+
+  call check(nf90mpi_enddef(ncid))
+
+  ! enter independent data mode
+  call check(nf90mpi_begin_indep_data(ncid))
+
+  ! Write the pretend data to the file.
+  call check(nf90mpi_put_var(ncid, varid1, data_out))
+  call check(nf90mpi_put_var(ncid, varid2, data_out))
+  call check(nf90mpi_put_var(ncid, varid3, TOE_SAN_VALUE))
+  call check(nf90mpi_put_var(ncid, varid4, data_out_1d))
+  call check(nf90mpi_put_var(ncid, varid5, data_out))
+
+  ! Close the file. 
+  call check(nf90mpi_close(ncid))
+
+  ! Reopen the file.
+  call check(nf90mpi_open(MPI_COMM_WORLD, filename, nf90_nowrite, MPI_INFO_NULL, ncid))
+  
+  ! Check some stuff out.
+  call check(nf90mpi_inquire(ncid, ndims, nvars, ngatts, unlimdimid, file_format))
+  if (ndims /= 2 .or. nvars /= 5 .or. ngatts /= 0 .or. unlimdimid /= -1 .or. &
+       file_format /= nf90_format_cdf5) stop 2
+
+  ! Get varids.
+  call check(nf90mpi_inq_varid(ncid, VAR1_NAME, varid1_in))
+  call check(nf90mpi_inq_varid(ncid, VAR2_NAME, varid2_in))
+  call check(nf90mpi_inq_varid(ncid, VAR3_NAME, varid3_in))
+  call check(nf90mpi_inq_varid(ncid, VAR4_NAME, varid4_in))
+  call check(nf90mpi_inq_varid(ncid, VAR5_NAME, varid5_in))
+
+  ! Check variable 1.
+  call check(nf90mpi_inquire_variable(ncid, varid1_in, name_in, xtype_in, ndims_in, dimids_in, natts_in))
+  if (name_in .ne. VAR1_NAME .or. xtype_in .ne. NF90_INT .or. ndims_in .ne. MAX_DIMS .or. &
+       natts_in .ne. 0 .or. dimids_in(1) .ne. dimids(1) .or. dimids_in(2) .ne. dimids(2)) stop 3
+
+  ! Check variable 2.
+  call check(nf90mpi_inquire_variable(ncid, varid2_in, name_in, xtype_in, ndims_in, dimids_in, natts_in))
+  if (name_in .ne. VAR2_NAME .or. xtype_in .ne. NF90_INT .or. ndims_in .ne. MAX_DIMS .or. &
+       natts_in .ne. 0 .or. dimids_in(1) .ne. dimids(1) .or. dimids_in(2) .ne. dimids(2)) stop 6
+
+  ! Check variable 3.
+  call check(nf90mpi_inquire_variable(ncid, varid3_in, name_in, xtype_in, ndims_in, dimids_in, natts_in))
+  if (name_in .ne. VAR3_NAME .or. xtype_in .ne. NF90_INT64 .or. ndims_in .ne. 0 .or. &
+       natts_in .ne. 0) stop 8
+  
+  ! Check variable 4.
+  call check(nf90mpi_inquire_variable(ncid, varid4_in, name_in, xtype_in, ndims_in, dimids_in, natts_in))
+  if (name_in .ne. VAR4_NAME .or. xtype_in .ne. NF90_INT .or. ndims_in .ne. 1 .or. &
+       natts_in .ne. 0 .or. dimids_in(1) .ne. x_dimid) stop 10
+
+  ! Check the data.
+  call check(nf90mpi_get_var_all(ncid, varid1_in, data_in))
+  do x = 1, NX
+     do y = 1, NY
+        if (data_out(y, x) .ne. data_in(y, x)) stop 12
+     end do
+  end do
+  call check(nf90mpi_get_var_all(ncid, varid2_in, data_in))
+  do x = 1, NX
+     do y = 1, NY
+        if (data_out(y, x) .ne. data_in(y, x)) stop 13
+     end do
+  end do
+  call check(nf90mpi_get_var_all(ncid, varid3_in, toe_san_in))
+  if (toe_san_in(1) .ne. TOE_SAN_VALUE) stop 14
+  call check(nf90mpi_get_var_all(ncid, varid4_in, data_in_1d))
+  do x = 1, NX
+     if (data_out_1d(x) .ne. data_in_1d(x)) stop 15
+  end do
+  call check(nf90mpi_get_var_all(ncid, varid5_in, data_in))
+  do x = 1, NX
+     do y = 1, NY
+        if (data_out(y, x) .ne. data_in(y, x)) stop 12
+     end do
+  end do
+
+  ! Close the file. 
+  call check(nf90mpi_close(ncid))
+
+  msg = '*** TESTING F90 '//trim(cmd)//' for def_var API'
+  if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999 call MPI_Finalize(ierr)
+
+contains
+!     This subroutine handles errors by printing an error message and
+!     exiting with a non-zero status.
+  subroutine check(errcode)
+    implicit none
+    integer, intent(in) :: errcode
+    
+    if(errcode /= nf90_noerr) then
+       print *, 'Error: ', trim(nf90mpi_strerror(errcode))
+       stop 2
+    endif
+  end subroutine check
+end program f90tst_vars2
+
diff --git a/test/F90/f90tst_vars3.f90 b/test/F90/f90tst_vars3.f90
new file mode 100644
index 0000000..74fe403
--- /dev/null
+++ b/test/F90/f90tst_vars3.f90
@@ -0,0 +1,193 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: f90tst_vars3.f90 2136 2015-10-07 19:25:34Z wkliao $
+
+!     This program tests PnetCDF variable functions from fortran 90.
+
+program f90tst_vars3
+  use mpi
+  use pnetcdf
+  implicit none
+  
+  ! This is the name of the data file we will create.
+  character (len = *), parameter :: FILE_NAME = "f90tst_vars3.nc"
+
+  ! We are writing 2D data, a 6 x 12 grid. 
+  integer, parameter :: MAX_DIMS = 2
+  integer, parameter :: NX = 6, NY = 12
+  integer :: data_out(NY, NX), data_in(NY, NX)
+  integer :: data_out_1d(NX), data_in_1d(NX)
+
+  ! We need these ids and other gunk for netcdf.
+  integer :: ncid, varid1, varid2, varid3, varid4, varid5, dimids(MAX_DIMS)
+  integer :: x_dimid, y_dimid
+  integer :: nvars, ngatts, ndims, unlimdimid, file_format
+  integer :: x, y
+  integer, parameter :: DEFAULT_CACHE_NELEMS = 10000, DEFAULT_CACHE_SIZE = 1000000
+  integer, parameter :: DEFAULT_CACHE_PREEMPTION = 22
+  integer, parameter :: DEFLATE_LEVEL = 4
+  integer, parameter :: EightByteInt = selected_int_kind(18)
+  integer (kind = EightByteInt) :: TOE_SAN_VALUE = 2147483648_EightByteInt
+  character (len = *), parameter :: VAR1_NAME = "Chon-Ji"
+  character (len = *), parameter :: VAR2_NAME = "Tan-Gun"
+  character (len = *), parameter :: VAR3_NAME = "Toe-San"
+  character (len = *), parameter :: VAR4_NAME = "Won-Hyo"
+  character (len = *), parameter :: VAR5_NAME = "Yul-Guk"
+  integer, parameter :: CACHE_SIZE = 8, CACHE_NELEMS = 571, CACHE_PREEMPTION = 66
+
+  ! Information read back from the file to check correctness.
+  integer :: varid1_in, varid2_in, varid3_in, varid4_in, varid5_in
+  integer :: xtype_in, ndims_in, natts_in, dimids_in(MAX_DIMS)
+  character (len = nf90_max_name) :: name_in
+  integer (kind = EightByteInt) :: toe_san_in(1)
+  integer :: cmode, err, ierr, get_args
+  integer(KIND=MPI_OFFSET_KIND) :: nx_ll, ny_ll
+  character(LEN=256) filename, cmd, msg
+  integer my_rank, p
+
+  call MPI_Init(ierr)
+  call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_Comm_size(MPI_COMM_WORLD, p, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      filename = FILE_NAME
+      err = get_args(cmd, filename)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+!  if (p .ne. 1 .AND. my_rank .eq. 0) then
+!     print *, 'Warning: ',trim(cmd),' is design to run on 1 process'
+!  endif
+
+  ! Create some pretend data.
+  do x = 1, NX
+     do y = 1, NY
+        data_out(y, x) = (x - 1) * NY + (y - 1)
+     end do
+  end do
+  do x = 1, NX
+        data_out_1d(x) = x
+  end do
+
+  ! Create the netCDF file. 
+  cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+  call check(nf90mpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, ncid))
+
+  ! Define the dimensions.
+  nx_ll = NX
+  ny_ll = NY
+  call check(nf90mpi_def_dim(ncid, "x", nx_ll, x_dimid))
+  call check(nf90mpi_def_dim(ncid, "y", ny_ll, y_dimid))
+  dimids =  (/ y_dimid, x_dimid /)
+
+  ! Define some variables. 
+  call check(nf90mpi_def_var(ncid, VAR1_NAME, NF90_INT, dimids, varid1))
+  call check(nf90mpi_def_var(ncid, VAR2_NAME, NF90_INT, dimids, varid2))
+  call check(nf90mpi_def_var(ncid, VAR3_NAME, NF90_INT64, varid3))
+  call check(nf90mpi_def_var(ncid, VAR4_NAME, NF90_INT, x_dimid, varid4))
+  call check(nf90mpi_def_var(ncid, VAR5_NAME, NF90_INT, dimids, varid5))
+
+  call check(nf90mpi_enddef(ncid))
+  call check(nf90mpi_begin_indep_data(ncid))
+
+  ! Write the pretend data to the file.
+  call check(nf90mpi_put_var(ncid, varid1, data_out))
+  call check(nf90mpi_put_var(ncid, varid2, data_out))
+  call check(nf90mpi_put_var(ncid, varid3, TOE_SAN_VALUE))
+  call check(nf90mpi_put_var(ncid, varid4, data_out_1d))
+  call check(nf90mpi_put_var(ncid, varid5, data_out))
+
+  ! Close the file. 
+  call check(nf90mpi_close(ncid))
+
+  ! Reopen the file.
+  call check(nf90mpi_open(MPI_COMM_WORLD, filename, nf90_nowrite, MPI_INFO_NULL, ncid))
+  
+  ! Check some stuff out.
+  call check(nf90mpi_inquire(ncid, ndims, nvars, ngatts, unlimdimid, file_format))
+  if (ndims /= 2 .or. nvars /= 5 .or. ngatts /= 0 .or. unlimdimid /= -1 .or. &
+       file_format /= nf90_format_cdf5) stop 2
+
+  ! Get varids.
+  call check(nf90mpi_inq_varid(ncid, VAR1_NAME, varid1_in))
+  call check(nf90mpi_inq_varid(ncid, VAR2_NAME, varid2_in))
+  call check(nf90mpi_inq_varid(ncid, VAR3_NAME, varid3_in))
+  call check(nf90mpi_inq_varid(ncid, VAR4_NAME, varid4_in))
+  call check(nf90mpi_inq_varid(ncid, VAR5_NAME, varid5_in))
+
+  ! Check variable 1.
+  call check(nf90mpi_inquire_variable(ncid, varid1_in, name_in, xtype_in, ndims_in, dimids_in, natts_in)) 
+  if (name_in .ne. VAR1_NAME .or. xtype_in .ne. NF90_INT .or. ndims_in .ne. MAX_DIMS .or. &
+       natts_in .ne. 0 .or. dimids_in(1) .ne. dimids(1) .or. dimids_in(2) .ne. dimids(2)) stop 3
+
+  ! Check variable 2.
+  call check(nf90mpi_inquire_variable(ncid, varid2_in, name_in, xtype_in, ndims_in, dimids_in, natts_in))
+  if (name_in .ne. VAR2_NAME .or. xtype_in .ne. NF90_INT .or. ndims_in .ne. MAX_DIMS .or. &
+       natts_in .ne. 0 .or. dimids_in(1) .ne. dimids(1) .or. dimids_in(2) .ne. dimids(2)) stop 6
+
+  ! Check variable 3.
+  call check(nf90mpi_inquire_variable(ncid, varid3_in, name_in, xtype_in, ndims_in, dimids_in, natts_in))
+  if (name_in .ne. VAR3_NAME .or. xtype_in .ne. NF90_INT64 .or. ndims_in .ne. 0 .or. &
+       natts_in .ne. 0) stop 8
+  
+  ! Check variable 4.
+  call check(nf90mpi_inquire_variable(ncid, varid4_in, name_in, xtype_in, ndims_in, dimids_in, natts_in))
+  if (name_in .ne. VAR4_NAME .or. xtype_in .ne. NF90_INT .or. ndims_in .ne. 1 .or. &
+       natts_in .ne. 0 .or. dimids_in(1) .ne. x_dimid) stop 10
+
+  ! Check the data.
+  call check(nf90mpi_get_var_all(ncid, varid1_in, data_in))
+  do x = 1, NX
+     do y = 1, NY
+        if (data_out(y, x) .ne. data_in(y, x)) stop 12
+     end do
+  end do
+  call check(nf90mpi_get_var_all(ncid, varid2_in, data_in))
+  do x = 1, NX
+     do y = 1, NY
+        if (data_out(y, x) .ne. data_in(y, x)) stop 13
+     end do
+  end do
+  call check(nf90mpi_get_var_all(ncid, varid3_in, toe_san_in))
+  if (toe_san_in(1) .ne. TOE_SAN_VALUE) stop 14
+  call check(nf90mpi_get_var_all(ncid, varid4_in, data_in_1d))
+  do x = 1, NX
+     if (data_out_1d(x) .ne. data_in_1d(x)) stop 15
+  end do
+  call check(nf90mpi_get_var_all(ncid, varid5_in, data_in))
+  do x = 1, NX
+     do y = 1, NY
+        if (data_out(y, x) .ne. data_in(y, x)) stop 12
+     end do
+  end do
+
+  ! Close the file. 
+  call check(nf90mpi_close(ncid))
+
+  msg = '*** TESTING F90 '//trim(cmd)//' for def_var API'
+  if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999 call MPI_Finalize(ierr)
+
+contains
+!     This subroutine handles errors by printing an error message and
+!     exiting with a non-zero status.
+  subroutine check(errcode)
+    implicit none
+    integer, intent(in) :: errcode
+    
+    if(errcode /= nf90_noerr) then
+       print *, 'Error: ', trim(nf90mpi_strerror(errcode))
+       stop 2
+    endif
+  end subroutine check
+end program f90tst_vars3
+
diff --git a/test/F90/f90tst_vars4.f90 b/test/F90/f90tst_vars4.f90
new file mode 100644
index 0000000..c4fdfbd
--- /dev/null
+++ b/test/F90/f90tst_vars4.f90
@@ -0,0 +1,131 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: f90tst_vars4.f90 2131 2015-09-25 22:33:12Z wkliao $
+
+!     This program tests PnetCDF variable functions from fortran 90.
+
+program f90tst_vars4
+  use mpi
+  use pnetcdf
+  implicit none
+
+  ! This is the name of the data file we will create.
+  character (len = *), parameter :: FILE_NAME = "f90tst_vars4.nc"
+
+  integer, parameter :: MAX_DIMS = 2
+  integer, parameter :: NX = 40, NY = 4096
+  integer :: data_out(NY, NX), data_in(NY, NX)
+
+  ! We need these ids and other gunk for netcdf.
+  integer :: ncid, varid, dimids(MAX_DIMS)
+  integer :: x_dimid, y_dimid
+  integer :: mode_flag
+  integer :: nvars, ngatts, ndims, unlimdimid, file_format
+  integer :: x, y
+  integer, parameter :: CACHE_SIZE = 1000000
+  integer :: xtype_in, natts_in, dimids_in(MAX_DIMS)
+  character (len = NF90_MAX_NAME) :: name_in
+  integer :: err, ierr, get_args
+  integer(KIND=MPI_OFFSET_KIND) :: nx_ll, ny_ll
+  character(LEN=256) filename, cmd, msg
+  integer my_rank, p
+
+  call MPI_Init(ierr)
+  call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_Comm_size(MPI_COMM_WORLD, p, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      filename = FILE_NAME
+      err = get_args(cmd, filename)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+!  if (p .ne. 1 .AND. my_rank .eq. 0) then
+!     print *, 'Warning: ',trim(cmd),' is design to run on 1 process'
+!  endif
+
+  ! Create some pretend data.
+  do x = 1, NX
+     do y = 1, NY
+        data_out(y, x) = (x - 1) * NY + (y - 1)
+     end do
+  end do
+
+  ! Create the netCDF file. 
+  mode_flag = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+  call handle_err(nf90mpi_create(MPI_COMM_WORLD, filename, mode_flag, MPI_INFO_NULL, ncid))
+
+  ! Define the dimensions.
+  nx_ll = NX
+  ny_ll = NY
+  call handle_err(nf90mpi_def_dim(ncid, "x", nx_ll, x_dimid))
+  call handle_err(nf90mpi_def_dim(ncid, "y", ny_ll, y_dimid))
+  dimids =  (/ y_dimid, x_dimid /)
+
+  ! Define the variable. 
+  call handle_err(nf90mpi_def_var(ncid, 'data', NF90_INT, dimids, varid))
+
+  ! enddef must be called.
+  call handle_err(nf90mpi_enddef(ncid))
+
+  call handle_err(nf90mpi_begin_indep_data(ncid))
+
+  ! Write the pretend data to the file.
+  call handle_err(nf90mpi_put_var(ncid, varid, data_out))
+
+  ! Close the file. 
+  call handle_err(nf90mpi_close(ncid))
+
+  ! Reopen the file.
+  call handle_err(nf90mpi_open(MPI_COMM_WORLD, filename, nf90_nowrite, MPI_INFO_NULL, ncid))
+  
+  ! Check some stuff out.
+  call handle_err(nf90mpi_inquire(ncid, ndims, nvars, ngatts, unlimdimid, file_format))
+  if (ndims /= 2 .or. nvars /= 1 .or. ngatts /= 0 .or. unlimdimid /= -1 .or. &
+       file_format /= nf90_format_cdf5) stop 3
+
+  call handle_err(nf90mpi_inquire_variable(ncid, varid, name_in, xtype_in, ndims, dimids_in, &
+       natts_in))
+  if (name_in .ne. 'data' .or. xtype_in .ne. NF90_INT .or. ndims .ne. MAX_DIMS .or. &
+       dimids_in(1) /= y_dimid .or. dimids_in(2) /= x_dimid .or. &
+       natts_in .ne. 0) &
+       stop 4
+
+  ! Check the data.
+  call handle_err(nf90mpi_get_var_all(ncid, varid, data_in))
+  do x = 1, NX
+     do y = 1, NY
+        if (data_out(y, x) .ne. data_in(y, x)) stop 3
+     end do
+  end do
+
+  ! Close the file. 
+  call handle_err(nf90mpi_close(ncid))
+
+  msg = '*** TESTING F90 '//trim(cmd)//' for def_var API'
+  if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999 call MPI_Finalize(ierr)
+
+contains
+!     This subroutine handles errors by printing an error message and
+!     exiting with a non-zero status.
+  subroutine handle_err(errcode)
+    implicit none
+    integer, intent(in) :: errcode
+    
+    if(errcode /= nf90_noerr) then
+       print *, 'Error: ', trim(nf90mpi_strerror(errcode))
+       stop 2
+    endif
+  end subroutine handle_err
+end program f90tst_vars4
+
diff --git a/test/F90/test_intent.f90 b/test/F90/test_intent.f90
new file mode 100644
index 0000000..0a0c607
--- /dev/null
+++ b/test/F90/test_intent.f90
@@ -0,0 +1,150 @@
+!
+!   Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_intent.f90 2231 2015-12-16 21:08:02Z wkliao $
+
+!
+! This program tests Fortran 90 INTENT modifier used in PnetCDF.
+! It also tests put_att on Little Endian when using parameter
+! buffer (read-only memory)
+!
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+          character(len=256) msg
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              msg = '*** TESTING F90 test_intent.f90 '
+              call pass_fail(1, msg)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          integer, parameter ::   OneByteInt = selected_int_kind(2), &
+                                  TwoByteInt = selected_int_kind(4), &
+                                 FourByteInt = selected_int_kind(9), &
+                                EightByteInt = selected_int_kind(18)
+
+          character(LEN=256) filename, cmd, msg
+          integer err, ierr, rank, get_args
+          integer cmode, ncid, varid, dimid(1), req(1), status(1)
+          integer(kind=MPI_OFFSET_KIND) start(1)
+          integer(kind=MPI_OFFSET_KIND) count(1)
+          integer(kind=MPI_OFFSET_KIND) bufsize
+
+          character(LEN=3)           cbuf
+          integer(KIND=OneByteInt)   i1buf(3)
+          integer(KIND=TwoByteInt)   sbuf(3)
+          integer                    ibuf(3)
+          real                       rbuf(3)
+          double precision           dbuf(3)
+          integer(KIND=EightByteInt) i8buf(3)
+
+          PARAMETER( cbuf="123")
+          PARAMETER(i1buf=(/1_OneByteInt,2_OneByteInt,3_OneByteInt/))
+          PARAMETER( sbuf=(/1_TwoByteInt,2_TwoByteInt,3_TwoByteInt/))
+          PARAMETER( ibuf=(/1,2,3/))
+          PARAMETER( rbuf=(/1.0,2.0,3.0/))
+          PARAMETER( dbuf=(/1.0,2.0,3.0/))
+          PARAMETER(i8buf=(/1_EightByteInt,2_EightByteInt,3_EightByteInt/))
+
+          call MPI_Init(ierr)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              filename = 'testfile.nc'
+              err = get_args(cmd, filename)
+          endif
+          call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+          if (err .EQ. 0) goto 999
+
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          err = nf90mpi_put_att(ncid, NF90_GLOBAL, 'nf90_attr_text', cbuf)
+          call check(err, 'In nf90mpi_put_att: ')
+          err = nf90mpi_put_att(ncid, NF90_GLOBAL, 'nf90_attr_int1', i1buf)
+          call check(err, 'In nf90mpi_put_att: ')
+          err = nf90mpi_put_att(ncid, NF90_GLOBAL, 'nf90_attr_int2', sbuf)
+          call check(err, 'In nf90mpi_put_att: ')
+          err = nf90mpi_put_att(ncid, NF90_GLOBAL, 'nf90_attr_int', ibuf)
+          call check(err, 'In nf90mpi_put_att: ')
+          err = nf90mpi_put_att(ncid, NF90_GLOBAL, 'nf90_attr_real', rbuf)
+          call check(err, 'In nf90mpi_put_att: ')
+          err = nf90mpi_put_att(ncid, NF90_GLOBAL, 'nf90_attr_double', dbuf)
+          call check(err, 'In nf90mpi_put_att: ')
+          err = nf90mpi_put_att(ncid, NF90_GLOBAL, 'nf90_attr_int8', i8buf)
+          call check(err, 'In nf90mpi_put_att: ')
+
+          err = nfmpi_put_att_text(ncid, NF90_GLOBAL, 'nf_attr_text', 3_MPI_OFFSET_KIND, cbuf)
+          call check(err, 'In nfmpi_put_att_text: ')
+          err = nfmpi_put_att_int1(ncid, NF90_GLOBAL, 'nf_attr_int1', NF90_INT1, 3_MPI_OFFSET_KIND, i1buf)
+          call check(err, 'In nfmpi_put_att_int1: ')
+          err = nfmpi_put_att_int2(ncid, NF90_GLOBAL, 'nf_attr_int2', NF90_INT2, 3_MPI_OFFSET_KIND, sbuf)
+          call check(err, 'In nfmpi_put_att_int2: ')
+          err = nfmpi_put_att_int(ncid, NF90_GLOBAL, 'nf_attr_int', NF90_INT, 3_MPI_OFFSET_KIND, ibuf)
+          call check(err, 'In nfmpi_put_att_int: ')
+          err = nfmpi_put_att_real(ncid, NF90_GLOBAL, 'nf_attr_real', NF90_FLOAT, 3_MPI_OFFSET_KIND, rbuf)
+          call check(err, 'In nfmpi_put_att_real: ')
+          err = nfmpi_put_att_double(ncid, NF90_GLOBAL, 'nf_attr_double', NF90_DOUBLE, 3_MPI_OFFSET_KIND, dbuf)
+          call check(err, 'In nfmpi_put_att_double: ')
+          err = nfmpi_put_att_int8(ncid, NF90_GLOBAL, 'nf_attr_int8', NF90_INT64, 3_MPI_OFFSET_KIND, i8buf)
+          call check(err, 'In nfmpi_put_att_int8: ')
+
+          ! define a variable of an integer array of size 3 in the nc file
+          err = nfmpi_def_dim(ncid, 'X', 3_MPI_OFFSET_KIND, dimid(1))
+          call check(err, 'In nfmpi_def_dim: ')
+
+          err = nfmpi_def_var(ncid, 'var', NF90_INT, 1, dimid, varid)
+          call check(err, 'In nfmpi_def_var: ')
+
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! bufsize must be max of data type converted before and after
+          bufsize = 3*4
+          err = nfmpi_buffer_attach(ncid, bufsize)
+          call check(err, 'In nfmpi_buffer_attach: ')
+
+          start(1) = 1
+          count(1) = 3
+          err = nfmpi_bput_vara_int(ncid, varid, start, count, ibuf, req(1))
+          call check(err, 'In nfmpi_bput_vara_int: ')
+
+          err = nfmpi_wait_all(ncid, 1, req, status)
+          call check(err, 'In nfmpi_wait_all: ')
+
+          if (status(1) .ne. NF90_NOERR) then
+              print*,'Error at bput status ', nfmpi_strerror(status(1))
+          endif
+
+          err = nfmpi_buffer_detach(ncid)
+          call check(err, 'In nfmpi_buffer_detach: ')
+
+          ! close the file
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          msg = '*** TESTING F90 '//trim(cmd)//' for INTENT modifier '
+          if (rank .eq. 0) call pass_fail(0, msg)
+
+ 999      call MPI_Finalize(ierr)
+      end program main
+
diff --git a/test/F90/tst_f90.f90 b/test/F90/tst_f90.f90
new file mode 100644
index 0000000..4b57043
--- /dev/null
+++ b/test/F90/tst_f90.f90
@@ -0,0 +1,207 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: tst_f90.f90 2136 2015-10-07 19:25:34Z wkliao $
+
+! This program provides an elementary check of some of the parts of the 
+!   Fortran 90 interface to netCDF 3.5. It is a Fortran 90 implementation
+!   of the nctst.cpp program provided with the C++ interface to netcdf
+!   (in the src/cxx directory of the netcdf distribution). 
+!
+module typeSizes
+  implicit none
+  public
+  integer, parameter ::   OneByteInt = selected_int_kind(2), &
+                          TwoByteInt = selected_int_kind(4), &
+                         FourByteInt = selected_int_kind(9), &
+                        EightByteInt = selected_int_kind(18)
+
+  integer, parameter ::                                          &
+                        FourByteReal = selected_real_kind(P =  6, R =  37), &
+                       EightByteReal = selected_real_kind(P = 13, R = 307)
+contains
+  logical function byteSizesOK()
+  ! Users may call this function once to ensure that the kind parameters 
+  !   the module defines are available with the current compiler. 
+  ! We can't ensure that the two REAL kinds are actually four and 
+  !   eight bytes long, but we can ensure that they are distinct. 
+  ! Early Fortran 90 compilers would sometimes report incorrect results for 
+  !   the bit_size intrinsic, but I haven't seen this in a long time. 
+
+    ! Local variables
+    integer (kind =  OneByteInt) :: One
+    integer (kind =  TwoByteInt) :: Two
+    integer (kind = FourByteInt) :: Four
+
+    if (bit_size( One) == 8  .and. bit_size( Two) == 16 .and.  &
+        bit_size(Four) == 32 .and.                             &
+        FourByteReal > 0 .and. EightByteReal > 0 .and. &
+        FourByteReal /= EightByteReal) then
+      byteSizesOK = .true.
+    else
+      byteSizesOK = .false.
+    end if
+  end function byteSizesOK
+end module typeSizes
+
+program netcdfTest
+  use mpi
+  use typeSizes
+  use pnetcdf
+  implicit none
+  
+  ! netcdf related variables
+  integer :: ncFileID,                                   &
+             latDimID, lonDimID, frTimeDimID, timeDimID, &
+             pressVarID, latVarID, lonVarID, frTimeVarID, refTimeVarID, scalarVarID
+             
+  ! Local variables
+  integer (kind = EightByteInt), parameter :: numLats = 4, numLons = 3, &
+                        numFrTimes = 2, timeStringLen = 20
+  character (len = *), parameter :: FILE_NAME = "tst_f90.nc"
+  integer :: counter, err, ierr, get_args
+  real, dimension(numLons, numLats, numFrTimes) :: pressure
+  integer (kind = FourByteInt), dimension(numFrTimes) :: frTimeVals
+  real (kind = FourByteReal) fillVal, scalarVarBuf
+  real (kind = FourByteReal), dimension(2) :: validRange
+  character (len = 20) frTimeUnits
+  real (kind = FourByteReal), dimension(numLats) :: latVarBuf
+  real (kind = FourByteReal), dimension(numLons) :: lonVarBuf
+  character(LEN=256) filename, cmd, msg
+  integer my_rank, p, info
+
+  call MPI_Init(ierr)
+  call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_Comm_size(MPI_COMM_WORLD, p, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      filename = FILE_NAME
+      err = get_args(cmd, filename)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+!  if (p .ne. 1 .AND. my_rank .eq. 0) then
+!     print *, 'Warning: ',trim(cmd),' is design to run on 1 process'
+!  endif
+
+! --------------------
+  ! Code begins
+  ! --------------------
+  if(.not. byteSizesOK()) then
+    print *, "Compiler does not appear to support required kinds of variables."
+    stop
+  end if
+
+  call MPI_Info_create(info, ierr)
+  ! call MPI_Info_set(info, "romio_pvfs2_posix_write", "enable",ierr)
+
+  ! Create the file
+  call check(nf90mpi_create(MPI_COMM_WORLD, filename, nf90_clobber, info, ncFileID))
+  
+  ! Define the dimensions
+  call check(nf90mpi_def_dim(ncid = ncFileID, name = "lat",     len = numLats,           dimid = latDimID))
+  call check(nf90mpi_def_dim(ncid = ncFileID, name = "lon",     len = numLons,           dimid = lonDimID))
+  call check(nf90mpi_def_dim(ncid = ncFileID, name = "frtime",  len = nf90mpi_unlimited, dimid = frTimeDimID))
+  call check(nf90mpi_def_dim(ncid = ncFileID, name = "timelen", len = timeStringLen,     dimid = timeDimID))
+
+  ! Create variables and attributes
+  call check(nf90mpi_def_var(ncid = ncFileID, name = "P", xtype = nf90_float,     &
+                     dimids = (/ lonDimID, latDimID, frTimeDimID /), varID = pressVarID) )
+  call check(nf90mpi_put_att(ncFileID, pressVarID, "long_name",   "pressure at maximum wind"))
+  call check(nf90mpi_put_att(ncFileID, pressVarID, "units",       "hectopascals") )
+  ! Use 4-byte reals explicitly, to match 4-byte attribute type in test file
+  validRange(1) = 0.
+  validRange(2) = 1500
+  call check(nf90mpi_put_att(ncFileID, pressVarID, "valid_range", validRange))
+  ! Use a 4-byte float constant, to match variable type
+  fillVal = -9999.0
+  call check(nf90mpi_put_att(ncFileID, pressVarID,  "_FillValue", fillVal ) )
+                      
+  call check(nf90mpi_def_var(ncFileID, "lat", nf90_float, dimids = latDimID, varID = latVarID) )
+  call check(nf90mpi_put_att(ncFileID, latVarID, "long_name", "latitude"))
+  call check(nf90mpi_put_att(ncFileID, latVarID, "units", "degrees_north"))
+
+  call check(nf90mpi_def_var(ncFileID, "lon", nf90_float, lonDimID, lonVarID) )
+  call check(nf90mpi_put_att(ncFileID, lonVarID, "long_name", "longitude"))
+  call check(nf90mpi_put_att(ncFileID, lonVarID, "units",     "degrees_east"))
+
+  call check(nf90mpi_def_var(ncFileID, "frtime", nf90_int, frTimeDimID, frTimeVarID) )
+  call check(nf90mpi_put_att(ncFileID, frTimeVarID, "long_name", "forecast time"))
+  call check(nf90mpi_put_att(ncFileID, frTimeVarID, "units",     "hours"))
+
+  call check(nf90mpi_def_var(ncFileID, "reftime", nf90_char, timeDimID, refTimeVarID) )
+  call check(nf90mpi_put_att(ncFileID, refTimeVarID, "long_name", "reference time"))
+  call check(nf90mpi_put_att(ncFileID, refTimeVarID, "units",     "text_time"))
+                     
+  ! In the C++ interface the define a scalar variable - do we know how to do this? 
+  call check(nf90mpi_def_var(ncFileID, "ScalarVariable", nf90_real, scalarVarID))
+  
+  ! Global attributes
+  call check(nf90mpi_put_att(ncFileID, nf90_global, "history", &
+                     "created by Unidata LDM from NPS broadcast"))
+  call check(nf90mpi_put_att(ncFileID, nf90_global, "title", &
+                     "NMC Global Product Set: Pressure at Maximum Wind"))
+  
+  ! Leave define mode
+  call check(nf90mpi_enddef(ncfileID))
+  
+  ! Write the dimension variables
+  latVarBuf = (/ -90., -87.5, -85., -82.5 /)
+  call check(nf90mpi_put_var_all(ncFileID, latVarID, latVarBuf))
+  lonVarBuf = (/ -180, -175, -170 /)
+  call check(nf90mpi_put_var_all(ncFileID, lonVarID, lonVarBuf))
+  ! Don't use anonymous array here, in case platform has 8-byte integers
+  frTimeVals(1) = 12
+  frTimeVals(2) = 18
+  call check(nf90mpi_put_var_all(ncFileID, frTimeVarID,  frTimeVals                  ) )
+  call check(nf90mpi_put_var_all(ncFileID, reftimeVarID, "1992-3-21 12:00"           ) )
+  
+  ! Write the pressure variable. Write a slab at a time to check incrementing.
+  pressure = 949. + real(reshape( (/ (counter, counter = 1, numLats * numLons * numFrTimes) /),  &
+                                    (/ numLons, numLats, numFrTimes /) ) )
+  call check(nf90mpi_put_var_all(ncFileID, pressVarID, pressure(:, :, 1:1)) )
+  call check(nf90mpi_put_var_all(ncFileID, pressVarID, pressure(:, :, 2:2), &
+                                 start = (/ 1_EightByteInt, 1_EightByteInt, 2_EightByteInt /)) )
+  
+  call check(nfmpi_begin_indep_data(ncFileID))
+  scalarVarBuf = 10
+  call check(nf90mpi_put_var(ncFileID, scalarVarID, scalarVarBuf))
+  call check(nfmpi_end_indep_data(ncFileID))
+
+  call check(nf90mpi_close(ncFileID))
+
+  ! Now open the file to read and check a few values
+  call check(nf90mpi_open(MPI_COMM_WORLD, filename, NF90_NOWRITE, info, ncFileID))
+  call check(nf90mpi_inq_varid(ncFileID,"frtime",frTimeVarID))
+  call check(nf90mpi_get_att(ncFileID,frTimeVarID,"units",frTimeUnits))
+  if(frTimeUnits .ne. "hours") then
+     print *, 'Attribute value not what was written:', frTimeUnits
+     stop 2
+  endif
+  call check(nf90mpi_close(ncFileID))
+  call MPI_Info_free(info, ierr)
+
+  msg = '*** TESTING F90 '//trim(cmd)
+  if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999 call MPI_Finalize(ierr)
+
+contains
+  ! Internal subroutine - checks error status after each netcdf, prints out text message each time
+  !   an error code is returned. 
+  subroutine check(status)
+    integer, intent ( in) :: status
+    
+    if(status /= nf90_noerr) then 
+      print *, trim(nf90mpi_strerror(status))
+      stop 2
+    end if
+  end subroutine check  
+end program netcdfTest
diff --git a/test/F90/tst_f90_cdf5.f90 b/test/F90/tst_f90_cdf5.f90
new file mode 100644
index 0000000..a62fcbe
--- /dev/null
+++ b/test/F90/tst_f90_cdf5.f90
@@ -0,0 +1,79 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: tst_f90_cdf5.f90 2131 2015-09-25 22:33:12Z wkliao $
+
+
+program tst_f90_nc4
+  use mpi
+  use pnetcdf
+  implicit none
+  integer :: fh, cmode, err, ierr, dimid, varid, ndim, nvar, get_args
+  character (len = *), parameter :: FILE_NAME = "tst_f90_nc4.nc"
+  integer(KIND=MPI_OFFSET_KIND) :: ten=10
+  character(LEN=256) filename, cmd, msg
+  integer my_rank, p
+
+  call MPI_Init(ierr)
+  call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_Comm_size(MPI_COMM_WORLD, p, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      filename = FILE_NAME
+      err = get_args(cmd, filename)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+!  if (p .ne. 1 .AND. my_rank .eq. 0) then
+!     print *, 'Warning: ',trim(cmd),' is design to run on 1 process'
+!  endif
+
+  cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+  call check(nf90mpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, fh))
+  call check(nf90mpi_def_dim(fh, 'fred', ten, dimid))
+  call check(nf90mpi_def_var(fh, 'john', NF90_INT, (/dimid/), varid))
+  call check(nf90mpi_close(fh))
+  
+  ! Check the file.
+  call check(nf90mpi_open(MPI_COMM_WORLD, filename, NF90_WRITE, MPI_INFO_NULL, fh))
+  call check(nf90mpi_inquire(fh, nDimensions = ndim, nVariables = nvar))
+  if (nvar .ne. 1 .or. ndim .ne. 1) stop 3
+  call check(nf90mpi_close(fh))
+
+  call check(nf90mpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, fh))
+  call check(nf90mpi_def_dim(fh, 'fred', ten, dimid))
+  call check(nf90mpi_def_var(fh, 'john', NF90_INT, (/dimid/), varid))
+  call check(nf90mpi_close(fh))
+  
+  ! Check the file.
+  call check(nf90mpi_open(MPI_COMM_WORLD, filename, NF90_WRITE, MPI_INFO_NULL, fh))
+  call check(nf90mpi_inquire(fh, nDimensions = ndim, nVariables = nvar))
+  if (nvar .ne. 1 .or. ndim .ne. 1) stop 3
+  call check(nf90mpi_close(fh))
+
+   msg = '*** TESTING F90 '//trim(cmd)
+   if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999 call MPI_Finalize(ierr)
+
+contains
+!     This subroutine handles errors by printing an error message and
+!     exiting with a non-zero status.
+  subroutine check(errcode)
+    implicit none
+    integer, intent(in) :: errcode
+    
+    if(errcode /= nf90_noerr) then
+       print *, 'Error: ', trim(nf90mpi_strerror(errcode))
+       stop 2
+    endif
+  end subroutine check
+end program tst_f90_nc4
+
diff --git a/test/F90/tst_flarge.f90 b/test/F90/tst_flarge.f90
new file mode 100644
index 0000000..b228da0
--- /dev/null
+++ b/test/F90/tst_flarge.f90
@@ -0,0 +1,102 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: tst_flarge.f90 2131 2015-09-25 22:33:12Z wkliao $
+
+! This program tests large files (> 4 GB)
+
+program tst_flarge
+  use mpi
+  use pnetcdf
+  implicit none
+
+  integer :: ncFileID, dimID, varID1, varID2 
+  integer(KIND=MPI_OFFSET_KIND) :: BIG_DIMENSION = 300000000
+  character (len = *), parameter :: FILE_NAME = "tst_flarge.nc"
+  character (len = *), parameter :: dimName = "really_big_dimension"
+  character (len = *), parameter :: var1Name = "TweedleDum"
+  character (len = *), parameter :: var2Name = "TweedleDee"
+  double precision, parameter :: VAL1 = 42.5
+  double precision, parameter :: VAL2 = -42.5
+  double precision :: val1_in
+  double precision :: val2_in
+  integer :: cmode, err, ierr, get_args
+  double precision dbl_buf(1)
+  integer(KIND=MPI_OFFSET_KIND) :: start(1), count(1)
+  character(LEN=256) filename, cmd, msg
+  integer my_rank, p
+
+  call MPI_Init(ierr)
+  call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_Comm_size(MPI_COMM_WORLD, p, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      filename = FILE_NAME
+      err = get_args(cmd, filename)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+!  if (p .ne. 1 .AND. my_rank .eq. 0) then
+!     print *, 'Warning: ',trim(cmd),' is design to run on 1 process'
+!  endif
+
+  ! Create the file with 2 NF90_DOUBLE vars, each with one really long dimension.
+  cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+  call check(nf90mpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, ncFileID))
+  call check(nf90mpi_def_dim(ncFileID, dimName, BIG_DIMENSION, dimID))
+  call check(nf90mpi_def_var(ncFileID, var1Name, nf90_double, (/ dimID /), varID1) )
+  call check(nf90mpi_def_var(ncFileID, var2Name, nf90_double, (/ dimID /), varID2) )
+
+  call check(nf90mpi_enddef(ncFileID))
+  call check(nf90mpi_begin_indep_data(ncFileID))
+
+  ! Write a value in each variable.
+  dbl_buf(1) = 42.5
+  start(1) = 1
+  count(1) = 1
+  call check(nf90mpi_put_var(ncFileID, VarID1, dbl_buf, start, count))
+  dbl_buf(1) = -42.5
+  start(1) = BIG_DIMENSION
+  count(1) = 1
+  call check(nf90mpi_put_var(ncFileID, VarID2, dbl_buf, start, count))
+
+  call check(nf90mpi_close(ncFileID))
+
+  ! Now open the file to read and check a few values
+  call check(nf90mpi_open(MPI_COMM_WORLD, filename, NF90_NOWRITE, MPI_INFO_NULL, ncFileID))
+  call check(nf90mpi_begin_indep_data(ncFileID))
+  start(1) = 1
+  call check(nf90mpi_get_var(ncFileID, VarID1, val1_in, start))
+  start(1) = BIG_DIMENSION
+  call check(nf90mpi_get_var(ncFileID, VarID2, val2_in, start))
+  if(val1_in /= VAL1 .or. val2_in /= VAL2) then
+     print *, 'Variable value not what was written'
+     stop 2
+  end if
+
+  call check(nf90mpi_close(ncFileID))
+
+  msg = '*** TESTING F90 '//trim(cmd)//' for large files'
+  if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999  call MPI_Finalize(ierr)
+
+contains
+  ! Internal subroutine - checks error status after each netcdf, prints out text message each time
+  !   an error code is returned. 
+  subroutine check(status)
+    integer, intent ( in) :: status
+
+    if(status /= nf90_noerr) then 
+       print *, trim(nf90mpi_strerror(status))
+       stop 2
+    end if
+  end subroutine check
+end program tst_flarge
diff --git a/test/F90/tst_io.f90 b/test/F90/tst_io.f90
new file mode 100644
index 0000000..29f2d55
--- /dev/null
+++ b/test/F90/tst_io.f90
@@ -0,0 +1,176 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: tst_io.f90 2147 2015-10-09 23:50:26Z wkliao $
+
+! This program tests large files (> 4 GB) in PnetCDF. 
+
+program tst_io
+  use mpi
+  use pnetcdf
+  implicit none
+  integer, parameter :: EightByteInt = selected_int_kind(18)
+  integer(kind=EightByteInt), parameter :: prsz1 = 50, prsz2 = 50, &
+       prsz3 = 50, prsz4 = 50, repct = 10
+  integer :: i1, i2, i3, i4
+  real :: psr
+  integer :: err, ierr, get_args
+  integer :: start, now, ncint1, ncint2, size
+  ! integer :: wrint1, wrint2, wrint3, ncint3
+  real, dimension (prsz1, prsz2, prsz3, prsz4) :: s, t, u, v, w, x, y, z
+  character(len = *), parameter :: nclFilenm1 = 'tst_io1.nc', &
+       nclFilenm2 = 'tst_io2.nc', nclFilenm3 = 'tst_io3.nc', &
+       nclFilenm4 = 'tst_io4.nc', nclFilenm5 = 'tst_io5.nc', &
+       nclFilenm6 = 'tst_io6.nc', nclFilenm7 = 'tst_io7.nc', &
+       nclFilenm8 = 'tst_io8.nc', nclFilenm9 = 'tst_io9.nc', &
+       nclFilenm10 = 'tst_io10.nc', nclFilenm11 = 'tst_io11.nc'
+  ! needed for netcdf
+  integer :: ncid, x1id, x2id, x3id, x4id, vrid
+  ! integer :: vrids, vridt, vridu, vridv, vridw, vridx, vridy, vridz
+  character(LEN=256) dirpath, cmd, msg
+  integer my_rank, p
+
+  call MPI_Init(ierr)
+  call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_Comm_size(MPI_COMM_WORLD, p, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      dirpath = '.'
+      err = get_args(cmd, dirpath)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(dirpath, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+!  if (p .ne. 1 .AND. my_rank .eq. 0) then
+!     print *, 'Warning: ',trim(cmd),' is design to run on 1 process'
+!  endif
+
+  psr = 1.7/real(prsz1)
+  ! print *, "Starting data initialization."
+  size = (prsz1 * prsz2 * prsz3 * prsz4 )/ 250000
+  do i1 = 1, prsz1
+     do i2 = 1, prsz2
+        do i3 = 1, prsz3 ! Jackson Pollock it is not
+           do i4 = 1, prsz4
+              x(i1, i2, i3, i4) = sin(i1*psr)*(0.5 + cos(i2*psr))+(psr/i3)+ i4/(10.0*prsz4)
+              s(i1, i2, i3, i4) = x(i1, i2, i3, i4) - 5.0
+              t(i1, i2, i3, i4) = x(i1, i2, i3, i4) - 4.0
+              u(i1, i2, i3, i4) = x(i1, i2, i3, i4) - 3.0
+              v(i1, i2, i3, i4) = x(i1, i2, i3, i4) - 2.0
+              w(i1, i2, i3, i4) = x(i1, i2, i3, i4) - 1.0
+              y(i1, i2, i3, i4) = x(i1, i2, i3, i4) + 1.0
+              z(i1, i2, i3, i4) = x(i1, i2, i3, i4) + 2.0
+           enddo
+        enddo
+     enddo
+  enddo
+
+  ! call setupNetCDF (trim(dirpath)//'/'//nclFilenm1, ncid, vrid, x, prsz1, prsz2, prsz3, prsz4, &
+  call setupNetCDF (trim(dirpath)//'/'//nclFilenm1, ncid, vrid, prsz1, prsz2, prsz3, prsz4, &
+       x1id, x2id, x3id, x4id, NF90_CLOBBER, 20)
+  call system_clock(start)
+  call check(nfmpi_begin_indep_data(ncid), 11)
+  call check (NF90MPI_PUT_VAR(ncid, vrid, x), 18)
+  call check(nfmpi_end_indep_data(ncid), 11)
+  call system_clock(now)
+  ncint1 = now - start
+!   print 3, size, "MB"," netcdf write = ", ncint1 * clockRate, &
+!        real(ncint1)/real (wrint1)
+! 3 format("Time for", i5, a, a25, i7, " msec. Spd ratio = ", f5.2)
+
+  call check (NF90MPI_CLOSE(ncid), 14)
+
+  call system_clock(start)
+  do i1 = 1, repct
+     ! call setupNetCDF (trim(dirpath)//'/'//nclFilenm1, ncid, vrid, x, prsz1, prsz2, prsz3, prsz4, &
+     call setupNetCDF (trim(dirpath)//'/'//nclFilenm1, ncid, vrid, prsz1, prsz2, prsz3, prsz4, &
+          x1id, x2id, x3id, x4id, NF90_CLOBBER, 130)
+     call check(nfmpi_begin_indep_data(ncid), 11)
+     call check (NF90MPI_PUT_VAR(ncid, vrid, x), 23 + i1)
+     call check(nfmpi_end_indep_data(ncid), 11)
+     call check (NF90MPI_CLOSE(ncid), 15)
+  enddo
+  call system_clock(now)
+  ncint2 = now - start
+!   print 4, size, repct, " repeated netcdf writes = ", ncint2 * clockRate, &
+!        real(ncint2)/real(wrint2);
+! 4 format("Time for", i5, "MB", i3, a22, i7, " msec. Spd ratio = ", f5.2)
+
+!  call system_clock(start)
+!  call setupNetCDF (trim(dirpath)//'/'//nclFilenm3, ncid, vrids, s, prsz1, prsz2, prsz3, prsz4, &
+!       x1id, x2id, x3id, x4id, NF90_CLOBBER, 20)
+!  call setupNetCDF (trim(dirpath)//'/'//nclFilenm4, ncid, vridt, t, prsz1, prsz2, prsz3, prsz4, &
+!       x1id, x2id, x3id, x4id, NF90_CLOBBER, 30)
+!  call setupNetCDF (trim(dirpath)//'/'//nclFilenm5, ncid, vridu, u, prsz1, prsz2, prsz3, prsz4, &
+!       x1id, x2id, x3id, x4id, NF90_CLOBBER, 40)
+!  call setupNetCDF (trim(dirpath)//'/'//nclFilenm6, ncid, vridv, v, prsz1, prsz2, prsz3, prsz4, &
+!       x1id, x2id, x3id, x4id, NF90_CLOBBER, 50)
+!  call setupNetCDF (trim(dirpath)//'/'//nclFilenm7, ncid, vridw, w, prsz1, prsz2, prsz3, prsz4, &
+!       x1id, x2id, x3id, x4id, NF90_CLOBBER, 60)
+!  call setupNetCDF (trim(dirpath)//'/'//nclFilenm8, ncid, vridx, x, prsz1, prsz2, prsz3, prsz4, &
+!       x1id, x2id, x3id, x4id, NF90_CLOBBER, 70)
+!  call setupNetCDF (trim(dirpath)//'/'//nclFilenm9, ncid, vridy, y, prsz1, prsz2, prsz3, prsz4, &
+!       x1id, x2id, x3id, x4id, NF90_CLOBBER, 80)
+!  call setupNetCDF (trim(dirpath)//'/'//nclFilenm10, ncid, vridz, z, prsz1, prsz2, prsz3, prsz4, &
+!       x1id, x2id, x3id, x4id, NF90_CLOBBER, 90)
+!  call check(nfmpi_begin_indep_data(ncid), 11)
+!  call check (NF90MPI_PUT_VAR(ncid, vrids, s), 118)
+!  call check (NF90MPI_PUT_VAR(ncid, vridt, t), 119)
+!  call check (NF90MPI_PUT_VAR(ncid, vridu, u), 120)
+!  call check (NF90MPI_PUT_VAR(ncid, vridv, v), 121)
+!  call check (NF90MPI_PUT_VAR(ncid, vridw, w), 122)
+!  call check (NF90MPI_PUT_VAR(ncid, vridx, x), 123)
+!  call check (NF90MPI_PUT_VAR(ncid, vridy, y), 124)
+!  call check (NF90MPI_PUT_VAR(ncid, vridz, z), 125)
+!  call check(nfmpi_end_indep_data(ncid), 11)
+!  call system_clock(now)
+!  ncint3 = now - start
+!  call check (NF90MPI_CLOSE(ncid), 16)
+!   print 4, size, 8, " netcdf file writes = ", ncint3 * clockRate, &
+!        real(ncint3)/real(wrint3);
+
+   msg = '*** TESTING F90 '//trim(cmd)
+   if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999 call MPI_Finalize(ierr)
+
+contains
+  subroutine check (st, n) ! checks the return error code
+    integer, intent (in) :: st, n
+    if ((n < 10.and.st /= 0).or.(n > 10.and.st /= NF90_noerr))then
+       print *, "I/O error at", n, " status = ", st
+       stop 2
+    endif
+  end subroutine check
+
+!  subroutine setupNetCDF(fn, nc, vr, vrnam, d1, d2, d3, d4, do1, do2, &
+!    real, dimension (:, :, :, :), intent (in) :: vrnam
+  subroutine setupNetCDF(fn, nc, vr, d1, d2, d3, d4, do1, do2, &
+       do3, do4, stat, deb)
+
+    character(len = *), intent(in) :: fn
+    integer(kind=EightByteInt), intent(in) :: d1, d2, d3, d4
+    integer, intent(in) :: stat, deb
+    integer, intent(out) :: do1, do2, do3, do4, vr
+    integer, intent(inout) :: nc
+    integer, dimension(4) :: dimids (4)
+
+    call check (NF90MPI_CREATE (MPI_COMM_WORLD, fn, stat, MPI_INFO_NULL, nc), deb + 1)
+    call check (NF90MPI_DEF_DIM(nc, "d1", d1, do1), deb + 2)
+    call check (NF90MPI_DEF_DIM(nc, "d2", d2, do2), deb + 3)
+    call check (NF90MPI_DEF_DIM(nc, "d3", d3, do3), deb + 4)
+    call check (NF90MPI_DEF_DIM(nc, "d4", d4, do4), deb + 5)
+
+    dimids = (/ do1, do2, do3, do4 /)
+    call check (NF90MPI_DEF_VAR(nc, "data", NF90_REAL, dimids, vr), deb + 6)
+    call check (NF90MPI_ENDDEF (nc), deb + 7)
+
+  end subroutine setupNetCDF
+
+end program tst_io
diff --git a/test/F90/tst_types2.f90 b/test/F90/tst_types2.f90
new file mode 100644
index 0000000..cdcb9b1
--- /dev/null
+++ b/test/F90/tst_types2.f90
@@ -0,0 +1,293 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: tst_types2.f90 2136 2015-10-07 19:25:34Z wkliao $
+
+!     This program tests PnetCDF int64 types from fortran 90.
+
+program tst_types2
+  use mpi
+  use pnetcdf
+  implicit none
+  
+  ! This is the name of the data file we will create.
+  character (len = *), parameter :: FILE_NAME = "tst_types2.nc"
+  
+  integer :: ncid, varid1, varid2, varid3, varid4, varid5, varid6, varid7
+  integer :: dimid1, dimid2, dimid3, dimid4, dimid5, dimid6, dimid7
+  integer :: dimids1(1), dimids2(2), dimids3(3), dimids4(4), dimids5(5), dimids6(6), dimids7(7)
+  integer :: i1, i2, i3, i4, i5, i6, i7
+  integer, parameter :: DLEN = 2
+  integer, parameter :: EightByteInt = selected_int_kind(18)
+  integer (kind = EightByteInt) :: data1_in(DLEN), data1_out(DLEN)
+  integer (kind = EightByteInt) :: data2_in(DLEN, DLEN), data2_out(DLEN, DLEN)
+  integer (kind = EightByteInt) :: data3_in(DLEN, DLEN, DLEN), data3_out(DLEN, DLEN, DLEN)
+  integer (kind = EightByteInt) :: data4_in(DLEN, DLEN, DLEN, DLEN), data4_out(DLEN, DLEN, DLEN, DLEN)
+  integer (kind = EightByteInt) :: data5_in(DLEN, DLEN, DLEN, DLEN, DLEN), data5_out(DLEN, DLEN, DLEN, DLEN, DLEN)
+  integer (kind = EightByteInt) :: data6_in(DLEN, DLEN, DLEN, DLEN, DLEN, DLEN), data6_out(DLEN, DLEN, DLEN, DLEN, DLEN, DLEN)
+  integer (kind = EightByteInt) :: data7_in(DLEN, DLEN, DLEN, DLEN, DLEN, DLEN, DLEN), &
+       data7_out(DLEN, DLEN, DLEN, DLEN, DLEN, DLEN, DLEN)
+  integer (kind = EightByteInt), parameter :: REALLY_BIG = 9223372036854775807_EightByteInt
+
+  integer :: cmode, err, ierr, get_args
+  integer(KIND=MPI_OFFSET_KIND) :: dlen_ll
+  character(LEN=256) filename, cmd, msg
+  integer my_rank, p
+  logical verbose
+
+  call MPI_Init(ierr)
+  call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr)
+  call MPI_Comm_size(MPI_COMM_WORLD, p, ierr)
+
+  ! take filename from command-line argument if there is any
+  if (my_rank .EQ. 0) then
+      filename = FILE_NAME
+      err = get_args(cmd, filename)
+  endif
+  call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+  if (err .EQ. 0) goto 999
+
+  call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+  verbose = .FALSE.
+  if (p .ne. 4 .AND. my_rank .eq. 0 .AND. verbose) then
+     print *, 'Warning: ',trim(cmd),' is design to run on 4 processes.'
+  endif
+
+  do i1 = 1, DLEN
+     data1_out(i1) = REALLY_BIG
+  end do
+  do i2 = 1, DLEN
+     do i1 = 1, DLEN
+        data2_out(i1, i2) = REALLY_BIG - i1 - i2
+     end do
+  end do
+  do i3 = 1, DLEN
+     do i2 = 1, DLEN
+        do i1 = 1, DLEN
+           data3_out(i1, i2, i3) = REALLY_BIG - i1 - i2 - i3
+        end do
+     end do
+  end do
+  do i4 = 1, DLEN
+     do i3 = 1, DLEN
+        do i2 = 1, DLEN
+           do i1 = 1, DLEN
+              data4_out(i1, i2, i3, i4) = REALLY_BIG - i1 - i2 - i3 - i4
+           end do
+        end do
+     end do
+  end do
+  do i5 = 1, DLEN
+     do i4 = 1, DLEN
+        do i3 = 1, DLEN
+           do i2 = 1, DLEN
+              do i1 = 1, DLEN
+                 data5_out(i1, i2, i3, i4, i5) = REALLY_BIG - i1 - i2 - i3 - i4 - i5
+              end do
+           end do
+        end do
+     end do
+  end do
+  do i6 = 1, DLEN
+     do i5 = 1, DLEN
+        do i4 = 1, DLEN
+           do i3 = 1, DLEN
+              do i2 = 1, DLEN
+                 do i1 = 1, DLEN
+                    data6_out(i1, i2, i3, i4, i5, i6) = REALLY_BIG - i1 - i2 - i3 - i4 - i5 - i6
+                 end do
+              end do
+           end do
+        end do
+     end do
+  end do
+  do i7 = 1, DLEN
+     do i6 = 1, DLEN
+        do i5 = 1, DLEN
+           do i4 = 1, DLEN
+              do i3 = 1, DLEN
+                 do i2 = 1, DLEN
+                    do i1 = 1, DLEN
+                       data7_out(i1, i2, i3, i4, i5, i6, i7) = REALLY_BIG - i1 - i2 - i3 - i4 - i5 - i6 - i7
+                    end do
+                 end do
+              end do
+           end do
+        end do
+     end do
+  end do
+  
+  ! Create the netCDF file. 
+  cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+  call check(nf90mpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, ncid))
+
+  ! Define dimensions.
+  dlen_ll = DLEN
+  call check(nf90mpi_def_dim(ncid, "d1", dlen_ll, dimid1))
+  call check(nf90mpi_def_dim(ncid, "d2", dlen_ll, dimid2))
+  call check(nf90mpi_def_dim(ncid, "d3", dlen_ll, dimid3))
+  call check(nf90mpi_def_dim(ncid, "d4", dlen_ll, dimid4))
+  call check(nf90mpi_def_dim(ncid, "d5", dlen_ll, dimid5))
+  call check(nf90mpi_def_dim(ncid, "d6", dlen_ll, dimid6))
+  call check(nf90mpi_def_dim(ncid, "d7", dlen_ll, dimid7))
+
+  ! Create some int64 variables, from 1 to 7D.
+  dimids1(1) = dimid1
+  call check(nf90mpi_def_var(ncid, "v1", nf90_int64, dimids1, varid1))
+  dimids2(1) = dimid1
+  dimids2(2) = dimid2
+  call check(nf90mpi_def_var(ncid, "v2", nf90_int64, dimids2, varid2))
+  dimids3(1) = dimid1
+  dimids3(2) = dimid2
+  dimids3(3) = dimid3
+  call check(nf90mpi_def_var(ncid, "v3", nf90_int64, dimids3, varid3))
+  dimids4(1) = dimid1
+  dimids4(2) = dimid2
+  dimids4(3) = dimid3
+  dimids4(4) = dimid4
+  call check(nf90mpi_def_var(ncid, "v4", nf90_int64, dimids4, varid4))
+  dimids5(1) = dimid1
+  dimids5(2) = dimid2
+  dimids5(3) = dimid3
+  dimids5(4) = dimid4
+  dimids5(5) = dimid5
+  call check(nf90mpi_def_var(ncid, "v5", nf90_int64, dimids5, varid5))
+  dimids6(1) = dimid1
+  dimids6(2) = dimid2
+  dimids6(3) = dimid3
+  dimids6(4) = dimid4
+  dimids6(5) = dimid5
+  dimids6(6) = dimid6
+  call check(nf90mpi_def_var(ncid, "v6", nf90_int64, dimids6, varid6))
+  dimids7(1) = dimid1
+  dimids7(2) = dimid2
+  dimids7(3) = dimid3
+  dimids7(4) = dimid4
+  dimids7(5) = dimid5
+  dimids7(6) = dimid6
+  dimids7(7) = dimid7
+  call check(nf90mpi_def_var(ncid, "v7", nf90_int64, dimids7, varid7))
+
+  call check(nf90mpi_enddef(ncid))
+  ! enter independent data mode
+  call check(nf90mpi_begin_indep_data(ncid))
+
+  ! Write some large integers.
+  call check(nf90mpi_put_var(ncid, varid1, data1_out))
+  call check(nf90mpi_put_var(ncid, varid2, data2_out))
+  call check(nf90mpi_put_var(ncid, varid3, data3_out))
+  call check(nf90mpi_put_var(ncid, varid4, data4_out))
+  call check(nf90mpi_put_var(ncid, varid5, data5_out))
+  call check(nf90mpi_put_var(ncid, varid6, data6_out))
+  call check(nf90mpi_put_var(ncid, varid7, data7_out))
+
+  ! Close the file. 
+  call check(nf90mpi_close(ncid))
+
+  ! Reopen the netCDF file. 
+  call check(nf90mpi_open(MPI_COMM_WORLD, filename, nf90_nowrite, MPI_INFO_NULL, ncid))
+
+  ! Read in the large numbers.
+  call check(nf90mpi_get_var_all(ncid, varid1, data1_in))
+  call check(nf90mpi_get_var_all(ncid, varid2, data2_in))
+  call check(nf90mpi_get_var_all(ncid, varid3, data3_in))
+  call check(nf90mpi_get_var_all(ncid, varid4, data4_in))
+  call check(nf90mpi_get_var_all(ncid, varid5, data5_in))
+  call check(nf90mpi_get_var_all(ncid, varid6, data6_in))
+  call check(nf90mpi_get_var_all(ncid, varid7, data7_in))
+
+  ! Check the values for correctness.
+  do i1 = 1, DLEN
+     if (data1_in(i1) .ne. data1_out(i1)) stop 2
+  end do
+  do i2 = 1, DLEN
+     do i1 = 1, DLEN
+        if (data2_in(i1, i2) .ne. data2_out(i1, i2)) stop 2
+     end do
+  end do
+  do i3 = 1, DLEN
+     do i2 = 1, DLEN
+        do i1 = 1, DLEN
+           if (data3_in(i1, i2, i3) .ne. data3_out(i1, i2, i3)) stop 2
+        end do
+     end do
+  end do
+  do i4 = 1, DLEN
+     do i3 = 1, DLEN
+        do i2 = 1, DLEN
+           do i1 = 1, DLEN
+              if (data4_in(i1, i2, i3, i4) .ne. &
+                   data4_out(i1, i2, i3, i4)) stop 2
+           end do
+        end do
+     end do
+  end do
+  do i5 = 1, DLEN
+     do i4 = 1, DLEN
+        do i3 = 1, DLEN
+           do i2 = 1, DLEN
+              do i1 = 1, DLEN
+                 if (data5_in(i1, i2, i3, i4, i5) .ne. &
+                      data5_out(i1, i2, i3, i4, i5)) stop 2
+              end do
+           end do
+        end do
+     end do
+  end do
+  do i6 = 1, DLEN
+     do i5 = 1, DLEN
+        do i4 = 1, DLEN
+           do i3 = 1, DLEN
+              do i2 = 1, DLEN
+                 do i1 = 1, DLEN
+                    if (data6_in(i1, i2, i3, i4, i5, i6) .ne. &
+                         data6_out(i1, i2, i3, i4, i5, i6)) stop 2
+                 end do
+              end do
+           end do
+        end do
+     end do
+  end do
+  do i7 = 1, DLEN
+     do i6 = 1, DLEN
+        do i5 = 1, DLEN
+           do i4 = 1, DLEN
+              do i3 = 1, DLEN
+                 do i2 = 1, DLEN
+                    do i1 = 1, DLEN
+                       if (data7_in(i1, i2, i3, i4, i5, i6, i7) .ne. &
+                            data7_out(i1, i2, i3, i4, i5, i6, i7)) stop 2
+                    end do
+                 end do
+              end do
+           end do
+        end do
+     end do
+  end do
+
+  ! Close the file. 
+  call check(nf90mpi_close(ncid))
+  
+   msg = '*** TESTING F90 '//trim(cmd)//' for 64-bit integer types'
+   if (my_rank .eq. 0) call pass_fail(0, msg)
+
+ 999 call MPI_Finalize(ierr)
+
+!     This subroutine handles errors by printing an error message and
+!     exiting with a non-zero status.
+contains
+  subroutine check(status)
+    integer, intent ( in) :: status
+    
+    if(status /= nf90_noerr) then 
+      print *, trim(nf90mpi_strerror(status))
+      stop 2
+    end if
+  end subroutine check  
+
+end program tst_types2
+
diff --git a/test/Makefile.in b/test/Makefile.in
new file mode 100644
index 0000000..a5fdd02
--- /dev/null
+++ b/test/Makefile.in
@@ -0,0 +1,106 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2249 2015-12-20 20:36:46Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../macros.make
+
+SUBDIRS = common \
+          nc_test \
+          C \
+          fandc \
+          nonblocking \
+          cdf_format \
+          header \
+          testcases
+
+# Packing subdirs must include all directories
+PACKING_SUBDIRS := $(SUBDIRS) largefile nf_test nf90_test F90 subfile CXX
+
+ifeq (@large_file_test@, yes)
+SUBDIRS += largefile
+endif
+
+ifeq (@has_mpicxx@, yes)
+SUBDIRS += CXX
+endif
+
+ifeq (@has_fortran@, yes)
+SUBDIRS += nf_test
+SUBDIRS += nf90_test
+SUBDIRS += F90
+endif
+
+ifeq (@enable_subfiling@, yes)
+SUBDIRS += subfile
+endif
+
+PACKING_LIST = Makefile.in
+
+all: $(SUBDIRS)
+$(SUBDIRS):
+	$(MAKE) $(MFLAGS) -C $@
+
+tests: all
+
+test_int: common
+test_float: common
+test_double_int: common
+test_double: common
+
+CHECK_DIRS = $(SUBDIRS:%=check-%)
+check testing: $(CHECK_DIRS)
+$(CHECK_DIRS):
+	$(MAKE) $(MFLAGS) -C $(@:check-%=%) testing
+
+VCHECK_DIRS = $(SUBDIRS:%=vcheck-%)
+verbose_check verbose_testing: $(VCHECK_DIRS)
+$(VCHECK_DIRS):
+	$(MAKE) $(MFLAGS) -C $(@:vcheck-%=%) verbose_testing
+
+ptest: all
+ifeq (@enable_coverage@, yes)
+	echo "Parallel test is disabled because coverage analysis was enabled"
+else
+	(echo "=============================================")  && \
+	(echo "    Parallel testing on 4 MPI processes")  && \
+	(echo "=============================================")  && \
+	( for d in $(SUBDIRS) ; do \
+		$(MAKE) $(MFLAGS) -C $$d ptest4 ; \
+	  done ) ;
+endif
+
+ptests: all
+ifeq (@enable_coverage@, yes)
+	echo "Parallel test is disabled because coverage analysis was enabled"
+else
+	for i in 2 4 6 8 10 ; do \
+	(echo "=============================================")  && \
+	(echo "    Parallel testing on $$i MPI processes")  && \
+	(echo "=============================================")  && \
+	( for d in $(SUBDIRS) ; do \
+		$(MAKE) $(MFLAGS) -C $$d ptest$$i ; \
+	  done ) ; \
+	done ;
+endif
+
+INSTALLDIRS = $(SUBDIRS:%=install-%)
+install: all $(INSTALLDIRS)
+$(INSTALLDIRS): 
+	$(MAKE) $(MFLAGS) -C $(@:install-%=%) install
+
+UNINSTALLDIRS = $(SUBDIRS:%=uninstall-%)
+uninstall: $(UNINSTALLDIRS)
+$(UNINSTALLDIRS): 
+	$(MAKE) $(MFLAGS) -C $(@:uninstall-%=%) uninstall
+
+include $(srcdir)/../rules.make
+
+.NOTPARALLEL:
+
diff --git a/test/cdf_format/Makefile.in b/test/cdf_format/Makefile.in
new file mode 100644
index 0000000..2bdd397
--- /dev/null
+++ b/test/cdf_format/Makefile.in
@@ -0,0 +1,77 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2306 2016-01-12 19:34:31Z wkliao $
+#
+# @configure_input@
+
+srcdir  = @srcdir@
+VPATH   = @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I../../src/lib -I$(srcdir)/../common
+LDFLAGS  := $(LDFLAGS) -L../common
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
+ifeq (@PNC_DEBUG@, yes)
+CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
+endif
+
+SRCS    = test_inq_format.c \
+          cdf_type.c \
+          dim_cdf12.c
+
+OBJS    = $(SRCS:.c=.o)
+PROGS   = $(SRCS:.c=)
+
+GARBAGE      = $(PROGS) testfile.nc
+PACKING_LIST = $(SRCS) Makefile.in depend \
+               test_cdf1.nc test_cdf2.nc test_cdf5.nc
+
+all: $(PROGS)
+
+$(OBJS): $(srcdir)/../common/testutils.h
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+test_inq_format: test_inq_format.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+cdf_type: cdf_type.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+dim_cdf12: dim_cdf12.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+testing check verbose_testing: all
+	$(TEST_SEQRUN) ./test_inq_format $(srcdir)
+	$(TEST_SEQRUN) ./cdf_type $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./dim_cdf12 $(TEST_OUTDIR)/testfile.nc
+
+# Some of these tests are designed to run on one process,
+# # Run them on 4 processes to see if they can handle well
+# Some of these tests are designed to run on 4 processes,
+# # Run them on 2, 4, and 6 processes to see if they can handle well
+TEST_MPIRUN_2  = $(subst NP,2,$(TEST_MPIRUN))
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+TEST_MPIRUN_6  = $(subst NP,6,$(TEST_MPIRUN))
+TEST_MPIRUN_8  = $(subst NP,8,$(TEST_MPIRUN))
+TEST_MPIRUN_10 = $(subst NP,10,$(TEST_MPIRUN))
+
+ptest4: $(PROGS)
+	$(TEST_MPIRUN_4) ./test_inq_format $(srcdir)
+	$(TEST_MPIRUN_4) ./cdf_type $(TEST_OUTDIR)/testfile.nc
+	$(TEST_MPIRUN_4) ./dim_cdf12 $(TEST_OUTDIR)/testfile.nc
+
+ptest ptests: ptest4
+
+ptest2 ptest6 ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+include $(srcdir)/depend
+
+$(LIBRARY): ;
diff --git a/test/cdf_format/cdf_type.c b/test/cdf_format/cdf_type.c
new file mode 100644
index 0000000..a7fb131
--- /dev/null
+++ b/test/cdf_format/cdf_type.c
@@ -0,0 +1,126 @@
+/*
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: cdf_type.c 2133 2015-09-26 19:16:01Z wkliao $ */
+
+/* This program tests if PnetCDF can detect CDF-5 data types that are not
+ * available in CDF-1 and CDF-2 formats
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <testutils.h>
+
+#define ERR {if(err!=NC_NOERR) {printf("Error(%d) at line %d: %s\n",err,__LINE__,ncmpi_strerror(err)); nerrs++; }}
+
+/*----< test_attr_types() >---------------------------------------------------*/
+static
+int test_attr_types(char *filename,
+                    int   format)
+{
+    int i, err, rank, ncid, cmode, nerrs=0, attr=0;
+    MPI_Info info=MPI_INFO_NULL;
+    MPI_Comm comm=MPI_COMM_WORLD;
+    nc_type xtype[5]={NC_UBYTE, NC_USHORT, NC_UINT, NC_INT64, NC_UINT64};
+
+    MPI_Comm_rank(comm, &rank);
+    cmode = NC_CLOBBER|format;
+
+    /* create a file in CDF-1 or CDF-2 format */
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    for (i=0; i<5; i++) {
+        char name[32];
+        sprintf(name, "gattr_%d", i);
+        err = ncmpi_put_att_int(ncid, NC_GLOBAL, name, xtype[i], 1, &attr);
+        if (err != NC_ESTRICTCDF2) {
+            printf("Error (line=%d): expecting NC_ESTRICTCDF2 but got %s\n", __LINE__,nc_err_code_name(err));
+            nerrs++;
+        }
+    }
+
+    err = ncmpi_close(ncid); ERR
+
+    return nerrs;
+}
+
+/*----< test_var_types() >----------------------------------------------------*/
+static
+int test_var_types(char *filename,
+                   int   format)
+{
+    int i, err, rank, ncid, cmode, nerrs=0;
+    int dimid, varid[5];
+    MPI_Info info=MPI_INFO_NULL;
+    MPI_Comm comm=MPI_COMM_WORLD;
+    nc_type xtype[5]={NC_UBYTE, NC_USHORT, NC_UINT, NC_INT64, NC_UINT64};
+
+    MPI_Comm_rank(comm, &rank);
+    cmode = NC_CLOBBER|format;
+
+    /* create a file in CDF-1 or CDF-2 format */
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "dim", NC_UNLIMITED, &dimid); ERR
+    for (i=0; i<5; i++) {
+        char name[32];
+        sprintf(name, "var_%d", i);
+        err = ncmpi_def_var(ncid, name, xtype[i], 1, &dimid, &varid[i]);
+        if (err != NC_ESTRICTCDF2) {
+            printf("Error (line=%d): expecting NC_ESTRICTCDF2 but got %s\n", __LINE__,nc_err_code_name(err));
+            nerrs++;
+        }
+    }
+    err = ncmpi_close(ncid); ERR
+
+    return nerrs;
+}
+
+/*----< main() >--------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    char *filename="testfile.nc";
+    int rank, nerrs=0;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for CDF-5 type in CDF-1 and 2 ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    nerrs += test_attr_types(filename, 0);
+    nerrs += test_attr_types(filename, NC_64BIT_OFFSET);
+
+    nerrs += test_var_types(filename, 0);
+    nerrs += test_var_types(filename, NC_64BIT_OFFSET);
+
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/cdf_format/depend b/test/cdf_format/depend
new file mode 100644
index 0000000..09cc529
--- /dev/null
+++ b/test/cdf_format/depend
@@ -0,0 +1,3 @@
+test_inq_format.o: test_inq_format.c
+cdf_type.o: cdf_type.c
+dim_cdf12.o: dim_cdf12.c
diff --git a/test/cdf_format/dim_cdf12.c b/test/cdf_format/dim_cdf12.c
new file mode 100644
index 0000000..0431ded
--- /dev/null
+++ b/test/cdf_format/dim_cdf12.c
@@ -0,0 +1,202 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2016, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id$ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program is to test CDF-1, CDF-2 file formats using the allowable
+ * maximal dimension size
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <limits.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <testutils.h>
+
+#define FOUR_G 4294967296
+#define TWO_G  2147483648
+#define ONE_G  1073741824
+
+#define NZ 4
+#define NY 10
+#define NX TWO_G
+
+#define ERR if (err!=NC_NOERR) {printf("Error at line %d: err=%s (%s)\n", __LINE__,nc_err_code_name(err),ncmpi_strerror(err)); nerrs++;}
+
+#define ERR_EXPECT(exp) if (err!=exp) {printf("Error at line %d: expect error %s but got %s\n", __LINE__,nc_err_code_name(exp),nc_err_code_name(err)); nerrs++;}
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int rank, nprocs, err, nerrs=0;
+    int ncid, cmode, varid, dimid[3];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for defining dim in CDF-1/2 format ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    /* create a new CDF-1 file ----------------------------------------------*/
+    cmode = NC_CLOBBER;
+
+    /* max dimension size for CDF-2 file is 2^31-3 = 2147483647 - 3 */
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", INT_MAX, &dimid[0]);
+    ERR_EXPECT(NC_EDIMSIZE)
+    err = ncmpi_def_dim(ncid, "Y", INT_MAX-3, &dimid[0]); ERR
+    err = ncmpi_close(ncid); ERR
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_close(ncid); ERR
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", INT_MAX-3, &dimid[0]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_CHAR, 1, dimid, &varid); ERR
+    err = ncmpi_close(ncid); ERR
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_close(ncid); ERR
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", INT_MAX-3,  &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 2,          &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_CHAR, 1, &dimid[0], &varid); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT,  1, &dimid[1], &varid); ERR
+    err = ncmpi_close(ncid);
+    ERR_EXPECT(NC_EVARSIZE)
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", INT_MAX-1024,  &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 2,             &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_CHAR, 1, &dimid[0], &varid); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT,  1, &dimid[1], &varid); ERR
+    err = ncmpi_close(ncid); ERR
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_close(ncid); ERR
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", INT_MAX-3, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 2,         &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_SHORT, 1, &dimid[0], &varid); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_CHAR,  1, &dimid[1], &varid); ERR
+    err = ncmpi_close(ncid);
+    ERR_EXPECT(NC_EVARSIZE)
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", INT_MAX-3-512-8, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 2,       &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_CHAR, 1, &dimid[0], &varid); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT,  1, &dimid[1], &varid); ERR
+    err = ncmpi_close(ncid); ERR
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", INT_MAX/2+1, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 2,           &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_INT, 1, &dimid[0], &varid); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT, 1, &dimid[1], &varid); ERR
+    err = ncmpi_close(ncid);
+    ERR_EXPECT(NC_EVARSIZE)
+
+    /* create a new CDF-2 file ----------------------------------------------*/
+    cmode = NC_CLOBBER;
+    cmode = NC_CLOBBER | NC_64BIT_OFFSET;
+
+    /* max dimension size for CDF-2 file is 2^32-3 = 4294967295 - 3 */
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", UINT_MAX, &dimid[0]);
+    ERR_EXPECT(NC_EDIMSIZE)
+    err = ncmpi_def_dim(ncid, "Y", UINT_MAX-3, &dimid[0]); ERR
+    err = ncmpi_close(ncid); ERR
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_close(ncid); ERR
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", UINT_MAX-3, &dimid[0]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_CHAR, 1, dimid, &varid); ERR
+    err = ncmpi_close(ncid); ERR
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_close(ncid); ERR
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", UINT_MAX-3, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 2,          &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_CHAR, 1, &dimid[0], &varid); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT,  1, &dimid[1], &varid); ERR
+    err = ncmpi_close(ncid); ERR
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_close(ncid); ERR
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", UINT_MAX-3, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 2,          &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_SHORT, 1, &dimid[0], &varid); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT,   1, &dimid[1], &varid); ERR
+    err = ncmpi_close(ncid);
+    ERR_EXPECT(NC_EVARSIZE)
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", INT_MAX, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 2,       &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_INT, 1, &dimid[0], &varid); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT, 1, &dimid[1], &varid); ERR
+    err = ncmpi_close(ncid);
+    ERR_EXPECT(NC_EVARSIZE)
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", INT_MAX/2+1, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 2,           &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_INT, 1, &dimid[0], &varid); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT, 1, &dimid[1], &varid); ERR
+    err = ncmpi_close(ncid);
+    ERR_EXPECT(NC_EVARSIZE)
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Y", INT_MAX/2, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 2,         &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_INT, 1, &dimid[0], &varid); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT, 1, &dimid[1], &varid); ERR
+    err = ncmpi_close(ncid); ERR
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/cdf_format/test_cdf1.nc b/test/cdf_format/test_cdf1.nc
new file mode 100644
index 0000000..39fc9f1
Binary files /dev/null and b/test/cdf_format/test_cdf1.nc differ
diff --git a/test/cdf_format/test_cdf2.nc b/test/cdf_format/test_cdf2.nc
new file mode 100644
index 0000000..71c6e61
Binary files /dev/null and b/test/cdf_format/test_cdf2.nc differ
diff --git a/test/cdf_format/test_cdf5.nc b/test/cdf_format/test_cdf5.nc
new file mode 100644
index 0000000..c171175
Binary files /dev/null and b/test/cdf_format/test_cdf5.nc differ
diff --git a/test/cdf_format/test_inq_format.c b/test/cdf_format/test_inq_format.c
new file mode 100644
index 0000000..4222aaf
--- /dev/null
+++ b/test/cdf_format/test_inq_format.c
@@ -0,0 +1,110 @@
+/*
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: test_inq_format.c 2250 2015-12-20 21:12:59Z wkliao $ */
+
+/* This program tests if PnetCDF can report correct file formats */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <testutils.h>
+
+#define ERR {if(err!=NC_NOERR) {printf("Error(%d) at line %d: %s\n",err,__LINE__,ncmpi_strerror(err)); nerrs++; }}
+
+int main(int argc, char **argv) {
+    char dir_name[256], filename[256];
+    int err, rank, nerrs=0, format, ncid;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc != 2) {
+        if (!rank) printf("Usage: %s dir_name\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(dir_name, argv[1]);
+    MPI_Bcast(dir_name, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for inquiring CDF file formats ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    /* test CDF-1 -----------------------------------------------------------*/
+    sprintf(filename,"%s/test_cdf1.nc",dir_name);
+    err = ncmpi_open(MPI_COMM_WORLD, filename, 0, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_inq_format(ncid, &format); ERR
+    if (format != NC_FORMAT_CLASSIC) {
+        printf("Error (line=%d): expecting CDF-1 format for file %s but got %d\n",
+               __LINE__,filename,format);
+        nerrs++;
+    }
+    err = ncmpi_close(ncid); ERR
+  
+    err = ncmpi_inq_file_format(filename, &format); ERR
+    if (format != NC_FORMAT_CLASSIC) {
+        printf("Error (line=%d): expecting CDF-1 format for file %s but got %d\n",
+               __LINE__,filename,format);
+        nerrs++;
+    }
+
+    /* test CDF-2 -----------------------------------------------------------*/
+    sprintf(filename,"%s/test_cdf2.nc",dir_name);
+    err = ncmpi_open(MPI_COMM_WORLD, filename, 0, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_inq_format(ncid, &format); ERR
+    if (format != NC_FORMAT_CDF2) {
+        printf("Error (line=%d): expecting CDF-2 format for file %s but got %d\n",
+               __LINE__,filename,format);
+        nerrs++;
+    }
+    err = ncmpi_close(ncid); ERR
+  
+    err = ncmpi_inq_file_format(filename, &format); ERR
+    if (format != NC_FORMAT_CDF2) {
+        printf("Error (line=%d): expecting CDF-2 format for file %s but got %d\n",
+               __LINE__,filename,format);
+        nerrs++;
+    }
+
+    /* test CDF-5 -----------------------------------------------------------*/
+    sprintf(filename,"%s/test_cdf5.nc",dir_name);
+    err = ncmpi_open(MPI_COMM_WORLD, filename, 0, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_inq_format(ncid, &format); ERR
+    if (format != NC_FORMAT_CDF5) {
+        printf("Error (line=%d): expecting CDF-5 format for file %s but got %d\n",
+               __LINE__,filename,format);
+        nerrs++;
+    }
+    err = ncmpi_close(ncid); ERR
+  
+    err = ncmpi_inq_file_format(filename, &format); ERR
+    if (format != NC_FORMAT_CDF5) {
+        printf("Error (line=%d): expecting CDF-5 format for file %s but got %d\n",
+               __LINE__,filename,format);
+        nerrs++;
+    }
+
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/test/common/Makefile.in b/test/common/Makefile.in
new file mode 100644
index 0000000..fb4f214
--- /dev/null
+++ b/test/common/Makefile.in
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2219 2015-12-11 22:30:03Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I../../src/lib
+
+ifeq (@PNC_DEBUG@, yes)
+CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
+FPPFLAGS := $(FPPFLAGS) @FC_DEFINE at PNC_DEBUG
+endif
+
+C_SRCS   = testutils.c
+
+F_SRCS   = testutilsf.F90
+
+HEADERS  = testutils.h
+
+OBJS     = $(C_SRCS:.c=.o)
+ifeq (@has_fortran@, yes)
+OBJS    += $(F_SRCS:.F90=.o)
+endif
+
+UTIL_LIB = libtestutils.a
+
+GARBAGE      = $(UTIL_LIB) *.mod
+PACKING_LIST = $(C_SRCS) $(F_SRCS) $(HEADERS) Makefile.in
+
+all: $(UTIL_LIB)
+
+$(C_SRCS:.c=.o) : $(HEADERS)
+
+$(UTIL_LIB): $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+testutils.o: testutils.c testutils.h
+
+testutilsf.o: testutilsf.F90
+
+testing check verbose_testing: $(UTIL_LIB)
+
+ptest ptests: $(UTIL_LIB)
+
+ptest2 ptest4 ptest6 ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+
diff --git a/test/common/testutils.c b/test/common/testutils.c
new file mode 100644
index 0000000..c49e03c
--- /dev/null
+++ b/test/common/testutils.c
@@ -0,0 +1,207 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: testutils.c 2247 2015-12-20 20:29:06Z wkliao $ */
+
+
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <mpi.h>
+
+#include <pnetcdf.h>
+#include "testutils.h"
+
+void parse_read_args(int argc, char **argv, int rank, params *p)
+{
+	int inlen, outlen;
+	if ( rank == 0 ) {
+		if (argc == 3 ) {
+			strcpy(p->infname, argv[1]);
+			strcpy(p->outfname, argv[2]);
+		} else if (argc == 1) {
+			strcpy(p->infname, "../data/test_double.nc");
+			strcpy(p->outfname, "testread.nc");
+		} else {
+			fprintf(stderr, "Usage: %s: <source> <destination>\n", 
+					argv[0]);
+			MPI_Abort(MPI_COMM_WORLD, 1);
+		}
+		inlen = strlen(p->infname);
+		outlen = strlen(p->outfname);
+	}
+	MPI_Bcast(&inlen, 1, MPI_INT, 0, MPI_COMM_WORLD);
+	MPI_Bcast(p->infname, inlen+1, MPI_CHAR, 0, MPI_COMM_WORLD);
+	MPI_Bcast(&outlen, 1, MPI_INT, 0, MPI_COMM_WORLD);
+	MPI_Bcast(p->outfname, outlen+1, MPI_CHAR, 0, MPI_COMM_WORLD);
+}
+
+void parse_write_args(int argc, char **argv, int rank, params *p)
+{
+	int outlen;
+	if ( rank == 0 ) {
+		if (argc == 2 ) {
+			strcpy(p->outfname, argv[1]);
+		} else if (argc == 1) {
+			strcpy(p->outfname, "testwrite.nc");
+		} else {
+			fprintf(stderr, "Usage: %s: <destination>\n", argv[0]);
+			MPI_Abort(MPI_COMM_WORLD, 1);
+		}
+		outlen = strlen(p->outfname);
+	}
+	MPI_Bcast(&outlen, 1, MPI_INT, 0, MPI_COMM_WORLD);
+	MPI_Bcast(p->outfname, outlen+1, MPI_CHAR, 0, MPI_COMM_WORLD);
+}
+
+
+char* nc_err_code_name(int err)
+{
+    static char unknown_str[32];
+    switch (err) {
+        case (NC_NOERR):			return "NC_NOERR";
+        case (NC_EBADID):			return "NC_EBADID";
+        case (NC_ENFILE):			return "NC_ENFILE";
+        case (NC_EEXIST):			return "NC_EEXIST";
+        case (NC_EINVAL):			return "NC_EINVAL";
+        case (NC_EPERM):			return "NC_EPERM";
+        case (NC_ENOTINDEFINE):			return "NC_ENOTINDEFINE";
+        case (NC_EINDEFINE):			return "NC_EINDEFINE";
+        case (NC_EINVALCOORDS):			return "NC_EINVALCOORDS";
+        case (NC_EMAXDIMS):			return "NC_EMAXDIMS";
+        case (NC_ENAMEINUSE):			return "NC_ENAMEINUSE";
+        case (NC_ENOTATT):			return "NC_ENOTATT";
+        case (NC_EMAXATTS):			return "NC_EMAXATTS";
+        case (NC_EBADTYPE):			return "NC_EBADTYPE";
+        case (NC_EBADDIM):			return "NC_EBADDIM";
+        case (NC_EUNLIMPOS):			return "NC_EUNLIMPOS";
+        case (NC_EMAXVARS):			return "NC_EMAXVARS";
+        case (NC_ENOTVAR):			return "NC_ENOTVAR";
+        case (NC_EGLOBAL):			return "NC_EGLOBAL";
+        case (NC_ENOTNC):			return "NC_ENOTNC";
+        case (NC_ESTS):				return "NC_ESTS";
+        case (NC_EMAXNAME):			return "NC_EMAXNAME";
+        case (NC_EUNLIMIT):			return "NC_EUNLIMIT";
+        case (NC_ENORECVARS):			return "NC_ENORECVARS";
+        case (NC_ECHAR):			return "NC_ECHAR";
+        case (NC_EEDGE):			return "NC_EEDGE";
+        case (NC_ESTRIDE):			return "NC_ESTRIDE";
+        case (NC_EBADNAME):			return "NC_EBADNAME";
+        case (NC_ERANGE):			return "NC_ERANGE";
+        case (NC_ENOMEM):			return "NC_ENOMEM";
+        case (NC_EVARSIZE):			return "NC_EVARSIZE";
+        case (NC_EDIMSIZE):			return "NC_EDIMSIZE";
+        case (NC_ETRUNC):			return "NC_ETRUNC";
+        case (NC_EAXISTYPE):			return "NC_EAXISTYPE";
+        case (NC_EDAP):				return "NC_EDAP";
+        case (NC_ECURL):			return "NC_ECURL";
+        case (NC_EIO):				return "NC_EIO";
+        case (NC_ENODATA):			return "NC_ENODATA";
+        case (NC_EDAPSVC):			return "NC_EDAPSVC";
+        case (NC_EDAS):				return "NC_EDAS";
+        case (NC_EDDS):				return "NC_EDDS";
+        case (NC_EDATADDS):			return "NC_EDATADDS";
+        case (NC_EDAPURL):			return "NC_EDAPURL";
+        case (NC_EDAPCONSTRAINT):		return "NC_EDAPCONSTRAINT";
+        case (NC_ETRANSLATION):			return "NC_ETRANSLATION";
+        case (NC_EACCESS):			return "NC_EACCESS";
+        case (NC_EAUTH):			return "NC_EAUTH";
+        case (NC_ENOTFOUND):			return "NC_ENOTFOUND";
+        case (NC_ECANTREMOVE):			return "NC_ECANTREMOVE";
+        case (NC_EHDFERR):			return "NC_EHDFERR";
+        case (NC_ECANTREAD):			return "NC_ECANTREAD";
+        case (NC_ECANTWRITE):			return "NC_ECANTWRITE";
+        case (NC_ECANTCREATE):			return "NC_ECANTCREATE";
+        case (NC_EFILEMETA):			return "NC_EFILEMETA";
+        case (NC_EDIMMETA):			return "NC_EDIMMETA";
+        case (NC_EATTMETA):			return "NC_EATTMETA";
+        case (NC_EVARMETA):			return "NC_EVARMETA";
+        case (NC_ENOCOMPOUND):			return "NC_ENOCOMPOUND";
+        case (NC_EATTEXISTS):			return "NC_EATTEXISTS";
+        case (NC_ENOTNC4):			return "NC_ENOTNC4";
+        case (NC_ESTRICTNC3):			return "NC_ESTRICTNC3";
+        case (NC_ENOTNC3):			return "NC_ENOTNC3";
+        case (NC_ENOPAR):			return "NC_ENOPAR";
+        case (NC_EPARINIT):			return "NC_EPARINIT";
+        case (NC_EBADGRPID):			return "NC_EBADGRPID";
+        case (NC_EBADTYPID):			return "NC_EBADTYPID";
+        case (NC_ETYPDEFINED):			return "NC_ETYPDEFINED";
+        case (NC_EBADFIELD):			return "NC_EBADFIELD";
+        case (NC_EBADCLASS):			return "NC_EBADCLASS";
+        case (NC_EMAPTYPE):			return "NC_EMAPTYPE";
+        case (NC_ELATEFILL):			return "NC_ELATEFILL";
+        case (NC_ELATEDEF):			return "NC_ELATEDEF";
+        case (NC_EDIMSCALE):			return "NC_EDIMSCALE";
+        case (NC_ENOGRP):			return "NC_ENOGRP";
+        case (NC_ESTORAGE):			return "NC_ESTORAGE";
+        case (NC_EBADCHUNK):			return "NC_EBADCHUNK";
+        case (NC_ENOTBUILT):			return "NC_ENOTBUILT";
+        case (NC_EDISKLESS):			return "NC_EDISKLESS";
+        case (NC_ECANTEXTEND):			return "NC_ECANTEXTEND";
+        case (NC_EMPI):				return "NC_EMPI";
+        // case (NC_EURL):				return "NC_EURL";
+        // case (NC_ECONSTRAINT):			return "NC_ECONSTRAINT";
+        case (NC_ESMALL):			return "NC_ESMALL";
+        case (NC_ENOTINDEP):			return "NC_ENOTINDEP";
+        case (NC_EINDEP):			return "NC_EINDEP";
+        case (NC_EFILE):			return "NC_EFILE";
+        case (NC_EREAD):			return "NC_EREAD";
+        case (NC_EWRITE):			return "NC_EWRITE";
+        case (NC_EOFILE):			return "NC_EOFILE";
+        case (NC_EMULTITYPES):			return "NC_EMULTITYPES";
+        case (NC_EIOMISMATCH):			return "NC_EIOMISMATCH";
+        case (NC_ENEGATIVECNT):			return "NC_ENEGATIVECNT";
+        case (NC_EUNSPTETYPE):			return "NC_EUNSPTETYPE";
+        case (NC_EINVAL_REQUEST):		return "NC_EINVAL_REQUEST";
+        case (NC_EAINT_TOO_SMALL):		return "NC_EAINT_TOO_SMALL";
+        case (NC_ENOTSUPPORT):			return "NC_ENOTSUPPORT";
+        case (NC_ENULLBUF):			return "NC_ENULLBUF";
+        case (NC_EPREVATTACHBUF):		return "NC_EPREVATTACHBUF";
+        case (NC_ENULLABUF):			return "NC_ENULLABUF";
+        case (NC_EPENDINGBPUT):			return "NC_EPENDINGBPUT";
+        case (NC_EINSUFFBUF):			return "NC_EINSUFFBUF";
+        case (NC_ENOENT):			return "NC_ENOENT";
+        case (NC_EINTOVERFLOW):			return "NC_EINTOVERFLOW";
+        case (NC_ENOTENABLED):			return "NC_ENOTENABLED";
+        case (NC_EBAD_FILE):			return "NC_EBAD_FILE";
+        case (NC_ENO_SPACE):			return "NC_ENO_SPACE";
+        case (NC_EQUOTA):			return "NC_EQUOTA";
+        case (NC_ENULLSTART):			return "NC_ENULLSTART";
+        case (NC_ENULLCOUNT):			return "NC_ENULLCOUNT";
+        case (NC_EINVAL_CMODE):			return "NC_EINVAL_CMODE";
+        case (NC_ETYPESIZE):			return "NC_ETYPESIZE";
+        case (NC_ETYPE_MISMATCH):		return "NC_ETYPE_MISMATCH";
+        case (NC_ETYPESIZE_MISMATCH):		return "NC_ETYPESIZE_MISMATCH";
+        case (NC_ESTRICTCDF2):			return "NC_ESTRICTCDF2";
+        case (NC_ENOTRECVAR):			return "NC_ENOTRECVAR";
+        case (NC_ENOTFILL):			return "NC_ENOTFILL";
+        case (NC_EMULTIDEFINE):			return "NC_EMULTIDEFINE";
+        case (NC_EMULTIDEFINE_OMODE):		return "NC_EMULTIDEFINE_OMODE";
+        case (NC_EMULTIDEFINE_DIM_NUM):		return "NC_EMULTIDEFINE_DIM_NUM";
+        case (NC_EMULTIDEFINE_DIM_SIZE):	return "NC_EMULTIDEFINE_DIM_SIZE";
+        case (NC_EMULTIDEFINE_DIM_NAME):	return "NC_EMULTIDEFINE_DIM_NAME";
+        case (NC_EMULTIDEFINE_VAR_NUM):		return "NC_EMULTIDEFINE_VAR_NUM";
+        case (NC_EMULTIDEFINE_VAR_NAME):	return "NC_EMULTIDEFINE_VAR_NAME";
+        case (NC_EMULTIDEFINE_VAR_NDIMS):	return "NC_EMULTIDEFINE_VAR_NDIMS";
+        case (NC_EMULTIDEFINE_VAR_DIMIDS):	return "NC_EMULTIDEFINE_VAR_DIMIDS";
+        case (NC_EMULTIDEFINE_VAR_TYPE):	return "NC_EMULTIDEFINE_VAR_TYPE";
+        case (NC_EMULTIDEFINE_VAR_LEN):		return "NC_EMULTIDEFINE_VAR_LEN";
+        case (NC_EMULTIDEFINE_NUMRECS):		return "NC_EMULTIDEFINE_NUMRECS";
+        case (NC_EMULTIDEFINE_VAR_BEGIN):	return "NC_EMULTIDEFINE_VAR_BEGIN";
+        case (NC_EMULTIDEFINE_ATTR_NUM):	return "NC_EMULTIDEFINE_ATTR_NUM";
+        case (NC_EMULTIDEFINE_ATTR_SIZE):	return "NC_EMULTIDEFINE_ATTR_SIZE";
+        case (NC_EMULTIDEFINE_ATTR_NAME):	return "NC_EMULTIDEFINE_ATTR_NAME";
+        case (NC_EMULTIDEFINE_ATTR_TYPE):	return "NC_EMULTIDEFINE_ATTR_TYPE";
+        case (NC_EMULTIDEFINE_ATTR_LEN):	return "NC_EMULTIDEFINE_ATTR_LEN";
+        case (NC_EMULTIDEFINE_ATTR_VAL):	return "NC_EMULTIDEFINE_ATTR_VAL";
+        case (NC_EMULTIDEFINE_FNC_ARGS):	return "NC_EMULTIDEFINE_FNC_ARGS";
+        case (NC_EMULTIDEFINE_FILL_MODE):	return "NC_EMULTIDEFINE_FILL_MODE";
+        case (NC_EMULTIDEFINE_VAR_FILL_MODE):	return "NC_EMULTIDEFINE_VAR_FILL_MODE";
+        case (NC_EMULTIDEFINE_VAR_FILL_VALUE):	return "NC_EMULTIDEFINE_VAR_FILL_VALUE";
+        default:
+              sprintf(unknown_str,"Unknown code %d",err);
+    }
+    return unknown_str;
+}
+
diff --git a/test/common/testutils.h b/test/common/testutils.h
new file mode 100644
index 0000000..ef2b7a4
--- /dev/null
+++ b/test/common/testutils.h
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: testutils.h 2133 2015-09-26 19:16:01Z wkliao $ */
+
+
+#ifndef _UTILS_H
+#define _UTILS_H
+
+#include <limits.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+typedef struct {
+	char infname[PATH_MAX];
+	char outfname[PATH_MAX];
+} params;
+
+void parse_read_args(int argc, char **argv, int rank, params *p);
+void parse_write_args(int argc, char **argv, int rank, params *p);
+
+#ifdef PNC_DEBUG
+#define PASS_STR "\x1b[32mpass\x1b[0m\n"
+#define FAIL_STR "\x1b[31mfail\x1b[0m with %d mismatches\n"
+#else
+#define PASS_STR "pass\n"
+#define FAIL_STR "fail with %d mismatches\n"
+#endif
+
+extern char* nc_err_code_name(int err);
+
+#endif
diff --git a/test/common/testutilsf.F90 b/test/common/testutilsf.F90
new file mode 100644
index 0000000..cfc7657
--- /dev/null
+++ b/test/common/testutilsf.F90
@@ -0,0 +1,59 @@
+!
+!  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!     This is part of the PnetCDF package.
+!
+!     $Id: testutilsf.F90 2133 2015-09-26 19:16:01Z wkliao $
+
+      ! This function gets the executable name and output file name from the
+      ! command line.
+      integer function get_args(cmd, filename)
+#ifdef NAGf90Fortran
+          USE F90_UNIX_ENV, only : iargc, getarg
+          implicit none
+#else
+          implicit none
+          integer iargc
+#endif
+          integer argc
+          character(len=*) cmd, filename
+
+          get_args = 1
+          call getarg(0, cmd)
+          argc = IARGC()
+          if (argc .GT. 1) then
+              print*,'Usage: ',trim(cmd),' [filename]'
+              get_args = 0
+              return
+          endif
+          if (argc .EQ. 1) call getarg(1, filename)
+      end function get_args
+
+      ! This function prints the pass/fail message on screen
+      subroutine pass_fail(nerrs, msg)
+          implicit none
+          integer nerrs
+          character(len=*) msg
+
+          ! local variables
+          CHARACTER ESC
+          PARAMETER (ESC=char(27))
+
+#ifdef PNC_DEBUG
+          CHARACTER (LEN=20) PASS_STR, FAIL_STR
+          PARAMETER (PASS_STR='------ '//ESC//'[32mpass'//ESC//'[0m')
+          PARAMETER (FAIL_STR='------ '//ESC//'[31mfail'//ESC//'[0m')
+#else
+          CHARACTER (LEN=11) PASS_STR, FAIL_STR
+          PARAMETER (PASS_STR='------ pass')
+          PARAMETER (FAIL_STR='------ fail')
+#endif
+
+          if (nerrs .EQ. 0) then
+              write(*,"(A67,A)") msg, PASS_STR
+          else
+              write(*,"(A67,A)") msg, FAIL_STR
+          endif
+      end subroutine pass_fail
+
diff --git a/test/fandc/Makefile.in b/test/fandc/Makefile.in
new file mode 100644
index 0000000..e91e3a3
--- /dev/null
+++ b/test/fandc/Makefile.in
@@ -0,0 +1,88 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+#
+# @configure_input@
+
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I../../src/lib -I$(srcdir)/../common
+FPPFLAGS += -I../../src/libf @FC_MODINC at ../../src/libf90
+LDFLAGS  := $(LDFLAGS) -L../common
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
+ifeq (@PNC_DEBUG@, yes)
+CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
+endif
+
+C_SRCS   = pnctest.c \
+           csnap.c
+
+F77_SRCS = pnf_test.f \
+           pnctestf.f
+
+ifeq (@F77_SUPPORT_FREEFORM@, yes)
+F77_SRCS += freeform.f
+endif
+
+F90_SRCS = fixedform.f90
+
+PROGS  = $(C_SRCS:.c=)
+OBJS   = $(C_SRCS:.c=.o)
+ifeq (@has_fortran@, yes)
+PROGS += $(F77_SRCS:.f=)   $(F90_SRCS:.f90=)
+OBJS  += $(F77_SRCS:.f=.o) $(F90_SRCS:.f90=.o)
+endif
+
+GARBAGE      = $(PROGS) *.nc
+PACKING_LIST = $(C_SRCS) $(F77_SRCS) $(F90_SRCS) Makefile.in depend
+
+all: $(PROGS)
+
+$(C_SRCS:.c=.o): $(srcdir)/../common/testutils.h
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+pnctest: pnctest.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+csnap:  csnap.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS) -lm
+
+pnctestf: pnctestf.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+pnf_test:  pnf_test.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+# check F77 program to see if accept Fortran free form
+freeform.o: freeform.f
+	$(COMPILE.f) @FFREEFORMFLAG@ $<
+
+freeform: freeform.o
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+# check F90 program to see if accept Fortran fixed form
+fixedform.o: fixedform.f90
+	$(COMPILE.f90) @FFIXEDFORMFLAG@ $<
+
+fixedform: fixedform.o
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+testing check verbose_testing:
+
+ptest ptests ptest2 ptest4 ptest6 ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+include $(srcdir)/depend
+
+$(LIBRARY): ;
+
diff --git a/test/fandc/csnap.c b/test/fandc/csnap.c
new file mode 100644
index 0000000..e7de071
--- /dev/null
+++ b/test/fandc/csnap.c
@@ -0,0 +1,475 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: csnap.c 2258 2015-12-22 04:50:40Z wkliao $ */
+
+
+/******************************************************************************
+
+  This code writes one or two arrays, tt[k][j][i] (and smf[j][i], if
+  'only_3d' is 0), into the file 'csnap.nc.' It then reads the field(s)
+  from the file, and compares with the original field values.
+ 
+  i=longitude, j=latitude, k=level
+ 
+  To run: Set the global sizes, parallel decomposition and other I/O
+  parameters below.
+ 
+  By Woo-Sun Yang and Chris Ding
+  NERSC, Lawrence Berkeley National Laboratory
+
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h> /* srand(), rand() */
+#include <string.h> /* strcpy() */
+#include <unistd.h>
+#include <math.h>  /* sqrt() */
+#include <limits.h>
+#include <float.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <testutils.h>
+
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));nerrs++;}}
+
+/*** Field parameters ***/
+static int verbose, nerrs;
+
+const MPI_Offset totsiz_3d[3] = { 256, 256, 256 }; /* global sizes of 3D field */
+MPI_Offset totsiz_2d[2];                           /* global sizes of 2D field */
+MPI_Offset locsiz_3d[3];                           /* local sizes of 3D fields */
+MPI_Offset locsiz_2d[2];                           /* local sizes of 2D fields */
+MPI_Offset istart, jstart, kstart;                 /* offsets of 3D field */
+
+const int random_fields = 0;                /* random fields? 1 or 0 */
+const int only_3d       = 1;                /* I/O 3D field only? 1 or 0 */
+
+int has_2d;                                 /* contains valid 2D data? */
+
+const int nwrites = 5;                      /* number of write samples */
+const int nreads  = 5;                      /* number of read samples */
+
+const int fillmode = NC_NOFILL;             /* NC_FILL or NC_NOFILL; actually
+                                               prefilling not supported */
+
+/*** Parallel domain decomposition parameters ***/
+
+MPI_Comm comm_cart;                         /* Cartesian communicator */
+int mype;                                   /* rank in comm_cart */
+int totpes;                                 /* total number of PEs */
+int numpes[3] = {   0,   1,   1 };          /* number of PEs along axes;
+                                               determined by MPI where
+                                               a zero is specified */
+int pe_coords[3];                           /* Cartesian PE coords */
+
+/*** function prototypes ***/
+
+void find_locnx(MPI_Offset nx, int mype, int totpes, MPI_Offset *locnx, MPI_Offset *xbegin);
+void write_file(char *filename, double *t);
+void read_file(char *filename, double *t);
+void get_fields(double *tt, double *smf);
+void compare_vec(double *a, double *b, int ndims, MPI_Offset *sizes, int corr_data);
+
+
+int main(int argc, char *argv[]) {
+  int isperiodic[3] = {0, 0, 0};
+  int reorder = 0;
+  double t[20], t_g[20];
+  double file_size;
+  double rates_l[4], rates_g[4];
+  int i, rank;
+  char filename[256];
+
+  MPI_Init(&argc,&argv);
+  MPI_Comm_size(MPI_COMM_WORLD,&totpes);
+  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for 3D array write/read ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+  verbose = 0;
+  nerrs = 0;
+
+  MPI_Dims_create(totpes,3,numpes);
+  MPI_Cart_create(MPI_COMM_WORLD,3,numpes,isperiodic,reorder,&comm_cart);
+  MPI_Comm_rank(comm_cart,&mype);
+  MPI_Cart_coords(comm_cart,mype,3,pe_coords);
+
+/*
+   Determine local sizes for tt (locsiz_3d) and smf (locsiz_2d).
+   Also determine whether the current processor contains valid 2D data.
+   Compute file_size in 1e6 Bytes
+ */
+
+  find_locnx(totsiz_3d[0],pe_coords[0],numpes[0],&locsiz_3d[0],&kstart);
+  find_locnx(totsiz_3d[1],pe_coords[1],numpes[1],&locsiz_3d[1],&jstart);
+  find_locnx(totsiz_3d[2],pe_coords[2],numpes[2],&locsiz_3d[2],&istart);
+
+  totsiz_2d[0] = totsiz_3d[1];
+  totsiz_2d[1] = totsiz_3d[2];
+
+  locsiz_2d[0] = locsiz_3d[1];
+  locsiz_2d[1] = locsiz_3d[2];
+
+  has_2d = (! only_3d) && (pe_coords[0] == numpes[0] - 1);
+
+  if (only_3d)
+    file_size = (((double) totsiz_3d[0])*((double) totsiz_3d[1])
+               * ((double) totsiz_3d[2])) * 1.0e-6 * sizeof(double);
+  else
+    file_size = (((double) totsiz_3d[0])*((double) totsiz_3d[1])
+               * ((double) totsiz_3d[2])
+               + ((double) totsiz_2d[0])*((double) totsiz_2d[1]))
+               * 1.0e-6 * sizeof(double);
+
+/* Print data decomposition information */
+
+  if (mype == 0 && verbose)
+    printf("mype  pe_coords    totsiz_3d         locsiz_3d       "
+           "kstart,jstart,istart\n");
+
+  MPI_Barrier(comm_cart);
+
+  if (verbose)
+  printf("%3d   %2d %2d %2d  %4lld %4lld %4lld    %4lld %4lld %4lld   %6lld %6lld %6lld\n",
+         mype, pe_coords[0], pe_coords[1], pe_coords[2],
+         totsiz_3d[0], totsiz_3d[1], totsiz_3d[2],
+         locsiz_3d[0], locsiz_3d[1], locsiz_3d[2],
+         kstart, jstart, istart);
+
+/* Write and then read back */
+
+  for (i=0; i < 20; t[i++] = DBL_MAX);   /* ready for timing */
+
+  write_file(filename, &t[ 0]);
+  read_file (filename, &t[10]);
+
+/* Compute I/O rates */
+
+  rates_l[0] = file_size / t[1];             /* write rate */
+  rates_l[1] = file_size /(t[0] + t[1]);     /* effective write rate */
+  rates_l[2] = file_size / t[11];            /* read rate */
+  rates_l[3] = file_size /(t[10] + t[11]);   /* effective read rate */
+
+  MPI_Allreduce(rates_l, rates_g, 4, MPI_DOUBLE, MPI_MIN, comm_cart);
+  MPI_Allreduce(t, t_g, 20, MPI_DOUBLE, MPI_MAX, comm_cart);
+
+  if (mype == 0 && verbose) {
+     printf("File size: %10.3e MB\n", file_size);
+     printf("    Write: %9.3f MB/s  (eff., %9.3f MB/s)\n",
+            rates_g[0], rates_g[1]);
+     printf("    Read : %9.3f MB/s  (eff., %9.3f MB/s)\n",
+            rates_g[2], rates_g[3]);
+     printf(" %c %10.3e %3d %10.3e %10.3e %8.3f %10.3e %10.3e %8.3f\n",
+           ((fillmode == NC_FILL) ? 'f' : 'n'), file_size, totpes,
+            t_g[0], t_g[1], rates_g[1], t_g[10], t_g[11], rates_g[3]);
+  }
+
+  MPI_Comm_free(&comm_cart);
+
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (mype == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+  MPI_Finalize();
+  return 0;
+}
+
+
+void write_file(char *filename, double *t) {
+  double *tt = NULL;
+  double *smf = NULL;
+  double t1, t2, t3;
+  int dim_id[3];
+  int lon_id, lat_id, lev_id;
+  int err;
+  int file_id;
+  int t_id, smf_id;
+  int ii;
+  MPI_Offset start_3d[3];
+  MPI_Offset count_3d[3];
+  MPI_Offset start_2d[2];
+  MPI_Offset count_2d[2];
+
+  start_3d[0] = kstart;
+  start_3d[1] = jstart;
+  start_3d[2] = istart;
+  count_3d[0] = locsiz_3d[0];
+  count_3d[1] = locsiz_3d[1];
+  count_3d[2] = locsiz_3d[2];
+  start_2d[0] = jstart;
+  start_2d[1] = istart;
+  count_2d[0] = locsiz_2d[0];
+  count_2d[1] = locsiz_2d[1];
+  
+  tt = (double*)malloc(locsiz_3d[0]*locsiz_3d[1]*locsiz_3d[2]*sizeof(double));
+
+  if (has_2d)
+    smf = (double*)malloc(locsiz_2d[0]*locsiz_2d[1]*sizeof(double));
+  else
+    smf = (double*)malloc(sizeof(double));
+
+  for (ii = 1; ii <= nwrites; ii++) {
+
+    if(mype == 0) unlink(filename);
+
+    get_fields(tt, smf);
+    MPI_Barrier(comm_cart);
+
+    t1 = MPI_Wtime();
+
+    err = ncmpi_create(comm_cart, filename, NC_CLOBBER, MPI_INFO_NULL,
+                        &file_id); ERR
+
+/*  err = nc_set_fill(file_id,fillmode,&old_fillmode); ERR */
+
+    err = ncmpi_def_dim(file_id,"level",    (MPI_Offset) totsiz_3d[0],&lev_id); ERR
+    err = ncmpi_def_dim(file_id,"latitude", (MPI_Offset) totsiz_3d[1],&lat_id); ERR
+    err = ncmpi_def_dim(file_id,"longitude",(MPI_Offset) totsiz_3d[2],&lon_id); ERR
+
+    dim_id[0] = lev_id; dim_id[1] = lat_id; dim_id[2] = lon_id;
+
+    err = ncmpi_def_var(file_id,"t",NC_DOUBLE,3,dim_id,&t_id); ERR
+
+    if (! only_3d) {
+      err = ncmpi_def_var(file_id,"smf",NC_DOUBLE,2,&dim_id[1],&smf_id); ERR
+    }
+
+    err = ncmpi_enddef(file_id); ERR
+
+    t2 = MPI_Wtime();
+
+    err = ncmpi_put_vara_double_all(file_id,t_id,start_3d,count_3d,tt); ERR
+
+    if (! only_3d) {
+      err = ncmpi_begin_indep_data(file_id); ERR
+
+      if (has_2d) {
+        err = ncmpi_put_vara_double(file_id,smf_id,start_2d,count_2d,smf); ERR
+      }
+
+      err = ncmpi_end_indep_data(file_id); ERR
+    }
+
+    err = ncmpi_close(file_id); ERR
+
+    MPI_Barrier(comm_cart);
+    t3 = MPI_Wtime();
+
+    if (t2 - t1 < t[0]) t[0] = t2 - t1;
+    if (t3 - t2 < t[1]) t[1] = t3 - t2;
+    if (mype == 0 && verbose) printf("write %d: %9.3e %9.3e\n", ii, t2-t1, t3-t2);
+  }
+
+  free(tt);
+  free(smf);
+}
+
+
+void read_file(char *filename, double *t) {
+  double *tt  = NULL;
+  double *smf = NULL;
+  double *buf = NULL;
+  double t1, t2, t3;
+  double dt1, dt2=0;
+  int ncid;
+  int vid_t, vid_smf;
+  int i, j, k, ii, err;
+
+  MPI_Offset start_3d[3];
+  MPI_Offset count_3d[3];
+  MPI_Offset start_2d[2];
+  MPI_Offset count_2d[2];
+
+  start_3d[0] = kstart;
+  start_3d[1] = jstart;
+  start_3d[2] = istart;
+  count_3d[0] = locsiz_3d[0];
+  count_3d[1] = locsiz_3d[1];
+  count_3d[2] = locsiz_3d[2];
+  start_2d[0] = jstart;
+  start_2d[1] = istart;
+  count_2d[0] = locsiz_2d[0];
+  count_2d[1] = locsiz_2d[1];
+
+  tt = (double*)malloc(locsiz_3d[0]*locsiz_3d[1]*locsiz_3d[2]*sizeof(double));
+
+  if (has_2d)
+    smf = (double*)malloc(locsiz_2d[0]*locsiz_2d[1]*sizeof(double));
+  else
+    smf = (double*)malloc(sizeof(double));
+
+  buf = (double*)malloc(locsiz_3d[0]*locsiz_3d[1]*locsiz_3d[2]*sizeof(double));
+
+  get_fields(tt, smf);
+
+  for (ii = 1; ii <= nreads; ii++) {
+
+    double *ptr = buf;
+    for (k = 0; k < locsiz_3d[0]; k++)
+      for (j = 0; j < locsiz_3d[1]; j++)
+        for (i = 0; i < locsiz_3d[2]; i++)
+          *ptr++ = 4.444;
+
+    MPI_Barrier(comm_cart);
+    t1 = MPI_Wtime();
+
+    err = ncmpi_open(comm_cart, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+
+    err = ncmpi_inq_varid(ncid,"t",&vid_t); ERR
+    if (! only_3d) {
+        err = ncmpi_inq_varid(ncid,"smf",&vid_smf); ERR
+    }
+
+    t2 = MPI_Wtime();
+
+    err = ncmpi_get_vara_double_all(ncid,vid_t,start_3d,count_3d,buf); ERR
+
+    dt1 = MPI_Wtime();
+    if (ii == 1) compare_vec(tt,buf,3,locsiz_3d,1);
+    dt1 = MPI_Wtime() - dt1;
+
+    if (! only_3d) {
+      err = ncmpi_begin_indep_data(ncid); ERR
+
+      if (has_2d) {
+          err = ncmpi_get_vara_double(ncid,vid_smf,start_2d,count_2d,buf); ERR
+      }
+
+      dt2 = MPI_Wtime();
+      if (ii == 1) compare_vec(smf,buf,2,locsiz_2d,has_2d);
+      dt2 = MPI_Wtime() - dt2;
+
+      err = ncmpi_end_indep_data(ncid); ERR
+    }
+
+    err = ncmpi_close(ncid); ERR
+
+    MPI_Barrier(comm_cart);
+    t3 = MPI_Wtime();
+
+    if (t2 - t1 < t[0]) t[0] = t2 - t1;
+    if ((t3 - t2) - (dt1 + dt2) < t[1]) t[1] = (t3 - t2) - (dt1 + dt2);
+    if (mype == 0 && verbose)
+        printf(" read %d: %9.3e %9.3e\n", ii, t2-t1, (t3-t2)-(dt1+dt2));
+  }
+
+  free(tt);
+  free(smf);
+  free(buf);
+}
+
+
+void find_locnx(MPI_Offset nx, int mype, int totpes, MPI_Offset *locnx, MPI_Offset *xbegin) {
+  MPI_Offset xremain;
+
+  *locnx = nx / totpes;
+  xremain = nx - totpes*(*locnx);
+  if (mype < xremain) (*locnx)++;
+  *xbegin = mype*(nx/totpes) + xremain;
+  if (mype < xremain) *xbegin += mype - xremain;
+}
+
+
+void get_fields(double *tt, double *smf) {
+  int i, j, k;
+
+  if (random_fields) {
+    unsigned int seed = (INT_MAX / totpes) * mype;
+    srand(seed);
+
+    for (k = 0; k < locsiz_3d[0]; k++)
+      for (j = 0; j < locsiz_3d[1]; j++)
+        for (i = 0; i < locsiz_3d[2]; i++) {
+            double tmp = rand();
+            *tt++ = tmp / (RAND_MAX + 1.);
+        }
+
+    if (has_2d)
+      for (j = 0; j < locsiz_2d[0]; j++)
+        for (i = 0; i < locsiz_2d[1]; i++) {
+            double tmp = rand();
+            *smf++ = tmp / (RAND_MAX + 1.);
+        }
+  }
+  else {
+    for (k = 0; k < locsiz_3d[0]; k++)
+      for (j = 0; j < locsiz_3d[1]; j++)
+        for (i = 0; i < locsiz_3d[2]; i++)
+           *tt++ = (istart + i + 1 + totsiz_3d[2]*(jstart + j
+                                   + totsiz_3d[1]*(kstart + k)))*1.e-3;
+
+    if (has_2d)
+      for (j = 0; j < locsiz_2d[0]; j++)
+        for (i = 0; i < locsiz_2d[1]; i++)
+           *smf++ = (istart + i + 1 + totsiz_2d[1]*(jstart + j))*1.e-2;
+  }
+}
+
+
+void compare_vec(double *a, double *b, int ndims, MPI_Offset *sizes, int corr_data) {
+  double diff, delta, delmax, delmin;
+  double ws[5], wr[5];
+  MPI_Offset totsiz;
+  int i;
+
+  if (corr_data) {
+    totsiz = 1;
+    for (i = 0; i < ndims; i++)
+      totsiz = totsiz * sizes[i];
+
+    ws[0] = 0.;           /*  diff    */
+    ws[1] = 0.;           /*  sumsq   */
+    ws[2] = totsiz;       /*  totsiz  */
+    ws[3] = 0.;           /*  delmax  */
+    ws[4] = DBL_MAX;      /*  delmin  */
+
+    for (i = 0; i < totsiz; i++) {
+      delta = (a[i] - b[i]) * (a[i] - b[i]);
+      ws[0] = ws[0] + delta;
+      ws[1] = ws[1] + a[i] * a[i];
+      if (delta > ws[3]) ws[3] = delta;
+      if (delta < ws[4]) ws[4] = delta;
+    }
+  }
+  else {
+    ws[0] = ws[1] = ws[2] = ws[3] = 0.;
+    ws[4] = DBL_MAX;
+  }
+
+  MPI_Allreduce( ws,     wr,     3, MPI_DOUBLE, MPI_SUM, comm_cart);
+  MPI_Allreduce(&ws[3], &delmax, 1, MPI_DOUBLE, MPI_MAX, comm_cart);
+  MPI_Allreduce(&ws[4], &delmin, 1, MPI_DOUBLE, MPI_MIN, comm_cart);
+
+  diff   = sqrt(wr[0]/wr[1]);           /*  Normalized error */
+  delmax = sqrt(wr[2]*delmax/wr[1]);    /*  Normalized max difference */
+  delmin = sqrt(wr[2]*delmin/wr[1]);    /*  Normalized min difference */
+
+  if (mype == 0 && verbose)
+      printf("diff, delmax, delmin = %9.3e %9.3e %9.3e\n", diff, delmax, delmin);
+}
diff --git a/test/fandc/depend b/test/fandc/depend
new file mode 100644
index 0000000..12bd79a
--- /dev/null
+++ b/test/fandc/depend
@@ -0,0 +1,2 @@
+pnf_test.o: pnf_test.f
+pnctestf.o: pnctestf.f
diff --git a/test/fandc/fixedform.f90 b/test/fandc/fixedform.f90
new file mode 100644
index 0000000..1ce6ab4
--- /dev/null
+++ b/test/fandc/fixedform.f90
@@ -0,0 +1,27 @@
+!
+!   Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: fixedform.f90 2257 2015-12-22 04:50:00Z wkliao $
+
+!
+! This program tests whether header file pnetcdf.inc conforms Fortran fixed
+! form. Hence this test is for compilation only.
+!
+
+      program main
+        implicit none
+        include "mpif.h"
+        include "pnetcdf.inc"
+
+        character(LEN=80) pnetcdf_version
+        integer err
+
+        call MPI_Init(err)
+
+        pnetcdf_version = nfmpi_inq_libvers()
+
+        call MPI_Finalize(err)
+
+      end program main
+
diff --git a/test/fandc/freeform.f b/test/fandc/freeform.f
new file mode 100644
index 0000000..6a87520
--- /dev/null
+++ b/test/fandc/freeform.f
@@ -0,0 +1,27 @@
+!
+!   Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: freeform.f 2257 2015-12-22 04:50:00Z wkliao $
+
+!
+! This program tests whether header file pnetcdf.inc conforms Fortran free form
+! for compilation only, not execution
+!
+
+program main
+    implicit none
+    include "mpif.h"
+    include "pnetcdf.inc"
+
+    character(LEN=80) pnetcdf_version
+    integer err
+
+    call MPI_Init(err)
+
+    pnetcdf_version = nfmpi_inq_libvers()
+
+    call MPI_Finalize(err)
+
+end program main
+
diff --git a/test/fandc/pnctest.c b/test/fandc/pnctest.c
new file mode 100644
index 0000000..9811e50
--- /dev/null
+++ b/test/fandc/pnctest.c
@@ -0,0 +1,70 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: pnctest.c 2258 2015-12-22 04:50:40Z wkliao $ */
+
+#include <stdio.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <testutils.h>
+
+/* Test program thanks to From: John Tannahill <tannahill1 at llnl.gov> */
+
+#define ERR if (err!=NC_NOERR) {printf("Error at line %d: %s\n", __LINE__,ncmpi_strerror(err)); nerrs++;}
+
+int main (int argc, char *argv[])
+{
+  int dim_id[3], isperiodic[3] = { 0, 0, 0 };
+  int err, lat_id, lev_id, lon_id, ncid, totpes, rank, tt_id;
+  int  reorder=0, nerrs=0;
+  int numpes[3] = { 0, 1, 1 };  /* number of PEs along axes;
+                                   determined by MPI where a
+                                   zero is specified */
+  MPI_Offset TOTSIZ_3D[3] = { 10, 20, 30 };
+  MPI_Comm comm_cart;
+
+  MPI_Init (&argc, &argv);
+  MPI_Comm_size (MPI_COMM_WORLD, &totpes);
+  MPI_Comm_size (MPI_COMM_WORLD, &rank);
+
+  MPI_Dims_create (totpes, 3, numpes);
+  MPI_Cart_create (MPI_COMM_WORLD, 3, numpes, isperiodic, reorder, &comm_cart);
+
+  err = ncmpi_create (comm_cart, "testfile.nc", NC_CLOBBER, MPI_INFO_NULL,
+                       &ncid); ERR
+
+  err = ncmpi_def_dim (ncid, "level",     TOTSIZ_3D[0], &lev_id); ERR
+  err = ncmpi_def_dim (ncid, "latitude",  TOTSIZ_3D[1], &lat_id); ERR
+  err = ncmpi_def_dim (ncid, "longitude", TOTSIZ_3D[2], &lon_id); ERR
+
+  dim_id[0] = lev_id;
+  dim_id[1] = lat_id;
+  dim_id[2] = lon_id;
+
+  err = ncmpi_def_var (ncid, "tt", NC_FLOAT, 3, dim_id, &tt_id); ERR
+
+  err = ncmpi_enddef (ncid); ERR
+
+  err = ncmpi_close (ncid); ERR
+
+  MPI_Comm_free (&comm_cart);
+
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+  MPI_Finalize ( );
+  return 0;
+}
diff --git a/test/fandc/pnctestf.f b/test/fandc/pnctestf.f
new file mode 100644
index 0000000..7d7d577
--- /dev/null
+++ b/test/fandc/pnctestf.f
@@ -0,0 +1,74 @@
+!
+!   Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+!   $Id: pnctestf.f 2224 2015-12-16 06:10:36Z wkliao $
+!
+      program Pnf_Test
+! Test program thanks to From: John Tannahill <tannahill1 at llnl.gov> 
+
+      implicit none
+      include "mpif.h"
+      include "pnetcdf.inc"
+
+      integer*8 TOTSIZ_3D(3)
+
+      logical reorder
+
+      logical isperiodic(3)
+
+      integer comm_cart
+      integer ierr
+      integer lat_id, lev_id, lon_id
+      integer ncid
+      integer totpes
+      integer tt_id
+
+      integer dim_id(3)
+
+      integer numpes(3)
+!    number of PEs along axes;
+!    determined by MPI where a zero is specified
+
+      data totsiz_3d/10,20,30/
+      data reorder /.false./
+      data isperiodic /.false., .false., .false./
+      data numpes/1,1,0/
+
+      call MPI_Init(ierr)
+
+      call MPI_Comm_Size(MPI_COMM_WORLD, totpes, ierr)
+
+      call MPI_Dims_Create(totpes, 3, numpes, ierr)
+
+      call MPI_Cart_Create(MPI_COMM_WORLD, 3, numpes, isperiodic,
+     +                     reorder, comm_cart, ierr)
+
+      ierr = nfmpi_create(comm_cart, "pnf_test.nc", NF_CLOBBER,
+     +                    MPI_INFO_NULL, ncid)
+
+      ierr = nfmpi_def_dim(ncid, "level",     totsiz_3d(1), lev_id)
+      ierr = nfmpi_def_dim(ncid, "latitude",  totsiz_3d(2), lat_id)
+      ierr = nfmpi_def_dim(ncid, "longitude", totsiz_3d(3), lon_id)
+
+      dim_id(1) = lev_id
+      dim_id(2) = lat_id
+      dim_id(3) = lon_id
+
+      ierr = nfmpi_def_var(ncid, "tt", NF_FLOAT, 3, dim_id, tt_id)
+
+      ierr = nfmpi_enddef(ncid)
+
+      ierr = nfmpi_close(ncid)
+
+      call MPI_Comm_Free(comm_cart, ierr)
+
+      call MPI_Finalize  (ierr)
+
+      Write (6,10)
+
+ 10   format(" No Errors")
+
+      Stop
+
+      end ! program Pnf_Test
diff --git a/test/fandc/pnf_test.f b/test/fandc/pnf_test.f
new file mode 100644
index 0000000..6de5120
--- /dev/null
+++ b/test/fandc/pnf_test.f
@@ -0,0 +1,696 @@
+!
+!  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!  $Id: pnf_test.f 2224 2015-12-16 06:10:36Z wkliao $
+!
+!=============================================================================
+!
+! CODE DEVELOPER
+!   John Tannahill, LLNL
+!   jrt at llnl.gov
+!   Note that this code was adapted from csnap.c, which was written by:
+!     Woo-Sun Yang and Chris Ding
+!     NERSC, Lawrence Berkeley National Laboratory
+!
+! FILE
+!   pnf_test.F
+!
+! ROUTINES
+!   Pnf_Test (Program)
+!
+! The purpose of this program is to test the Fortran interface to the
+! parallel netCDF library being developed at Argonne National Lab and
+! Northwestern Univ.
+!
+! This code writes the array, tt(k)(j)(i), into the file 'pnf_test.nc'. It
+! then reads the array from the file, and compares it with the original
+! values.
+! 
+! i=longitude, j=latitude, k=level
+!
+!=============================================================================
+
+      program Pnf_Test
+
+      implicit none
+
+      include "mpif.h"
+      include "pnetcdf.inc"
+
+
+!     -----------------------
+!     Parameter declarations.
+!     -----------------------
+
+      integer NREADS, NWRITES 
+      parameter (NREADS = 5, NWRITES = 5 )
+      ! number of read samples
+      ! number of write samples
+
+      integer*8 TOTSIZ_3D(3) ! global sizes of 3D field
+
+
+!     ----------------------
+!     Variable declarations.
+!     ----------------------
+
+      logical reorder
+              
+      logical isperiodic(3)
+              
+      integer comm_cart                   ! Cartesian communicator
+      integer ierr
+      integer*8 istart, jstart, kstart ! offsets of 3D field
+      integer*8 locsiz
+      integer mype                        ! rank in comm_cart
+      integer totpes                      ! total number of PEs
+              
+      integer*8 locsiz_3d(3) ! local sizes of 3D fields
+      integer pe_coords(3)                ! Cartesian PE coords
+              
+      integer numpes(3)                      ! number of PEs along axes;
+                                             !   determined by MPI where a
+                                             !   zero is specified
+
+      double precision  filsiz
+              
+      real*4  rdt_g(2)
+      real*4  rdt_l(2)
+      real*4  wrt_g(2)
+      real*4  wrt_l(2)
+              
+      real*4  rrates_g(2)
+      real*4  rrates_l(2)
+      real*4  wrates_g(2)
+      real*4  wrates_l(2)
+
+
+      data reorder / .false. /
+      data isperiodic / .false., .false., .false. /
+      data numpes / 1, 1, 0 /
+      data TOTSIZ_3D / 256, 256, 256 /
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+      call MPI_Init (ierr)
+
+      call MPI_Comm_Size (MPI_COMM_WORLD, totpes, ierr)
+
+      call MPI_Dims_Create (totpes, 3, numpes, ierr)
+
+      call MPI_Cart_Create
+     &  (MPI_COMM_WORLD, 3, numpes, isperiodic, reorder,
+     &   comm_cart, ierr)
+
+      call MPI_Comm_Rank (comm_cart, mype, ierr)
+
+      call MPI_Cart_Coords (comm_cart, mype, 3, pe_coords, ierr)
+
+
+      rdt_l(1) = 1.0e38
+      rdt_l(2) = 1.0e38
+      wrt_l(1) = 1.0e38
+      wrt_l(2) = 1.0e38
+!      rdt_l(:) = Huge (rdt_l)   ! initialize for timing
+!      wrt_l(:) = Huge (wrt_l)
+
+
+!     ----------------------------------------
+!     Determine local size for tt (locsiz_3d).
+!     ----------------------------------------
+
+!     ===============
+      call Find_Locnx
+     &  (TOTSIZ_3D(1), pe_coords(1), numpes(1), locsiz_3d(1), istart)
+      call Find_Locnx
+     &  (TOTSIZ_3D(2), pe_coords(2), numpes(2), locsiz_3d(2), jstart)
+      call Find_Locnx
+     &  (TOTSIZ_3D(3), pe_coords(3), numpes(3), locsiz_3d(3), kstart)
+!     ===============
+
+
+!     -------------------------------
+!     Compute file size in 1d6 bytes.
+!     -------------------------------
+
+      filsiz = (TOTSIZ_3D(1) * TOTSIZ_3D(2) * TOTSIZ_3D(3)) *
+     &         1.0d-6 * 4.0d0
+
+
+!     -------------------------------------
+!     Print data decomposition information.
+!     -------------------------------------
+
+      if (mype .EQ. 0) Write (6,900)
+
+      call MPI_Barrier (comm_cart, ierr)
+
+      Write (6, 902)
+     &  mype, pe_coords(1), pe_coords(2), pe_coords(3),
+     &  TOTSIZ_3D(1), TOTSIZ_3D(2), TOTSIZ_3D(3),
+     &  locsiz_3d(1), locsiz_3d(2), locsiz_3d(3),
+     &  kstart, jstart, istart
+
+ 900  format ("mype  pe_coords    totsiz_3d         locsiz_3d       ",
+     &        "kstart,jstart,istart")
+ 902  format (i3,3x,i2,1x,i2,1x,i2,2x,i4,1x,i4,1x,i4,4x,i4,1x,i4,1x,i4,
+     &        3x,i6,1x,i6,1x,i6)
+
+
+!     -------------------------
+!     Write and then read back.
+!     -------------------------
+
+      locsiz = locsiz_3d(1) * locsiz_3d(2) * locsiz_3d(3)
+
+!     ===============
+      call Write_File
+!     ===============
+     &  ("pnf_test.nc", NWRITES, mype, comm_cart, istart, jstart,
+     &   kstart, locsiz, locsiz_3d, TOTSIZ_3D, wrt_l)
+!!!   Write (6,*) wrt_l(1), wrt_l(2)
+
+!     ==============
+      call Read_File
+!     ==============
+     &  ("pnf_test.nc", NREADS,  mype, comm_cart, istart, jstart,
+     &   kstart, locsiz, locsiz_3d, TOTSIZ_3D, rdt_l)
+
+
+!     ----------------------------
+!     Compute and print I/O rates.
+!     ----------------------------
+
+      wrates_l(1) = real(filsiz / wrt_l(2))               ! write rate
+      wrates_l(2) = real(filsiz / (wrt_l(1) + wrt_l(2)))  ! effective write rate
+
+      rrates_l(1) = real(filsiz / rdt_l(2))               ! read rate
+      rrates_l(2) = real(filsiz / (rdt_l(1) + rdt_l(2)))  ! effective read  rate
+
+
+      call MPI_Allreduce
+     &  (wrates_l, wrates_g, 2, MPI_REAL, MPI_MIN, comm_cart, ierr)
+      call MPI_Allreduce
+     &  (rrates_l, rrates_g, 2, MPI_REAL, MPI_MIN, comm_cart, ierr)
+
+      call MPI_Allreduce
+     &  (wrt_l,    wrt_g,    2, MPI_REAL, MPI_MAX, comm_cart, ierr)
+      call MPI_Allreduce
+     &  (rdt_l,    rdt_g,    2, MPI_REAL, MPI_MAX, comm_cart, ierr)
+
+
+      if (mype .EQ. 0) then
+        Write (6,905) filsiz
+        Write (6,910) wrates_g(1), wrates_g(2)
+        Write (6,915) rrates_g(1), rrates_g(2)
+        Write (6,920) totpes
+        Write (6,922) wrt_g(1), wrt_g(2), wrates_g(2),
+     &                rdt_g(1), rdt_g(2), rrates_g(2)
+      end if 
+
+ 905  format ("File size: ", e10.3, " MB")
+ 910  format ("    Write: ", f9.3, " MB/s  (eff., ", f9.3, " MB/s)")
+ 915  format ("    Read : ", f9.3, " MB/s  (eff., ", f9.3, " MB/s)")
+ 920  format ("Total number PEs: ", i4)
+ 922  format (e11.3, e11.3, f9.3, e11.3, e11.3, f9.3)
+
+
+      call MPI_Comm_Free (comm_cart, ierr)
+
+      call MPI_Finalize  (ierr)
+
+
+      Stop
+
+      end ! program Pnf_Test
+
+
+!     ------------
+
+
+      subroutine Write_File
+     &  (filename, nwrites, mype, comm_cart, istart, jstart, kstart,
+     &   locsiz, locsiz_3d, totsiz_3d, wrt_l)
+
+      implicit none
+
+      include "mpif.h"
+      include "pnetcdf.inc"
+
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      character*(*) filename
+      integer nwrites
+      integer mype
+      integer comm_cart
+      integer*8 istart, jstart, kstart
+      integer*8 locsiz
+      integer*8 locsiz_3d(3)
+      integer*8 totsiz_3d(3)
+      real*4  wrt_l(2)
+
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      integer ierr
+      integer lon_id, lat_id, lev_id
+      integer ncid
+      integer nw
+      integer tt_id
+              
+      integer*8 count_3d(3)
+      integer*8 start_3d(3)
+              
+      integer dim_id(3)
+              
+      double precision  t1, t2, t3
+           
+      integer max_loc_size
+      parameter( max_loc_size = 20000000 )
+      real*4  tt(max_loc_size)   ! Need tt(locsiz)
+
+
+      if (locsiz .gt. MAX_LOC_SIZE) then
+         print *, 'locsiz = ', locsiz, ' larger than MAX_LOC_SIZE'
+         stop
+      endif
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+!      start_3d(1:3) = (/ kstart, jstart, istart /)
+!      count_3d(:)   = locsiz_3d(:)
+      start_3d(1) = istart
+      start_3d(2) = jstart
+      start_3d(3) = kstart
+      count_3d(1) = locsiz_3d(1)
+      count_3d(2) = locsiz_3d(2)
+      count_3d(3) = locsiz_3d(3)
+
+
+      do nw = 1, nwrites
+
+!       ==============
+        call Get_Field
+!       ==============
+     &    (istart, jstart, kstart, locsiz, locsiz_3d, totsiz_3d, tt)
+
+
+        call MPI_Barrier (comm_cart, ierr)
+        t1 = MPI_Wtime ( )
+
+
+!       =================
+        ierr = Nfmpi_Create
+!       =================
+     &    (comm_cart, filename, NF_CLOBBER, MPI_INFO_NULL, ncid)
+
+
+!       ==================
+        ierr = Nfmpi_Def_Dim
+     &    (ncid, "level",     totsiz_3d(1), lon_id)
+        ierr = Nfmpi_Def_Dim
+     &    (ncid, "latitude",  totsiz_3d(2), lat_id)
+        ierr = Nfmpi_Def_Dim
+     &    (ncid, "longitude", totsiz_3d(3), lev_id)
+!       ==================
+
+
+        dim_id(1) = lon_id
+        dim_id(2) = lat_id
+        dim_id(3) = lev_id
+
+!       ==================
+        ierr = Nfmpi_Def_Var
+!       ==================
+     &    (ncid, "tt", NF_REAL, 3, dim_id, tt_id)
+
+
+!       =================
+        ierr = Nfmpi_Enddef (ncid)
+!       =================
+
+
+        t2 = MPI_Wtime ( )
+
+
+!       =============================
+        ierr = Nfmpi_Put_Vara_Real_All
+!       =============================
+     &    (ncid, tt_id, start_3d, count_3d, tt)
+
+
+!       ================
+        ierr = Nfmpi_Close (ncid)
+!       ================
+
+
+        call MPI_Barrier (comm_cart, ierr)
+        t3 = MPI_Wtime ( )
+
+
+        if (t2 - t1 .LT. wrt_l(1)) wrt_l(1) = real(t2 - t1)
+        if (t3 - t2 .LT. wrt_l(2)) wrt_l(2) = real(t3 - t2)
+
+        if (mype .EQ. 0) Write (6,950) nw, t2-t1, t3-t2
+
+      end do
+
+
+ 950  format ("write ", i1, ": ", e10.3, 1x, e10.3)
+
+
+      Return
+
+      end
+
+
+!     ------------
+
+
+      subroutine Read_File
+     &  (filename, nreads, mype, comm_cart, istart, jstart, kstart,
+     &   locsiz, locsiz_3d, totsiz_3d, rdt_l)
+
+      implicit none
+
+      include "mpif.h"
+      include "pnetcdf.inc"
+
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      character*(*) filename
+      integer nreads
+      integer mype
+      integer comm_cart
+      integer*8 istart, jstart, kstart
+      integer*8 locsiz
+      integer*8 locsiz_3d(3)
+      integer*8 totsiz_3d(3)
+      real*4  rdt_l(2)
+
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      integer ierr
+      integer ncid
+      integer nr
+      integer tt_id
+      integer ii
+              
+      integer*8 count_3d(3)
+      integer*8 start_3d(3)
+              
+      double precision  t1, t2, t3
+              
+      integer max_loc_size
+      parameter( max_loc_size = 20000000 )
+      real*4  buf(max_loc_size)
+      real*4  tt (max_loc_size)
+
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+!     ==============
+      call Get_Field
+!     ==============
+     &  (istart, jstart, kstart, locsiz, locsiz_3d, totsiz_3d, tt)
+
+
+!     start_3d(1:3) = (/ kstart, jstart, istart /)
+!     count_3d(:)   = locsiz_3d(:)
+      start_3d(1) = istart
+      start_3d(2) = jstart
+      start_3d(3) = kstart
+      count_3d(1) = locsiz_3d(1)
+      count_3d(2) = locsiz_3d(2)
+      count_3d(3) = locsiz_3d(3)
+
+
+      do nr = 1, nreads
+
+         do ii=1, int(locsiz)
+            buf(ii) =  -99.99
+         enddo
+
+
+        call MPI_Barrier (comm_cart, ierr)
+        t1 = MPI_Wtime ( )
+
+
+!       ===============
+        ierr = Nfmpi_Open
+!       ===============
+     &    (comm_cart, filename, NF_NOWRITE, MPI_INFO_NULL, ncid)
+
+
+!       ====================
+        ierr = Nfmpi_Inq_Varid
+!       ====================
+     &    (ncid, "tt", tt_id)
+
+
+        t2 = MPI_Wtime ( )
+
+
+!       =============================
+        ierr = Nfmpi_Get_Vara_Real_All
+!       =============================
+     &    (ncid, tt_id, start_3d, count_3d, buf)
+
+
+!       ================
+        ierr = Nfmpi_Close (ncid)
+!       ================
+
+
+        call MPI_Barrier (comm_cart, ierr)
+        t3 = MPI_Wtime ( )
+
+
+        if (t2 - t1 .LT. rdt_l(1)) rdt_l(1) = real(t2 - t1)
+        if (t3 - t2 .LT. rdt_l(2)) rdt_l(2) = real(t3 - t2)
+
+        if (mype .EQ. 0) Write (6,970) nr, t2-t1, t3-t2
+
+
+        if (nr .EQ. 1) then
+!         ================
+          call Compare_Vec
+!         ================
+     &      (mype, comm_cart, locsiz, tt, buf)
+        end if
+
+      end do
+
+
+ 970  format (" read ", i1, ": ", e10.3, 1x, e10.3)
+
+
+      Return
+
+      end
+
+
+!     ------------
+
+
+      subroutine Find_Locnx
+     &  (nx, mype, totpes, locnx, ibegin)
+
+      implicit none
+
+      include "mpif.h"
+      include "pnetcdf.inc"
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      integer*8 nx
+      integer mype
+      integer totpes
+      integer*8 locnx
+      integer*8 ibegin
+
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      integer*8 iremain
+
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+      locnx = nx / totpes
+
+      iremain = nx - (totpes * locnx)
+
+      if (mype .LT. iremain) locnx = locnx + 1
+
+      ibegin = mype * (nx / totpes) + iremain + 1
+
+      if (mype .LT. iremain) ibegin = ibegin + (mype - iremain)
+
+
+      Return
+
+      end
+
+
+!     ------------
+
+
+      subroutine Get_Field
+     &  (istart, jstart, kstart, locsiz, locsiz_3d, totsiz_3d, tt)
+
+      implicit none
+
+      include "mpif.h"
+      include "pnetcdf.inc"
+
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      integer*8 istart, jstart, kstart
+      integer*8 locsiz
+      integer*8 locsiz_3d(3)
+      integer*8 totsiz_3d(3)
+      real*4  tt(locsiz)
+
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      integer ii, jj, kk
+      integer ind
+
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+      ind = 1
+
+
+      do kk = 1, int(locsiz_3d(3))
+        do jj = 1, int(locsiz_3d(2))
+          do ii = 1, int(locsiz_3d(1))
+
+             tt(ind) = real(
+     &         (istart-1 +(ii - 1) + 1 + totsiz_3d(3)*(jstart-1 + 
+     &                 (jj - 1) + totsiz_3d(2)*(kstart-1 + 
+     &                 (kk-1)))) * 1.0d-3)
+             ind = ind + 1
+
+          end do
+        end do
+      end do
+
+
+      Return
+
+      end
+
+
+!     ------------
+
+
+      subroutine Compare_Vec
+     &  (mype, comm_cart, locsiz, tt, buf)
+
+      implicit none
+
+      include "mpif.h"
+
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      integer mype
+      integer comm_cart
+      integer*8 locsiz
+      real*4  tt (locsiz)
+      real*4  buf(locsiz)
+
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      integer ierr
+      integer ii
+              
+      real*4  delmax, delmin, delta
+      real*4  diff
+              
+      real*4  wr(5)
+      real*4  ws(5)
+
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+      ws(1) = 0.0d0      ! diff
+      ws(2) = 0.0d0      ! sumsq
+      ws(3) = int(locsiz)     ! locsiz
+      ws(4) = 0.0d0      ! delmax
+      ws(5) = 1.0d38     ! Huge (ws)  ! delmin
+
+
+      do ii = 1, int(locsiz)
+        delta = (tt(ii) - buf(ii)) * (tt(ii) - buf(ii))
+        ws(1) = ws(1) + delta
+        ws(2) = ws(2) + tt(ii) * tt(ii)
+        if (delta .GT. ws(4)) ws(4) = delta
+        if (delta .LT. ws(5)) ws(5) = delta
+      end do
+
+
+      call MPI_Allreduce
+     &  (ws,    wr,     3, MPI_REAL, MPI_SUM, comm_cart, ierr)
+      call MPI_Allreduce
+     &  (ws(4), delmax, 1, MPI_REAL, MPI_MAX, comm_cart, ierr)
+      call MPI_Allreduce
+     &  (ws(5), delmin, 1, MPI_REAL, MPI_MIN, comm_cart, ierr)
+
+
+      diff   = Sqrt (wr(1) / wr(2))         ! normalized error
+      delmax = Sqrt (wr(3) * delmax/wr(2))  ! normalized max difference
+      delmin = Sqrt (wr(3) * delmin/wr(2))  ! normalized min difference
+
+
+      if (mype .EQ. 0) Write (6,990) diff, delmax, delmin
+
+ 990  format ("diff, delmax, delmin = ",
+     &        e10.3, 1x, e10.3, 1x, e10.3)
+
+
+
+      Return
+
+      end
+
diff --git a/test/header/Makefile.in b/test/header/Makefile.in
new file mode 100644
index 0000000..9dd45fa
--- /dev/null
+++ b/test/header/Makefile.in
@@ -0,0 +1,64 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+#
+# @configure_input@
+
+srcdir  = @srcdir@
+VPATH   = @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I../../src/lib -I$(srcdir)/../common
+LDFLAGS  := $(LDFLAGS) -L../common
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
+ifeq (@PNC_DEBUG@, yes)
+CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
+endif
+
+SRCS      = header_consistency.c
+
+OBJS      = $(SRCS:.c=.o)
+PROGS     = $(SRCS:.c=)
+
+GARBAGE      = $(PROGS) *.nc
+PACKING_LIST = $(SRCS) Makefile.in
+
+all: $(PROGS)
+
+$(OBJS): $(srcdir)/../common/testutils.h
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+header_consistency: header_consistency.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+testing check verbose_testing:
+
+TEST_MPIRUN_2  = $(subst NP,2,$(TEST_MPIRUN))
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+
+ptest2: $(PROGS)
+	@for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_2) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest4: $(PROGS)
+	@for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_4) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest: ptest4
+
+ptests: ptest2 ptest4
+ptest6 ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+
+$(LIBRARY): ;
+
diff --git a/test/header/header_consistency.c b/test/header/header_consistency.c
new file mode 100644
index 0000000..235adf2
--- /dev/null
+++ b/test/header/header_consistency.c
@@ -0,0 +1,621 @@
+/*
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: header_consistency.c 2200 2015-11-28 17:54:14Z wkliao $ */
+
+/* This program tests if PnetCDF can detect file header inconsistency and
+ * overwrite the inconsistent header with root's.
+ * This program is designed to run on more than 2 MPI processes.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <testutils.h>
+
+#define ERR_EXP(e, exp) {if (e != exp) { printf("Error (line %d): expecting error code %s but got %s\n", __LINE__, nc_err_code_name(exp), nc_err_code_name(e)); nerrs++; }}
+#define ERR_EXP2(e, exp1, exp2) {if (e != exp1 && e != exp2) { printf("Error (line %d): expecting error code %s or %s but got %s\n", __LINE__, nc_err_code_name(exp1), nc_err_code_name(exp2), nc_err_code_name(e)); nerrs++; }}
+
+#define CHECK_ERR(expect) { \
+    if (safe_mode) { \
+        if (err != NC_EMULTIDEFINE && err != expect) { \
+            printf("Error (line %d): expecting error code NC_EMULTIDEFINE or %s but got %s\n", __LINE__, nc_err_code_name(expect), nc_err_code_name(err)); \
+            nerrs++; \
+        } \
+    } \
+    else if (rank > 0) { \
+        if (err != expect) { \
+            printf("Error (line %d): expecting error code %s but got %s\n", __LINE__, nc_err_code_name(expect), nc_err_code_name(err)); \
+            nerrs++; \
+        } \
+    } \
+}
+
+#define ERR {if(err!=NC_NOERR) {printf("Error(%d) at line %d: %s\n",err,__LINE__,ncmpi_strerror(err)); nerrs++; }}
+
+/*----< test_open_mode() >----------------------------------------------------*/
+static
+int test_open_mode(char *filename, int safe_mode)
+{
+    int err, rank, ncid, cmode, omode, nerrs=0;
+    MPI_Info info=MPI_INFO_NULL;
+    MPI_Comm comm=MPI_COMM_WORLD;
+
+    MPI_Comm_rank(comm, &rank);
+
+    /* Test inconsistent cmode -----------------------------------------------*/
+    cmode = NC_CLOBBER|NC_64BIT_OFFSET;
+    if (rank == 0) cmode = NC_CLOBBER;
+    err = ncmpi_create(comm, filename, cmode, info, &ncid);
+    /* if safe_mode is on, then we expect all non-root ranks to print a warning
+     * message "inconsistent file create mode, overwrite with root's" and error
+     * code NC_EMULTIDEFINE_OMODE from non-root processes.
+     * if safe_mode is off, then no error code should be returned.
+     */
+    if (safe_mode && rank > 0) ERR_EXP(err, NC_EMULTIDEFINE_OMODE)
+    else                       ERR
+
+    err = ncmpi_close(ncid);
+    /* if safe_mode is on, then no error code should be returned.
+     * if safe_mode is off, then we expect error code NC_EMULTIDEFINE_OMODE
+     * from all non-root processes and NC_EMULTIDEFINE from root process.
+     */
+    if (safe_mode) ERR
+    else if (rank > 0) ERR_EXP(err, NC_EMULTIDEFINE_OMODE)
+
+    int format;
+    err = ncmpi_inq_file_format(filename, &format); ERR
+    if (format != 1) {
+        printf("Error (line %d): output file should be in CDF-1 format\n",__LINE__);
+        nerrs++;
+    }
+
+    /* Test inconsistent omode -----------------------------------------------*/
+    omode = NC_WRITE;
+    if (rank == 0) omode = NC_NOWRITE;
+    err = ncmpi_open(comm, filename, omode, info, &ncid);
+    if (safe_mode) {
+        /* in safe_mode, we expect all non-root ranks to print a warning message
+         * "inconsistent file open mode, overwrite with root's" and error code
+         * code NC_EMULTIDEFINE_OMODE and no error on root process.
+         */
+        if (rank == 0) ERR
+        else           ERR_EXP(err, NC_EMULTIDEFINE_OMODE)
+
+        /* in safe mode, open mode inconsistent is not a fatal error, file is
+         * still opened, with root's omode overwriting others. Hence, once the
+         * test is done, we need to close the file */
+        err = ncmpi_close(ncid); ERR
+    }
+    else {
+        /* expected errors: NC_EMULTIDEFINE_OMODE or NC_EMULTIDEFINE_FNC_ARGS */
+        ERR_EXP2(err, NC_EMULTIDEFINE_OMODE, NC_EMULTIDEFINE_FNC_ARGS)
+
+        /* When not in safe mode, the inconsistent omode will be passed to
+         * MPI_File_open(). MPI-IO should return error class MPI_ERR_NOT_SAME
+         * which will be translated to NC_EMULTIDEFINE_FNC_ARGS in PnetCDF.
+         * If MPI-IO reports error class MPI_ERR_AMODE instead, then it will be
+         * translated to NC_EMULTIDEFINE_OMODE in PnetCDF. In any case, the file
+         * will not be opened by MPI-IO and hence we need not close the file.
+         */
+    }
+    return nerrs;
+}
+
+/*----< test_dim() >----------------------------------------------------------*/
+static
+int test_dim(char *filename, int safe_mode)
+{
+    int err, rank, ncid, cmode, ndims, dimid1, dimid2, dimid3, nerrs=0;
+    MPI_Offset dimlen;
+    MPI_Info info=MPI_INFO_NULL;
+    MPI_Comm comm=MPI_COMM_WORLD;
+
+    MPI_Comm_rank(comm, &rank);
+    cmode = NC_CLOBBER|NC_64BIT_OFFSET;
+
+    /* Test inconsistency on number of dimensions ----------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "x", 100, &dimid1); ERR
+    if (rank == 0) {
+        err = ncmpi_def_dim(ncid, "y", 100, &dimid2); ERR
+    }
+    err = ncmpi_enddef(ncid);
+    /* expected errors: NC_EMULTIDEFINE or NC_EMULTIDEFINE_DIM_NUM */
+    CHECK_ERR(NC_EMULTIDEFINE_DIM_NUM)
+
+    err = ncmpi_inq_ndims(ncid, &ndims); ERR
+    if (ndims != 2) {
+        printf("Error (line %d): number of dimesnions (%d) defined should be 2\n",__LINE__,ndims);
+        nerrs++;
+    }
+    /* all processes should be able to see dim "y" */
+    err = ncmpi_inq_dimid(ncid, "y", &dimid2);
+    if (err != NC_NOERR) {
+        printf("Error (line %d): all processes should be able to see dim \"y\"\n",__LINE__);
+        nerrs++;
+        ERR
+    }
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistency on number of dimensions ----------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "x", 100, &dimid1); ERR
+    if (rank > 0) {
+        err = ncmpi_def_dim(ncid, "y", 100, &dimid2); ERR
+    }
+    err = ncmpi_enddef(ncid);
+    /* expected errors: NC_EMULTIDEFINE or NC_EMULTIDEFINE_DIM_NUM */
+    CHECK_ERR(NC_EMULTIDEFINE_DIM_NUM)
+
+    err = ncmpi_inq_ndims(ncid, &ndims); ERR
+    if (ndims != 1) {
+        printf("Error (line %d): number of dimesnions (%d) defined should be 1\n",__LINE__,ndims);
+        nerrs++;
+    }
+    /* no process should be able to get dim "y" */
+    err = ncmpi_inq_dimid(ncid, "y", &dimid2);
+    CHECK_ERR(NC_EBADDIM)
+
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistency on dimension names ---------------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    if (rank == 0)
+        err = ncmpi_def_dim(ncid, "y", 100, &dimid1);
+    else
+        err = ncmpi_def_dim(ncid, "xx", 100, &dimid1);
+    ERR
+    err = ncmpi_enddef(ncid);
+    /* expected errors: NC_EMULTIDEFINE or NC_EMULTIDEFINE_DIM_NAME */
+    CHECK_ERR(NC_EMULTIDEFINE_DIM_NAME)
+
+    /* all processes should be able to get dim "y" */
+    err = ncmpi_inq_dimid(ncid, "y", &dimid2); ERR
+
+    /* no process should be able to get dim "x" */
+    err = ncmpi_inq_dimid(ncid, "xx", &dimid3);
+    CHECK_ERR(NC_EBADDIM)
+
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistency on dimension size ----------------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    if (rank == 0)
+        err = ncmpi_def_dim(ncid, "x", 99, &dimid1);
+    else
+        err = ncmpi_def_dim(ncid, "x", 100, &dimid1);
+    ERR
+    err = ncmpi_enddef(ncid);
+    /* expected errors: NC_EMULTIDEFINE or NC_EMULTIDEFINE_DIM_SIZE */
+    CHECK_ERR(NC_EMULTIDEFINE_DIM_SIZE)
+
+    /* all processes should be able to get dim "x" of size == 99 */
+    err = ncmpi_inq_dimlen(ncid, dimid1, &dimlen); ERR
+    if (dimlen != 99) {
+        printf("Error (line %d): dimesnion size (%lld) should be 99\n",__LINE__,dimlen);
+        nerrs++;
+    }
+
+    err = ncmpi_close(ncid); ERR
+    return nerrs;
+}
+
+/*----< test_attr() >---------------------------------------------------------*/
+static
+int test_attr(char *filename, int safe_mode)
+{
+    int err, rank, ncid, cmode, nerrs=0;
+    char  gattr[128];
+    int   int_attr;
+    float flt_attr;
+    MPI_Info info=MPI_INFO_NULL;
+    MPI_Comm comm=MPI_COMM_WORLD;
+
+    MPI_Comm_rank(comm, &rank);
+    cmode = NC_CLOBBER|NC_64BIT_OFFSET;
+
+    /* Test inconsistent global attribute numbers ----------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    int_attr = 1;
+    flt_attr = 1.0;
+    err = ncmpi_put_att_int(ncid, NC_GLOBAL, "gattr_1", NC_INT, 1, &int_attr);
+    ERR
+    if (rank == 0) {
+        err = ncmpi_put_att_float(ncid, NC_GLOBAL, "gattr_2", NC_FLOAT, 1,
+                                  &flt_attr); ERR
+    }
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_ATTR_NUM)
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent global attribute name -------------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    int_attr = 1;
+    sprintf(gattr, "gattr_name.%d",rank);
+    err = ncmpi_put_att_int(ncid, NC_GLOBAL, gattr, NC_INT, 1, &int_attr); ERR
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_ATTR_NAME)
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent global attribute type -------------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    if (rank == 0)
+        err = ncmpi_put_att_int(ncid, NC_GLOBAL, "gatt", NC_INT, 1, &int_attr);
+    else
+        err = ncmpi_put_att_float(ncid, NC_GLOBAL, "gatt", NC_FLOAT, 1, &flt_attr);
+    ERR
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_ATTR_TYPE)
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent global attribute length -----------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    int intv[2]={1,2};
+    if (rank == 0)
+        err = ncmpi_put_att_int(ncid, NC_GLOBAL, "gatt", NC_INT, 2, intv);
+    else
+        err = ncmpi_put_att_int(ncid, NC_GLOBAL, "gatt", NC_INT, 1, intv);
+    ERR
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_ATTR_LEN)
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent global attribute length -----------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    if (rank == 0) intv[1]=3;
+    err = ncmpi_put_att_int(ncid, NC_GLOBAL, "gatt", NC_INT, 2, intv);
+    ERR
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_ATTR_VAL)
+    err = ncmpi_close(ncid); ERR
+
+    return nerrs;
+}
+
+/*----< test_var() >----------------------------------------------------------*/
+static
+int test_var(char *filename, int safe_mode)
+{
+    int err, rank, ncid, cmode, nerrs=0;
+    int ndims, dimid[3], nvars, varid1, varid2, int_attr;
+    float flt_attr;
+    char name[128], var_attr[128];
+    nc_type xtype;
+    MPI_Offset dimlen;
+    MPI_Info info=MPI_INFO_NULL;
+    MPI_Comm comm=MPI_COMM_WORLD;
+
+    MPI_Comm_rank(comm, &rank);
+    cmode = NC_CLOBBER|NC_64BIT_OFFSET;
+
+    /* Test inconsistent variable attribute numbers --------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "dim1", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT, 1, dimid, &varid1); ERR
+    int_attr = 1;
+    flt_attr = 1.0;
+    err = ncmpi_put_att_int(ncid, varid1, "var_attr_1", NC_INT, 1, &int_attr);
+    ERR
+    if (rank == 0) {
+        err = ncmpi_put_att_float(ncid, varid1, "var_attr_2", NC_FLOAT, 1,
+                                  &flt_attr); ERR
+    }
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_ATTR_NUM)
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent global attribute name -------------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "dim1", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT, 1, dimid, &varid1); ERR
+    int_attr = 1;
+    sprintf(var_attr, "var_attr_name.%d",rank);
+    err = ncmpi_put_att_int(ncid, varid1, var_attr, NC_INT, 1, &int_attr); ERR
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_ATTR_NAME)
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent global attribute type -------------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "dim1", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT, 1, dimid, &varid1); ERR
+    if (rank == 0)
+        err = ncmpi_put_att_int(ncid, varid1, "var_att", NC_INT, 1, &int_attr);
+    else
+        err = ncmpi_put_att_float(ncid, varid1, "var_att", NC_FLOAT, 1, &flt_attr);
+    ERR
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_ATTR_TYPE)
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent global attribute length -----------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "dim1", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT, 1, dimid, &varid1); ERR
+    int intv[2]={1,2};
+    if (rank == 0)
+        err = ncmpi_put_att_int(ncid, varid1, "var_att", NC_INT, 2, intv);
+    else
+        err = ncmpi_put_att_int(ncid, varid1, "var_att", NC_INT, 1, intv);
+    ERR
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_ATTR_LEN)
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent global attribute length -----------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "dim1", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT, 1, dimid, &varid1); ERR
+    if (rank == 0) intv[1]=3;
+    err = ncmpi_put_att_int(ncid, varid1, "var_att", NC_INT, 2, intv);
+    ERR
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_ATTR_VAL)
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent number of variables ---------------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "dim1", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT, 1, dimid, &varid1); ERR
+    if (rank == 0) {
+        err = ncmpi_def_var(ncid, "var2", NC_INT, 1, dimid, &varid2); ERR
+    }
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_VAR_NUM)
+
+    err = ncmpi_inq_nvars(ncid, &nvars); ERR
+    if (nvars != 2) {
+        printf("Error (line %d): all processes should see 2 variables\n",__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent variable name ---------------------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "dim1", NC_UNLIMITED, &dimid[0]); ERR
+    sprintf(name, "var.%d",rank);
+    err = ncmpi_def_var(ncid, name, NC_INT, 1, dimid, &varid1); ERR
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_VAR_NAME)
+
+    err = ncmpi_inq_varname(ncid, varid1, name); ERR
+    if (strcmp(name, "var.0")) {
+        printf("Error (line %d): all processes should see variable name: \"var.0\"\n",__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent variable ndims --------------------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "dim0", 3, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "dim1", 2, &dimid[1]); ERR
+    if (rank == 0)
+        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid, &varid1);
+    else
+        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 1, dimid, &varid1);
+    ERR
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_VAR_NDIMS)
+
+    err = ncmpi_inq_varndims(ncid, varid1, &ndims); ERR
+    if (ndims != 2) {
+        printf("Error (line %d): all processes should see var has 2 dimensions\n",__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent variable type ---------------------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "dim1", NC_UNLIMITED, &dimid[0]); ERR
+    if (rank == 0)
+        err = ncmpi_def_var(ncid, "var", NC_INT, 1, dimid, &varid1);
+    else
+        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 1, dimid, &varid1);
+    ERR
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_VAR_TYPE)
+
+    err = ncmpi_inq_vartype(ncid, varid1, &xtype); ERR
+    if (xtype != NC_INT) {
+        printf("Error (line %d): all processes should see var is of type NC_INT\n",__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent variable length -------------------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "dim0", 5, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "dim1", 4, &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "dim2", 3, &dimid[2]); ERR
+    if (rank == 0) {
+        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid, &varid1); ERR
+    }
+    else {
+        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid+1, &varid1); ERR
+    }
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_VAR_LEN)
+
+    err = ncmpi_inq_vardimid(ncid, varid1, dimid); ERR
+    err = ncmpi_inq_dimname(ncid, dimid[0], name); ERR
+    if (strcmp(name, "dim0")) {
+        printf("Error (line %d): all processes should see var's dim[0] name \"dim0\"\n",__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_inq_dimname(ncid, dimid[1], name); ERR
+    if (strcmp(name, "dim1")) {
+        printf("Error (line %d): all processes should see var's dim[1] name \"dim1\"\n",__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_inq_dimlen(ncid, dimid[0], &dimlen); ERR
+    if (dimlen != 5) {
+        printf("Error (line %d): all processes should see var's dim[0] len == 5\n",__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_inq_dimlen(ncid, dimid[1], &dimlen); ERR
+    if (dimlen != 4) {
+        printf("Error (line %d): all processes should see var's dim[1] len == 4\n",__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_close(ncid); ERR
+
+    /* Test inconsistent variable dimension IDs ------------------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "Z", 3, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "Y", 3, &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "X", 3, &dimid[2]); ERR
+    if (rank == 0) {
+        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid+1, &varid1); ERR
+    }
+    else {
+        err = ncmpi_def_var(ncid, "var", NC_FLOAT, 2, dimid, &varid1); ERR
+    }
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_VAR_DIMIDS)
+
+    err = ncmpi_inq_vardimid(ncid, varid1, dimid); ERR
+    err = ncmpi_inq_dimname(ncid, dimid[0], name); ERR
+    if (strcmp(name, "Y")) {
+        printf("Error (line %d): all processes should see var's dim[0] name \"Y\"\n",__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_inq_dimname(ncid, dimid[1], name); ERR
+    if (strcmp(name, "X")) {
+        printf("Error (line %d): all processes should see var's dim[1] name \"X\"\n",__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_close(ncid); ERR
+
+    return nerrs;
+}
+
+/*----< test_dim_var() >------------------------------------------------------*/
+static
+int test_dim_var(char *filename, int safe_mode)
+{
+    int i, err, rank, ncid, cmode, nerrs=0;
+    int ndims, dimid[3], varid1;
+    char name[128], dimname[128];
+    MPI_Offset dimlen;
+    MPI_Info info=MPI_INFO_NULL;
+    MPI_Comm comm=MPI_COMM_WORLD;
+
+    MPI_Comm_rank(comm, &rank);
+    cmode = NC_CLOBBER|NC_64BIT_OFFSET;
+
+    /* Test inconsistent of dimensions impact to variables -------------------*/
+    err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR
+    err = ncmpi_def_dim(ncid, "dim1", 5, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "dim2", 4, &dimid[1]); ERR
+    if (rank == 0) {
+        err = ncmpi_def_dim(ncid, "dim3", 3, &dimid[2]); ERR
+        err = ncmpi_def_var(ncid, "var1", NC_INT, 2, dimid+1, &varid1); ERR
+    }
+    else {
+        err = ncmpi_def_var(ncid, "var1", NC_INT, 2, dimid, &varid1); ERR
+    }
+    err = ncmpi_enddef(ncid);
+    CHECK_ERR(NC_EMULTIDEFINE_DIM_NUM)
+
+    err = ncmpi_inq_ndims(ncid, &ndims); ERR
+    if (ndims != 3) {
+        printf("Error (line %d): all processes should see 3 dimensions\n",__LINE__);
+        nerrs++;
+    }
+    dimid[0] = dimid[1] = dimid[2] = -1;
+    err = ncmpi_inq_vardimid(ncid, varid1, dimid); ERR
+    for (i=0; i<2; i++) {
+        err = ncmpi_inq_dimname(ncid, dimid[i], name); ERR
+        sprintf(dimname, "dim%d", i);
+        if (!strcmp(name, dimname)) {
+            printf("Error (line %d): all processes should see dimid[%d] name \"%s\"\n",__LINE__,i,dimname);
+            nerrs++;
+        }
+    }
+    err = ncmpi_inq_dimlen(ncid, dimid[0], &dimlen); ERR
+    if (dimlen != 4) {
+        printf("Error (line %d): all processes should see dimid[0] len = 4\n",__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_inq_dimlen(ncid, dimid[1], &dimlen); ERR
+    if (dimlen != 3) {
+        printf("Error (line %d): all processes should see dimid[1] len = 3\n",__LINE__);
+        nerrs++;
+    }
+    err = ncmpi_close(ncid); ERR
+
+
+    return nerrs;
+}
+
+/*----< main() >--------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    char *filename="testfile.nc", *mode[2] = {"0", "1"};
+    int i, rank, nprocs, verbose, nerrs=0;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (nprocs < 2) {
+        if (!rank) printf("This program is for running 2 or more processes. Exiting ...\n");
+        MPI_Finalize();
+        return 0;
+    }
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for header consistency", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    verbose = 0;
+    for (i=verbose; i>=0; i--) {
+        /* test with safe mode off and on :
+         * Note even if --enable-debug is set at configure time, safe mode
+         * can still be disabled by setting the environment variable
+         * PNETCDF_SAFE_MODE to 0.
+         */
+        setenv("PNETCDF_SAFE_MODE", mode[i], 1);
+        nerrs += test_open_mode(filename, i);
+
+        nerrs += test_dim(filename, i);
+
+        nerrs += test_attr(filename, i);
+
+        nerrs += test_var(filename, i);
+
+        nerrs += test_dim_var(filename, i);
+    }
+
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/largefile/Makefile.in b/test/largefile/Makefile.in
new file mode 100644
index 0000000..c931567
--- /dev/null
+++ b/test/largefile/Makefile.in
@@ -0,0 +1,86 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I../../src/lib -I$(srcdir)/../common
+LDFLAGS  := $(LDFLAGS) -L../common
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
+ifeq (@PNC_DEBUG@, yes)
+CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
+endif
+
+ifeq (@is_bigendian@, yes)
+DEFS := $(DEFS) -DWORDS_BIGENDIAN
+endif
+
+SRCS    = large_files.c \
+          large_var.c
+
+OBJS    = $(SRCS:.c=.o)
+PROGS   = $(SRCS:.c=)
+
+GARBAGE      = $(PROGS) *.nc
+PACKING_LIST = $(SRCS) Makefile.in
+
+all: $(PROGS)
+
+$(OBJS): $(srcdir)/../common/testutils.h
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+large_files: large_files.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+large_var: large_var.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+testing check verbose_testing: $(PROGS)
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc $(TEST_OUTDIR)/testfile.nc
+	for i in $< ; do ( \
+	$(TEST_SEQRUN) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+# Some of these tests are designed to run on one processes,
+# Run them on 4 processes to see if they can handle well
+TEST_MPIRUN_2  = $(subst NP,2,$(TEST_MPIRUN))
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+TEST_MPIRUN_6  = $(subst NP,6,$(TEST_MPIRUN))
+
+ptest4: $(PROGS)
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc $(TEST_OUTDIR)/testfile.nc
+	for i in $< ; do ( \
+	$(TEST_MPIRUN_4) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest2: $(PROGS)
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc $(TEST_OUTDIR)/testfile.nc
+	@for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_2) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest6: $(PROGS)
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc $(TEST_OUTDIR)/testfile.nc
+	@for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_6) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest: ptest4
+ptests: ptest2 ptest4 ptest6
+ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+
+$(LIBRARY): ;
+
diff --git a/test/largefile/large_files.c b/test/largefile/large_files.c
new file mode 100644
index 0000000..efa0d8a
--- /dev/null
+++ b/test/largefile/large_files.c
@@ -0,0 +1,194 @@
+/*
+  Copyright 2004-2006, UCAR/Unidata
+  See COPYRIGHT file for copying and redistribution conditions.
+
+  This is part of netCDF.
+   
+  This program also takes a long time to run - it writes some data in
+  a very large file, and then reads it all back to be sure it's
+  correct.
+
+  This program is an add-on test to check very large 64-bit offset
+  files (8 GB, so make sure you have the disk space!).
+
+  $Id: large_files.c 2133 2015-09-26 19:16:01Z wkliao $
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#define FILE_NAME "./testfile.nc"
+
+static
+void check_err(const int stat, const int line, const char *file) {
+    if (stat != NC_NOERR) {
+	   (void) fprintf(stderr, "line %d of %s: %s\n", line, file, ncmpi_strerror(stat));
+        exit(1);
+    }
+}
+
+int
+main(int argc, char **argv) {
+
+   int  stat;			/* return status */
+   int  ncid;			/* netCDF id */
+   int rec, i, j, k, rank, nprocs, nerrs=0;
+   signed char x[] = {42, 21};
+
+   /* dimension ids */
+   int rec_dim;
+   int i_dim;
+   int j_dim;
+   int k_dim;
+   int n_dim;
+ 
+#define NUMRECS 1
+#define I_LEN 4104
+#define J_LEN 1023
+#define K_LEN 1023
+#define N_LEN 2
+
+   /* dimension lengths */
+   MPI_Offset rec_len = NC_UNLIMITED;
+   MPI_Offset i_len = I_LEN;
+   MPI_Offset j_len = J_LEN;
+   MPI_Offset k_len = K_LEN;
+   MPI_Offset n_len = N_LEN;
+
+   /* variable ids */
+   int var1_id;
+   int x_id;
+
+   /* rank (number of dimensions) for each variable */
+#  define RANK_var1 4
+#  define RANK_x 2
+
+   /* variable shapes */
+   int var1_dims[RANK_var1];
+   int x_dims[RANK_x];
+
+   MPI_Init(&argc, &argv);
+   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+   MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+   if (rank > 0) goto fn_exit;
+
+   printf("\n*** Testing large files, slowly.\n");
+   printf("*** Creating large file %s...", FILE_NAME);
+
+   /* enter define mode */
+   stat = ncmpi_create(MPI_COMM_SELF, FILE_NAME, NC_CLOBBER|NC_64BIT_DATA, 
+		   MPI_INFO_NULL, &ncid);
+   check_err(stat,__LINE__,__FILE__);
+ 
+   /* define dimensions */
+   stat = ncmpi_def_dim(ncid, "rec", rec_len, &rec_dim);
+   check_err(stat,__LINE__,__FILE__);
+   stat = ncmpi_def_dim(ncid, "i", i_len, &i_dim);
+   check_err(stat,__LINE__,__FILE__);
+   stat = ncmpi_def_dim(ncid, "j", j_len, &j_dim);
+   check_err(stat,__LINE__,__FILE__);
+   stat = ncmpi_def_dim(ncid, "k", k_len, &k_dim);
+   check_err(stat,__LINE__,__FILE__);
+   stat = ncmpi_def_dim(ncid, "n", n_len, &n_dim);
+   check_err(stat,__LINE__,__FILE__);
+
+   /* define variables */
+
+   var1_dims[0] = rec_dim;
+   var1_dims[1] = i_dim;
+   var1_dims[2] = j_dim;
+   var1_dims[3] = k_dim;
+   stat = ncmpi_def_var(ncid, "var1", NC_BYTE, RANK_var1, var1_dims, &var1_id);
+   check_err(stat,__LINE__,__FILE__);
+
+   x_dims[0] = rec_dim;
+   x_dims[1] = n_dim;
+   stat = ncmpi_def_var(ncid, "x", NC_BYTE, RANK_x, x_dims, &x_id);
+   check_err(stat,__LINE__,__FILE__);
+   /* don't initialize variables with fill values */
+   stat = ncmpi_set_fill(ncid, NC_NOFILL, 0);
+   check_err(stat,__LINE__,__FILE__);
+
+   /* leave define mode */
+   stat = ncmpi_enddef (ncid);
+   check_err(stat,__LINE__,__FILE__);
+
+   {			/* store var1 */
+       int n = 0;
+       static signed char var1[J_LEN][K_LEN];
+       static MPI_Offset var1_start[RANK_var1] = {0, 0, 0, 0};
+       static MPI_Offset var1_count[RANK_var1] = {1, 1, J_LEN, K_LEN};
+       static MPI_Offset x_start[RANK_x] = {0, 0};
+       static MPI_Offset x_count[RANK_x] = {1, N_LEN};
+       for(rec=0; rec<NUMRECS; rec++) {
+	   var1_start[0] = rec;
+	   x_start[0] = rec;
+	   for(i=0; i<I_LEN; i++) {
+	       for(j=0; j<J_LEN; j++) {
+		   for (k=0; k<K_LEN; k++) {
+		       var1[j][k] = n++;
+		   }
+	       }
+	       var1_start[1] = i;
+	       stat = ncmpi_put_vara_schar_all(ncid, var1_id, var1_start, var1_count, &var1[0][0]);
+	       check_err(stat,__LINE__,__FILE__);
+	   }
+       }
+       stat = ncmpi_put_vara_schar_all(ncid, x_id, x_start, x_count, x);
+       check_err(stat,__LINE__,__FILE__);
+   }
+
+   stat = ncmpi_close(ncid);
+   check_err(stat,__LINE__,__FILE__);
+
+   printf("ok\n");
+   printf("*** Reading large file %s...", FILE_NAME);
+
+   stat = ncmpi_open(MPI_COMM_SELF, FILE_NAME, NC_NOWRITE, 
+		   MPI_INFO_NULL, &ncid);
+   check_err(stat,__LINE__,__FILE__);
+
+   {			/* read var1 */
+       int n = 0;
+       static signed char var1[J_LEN][K_LEN];
+       static MPI_Offset var1_start[RANK_var1] = {0, 0, 0, 0};
+       static MPI_Offset var1_count[RANK_var1] = {1, 1, J_LEN, K_LEN};
+       static MPI_Offset x_start[RANK_x] = {0, 0};
+       static MPI_Offset x_count[RANK_x] = {1, N_LEN};
+       for(rec=0; rec<NUMRECS; rec++) {
+	   var1_start[0] = rec;
+	   x_start[0] = rec;
+	   for(i=0; i<I_LEN; i++) {
+	       var1_start[1] = i;
+	       stat = ncmpi_get_vara_schar_all(ncid, var1_id, var1_start, var1_count, &var1[0][0]);
+	       check_err(stat,__LINE__,__FILE__);
+	       for(j=0; j<J_LEN; j++) {
+		   for (k=0; k<K_LEN; k++) {
+		       if (var1[j][k] != (signed char) n) {
+			   printf("Error on read, var1[%d, %d, %d, %d] = %d wrong, "
+				  "should be %d !\n", rec, i, j, k, var1[j][k], (signed char) n); 
+			   nerrs++;
+		       }
+		       n++;
+		   }
+	       }
+	   }
+	   ncmpi_get_vara_schar_all(ncid, x_id, x_start, x_count, x);
+	   if(x[0] != 42 || x[1] != 21) {
+	       printf("Error on read, x[] = %d, %d\n", x[0], x[1]);
+	       nerrs++;
+	   }
+       }
+   }
+   stat = ncmpi_close(ncid);
+   check_err(stat,__LINE__,__FILE__);
+
+   printf("ok\n");
+   printf("*** Tests successful!\n");
+
+fn_exit:
+   MPI_Finalize();
+   return 0;
+}
diff --git a/test/largefile/large_var.c b/test/largefile/large_var.c
new file mode 100644
index 0000000..19b9800
--- /dev/null
+++ b/test/largefile/large_var.c
@@ -0,0 +1,293 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: large_var.c 2300 2016-01-09 06:16:29Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program is to test if MPI filetypes are defined correctly for accessing
+ * arrays with more than 2G elements.
+ *
+ * This program calls ncmpi_put_vara_int_all() and ncmpi_iput_vara_int()
+ * to write multiple subarray of a large 3D 4-byte integer array. It first
+ * defines a netCDF variable of size 4 x 10 x 4294967296.
+ * 1st write: subarray of 1 x 2 x 10 at the start 1 x 8 x (2G + rank * 10)
+ * 2nd write: subarray of 1 x 2 x 5  at the start 3 x 8 x (2G + rank * 10)
+ * 3rd write: subarray of 1 x 1 x 5  at the start 3 x 8 x (2G + rank * 10 + 5)
+ * 4th write: subarray of 1 x 1 x 5  at the start 3 x 9 x (2G + rank * 10 + 5)
+ *
+ * The written contents are read back by a different process to check
+ * correctness. Two reads are performed: PnetCDF and MPI-IO.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <testutils.h>
+
+#define FOUR_G 4294967296
+#define TWO_G  2147483648
+#define ONE_G  1073741824
+
+#define NZ 4
+#define NY 10
+#define NX FOUR_G
+
+#define ERR if (err!=NC_NOERR) {printf("Error at line %d: err=%s (%s)\n", __LINE__,nc_err_code_name(err),ncmpi_strerror(err)); exit(-1);}
+
+#ifndef WORDS_BIGENDIAN
+/* Endianness byte swap: done in-place */
+#define SWAP(x,y) {tmp = (x); (x) = (y); (y) = tmp;}
+static void
+swapn(void       *buf,
+           MPI_Offset  nelems)
+{
+    int  i;
+    unsigned char tmp, *op = (unsigned char*)buf;
+
+    while (nelems-- > 0) {
+        for (i=0; i<2; i++)
+            SWAP(op[i], op[3-i])
+        op += 4;
+    }
+}
+#endif
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int i, j, rank, nprocs, err, nerrs=0, bufsize;
+    int ncid, cmode, varid, dimid[3], req[3], st[3], *buf, *buf_ptr;
+    MPI_Offset offset, var_offset, start[3], count[3];
+    MPI_File fh;
+    MPI_Status status;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* get command-line arguments */
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for writing to a large variable ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* define dimensions Z, Y, and X */
+    err = ncmpi_def_dim(ncid, "Z", NZ, &dimid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[1]);
+    ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[2]);
+    ERR
+
+    /* define a 3D variable of integer type */
+    err = ncmpi_def_var(ncid, "var", NC_INT, 3, dimid, &varid);
+    ERR
+
+    /* do not forget to exit define mode */
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* get the beginning of file offset for the varaiable */
+    err = ncmpi_inq_varoffset(ncid, varid, &var_offset);
+    ERR
+
+    /* now we are in data mode */
+    start[0] = 1;
+    start[1] = NY - 2;
+    start[2] = TWO_G + 10 * rank;
+    count[0] = 1;
+    count[1] = 2;
+    count[2] = 10;
+
+    bufsize = count[0]*count[1]*count[2];
+    buf = (int*) malloc(bufsize * sizeof(int));
+    for (i=0; i<bufsize; i++) buf[i] = rank*100 + i;
+
+    err = ncmpi_put_vara_int_all(ncid, varid, start, count, buf);
+    ERR
+
+    /* now test nonblocking put */
+    /* rearrange buffer contents */
+    for (i=5;  i<10; i++) buf[i] = rank*100 + i + 5;
+    for (i=10; i<15; i++) buf[i] = rank*100 + i - 5;
+
+    start[0] = NZ-1;
+    count[2] = 5;
+    err = ncmpi_iput_vara_int(ncid, varid, start, count, buf, &req[0]);
+    ERR
+
+    start[2] += 5;
+    count[1]  = 1;
+    err = ncmpi_iput_vara_int(ncid, varid, start, count, buf+10, &req[1]);
+    ERR
+
+    start[1]++;
+    err = ncmpi_iput_vara_int(ncid, varid, start, count, buf+15, &req[2]);
+    ERR
+
+    err = ncmpi_wait_all(ncid, 3, req, st);
+    ERR
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    /* open the same file and read back for validation */
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL,
+                     &ncid); ERR
+
+    err = ncmpi_inq_varid(ncid, "var", &varid); ERR
+
+    /* initialize the contents of the array to a different value */
+    for (i=0; i<bufsize; i++) buf[i] = -1;
+
+    /* read back subarray written by the process (rank+1)%nprocs */
+    start[0] = 1;
+    start[1] = NY - 2;
+    start[2] = TWO_G + ((rank == nprocs - 1) ? 0 : 10 * (rank + 1));
+    count[0] = 1;
+    count[1] = 2;
+    count[2] = 10;
+
+    err = ncmpi_get_vara_int_all(ncid, varid, start, count, buf); ERR
+
+    /* check if the contents of buf are expected */
+    for (i=0; i<bufsize; i++) {
+        int expected = (rank == nprocs - 1) ? i : (rank+1)*100 + i;
+        if (buf[i] != expected) {
+            printf("%d (at line %d): Unexpected read buf[%d]=%d, should be %d\n",
+                   rank, __LINE__, i, buf[i], expected);
+            nerrs++;
+        }
+    }
+
+    for (i=0; i<bufsize; i++) buf[i] = -1;
+
+    start[0] = NZ-1;
+    err = ncmpi_get_vara_int_all(ncid, varid, start, count, buf); ERR
+
+    /* check if the contents of buf are expected */
+    for (i=0; i<bufsize; i++) {
+        int expected = (rank == nprocs - 1) ? i : (rank+1)*100 + i;
+        if (buf[i] != expected) {
+            printf("%d (at line %d): Unexpected read buf[%d]=%d, should be %d\n",
+                   rank, __LINE__, i, buf[i], expected);
+            nerrs++;
+        }
+    }
+
+    err = ncmpi_close(ncid); ERR
+
+    /* MPI file open the same file and read back for validation */
+    err = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_RDONLY, MPI_INFO_NULL, &fh);
+    if (err != MPI_SUCCESS) {
+        int errorStringLen;
+        char errorString[MPI_MAX_ERROR_STRING];
+        MPI_Error_string(err, errorString, &errorStringLen);
+        printf("MPI error MPI_File_open : %s\n", errorString);
+    }
+
+    /* initialize the contents of the array to a different value */
+    for (i=0; i<bufsize; i++) buf[i] = -1;
+
+    /* read back subarray written by the process (rank+1)%nprocs */
+    start[0] = 1;
+    start[1] = NY - 2;
+    start[2] = TWO_G + ((rank == nprocs - 1) ? 0 : 10 * (rank + 1));
+    count[0] = 1;
+    count[1] = 2;
+    count[2] = 10;
+
+    buf_ptr = buf;
+    for (i=0; i<count[0]; i++) {
+        for (j=0; j<count[1]; j++) {
+            offset = var_offset + ((start[0] + i) * NY * NX + (start[1] + j) * NX + start[2]) * sizeof(int);
+            MPI_File_read_at(fh, offset, buf_ptr, count[2], MPI_INT, &status);
+#ifndef WORDS_BIGENDIAN
+            swapn(buf_ptr, count[2]);
+#endif
+            buf_ptr += count[2];
+        }
+    }
+
+    /* check if the contents of buf are expected */
+    for (i=0; i<bufsize; i++) {
+        int expected = (rank == nprocs - 1) ? i : (rank+1)*100 + i;
+        if (buf[i] != expected) {
+            printf("%d (at line %d): Unexpected read buf[%d]=%d, should be %d\n",
+                   rank, __LINE__, i, buf[i], expected);
+            nerrs++;
+        }
+    }
+
+    for (i=0; i<bufsize; i++) buf[i] = -1;
+
+    start[0] = NZ-1;
+
+    buf_ptr = buf;
+    for (i=0; i<count[0]; i++) {
+        for (j=0; j<count[1]; j++) {
+            offset = var_offset + ((start[0] + i) * NY * NX + (start[1] + j) * NX + start[2]) * sizeof(int);
+            MPI_File_read_at(fh, offset, buf_ptr, count[2], MPI_INT, &status);
+#ifndef WORDS_BIGENDIAN
+            swapn(buf_ptr, count[2]);
+#endif
+            buf_ptr += count[2];
+        }
+    }
+
+    /* check if the contents of buf are expected */
+    for (i=0; i<bufsize; i++) {
+        int expected = (rank == nprocs - 1) ? i : (rank+1)*100 + i;
+        if (buf[i] != expected) {
+            printf("%d (at line %d): Unexpected read buf[%d]=%d, should be %d\n",
+                   rank, __LINE__, i, buf[i], expected);
+            nerrs++;
+        }
+    }
+
+    MPI_File_close(&fh);
+
+    free(buf);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/nc_test/Makefile.in b/test/nc_test/Makefile.in
new file mode 100644
index 0000000..3940659
--- /dev/null
+++ b/test/nc_test/Makefile.in
@@ -0,0 +1,138 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2294 2016-01-06 20:10:13Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I../../src/lib -I$(srcdir) -I$(srcdir)/../common
+LDFLAGS  := -L../common $(LDFLAGS)
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) -lm @LCOV_LIB@
+ifeq (@PNC_DEBUG@, yes)
+CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
+endif
+
+SRCS      = test_read.c \
+            test_write.c \
+            error.c \
+            util.c
+
+PROG_SRCS = nc_test.c \
+            t_nc.c \
+            tst_misc.c \
+            tst_norm.c \
+            tst_small.c \
+            tst_names.c \
+            tst_atts3.c \
+            tst_atts.c \
+            tst_nofill.c
+
+M4_SRCS   = test_get.m4 \
+            test_put.m4 \
+            test_iget.m4 \
+            test_iput.m4
+
+HEADERS   = tests.h \
+            error.h
+
+OBJS      = $(SRCS:.c=.o) $(M4_SRCS:.m4=.o)
+
+PROGS     = $(PROG_SRCS:.c=)
+
+GARBAGE      = $(PROGS) $(M4_SRCS:.m4=.c) \
+               test.nc testfile.nc scratch.nc testfile.nc.2 \
+               testfile.nc.nofill testfile.nc.fill
+
+PACKING_LIST = $(SRCS) $(M4_SRCS) $(HEADERS) $(PROG_SRCS) \
+               Makefile.in depend README
+
+all: $(PROGS)
+
+$(OBJS): $(srcdir)/../common/testutils.h
+
+$(PROG_SRCS:.c=.o): $(srcdir)/../common/testutils.h
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+nc_test: nc_test.o $(OBJS) $(LIBRARY)
+	$(LINK.c) $< $(OBJS) $(LDFLAGS) $(LIBS)
+
+t_nc: t_nc.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+tst_misc: tst_misc.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+tst_norm: tst_norm.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+tst_small: tst_small.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+tst_names: tst_names.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+tst_atts3: tst_atts3.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+tst_atts: tst_atts.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+tst_nofill: tst_nofill.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+# This simple testing target ensures that the test files are present
+check testing: all
+	$(RM) -f $(TEST_OUTDIR)/scratch.nc
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc
+	$(RM) -f $(TEST_OUTDIR)/tooth-fairy.nc
+	$(TEST_SEQRUN) ./nc_test -c    -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nc_test -d       $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nc_test -c -2 -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nc_test -2 -d    $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nc_test -c -5 -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nc_test -5 -d    $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./t_nc             $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_misc         $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_norm         $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_small        $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_names        $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_atts3        $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_atts         $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_nofill       $(TEST_OUTDIR)/testfile.nc
+
+verbose_testing: all
+	$(RM) -f $(TEST_OUTDIR)/scratch.nc
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc
+	$(RM) -f $(TEST_OUTDIR)/tooth-fairy.nc
+	$(TEST_SEQRUN) ./nc_test -c -v    -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nc_test -v -d       $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nc_test -c -v -2 -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nc_test -v -2 -d    $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nc_test -c -v -5 -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nc_test -v -5 -d    $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./t_nc                $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_misc            $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_norm            $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_small           $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_names           $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_atts3           $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_atts            $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) ./tst_nofill          $(TEST_OUTDIR)/testfile.nc
+
+ptest ptests ptest2 ptest4 ptest6 ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+include $(srcdir)/depend
+
+$(LIBRARY): ;
+
diff --git a/test/nc_test/README b/test/nc_test/README
new file mode 100644
index 0000000..95d2f43
--- /dev/null
+++ b/test/nc_test/README
@@ -0,0 +1,9 @@
+This test is ported from Unidata netCDF-3.5 to test the functionality
+of the PnetCDF API C interface particularly on a single processor. 
+
+The typical way to run the test includes two steps:
+
+ 	(1) create test.nc by 	"<mpirun -np 1> ./nc_test -c"
+	(2) run the test   by 	"<mpirun -np 1> ./nc_test -v"
+
+
diff --git a/test/nc_test/depend b/test/nc_test/depend
new file mode 100644
index 0000000..a29bc04
--- /dev/null
+++ b/test/nc_test/depend
@@ -0,0 +1,41 @@
+error.o: error.c
+nc_test.o: ../../src/lib/pnetcdf.h
+nc_test.o: error.h
+nc_test.o: nc_test.c
+nc_test.o: tests.h
+test_get.o: ../../src/lib/pnetcdf.h
+test_get.o: error.h
+test_get.o: test_get.c
+test_get.o: tests.h
+test_put.o: ../../src/lib/pnetcdf.h
+test_put.o: error.h
+test_put.o: test_put.c
+test_put.o: tests.h
+test_iget.o: ../../src/lib/pnetcdf.h
+test_iget.o: error.h
+test_iget.o: test_iget.c
+test_iget.o: tests.h
+test_iput.o: ../../src/lib/pnetcdf.h
+test_iput.o: error.h
+test_iput.o: test_iput.c
+test_iput.o: tests.h
+test_read.o: ../../src/lib/pnetcdf.h
+test_read.o: error.h
+test_read.o: test_read.c
+test_read.o: tests.h
+test_write.o: ../../src/lib/pnetcdf.h
+test_write.o: error.h
+test_write.o: test_write.c
+test_write.o: tests.h
+util.o: ../../src/lib/pnetcdf.h
+util.o: error.h
+util.o: tests.h
+util.o: util.c
+t_nc.o: t_nc.c
+tst_misc.o: tst_misc.c
+tst_norm.o: tst_norm.c
+tst_small.o: tst_small.c
+tst_names.o: tst_names.c
+tst_atts3.o: tst_atts3.c
+tst_atts.o: tst_atts.c
+tst_nofill.o: tst_nofill.c
diff --git a/test/nc_test/error.c b/test/nc_test/error.c
new file mode 100644
index 0000000..5bad4d8
--- /dev/null
+++ b/test/nc_test/error.c
@@ -0,0 +1,80 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: error.c 1468 2013-10-26 16:53:18Z wkliao $
+ */
+
+#include <stddef.h>	/* because gcc 2.7.2.2 doesn't define size_t */
+			/* in <stdio.h> and it cannot hurt */
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <mpi.h>
+
+extern int  nfails;             /* number of failures in specific test */
+extern int  max_nmpt;		/* max. number of messages per test */
+
+/* Prototypes */
+void error(const char *fmt, ...);
+void print(const char *fmt, ...);
+int ifFail(const int expr, const int line, const char *file);
+void print_n_size_t(size_t nelems, const MPI_Offset *array);
+
+/*
+ * Use for logging error conditions
+ */
+void
+error(const char *fmt, ...)
+{
+    va_list args ;
+
+    va_start(args, fmt) ;
+    if (nfails <= max_nmpt)
+	(void) vfprintf(stderr,fmt,args) ;
+    va_end(args) ;
+}
+
+/*
+ * Use for general printing (other than error conditions)
+ * This also currently goes to stderr, but this could change
+ */
+void
+print(const char *fmt, ...)
+{
+    va_list args ;
+
+    va_start(args, fmt) ;
+    (void) vfprintf(stderr,fmt,args) ;
+    va_end(args) ;
+}
+
+/*
+ * Called by macro IF
+ */
+int
+ifFail(const int expr, const int line, const char *file)
+{
+    if (expr) {
+	++nfails;
+	error("\n\tFAILURE at line %d of %s: ", line, file);
+    }
+    return expr;
+}
+
+/* TODO:
+ * This diagnostic doesn't fit very well with the diagnostic message 
+ * "architecture" of this program.
+ */
+void
+print_n_size_t(size_t nelems, const MPI_Offset *array)
+{
+	fprintf(stderr, "[");
+	while(nelems-- > 0)
+	{
+		fprintf(stderr, "%ld", (long)*array++);
+		if(nelems > 0)
+			fprintf(stderr, " ");
+	}
+	fprintf(stderr, "]");
+}
diff --git a/test/nc_test/error.h b/test/nc_test/error.h
new file mode 100644
index 0000000..47e13b3
--- /dev/null
+++ b/test/nc_test/error.h
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: error.h 1468 2013-10-26 16:53:18Z wkliao $ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Print error message to stderr, don't exit */
+extern void	error (const char *fmt, ...)
+#ifdef _GNUC_
+__attribute__ ((format (printf, 1, 2)))
+#endif
+;
+
+
+void print(const char *fmt, ...)
+#ifdef _GNUC_
+__attribute__ ((format (printf, 1, 2)))
+#endif
+;
+
+
+extern int ifFail(const int expr, const int line, const char *file);
+
+extern void
+print_n_size_t(size_t nelems, const MPI_Offset *array);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define IF(EXPR) if (ifFail(EXPR, __LINE__, __FILE__))
+#define ELSE_NOK else {nok++;}
diff --git a/test/nc_test/nc_test.c b/test/nc_test/nc_test.c
new file mode 100644
index 0000000..a88bec5
--- /dev/null
+++ b/test/nc_test/nc_test.c
@@ -0,0 +1,549 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: nc_test.c 2302 2016-01-10 20:33:45Z wkliao $
+ */
+
+#include <unistd.h>
+
+int cdf_format;  /* 1: CDF-1, 2: CDF-2 5: CDF-5 */
+int extra_flags; /* if using CDF-2 format, will be set to NC_64BIT_OFFSET
+                    if using CDF-5 format, will be set to NC_64BIT_DATA */
+int numGatts;  /* number of global attributes */
+int numVars;   /* number of variables */
+int numTypes;  /* number of netCDF data types to test */
+
+#include "tests.h"
+
+/*
+ * Test driver for netCDF-3 interface.  This program performs tests against
+ * the netCDF-3 specification for all user-level functions in an
+ * implementation of the netCDF library.
+ *
+ * Unless invoked with "-r" (read_only) option, must be invoked from a
+ * directory in which the invoker has write permission.
+ *
+ * Files:
+ * The read-only tests read files:
+ *     test.nc (see below)
+ *     test_get.c (used merely as an example of a non-netCDF file)
+ * 
+ * The write tests 
+ *     read test.nc (see below) 
+ *     write scratch.nc (deleted after each test)
+ * 
+ * The file test.nc is created by running nc_test with the -c (create) option.
+ * It is described by the following global variables.
+ */
+
+
+/* 
+ * global variables (defined by function init_gvars) describing file test.nc
+ */
+char dim_name[NDIMS][3];
+MPI_Offset dim_len[NDIMS];
+char var_name[NVARS][2+MAX_RANK];
+nc_type var_type[NVARS];
+size_t var_rank[NVARS];
+int var_dimid[NVARS][MAX_RANK];
+MPI_Offset var_shape[NVARS][MAX_RANK];
+size_t var_nels[NVARS];
+size_t var_natts[NVARS];
+char att_name[NVARS][MAX_NATTS][2];
+char gatt_name[NGATTS][3];
+nc_type att_type[NVARS][NGATTS];
+nc_type gatt_type[NGATTS];
+size_t att_len[NVARS][MAX_NATTS];
+size_t gatt_len[NGATTS];
+
+/* 
+ * command-line options
+ */
+static int  create_file;	/* if 1, create file test.nc */
+int  read_only;		/* if 1, don't try to change files */
+int  verbose;		/* if 1, print details of tests */
+int  max_nmpt;		/* max. number of messages per test */
+
+/* 
+ * Misc. global variables
+ */
+int  nfails;		/* number of failures in specific test */
+char testfile[128];
+char scratch[128];
+MPI_Comm comm = MPI_COMM_WORLD; /* mpi communicator for parallel-netcdf */
+MPI_Info info;
+
+static void
+usage(char *progname)
+{
+    error("%s [-c | -hrv -n <MAX_NMPT>]\n", progname);
+    error("   [-h] Print help\n" );
+    error("   [-c] Create file test.nc (Do not do tests)\n" );
+    error("   [-r] Just do read-only tests\n" );
+    error("   [-v] Verbose mode\n" );
+    error("   [-2] (with -c) create file with CDF-2 format\n" );
+    error("   [-n <MAX_NMPT>] max. number of messages per test (Default: 8)\n");
+    error("   [-d directory] directory for storing input/output files\n");
+}
+
+#define NC_TEST(func) {                                                  \
+    char func_name[64];                                                  \
+    int noks;                                                            \
+    nfails = 0;                                                          \
+    sprintf(func_name, "test_%s",#func);                                 \
+    noks = test_ ## func();                                              \
+    nfailsTotal += nfails;                                               \
+    if (verbose && nfails == 0) {                                        \
+        if (verbose) printf( "*** Testing %-30s ... ",func_name);        \
+        if (noks > 0)                                                    \
+            printf("%4d good comparisons. ok\n", noks);                  \
+        else                                                             \
+            printf("\n");                                                \
+    }                                                                    \
+    else if (nfails > 0) {                                               \
+        if (verbose) print( "*** Testing %-30s ... ",func_name);         \
+        print("\n\t### %d FAILURES TESTING %s! Stop ... ###\n",          \
+              nfails,func_name);                                         \
+        goto fn_exit;                                                    \
+    }                                                                    \
+}
+
+#if 1		/* both CRAY MPP and OSF/1 Alpha systems need this */
+#include <signal.h>
+#endif /* T90 */
+
+int
+main(int argc, char *argv[])
+{
+    extern char *optarg;
+    int c;
+    int  nfailsTotal = 0;        /* total number of failures */
+
+#if 1		/* both CRAY MPP and OSF/1 Alpha systems need this */
+	/*
+	 * Some of the extreme test assignments in this program trigger
+         * floating point exceptions on CRAY T90
+	 */
+	(void) signal(SIGFPE, SIG_IGN);
+#endif
+
+    MPI_Init(&argc, &argv);
+
+    cdf_format = 1; 	/* 1: CDF-1, 2: CDF-2 5: CDF-5 */
+    extra_flags = 0;    /* NC_64BIT_OFFSET or NC_64BIT_DATA */
+    create_file = 0;            /* file test.nc will normally already exist */
+    read_only = 0;               /* assume may write in test dir as default */
+    verbose = 0;
+    max_nmpt = 8;
+    strcpy(testfile, "test.nc");    /* read-only testfile */
+    strcpy(scratch, "scratch.nc");  /* writable scratch file */
+
+    while ((c = getopt(argc, argv, "c25hrvn:d:")) != EOF)
+      switch(c) {
+	case 'c':		/* Create file test.nc */
+	  create_file = 1;
+	  break;
+	case 'r':		/* just perform read-only tests */
+	  read_only = 1;
+	  break;
+	case 'v':		/* verbose mode */
+	  verbose = 1;
+	  break;
+	case 'n':		/* verbose mode */
+	  max_nmpt = atoi(optarg);
+	  break;
+	case '2':
+	  cdf_format = 2;
+	  extra_flags = NC_64BIT_OFFSET;
+	  break;
+	case '5':
+	  cdf_format = 5;
+	  extra_flags = NC_64BIT_DATA;
+	case 'd':
+          sprintf(testfile, "%s/test.nc", optarg);
+          sprintf(scratch, "%s/scratch.nc", optarg);
+	  break;
+	case 'h':
+	case '?':
+	  usage(argv[0]);
+	  return 1;
+      }
+
+    MPI_Info_create(&info);
+    /* MPI_Info_set(info, "romio_pvfs2_posix_write", "enable"); */
+
+    numGatts = 6;
+    numVars  = 136;
+    numTypes = 6;
+    if (cdf_format == 5) {
+        numGatts = NGATTS;
+        numVars  = NVARS;
+        numTypes = NTYPES;
+    }
+
+    /* Initialize global variables defining test file */
+    init_gvars();
+
+    if ( create_file ) {
+	write_file(testfile);
+        MPI_Info_free(&info);
+	MPI_Finalize();
+	return nfailsTotal > 0;
+    }
+
+    /* delete any existing scratch netCDF file */
+    if ( ! read_only ) {
+        if (access(scratch, F_OK) == 0)
+            unlink(scratch);
+    }
+
+    char cmd_str[256];
+    sprintf(cmd_str, "*** TESTING C   %s for format CDF-%d ", argv[0], cdf_format);
+    printf("%-66s ------ ",cmd_str);
+
+    /* Test read-only functions, using pregenerated test-file */
+    NC_TEST(ncmpi_strerror);
+    NC_TEST(ncmpi_open);
+    NC_TEST(ncmpi_close);
+    NC_TEST(ncmpi_inq);
+    NC_TEST(ncmpi_inq_dimid);
+    NC_TEST(ncmpi_inq_dim);
+    NC_TEST(ncmpi_inq_dimlen);
+    NC_TEST(ncmpi_inq_dimname);
+    NC_TEST(ncmpi_inq_varid);
+    NC_TEST(ncmpi_inq_var);
+    NC_TEST(ncmpi_inq_natts);
+    NC_TEST(ncmpi_inq_ndims);
+    NC_TEST(ncmpi_inq_nvars);
+    NC_TEST(ncmpi_inq_unlimdim);
+    NC_TEST(ncmpi_inq_vardimid);
+    NC_TEST(ncmpi_inq_varname);
+    NC_TEST(ncmpi_inq_varnatts);
+    NC_TEST(ncmpi_inq_varndims);
+    NC_TEST(ncmpi_inq_vartype);
+    NC_TEST(ncmpi_get_var_text);
+    NC_TEST(ncmpi_get_var_schar);
+    NC_TEST(ncmpi_get_var_short);
+    NC_TEST(ncmpi_get_var_int);
+    NC_TEST(ncmpi_get_var_long); 
+    NC_TEST(ncmpi_get_var_float);
+    NC_TEST(ncmpi_get_var_double);
+    NC_TEST(ncmpi_get_var_uchar); 
+    NC_TEST(ncmpi_get_var_ushort);
+    NC_TEST(ncmpi_get_var_uint);
+    NC_TEST(ncmpi_get_var_longlong);
+    NC_TEST(ncmpi_get_var_ulonglong);
+    NC_TEST(ncmpi_get_var1_text);
+    NC_TEST(ncmpi_get_var1_schar);
+    NC_TEST(ncmpi_get_var1_short);
+    NC_TEST(ncmpi_get_var1_int);
+    NC_TEST(ncmpi_get_var1_long);
+    NC_TEST(ncmpi_get_var1_float);
+    NC_TEST(ncmpi_get_var1_double);
+    NC_TEST(ncmpi_get_var1_uchar); 
+    NC_TEST(ncmpi_get_var1_ushort);
+    NC_TEST(ncmpi_get_var1_uint);
+    NC_TEST(ncmpi_get_var1_longlong);
+    NC_TEST(ncmpi_get_var1_ulonglong);
+    NC_TEST(ncmpi_get_var1);
+    NC_TEST(ncmpi_get_vara_text);
+    NC_TEST(ncmpi_get_vara_schar);
+    NC_TEST(ncmpi_get_vara_short);
+    NC_TEST(ncmpi_get_vara_int);
+    NC_TEST(ncmpi_get_vara_long); 
+    NC_TEST(ncmpi_get_vara_float);
+    NC_TEST(ncmpi_get_vara_double);
+    NC_TEST(ncmpi_get_vara_uchar);
+    NC_TEST(ncmpi_get_vara_ushort);
+    NC_TEST(ncmpi_get_vara_uint);
+    NC_TEST(ncmpi_get_vara_longlong);
+    NC_TEST(ncmpi_get_vara_ulonglong);
+    NC_TEST(ncmpi_get_vara);
+    NC_TEST(ncmpi_get_vars_text);
+    NC_TEST(ncmpi_get_vars_schar);
+    NC_TEST(ncmpi_get_vars_short);
+    NC_TEST(ncmpi_get_vars_int);
+    NC_TEST(ncmpi_get_vars_long); 
+    NC_TEST(ncmpi_get_vars_float);
+    NC_TEST(ncmpi_get_vars_double);
+    NC_TEST(ncmpi_get_vars_uchar);
+    NC_TEST(ncmpi_get_vars_ushort);
+    NC_TEST(ncmpi_get_vars_uint);
+    NC_TEST(ncmpi_get_vars_longlong);
+    NC_TEST(ncmpi_get_vars_ulonglong);
+    NC_TEST(ncmpi_get_vars);
+    NC_TEST(ncmpi_get_varm_text);
+    NC_TEST(ncmpi_get_varm_schar);
+    NC_TEST(ncmpi_get_varm_short);
+    NC_TEST(ncmpi_get_varm_int);
+    NC_TEST(ncmpi_get_varm_long);
+    NC_TEST(ncmpi_get_varm_float);
+    NC_TEST(ncmpi_get_varm_double);
+    NC_TEST(ncmpi_get_varm_uchar);
+    NC_TEST(ncmpi_get_varm_ushort);
+    NC_TEST(ncmpi_get_varm_uint);
+    NC_TEST(ncmpi_get_varm_longlong);
+    NC_TEST(ncmpi_get_varm_ulonglong);
+    NC_TEST(ncmpi_get_varm);
+    NC_TEST(ncmpi_get_att_text);
+    NC_TEST(ncmpi_get_att_schar);
+    NC_TEST(ncmpi_get_att_short);
+    NC_TEST(ncmpi_get_att_int);
+    NC_TEST(ncmpi_get_att_long);
+    NC_TEST(ncmpi_get_att_float);
+    NC_TEST(ncmpi_get_att_double);
+    NC_TEST(ncmpi_get_att_uchar);
+    NC_TEST(ncmpi_get_att_ushort);
+    NC_TEST(ncmpi_get_att_uint);
+    NC_TEST(ncmpi_get_att_longlong);
+    NC_TEST(ncmpi_get_att_ulonglong);
+    NC_TEST(ncmpi_get_att);
+    NC_TEST(ncmpi_inq_att);
+    NC_TEST(ncmpi_inq_attname);
+    NC_TEST(ncmpi_inq_attid);
+    NC_TEST(ncmpi_inq_attlen);
+    NC_TEST(ncmpi_inq_atttype);
+
+    /* nonblocking I/O */
+    NC_TEST(ncmpi_iget_var_text);
+    NC_TEST(ncmpi_iget_var_schar);
+    NC_TEST(ncmpi_iget_var_short);
+    NC_TEST(ncmpi_iget_var_int);
+    NC_TEST(ncmpi_iget_var_long); 
+    NC_TEST(ncmpi_iget_var_float);
+    NC_TEST(ncmpi_iget_var_double);
+    NC_TEST(ncmpi_iget_var_uchar); 
+    NC_TEST(ncmpi_iget_var_ushort);
+    NC_TEST(ncmpi_iget_var_uint);
+    NC_TEST(ncmpi_iget_var_longlong);
+    NC_TEST(ncmpi_iget_var_ulonglong);
+    NC_TEST(ncmpi_iget_var);
+    NC_TEST(ncmpi_iget_var1_text);
+    NC_TEST(ncmpi_iget_var1_schar);
+    NC_TEST(ncmpi_iget_var1_short);
+    NC_TEST(ncmpi_iget_var1_int);
+    NC_TEST(ncmpi_iget_var1_long);
+    NC_TEST(ncmpi_iget_var1_float);
+    NC_TEST(ncmpi_iget_var1_double);
+    NC_TEST(ncmpi_iget_var1_uchar); 
+    NC_TEST(ncmpi_iget_var1_ushort);
+    NC_TEST(ncmpi_iget_var1_uint);
+    NC_TEST(ncmpi_iget_var1_longlong);
+    NC_TEST(ncmpi_iget_var1_ulonglong);
+    NC_TEST(ncmpi_iget_var1);
+    NC_TEST(ncmpi_iget_vara_text);
+    NC_TEST(ncmpi_iget_vara_schar);
+    NC_TEST(ncmpi_iget_vara_short);
+    NC_TEST(ncmpi_iget_vara_int);
+    NC_TEST(ncmpi_iget_vara_long); 
+    NC_TEST(ncmpi_iget_vara_float);
+    NC_TEST(ncmpi_iget_vara_double);
+    NC_TEST(ncmpi_iget_vara_uchar);
+    NC_TEST(ncmpi_iget_vara_ushort);
+    NC_TEST(ncmpi_iget_vara_uint);
+    NC_TEST(ncmpi_iget_vara_longlong);
+    NC_TEST(ncmpi_iget_vara_ulonglong);
+    NC_TEST(ncmpi_iget_vara);
+    NC_TEST(ncmpi_iget_vars_text);
+    NC_TEST(ncmpi_iget_vars_schar);
+    NC_TEST(ncmpi_iget_vars_short);
+    NC_TEST(ncmpi_iget_vars_int);
+    NC_TEST(ncmpi_iget_vars_long); 
+    NC_TEST(ncmpi_iget_vars_float);
+    NC_TEST(ncmpi_iget_vars_double);
+    NC_TEST(ncmpi_iget_vars_uchar);
+    NC_TEST(ncmpi_iget_vars_ushort);
+    NC_TEST(ncmpi_iget_vars_uint);
+    NC_TEST(ncmpi_iget_vars_longlong);
+    NC_TEST(ncmpi_iget_vars_ulonglong);
+    NC_TEST(ncmpi_iget_vars);
+    NC_TEST(ncmpi_iget_varm_text);
+    NC_TEST(ncmpi_iget_varm_schar);
+    NC_TEST(ncmpi_iget_varm_short);
+    NC_TEST(ncmpi_iget_varm_int);
+    NC_TEST(ncmpi_iget_varm_long);
+    NC_TEST(ncmpi_iget_varm_float);
+    NC_TEST(ncmpi_iget_varm_double);
+    NC_TEST(ncmpi_iget_varm_uchar);
+    NC_TEST(ncmpi_iget_varm_ushort);
+    NC_TEST(ncmpi_iget_varm_uint);
+    NC_TEST(ncmpi_iget_varm_longlong);
+    NC_TEST(ncmpi_iget_varm_ulonglong);
+    NC_TEST(ncmpi_iget_varm);
+
+	/* Test write functions */
+    if (! read_only) {
+	NC_TEST(ncmpi_create);
+	NC_TEST(ncmpi_redef);
+	/* NC_TEST(ncmpi_enddef);  redundant, as it calls test_ncmpi_redef() */
+	NC_TEST(ncmpi_sync);
+	NC_TEST(ncmpi_abort);
+	NC_TEST(ncmpi_def_dim);
+	NC_TEST(ncmpi_rename_dim);
+	NC_TEST(ncmpi_def_var);
+	NC_TEST(ncmpi_put_var_text);
+	NC_TEST(ncmpi_put_var_schar);
+	NC_TEST(ncmpi_put_var_short);
+	NC_TEST(ncmpi_put_var_int);
+	NC_TEST(ncmpi_put_var_long); 
+	NC_TEST(ncmpi_put_var_float);
+	NC_TEST(ncmpi_put_var_double);
+	NC_TEST(ncmpi_put_var_uchar);
+	NC_TEST(ncmpi_put_var_ushort);
+	NC_TEST(ncmpi_put_var_uint);
+	NC_TEST(ncmpi_put_var_longlong);
+	NC_TEST(ncmpi_put_var_ulonglong);
+	NC_TEST(ncmpi_put_var1_text);
+	NC_TEST(ncmpi_put_var1_schar);
+	NC_TEST(ncmpi_put_var1_short);
+	NC_TEST(ncmpi_put_var1_int);
+	NC_TEST(ncmpi_put_var1_long); 
+	NC_TEST(ncmpi_put_var1_float);
+	NC_TEST(ncmpi_put_var1_double);
+	NC_TEST(ncmpi_put_var1_uchar); 
+	NC_TEST(ncmpi_put_var1_ushort);
+	NC_TEST(ncmpi_put_var1_uint);
+	NC_TEST(ncmpi_put_var1_longlong);
+	NC_TEST(ncmpi_put_var1_ulonglong);
+	NC_TEST(ncmpi_put_var1);
+	NC_TEST(ncmpi_put_vara_text);
+	NC_TEST(ncmpi_put_vara_schar); 
+	NC_TEST(ncmpi_put_vara_short);
+	NC_TEST(ncmpi_put_vara_int);
+	NC_TEST(ncmpi_put_vara_long);
+	NC_TEST(ncmpi_put_vara_float);
+	NC_TEST(ncmpi_put_vara_double);
+	NC_TEST(ncmpi_put_vara_uchar);
+	NC_TEST(ncmpi_put_vara_ushort);
+	NC_TEST(ncmpi_put_vara_uint);
+	NC_TEST(ncmpi_put_vara_longlong);
+	NC_TEST(ncmpi_put_vara_ulonglong);
+	NC_TEST(ncmpi_put_vara);
+	NC_TEST(ncmpi_put_vars_text);
+	NC_TEST(ncmpi_put_vars_schar);
+	NC_TEST(ncmpi_put_vars_short);
+	NC_TEST(ncmpi_put_vars_int);
+	NC_TEST(ncmpi_put_vars_long); 
+	NC_TEST(ncmpi_put_vars_float);
+	NC_TEST(ncmpi_put_vars_double);
+	NC_TEST(ncmpi_put_vars_uchar);
+	NC_TEST(ncmpi_put_vars_ushort);
+	NC_TEST(ncmpi_put_vars_uint);
+	NC_TEST(ncmpi_put_vars_longlong);
+	NC_TEST(ncmpi_put_vars_ulonglong);
+	NC_TEST(ncmpi_put_vars);
+	NC_TEST(ncmpi_put_varm_text);
+	NC_TEST(ncmpi_put_varm_schar);
+	NC_TEST(ncmpi_put_varm_short);
+	NC_TEST(ncmpi_put_varm_int);
+	NC_TEST(ncmpi_put_varm_long);
+	NC_TEST(ncmpi_put_varm_float);
+	NC_TEST(ncmpi_put_varm_double);
+	NC_TEST(ncmpi_put_varm_uchar);
+	NC_TEST(ncmpi_put_varm_ushort);
+	NC_TEST(ncmpi_put_varm_uint);
+	NC_TEST(ncmpi_put_varm_longlong);
+	NC_TEST(ncmpi_put_varm_ulonglong);
+	NC_TEST(ncmpi_put_varm);
+	NC_TEST(ncmpi_rename_var);
+	NC_TEST(ncmpi_put_att_text);
+	NC_TEST(ncmpi_put_att_schar);
+	NC_TEST(ncmpi_put_att_short);
+	NC_TEST(ncmpi_put_att_int);
+	NC_TEST(ncmpi_put_att_long);
+	NC_TEST(ncmpi_put_att_float);
+	NC_TEST(ncmpi_put_att_double);
+	NC_TEST(ncmpi_put_att_uchar);
+	NC_TEST(ncmpi_put_att_ushort);
+	NC_TEST(ncmpi_put_att_uint);
+	NC_TEST(ncmpi_put_att_longlong);
+	NC_TEST(ncmpi_put_att_ulonglong);
+	NC_TEST(ncmpi_put_att);
+	NC_TEST(ncmpi_copy_att);
+	NC_TEST(ncmpi_rename_att);
+	NC_TEST(ncmpi_del_att);
+	NC_TEST(ncmpi_set_fill);
+	NC_TEST(ncmpi_delete);
+
+        /* test nonblocking APIs */
+	NC_TEST(ncmpi_iput_var_text);
+	NC_TEST(ncmpi_iput_var_schar);
+	NC_TEST(ncmpi_iput_var_short);
+	NC_TEST(ncmpi_iput_var_int);
+	NC_TEST(ncmpi_iput_var_long); 
+	NC_TEST(ncmpi_iput_var_float);
+	NC_TEST(ncmpi_iput_var_double);
+	NC_TEST(ncmpi_iput_var_uchar);
+	NC_TEST(ncmpi_iput_var_ushort);
+	NC_TEST(ncmpi_iput_var_uint);
+	NC_TEST(ncmpi_iput_var_longlong);
+	NC_TEST(ncmpi_iput_var_ulonglong);
+	NC_TEST(ncmpi_iput_var);
+	NC_TEST(ncmpi_iput_var1_text);
+	NC_TEST(ncmpi_iput_var1_schar);
+	NC_TEST(ncmpi_iput_var1_short);
+	NC_TEST(ncmpi_iput_var1_int);
+	NC_TEST(ncmpi_iput_var1_long); 
+	NC_TEST(ncmpi_iput_var1_float);
+	NC_TEST(ncmpi_iput_var1_double);
+	NC_TEST(ncmpi_iput_var1_uchar); 
+	NC_TEST(ncmpi_iput_var1_ushort);
+	NC_TEST(ncmpi_iput_var1_uint);
+	NC_TEST(ncmpi_iput_var1_longlong);
+	NC_TEST(ncmpi_iput_var1_ulonglong);
+	NC_TEST(ncmpi_iput_var1);
+	NC_TEST(ncmpi_iput_vara_text);
+	NC_TEST(ncmpi_iput_vara_schar); 
+	NC_TEST(ncmpi_iput_vara_short);
+	NC_TEST(ncmpi_iput_vara_int);
+	NC_TEST(ncmpi_iput_vara_long);
+	NC_TEST(ncmpi_iput_vara_float);
+	NC_TEST(ncmpi_iput_vara_double);
+	NC_TEST(ncmpi_iput_vara_uchar);
+	NC_TEST(ncmpi_iput_vara_ushort);
+	NC_TEST(ncmpi_iput_vara_uint);
+	NC_TEST(ncmpi_iput_vara_longlong);
+	NC_TEST(ncmpi_iput_vara_ulonglong);
+	NC_TEST(ncmpi_iput_vara);
+	NC_TEST(ncmpi_iput_vars_text);
+	NC_TEST(ncmpi_iput_vars_schar);
+	NC_TEST(ncmpi_iput_vars_short);
+	NC_TEST(ncmpi_iput_vars_int);
+	NC_TEST(ncmpi_iput_vars_long); 
+	NC_TEST(ncmpi_iput_vars_float);
+	NC_TEST(ncmpi_iput_vars_double);
+	NC_TEST(ncmpi_iput_vars_uchar);
+	NC_TEST(ncmpi_iput_vars_ushort);
+	NC_TEST(ncmpi_iput_vars_uint);
+	NC_TEST(ncmpi_iput_vars_longlong);
+	NC_TEST(ncmpi_iput_vars_ulonglong);
+	NC_TEST(ncmpi_iput_vars);
+	NC_TEST(ncmpi_iput_varm_text);
+	NC_TEST(ncmpi_iput_varm_schar);
+	NC_TEST(ncmpi_iput_varm_short);
+	NC_TEST(ncmpi_iput_varm_int);
+	NC_TEST(ncmpi_iput_varm_long);
+	NC_TEST(ncmpi_iput_varm_float);
+	NC_TEST(ncmpi_iput_varm_double);
+	NC_TEST(ncmpi_iput_varm_uchar);
+	NC_TEST(ncmpi_iput_varm_ushort);
+	NC_TEST(ncmpi_iput_varm_uint);
+	NC_TEST(ncmpi_iput_varm_longlong);
+	NC_TEST(ncmpi_iput_varm_ulonglong);
+	NC_TEST(ncmpi_iput_varm);
+    }
+
+fn_exit:
+    MPI_Info_free(&info);
+
+    if (nfailsTotal == 0)  {
+        printf(PASS_STR);
+    }
+    else {
+        print("\n%s: expects 0 failures ... ",argv[0]);
+        printf(FAIL_STR, nfailsTotal);
+    }
+    MPI_Finalize();
+    return nfailsTotal > 0;
+}
diff --git a/test/nc_test/t_nc.c b/test/nc_test/t_nc.c
new file mode 100644
index 0000000..fddcdfe
--- /dev/null
+++ b/test/nc_test/t_nc.c
@@ -0,0 +1,664 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: t_nc.c 2219 2015-12-11 22:30:03Z wkliao $ */
+
+/* This program is based on the test program t_nc.c of the netCDF package */
+
+/* Copyright 1988-2010 University Corporation for Atmospheric Research
+   See netcdf/COPYRIGHT file for copying and redistribution
+   conditions.
+
+   Program to create a cdf, exercise all cdf functions.  Creates cdf,
+   stuff it full of numbers, closes it. Then reopens it, and checks
+   for consistency.  Leaves the file around afterwards.
+ 
+   Based on a program to test the nasa look-alike program, so not the
+   most appropropriate test. See ../nctest for a complete spec test.
+*/
+ 
+#define REDEF
+/* #define SYNCDEBUG */
+
+#undef NDEBUG	/* always active assert() in this file */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define MAXSHORT	32767
+#define MAXINT		2147483647
+#define MAXBYTE		127
+
+
+#define	NUM_DIMS 	3
+#define DONT_CARE	-1
+/* make these numbers big when you want to give this a real workout */
+#define NUM_RECS	8
+#define SIZE_1		7
+#define SIZE_2		8
+
+static struct {
+	int num_dims;
+	int num_vars;
+	int num_attrs;
+	int xtendim;
+} cdesc[1];
+
+static struct {
+	char mnem[NC_MAX_NAME];
+	nc_type type;
+	int ndims;
+	int dims[NC_MAX_VAR_DIMS];
+	int num_attrs;
+} vdesc[1];
+
+static struct {
+	char mnem[NC_MAX_NAME];
+	nc_type type;
+	MPI_Offset len;
+} adesc[1];
+
+union getret
+{
+    char            by[8];
+    short           sh[4];
+    int          in[2];
+    float           fl[2];
+    double          dbl;
+};
+
+
+#define ERR {if (err != NC_NOERR) {printf("Error at %s line %d: %s\n",__func__,__LINE__,ncmpi_strerror(err)); return 1;}}
+
+static void
+chkgot(nc_type type, union getret got, double check)
+{
+	switch(type){
+	case NC_BYTE :
+		assert( (char)check == got.by[0] );
+		break;
+	case NC_CHAR :	/* TODO */
+		assert( (char)check == got.by[0] );
+		break;
+	case NC_SHORT :
+		assert( (short)check == got.sh[0] );
+		break;
+	case NC_INT :
+		assert( (int)check == got.in[0] );
+		break;
+	case NC_FLOAT :
+		assert( (float)check == got.fl[0] );
+		break;
+	case NC_DOUBLE :
+		assert( check == got.dbl );
+		break;
+	default:
+		break;
+	}
+}
+
+
+static size_t num_dims = NUM_DIMS;
+static MPI_Offset sizes[] = { NC_UNLIMITED, SIZE_1 , SIZE_2 };
+static const char * const dim_names[] = { "record", "ixx", "iyy"};
+
+static int
+createtestdims(int cdfid, size_t num_dims, const MPI_Offset *sizes, const char * const dim_names[])
+{
+	int dimid, err;
+	while(num_dims-- != 0)
+	{
+		err = ncmpi_def_dim(cdfid, *dim_names++, *sizes, &dimid); ERR
+		sizes++;
+	}
+	return 0;
+}
+
+
+static int
+testdims(int cdfid, size_t num_dims, MPI_Offset *sizes, const char * const dim_names[])
+{
+	int ii, err;
+	MPI_Offset size;
+	char cp[NC_MAX_NAME];
+	for(ii=0; (size_t) ii < num_dims; ii++, sizes++)
+	{
+		err = ncmpi_inq_dim(cdfid, ii, cp, &size); ERR
+		if( size != *sizes)
+			(void) fprintf(stderr, "%d: %lu != %lu\n",
+				ii, (unsigned long)size, (unsigned long)*sizes);
+		if ( size != *sizes) return 1;
+		if ( strcmp(cp, *dim_names++) != 0) return 1;
+	}
+	return 0;
+}
+
+
+
+static const char * const reqattr[] = {
+	"UNITS",
+	"VALIDMIN",
+	"VALIDMAX",
+	"SCALEMIN",
+	"SCALEMAX",
+	"FIELDNAM",
+	_FillValue
+};
+#define NUM_RATTRS	6
+
+static struct tcdfvar {
+	const char *mnem;
+	nc_type type;
+	const char *fieldnam;
+	double validmin;
+	double validmax;
+	double scalemin;
+	double scalemax;
+	const char *units;
+	int ndims;
+	int dims[NUM_DIMS];
+} const testvars[]  = {
+#define Byte_id 0
+	{ "Byte", NC_BYTE, "Byte sized integer variable",
+		-MAXBYTE, MAXBYTE, -MAXBYTE, MAXBYTE , "ones",
+			2, {0,1,DONT_CARE} },
+#define Char_id 1
+	{ "Char", NC_CHAR, "char (string) variable",
+		DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, "(unitless)",
+			2, {0,2,DONT_CARE} },
+#define Short_id 2
+	{ "Short", NC_SHORT, "Short variable",
+		-MAXSHORT, MAXSHORT, -MAXSHORT, MAXSHORT , "ones",
+			2, {0, 2, DONT_CARE }},
+#define Long_id 3
+	{ "Long", NC_INT, "Long Integer variable", /* 2.x backward strings */
+		-MAXINT, MAXINT, -MAXINT, MAXINT, "ones",
+			2, {1, 2, DONT_CARE}},
+#define Float_id 4
+	{ "Float", NC_FLOAT, "Single Precision Floating Point variable",
+		-MAXINT, MAXINT, -MAXINT, MAXINT, "flots",
+			3, {0, 1, 2 }},
+#define Double_id 5
+	{ "Double", NC_DOUBLE, "Double Precision Floating Point variable",
+		-MAXINT, MAXINT, -MAXINT, MAXINT, "dflots",
+			3, {0, 1, 2 }},
+};
+#define	NUM_TESTVARS	6
+
+static int
+createtestvars(int id, const struct tcdfvar *testvars, size_t count)
+{
+	int ii, err;
+	int varid;
+	const struct tcdfvar *vp = testvars;
+
+	for(ii = 0; (size_t) ii < count; ii++, vp++ )
+	{
+		err = ncmpi_def_var(id, vp->mnem, vp->type, vp->ndims, vp->dims, &varid); ERR
+
+	 	err = ncmpi_put_att_text(id,ii,reqattr[0],strlen(vp->units), vp->units); ERR
+	 	err = ncmpi_put_att_double(id,ii,reqattr[1],NC_DOUBLE,1, &vp->validmin); ERR
+	 	err = ncmpi_put_att_double(id,ii,reqattr[2],NC_DOUBLE,1, &vp->validmax); ERR
+	 	err = ncmpi_put_att_double(id,ii,reqattr[3],NC_DOUBLE,1, &vp->scalemin); ERR
+	 	err = ncmpi_put_att_double(id,ii,reqattr[4],NC_DOUBLE,1, &vp->scalemax); ERR
+	 	err = ncmpi_put_att_text(id,ii,reqattr[5],strlen(vp->fieldnam), vp->fieldnam); ERR
+	}
+	return 0;
+}
+
+/* static void */
+/* parray(const char *label, size_t count, const size_t array[]) */
+/* { */
+/* 	(void) fprintf(stdout, "%s", label); */
+/* 	(void) fputc('\t',stdout);	 */
+/* 	for(; count != 0; count--, array++) */
+/* 		(void) fprintf(stdout," %lu", (unsigned long) *array); */
+/* } */
+
+
+static int
+fill_seq(int id)
+{
+        int err;
+	float values[NUM_RECS * SIZE_1 * SIZE_2];
+	MPI_Offset vindices[NUM_DIMS];
+
+	{
+		size_t ii = 0;
+		for(; ii < sizeof(values)/sizeof(values[0]); ii++)
+		{
+			values[ii] = (float) ii;
+		}
+	}
+
+	/* zero the vindices */
+	{
+		MPI_Offset *cc = vindices;
+		while (cc < &vindices[num_dims])
+			*cc++ = 0; 
+	}
+
+	sizes[0] = NUM_RECS;
+	err = ncmpi_put_vara_float(id, Float_id, vindices, sizes, values); ERR
+	return 0;
+}
+
+static int
+check_fill_seq(int id)
+{
+	MPI_Offset vindices[NUM_DIMS];
+	MPI_Offset *cc, *mm;
+	union getret got;
+	int ii = 0;
+	/*float val;*/
+
+	sizes[0] = NUM_RECS;
+	cc = vindices;
+	while (cc < &vindices[num_dims])
+		*cc++ = 0; 
+
+	/* ripple counter */
+	cc = vindices;
+	mm = sizes;
+	while (*vindices < *sizes)
+	{
+	    while (*cc < *mm)
+	    {
+		if (mm == &sizes[num_dims - 1])
+		{
+	if(ncmpi_get_var1_float(id, Float_id, vindices, &got.fl[0]) == -1) 
+		goto bad_ret;
+	/* val = (float) ii;  */
+	/* if(val != got.fl[0]) */
+	/* { */
+	/* 	parray("indices", NUM_DIMS, vindices); */
+	/* 	(void) printf("\t%f != %f\n", val, got.fl[0]); */
+	/* } */
+		    (*cc)++; ii++;
+		    continue;
+		}
+		cc++;
+		mm++;
+	    }
+		if(cc == vindices)
+			break;
+	    *cc = 0;
+	    cc--;
+	    mm--;
+	    (*cc)++;
+	}
+	return 0;
+bad_ret :
+	(void) printf("couldn't get a var in check_fill_seq() %d\n", ii);
+	return 1;
+}
+
+static MPI_Offset	indices[][3] = {
+	{0, 1, 3},
+	{0, 3, 0},
+	{1, 2, 3},
+	{3, 2, 1},
+	{2, 1, 3},
+	{1, 0, 0},
+	{0, 0, 0},
+};
+
+static const char chs[] = {'A','B', ((char)0xff) };
+static const MPI_Offset s_start[] = {0,1};
+static const MPI_Offset s_edges[] = {NUM_RECS, SIZE_1 - 1};
+static char sentence[NUM_RECS* SIZE_1 -1] =
+	"The red death had long devastated the country.";
+static short shs[] = {97, 99};
+static int birthday = 82555;
+#define M_E	2.7182818284590452354
+static float e = (float) M_E;
+static double pinot = 3.25;
+static double zed = 0.0;
+
+
+/*ARGSUSED*/
+static
+int t_nc(char *filename, int cmode)
+{
+	int id, err;
+	char buf[256];
+#ifdef SYNCDEBUG
+	char *str = "one";
+#endif
+	int ii;
+	MPI_Offset ui;
+	const struct tcdfvar *tvp = testvars;
+	union getret got;
+	MPI_Offset align = 8192/32;
+
+	err = ncmpi_create(MPI_COMM_WORLD, filename,cmode, MPI_INFO_NULL, &id); ERR
+	
+	err = ncmpi_put_att_text(id, NC_GLOBAL, "TITLE", 12, "another name"); ERR
+	err = ncmpi_get_att_text(id, NC_GLOBAL, "TITLE", buf); ERR
+/*	(void) printf("title 1 \"%s\"\n", buf); */
+	err = ncmpi_put_att_text(id, NC_GLOBAL, "TITLE", strlen(filename), filename); ERR
+	err = ncmpi_get_att_text(id, NC_GLOBAL, "TITLE", buf); ERR
+	buf[strlen(filename)] = 0;
+/*	(void) printf("title 2 \"%s\"\n", buf); */
+	assert(strcmp(filename, buf) == 0);
+
+	err = createtestdims(id, NUM_DIMS, sizes, dim_names); ERR
+	testdims(id, NUM_DIMS, sizes, dim_names);
+
+	err = createtestvars(id, testvars, NUM_TESTVARS); ERR
+
+ 	{
+ 	int ifill = -1; double dfill = -9999;
+ 	err = ncmpi_put_att_int(id, Long_id, _FillValue, NC_INT, 1, &ifill); ERR
+ 	err = ncmpi_put_att_double(id, Double_id, _FillValue, NC_DOUBLE, 1, &dfill); ERR
+ 	}
+
+#ifdef REDEF
+	err = ncmpi__enddef(id, 0, align, 0, 2*align); ERR
+	err = ncmpi_begin_indep_data(id); ERR
+	err = ncmpi_put_var1_int(id, Long_id, indices[3], &birthday); ERR
+	err = fill_seq(id); ERR
+	err = ncmpi_end_indep_data(id); ERR
+
+	err = ncmpi_redef(id); ERR
+/*	err = ncmpi_rename_dim(id,2, "a long dim name"); ERR */
+#endif
+
+	err = ncmpi_rename_dim(id,1, "IXX"); ERR 
+	err = ncmpi_inq_dim(id, 1, buf, &ui); ERR 
+	/* (void) printf("dimrename: %s\n", buf); */
+	err = ncmpi_rename_dim(id,1, dim_names[1]); ERR 
+
+#ifdef ATTRX
+	err = ncmpi_rename_att(id, 1, "UNITS", "units"); ERR 
+	err = ncmpi_del_att(id, 4, "FIELDNAM"); ERR
+	err = ncmpi_del_att(id, 2, "SCALEMIN"); ERR
+	err = ncmpi_del_att(id, 2, "SCALEMAX"); ERR
+#endif /* ATTRX */
+
+	err = ncmpi__enddef(id, 0, align, 0, 2*align); ERR
+	err = ncmpi_begin_indep_data(id); ERR
+
+#ifndef REDEF
+	err = fill_seq(id); ERR
+	err = ncmpi_put_var1_int(id, Long_id, indices[3], &birthday); ERR
+#endif
+
+	err = ncmpi_put_vara_schar(id, Byte_id, s_start, s_edges, (signed char *)sentence); ERR
+	err = ncmpi_put_var1_schar(id, Byte_id, indices[6], (signed char *)(chs+1)); ERR
+	err = ncmpi_put_var1_schar(id, Byte_id, indices[5], (signed char *)chs); ERR
+
+	err = ncmpi_put_vara_text(id, Char_id, s_start, s_edges, sentence); ERR
+	err = ncmpi_put_var1_text(id, Char_id, indices[6], (chs+1)); ERR
+	err = ncmpi_put_var1_text(id, Char_id, indices[5], chs); ERR
+
+	err = ncmpi_put_var1_short(id, Short_id, indices[4], shs); ERR
+
+	err = ncmpi_put_var1_float(id, Float_id, indices[2], &e); ERR
+
+	err = ncmpi_put_var1_double(id, Double_id, indices[1], &zed); ERR
+	err = ncmpi_put_var1_double(id, Double_id, indices[0], &pinot); ERR
+
+#ifdef SYNCDEBUG
+	(void) printf("Hit Return to sync\n");
+	gets(str);
+	ncmpi_sync(id,0);
+	(void) printf("Sync done. Hit Return to continue\n");
+	gets(str);
+#endif /* SYNCDEBUG */
+
+	err = ncmpi_close(id); ERR
+
+
+/*
+ *	read it
+ */
+	err = ncmpi_open(MPI_COMM_WORLD, filename,NC_NOWRITE, MPI_INFO_NULL, &id); ERR
+	err = ncmpi_begin_indep_data(id); ERR
+
+	/*	NC	*/ 
+	/* (void) printf("NC "); */
+	err = ncmpi_inq(id, &(cdesc->num_dims), &(cdesc->num_vars), &(cdesc->num_attrs), &(cdesc->xtendim) ); ERR
+	assert((MPI_Offset) cdesc->num_dims == num_dims);
+	assert(cdesc->num_attrs == 1);
+	assert(cdesc->num_vars == NUM_TESTVARS);
+	/* (void) printf("done\n"); */
+	
+	/*	GATTR	*/
+	/* (void) printf("GATTR "); */
+
+	err = ncmpi_inq_attname(id, NC_GLOBAL, 0, adesc->mnem); ERR
+	assert(strcmp("TITLE",adesc->mnem) == 0);
+	err = ncmpi_inq_att(id, NC_GLOBAL, adesc->mnem, &(adesc->type), &(adesc->len)); ERR
+	assert( adesc->type == NC_CHAR );
+	assert( adesc->len == strlen(filename) );
+	err = ncmpi_get_att_text(id, NC_GLOBAL, "TITLE", buf); ERR
+	buf[adesc->len] = 0;
+	assert( strcmp(filename, buf) == 0);
+
+	/*	VAR	*/
+	/* (void) printf("VAR "); */
+	assert( cdesc->num_vars == NUM_TESTVARS );
+
+	for(ii = 0; ii < cdesc->num_vars; ii++, tvp++ ) 
+	{
+		int jj;
+		err = ncmpi_inq_var(id, ii,
+			vdesc->mnem,
+			&(vdesc->type),
+			&(vdesc->ndims),
+			vdesc->dims,
+			&(vdesc->num_attrs)); ERR
+		if(strcmp(tvp->mnem , vdesc->mnem) != 0)
+		{
+			(void) printf("attr %d mnem mismatch %s, %s\n",
+				ii, tvp->mnem, vdesc->mnem);
+			continue;
+		}
+		if(tvp->type != vdesc->type)
+		{
+			(void) printf("attr %d type mismatch %d, %d\n",
+				ii, (int)tvp->type, (int)vdesc->type);
+			continue;
+		}
+		for(jj = 0; jj < vdesc->ndims; jj++ )
+		{
+			if(tvp->dims[jj] != vdesc->dims[jj] )
+			{
+		(void) printf(
+		"inconsistent dim[%d] for variable %d: %d != %d\n",
+		jj, ii, tvp->dims[jj], vdesc->dims[jj] );
+			continue;
+			}
+		}
+
+		/* VATTR */
+		/* (void) printf("VATTR\n"); */
+		for(jj=0; jj<vdesc->num_attrs; jj++ ) 
+		{
+			err = ncmpi_inq_attname(id, ii, jj, adesc->mnem); ERR
+			if( strcmp(adesc->mnem, reqattr[jj]) != 0 )
+			{
+				(void) printf("var %d attr %d mismatch %s != %s\n",
+					ii, jj, adesc->mnem, reqattr[jj] );
+				break;
+			}
+		}
+
+		if( ncmpi_inq_att(id, ii, reqattr[0], &(adesc->type), &(adesc->len))
+			!= -1) {
+		assert( adesc->type == NC_CHAR );
+		assert( adesc->len == strlen(tvp->units) );
+	 	err = ncmpi_get_att_text(id,ii,reqattr[0],buf); ERR
+		buf[adesc->len] = 0;
+		assert( strcmp(tvp->units, buf) == 0);
+		}
+
+		if(
+			ncmpi_inq_att(id, ii, reqattr[1], &(adesc->type), &(adesc->len))
+			!= -1)
+		{
+		assert( adesc->type == NC_DOUBLE );
+		assert( adesc->len == 1 );
+	 	err = ncmpi_get_att_double(id, ii, reqattr[1], &got.dbl); ERR
+		chkgot(adesc->type, got, tvp->validmin);
+		}
+
+		if(
+			ncmpi_inq_att(id, ii, reqattr[2], &(adesc->type), &(adesc->len))
+			!= -1)
+		{
+		assert( adesc->type == NC_DOUBLE );
+		assert( adesc->len == 1 );
+	 	err = ncmpi_get_att_double(id, ii, reqattr[2], &got.dbl); ERR
+		chkgot(adesc->type, got, tvp->validmax);
+		}
+
+		if(
+			ncmpi_inq_att(id, ii, reqattr[3], &(adesc->type), &(adesc->len))
+			!= -1)
+		{
+		assert( adesc->type == NC_DOUBLE );
+		assert( adesc->len ==1 );
+	 	err = ncmpi_get_att_double(id, ii, reqattr[3], &got.dbl); ERR
+		chkgot(adesc->type, got, tvp->scalemin);
+		}
+
+		if(
+			ncmpi_inq_att(id, ii, reqattr[4], &(adesc->type), &(adesc->len))
+			!= -1)
+		{
+		assert( adesc->type == NC_DOUBLE );
+		assert( adesc->len == 1 );
+	 	err = ncmpi_get_att_double(id, ii, reqattr[4], &got.dbl); ERR
+		chkgot(adesc->type, got, tvp->scalemax);
+		}
+
+		if( ncmpi_inq_att(id, ii, reqattr[5], &(adesc->type), &(adesc->len)) == NC_NOERR)
+		{
+		assert( adesc->type == NC_CHAR );
+		assert( adesc->len == strlen(tvp->fieldnam) );
+	 	err = ncmpi_get_att_text(id,ii,reqattr[5],buf); ERR
+		buf[adesc->len] = 0;
+		assert( strcmp(tvp->fieldnam, buf) == 0);
+		}
+	}
+
+	/* (void) printf("fill_seq "); */
+	err = check_fill_seq(id); ERR
+	/* (void) printf("Done\n"); */
+
+	err = ncmpi_get_var1_double(id, Double_id, indices[0], &got.dbl); ERR
+	/* (void) printf("got val = %f\n", got.dbl ); */
+
+	err = ncmpi_get_var1_double(id, Double_id, indices[1], &got.dbl); ERR
+	/* (void) printf("got val = %f\n", got.dbl ); */
+
+	err = ncmpi_get_var1_float(id, Float_id, indices[2], &got.fl[0]); ERR
+	/* (void) printf("got val = %f\n", got.fl[0] ); */
+
+	err = ncmpi_get_var1_int(id, Long_id, indices[3], &got.in[0]); ERR
+	/* (void) printf("got val = %d\n", got.in[0] ); */
+
+	err = ncmpi_get_var1_short(id, Short_id, indices[4], &got.sh[0]); ERR
+	/* (void) printf("got val = %d\n", got.sh[0] ); */
+
+	err = ncmpi_get_var1_text(id, Char_id, indices[5], &got.by[0]); ERR
+	/* (void) printf("got NC_CHAR val = %c (0x%02x) \n", */
+		 /* got.by[0] , got.by[0]); */
+
+	err = ncmpi_get_var1_text(id, Char_id, indices[6], &got.by[0]); ERR
+	/* (void) printf("got NC_CHAR val = %c (0x%02x) \n", */
+	/* 	 got.by[0], got.by[0] ); */
+
+	(void) memset(buf,0,sizeof(buf));
+	err = ncmpi_get_vara_text(id, Char_id, s_start, s_edges, buf); ERR
+	/* (void) printf("got NC_CHAR val = \"%s\"\n", buf); */
+
+	err = ncmpi_get_var1_schar(id, Byte_id, indices[5], (signed char *)&got.by[0]); ERR
+	/* (void) printf("got val = %c (0x%02x) \n", got.by[0] , got.by[0]); */
+
+	err = ncmpi_get_var1_schar(id, Byte_id, indices[6], (signed char *)&got.by[0]); ERR
+	/* (void) printf("got val = %c (0x%02x) \n", got.by[0], got.by[0] ); */
+
+	(void) memset(buf,0,sizeof(buf));
+	err = ncmpi_get_vara_schar(id, Byte_id, s_start, s_edges, (signed char *)buf); ERR
+	/* (void) printf("got val = \"%s\"\n", buf); */
+
+	{
+		double dbuf[NUM_RECS * SIZE_1 * SIZE_2];
+                err = ncmpi_get_var_double(id, Float_id, dbuf); ERR
+
+		/* (void) printf("got vals = %f ... %f\n", dbuf[0], */
+		/* 	 dbuf[NUM_RECS * SIZE_1 * SIZE_2 -1] ); */
+	}
+
+	err = ncmpi_close(id); ERR
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    char filename[256];
+    int rank, nprocs, cmode, err, nerrs=0;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for emulating netCDF t_nc ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    /* test CDF-1 format */
+    cmode = NC_CLOBBER;
+    nerrs += t_nc(filename, cmode);
+
+    /* test CDF-2 format */
+    cmode = NC_CLOBBER | NC_64BIT_OFFSET;
+    nerrs += t_nc(filename, cmode);
+
+    /* test CDF-5 format */
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    nerrs += t_nc(filename, cmode);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/nc_test/test_get.m4 b/test/nc_test/test_get.m4
new file mode 100644
index 0000000..7d91848
--- /dev/null
+++ b/test/nc_test/test_get.m4
@@ -0,0 +1,958 @@
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: test_get.m4 2292 2016-01-04 05:30:45Z wkliao $ */
+
+
+undefine(`index')dnl
+dnl dnl dnl
+dnl
+dnl Macros
+dnl
+dnl dnl dnl
+dnl
+dnl Upcase(str)
+dnl
+define(`Upcase',dnl
+`dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)')dnl
+dnl dnl dnl
+dnl
+dnl NCT_ITYPE(type)
+dnl
+define(`NCT_ITYPE', ``NCT_'Upcase($1)')dnl
+dnl
+
+define(`CheckText', `ifelse(`$1',`text', , `== (NCT_ITYPE($1) == NCT_TEXT)')')dnl
+define(`CheckRange',`ifelse(`$1',`text', `1', `($2 >= $1_min && $2 <= $1_max)')')dnl
+define(`IfCheckTextChar', `ifelse(`$1',`text', `if ($2 != NC_CHAR)')')dnl
+define(`CheckNumRange',
+       `ifelse(`$1',`text', `1',
+               `inRange3($2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl
+
+#include "tests.h"
+
+dnl TEST_NC_GET_VAR1(TYPE)
+dnl
+define(`TEST_NC_GET_VAR1',dnl
+`dnl
+int
+test_ncmpi_get_var1_$1(void)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset index[MAX_RANK];
+    int canConvert;     /* Both text or both numeric */
+    double expect;
+    $1 value;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    ncmpi_begin_indep_data(ncid);
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        for (j = 0; j < var_rank[i]; j++)
+            index[j] = 0;
+
+        /* check if pnetcdf can detect a bad file ID */
+        err = ncmpi_get_var1_$1(BAD_ID, i, index, &value);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+
+        /* check if pnetcdf can detect a bad variable ID */
+        err = ncmpi_get_var1_$1(ncid, BAD_VARID, index, &value);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+
+        /* check if pnetcdf can detect out of boundary requests */
+        for (j = 0; j < var_rank[i]; j++) {
+            index[j] = var_shape[i][j]; /* make an out-of-boundary starts[] */
+            err = ncmpi_get_var1_$1(ncid, i, index, &value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    error("conversion: err = %d", err);
+            } else IF (err != NC_EINVALCOORDS)
+                error("bad index: err = %d", err);
+            index[j] = 0;
+        }
+
+        /* check if the contents are supposed to be */
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR)
+                error("error in toMixedBase 1");
+
+            /* when file is created the variable contents are generated by
+             * hash functions */
+            expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1) );
+
+            if (var_rank[i] == 0 && i%2 )
+                /* this var has no dim, a scalar variable */
+                err = ncmpi_get_var1_$1(ncid, i, NULL, &value);
+            else
+                err = ncmpi_get_var1_$1(ncid, i, index, &value);
+
+            if (canConvert) {
+                if (inRange3(expect,var_type[i], NCT_ITYPE($1))) {
+                    if (CheckRange($1, expect)) {
+                        IF (err != NC_NOERR) {
+                            error("%s", ncmpi_strerror(err));
+                        } else {
+                            IF (!equal(value,expect,var_type[i],NCT_ITYPE($1))) {
+                                error("expected: %G, got: %G", expect, (double) value);
+                            } else {
+                                nok++;
+                            }
+                        }
+                    } else {
+                        IF (err != NC_ERANGE)
+                            error("Range error: err = %d", err);
+                    }
+                } else {
+                    IF (err != NC_NOERR && err != NC_ERANGE)
+                        error("OK or Range error: err = %d", err);
+                }
+            } else {
+                IF (err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+            }
+        }
+    }
+    ncmpi_end_indep_data(ncid);
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+TEST_NC_GET_VAR1(text)
+TEST_NC_GET_VAR1(schar)
+TEST_NC_GET_VAR1(uchar)
+TEST_NC_GET_VAR1(short)
+TEST_NC_GET_VAR1(int)
+TEST_NC_GET_VAR1(long)
+TEST_NC_GET_VAR1(float)
+TEST_NC_GET_VAR1(double)
+TEST_NC_GET_VAR1(ushort)
+TEST_NC_GET_VAR1(uint)
+TEST_NC_GET_VAR1(longlong)
+TEST_NC_GET_VAR1(ulonglong)
+
+
+dnl TEST_NC_GET_VAR(TYPE)
+dnl
+define(`TEST_NC_GET_VAR',dnl
+`dnl
+int
+test_ncmpi_get_var_$1(void)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    int allInExtRange;  /* all values within range of external data type */
+    int allInIntRange;  /* all values within range of internal data type */
+    int nels;
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset index[MAX_RANK];
+    int canConvert;     /* Both text or both numeric */
+    double expect[MAX_NELS];
+    $1 value[MAX_NELS];
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        /* check if pnetcdf can detect a bad file ID */
+        err = ncmpi_get_var_$1_all(BAD_ID, i, value);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+
+        /* check if pnetcdf can detect a bad variable ID */
+        err = ncmpi_get_var_$1_all(ncid, BAD_VARID, value);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+
+        /* check if the contents are supposed to be */
+        nels = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            nels *= var_shape[i][j];
+        }
+        allInExtRange = allInIntRange = 1;
+        for (j = 0; j < nels; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR)
+                error("error in toMixedBase 1");
+            expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+            if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) {
+                IfCheckTextChar($1, var_type[i])
+                    allInIntRange &= CheckRange($1,expect[j]);
+            } else {
+                allInExtRange = 0;
+            }
+        }
+        err = ncmpi_get_var_$1_all(ncid, i, value);
+        if (canConvert) {
+            if (allInExtRange) {
+                if (allInIntRange) {
+                    IF (err != NC_NOERR)
+                        error("(%s) %s", ncmpii_err_code_name(err),ncmpi_strerror(err));
+                } else {
+                    IF (err != NC_ERANGE)
+                        error("Range error: err = %d", err);
+                }
+            } else {
+                IF (err != NC_NOERR && err != NC_ERANGE)
+                    error("OK or Range error: err = %d", err);
+            }
+            for (j = 0; j < nels; j++) {
+                if (CheckNumRange($1, expect[j], var_type[i])) {
+                    IF (!equal(value[j],expect[j],var_type[i],NCT_ITYPE($1))){
+                        error("value read not that expected");
+                        if (verbose) {
+                            error("\n");
+                            error("varid: %d, ", i);
+                            error("var_name: %s, ", var_name[i]);
+                            error("var_type: %s, ", s_nc_type(var_type[i]));
+                            error("element number: %d, ", j);
+                            error("expect: %g, ", expect[j]);
+                            error("got: %g", (double) value[j]);
+                        }
+                    } else {
+                        nok++;
+                    }
+                }
+            }
+        } else {
+            IF (nels > 0 && err != NC_ECHAR)
+                error("wrong type: err = %d", err);
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+TEST_NC_GET_VAR(text)
+TEST_NC_GET_VAR(uchar)
+TEST_NC_GET_VAR(schar)
+TEST_NC_GET_VAR(short)
+TEST_NC_GET_VAR(int)
+TEST_NC_GET_VAR(long)
+TEST_NC_GET_VAR(float)
+TEST_NC_GET_VAR(double)
+TEST_NC_GET_VAR(ushort)
+TEST_NC_GET_VAR(uint)
+TEST_NC_GET_VAR(longlong)
+TEST_NC_GET_VAR(ulonglong)
+
+
+dnl TEST_NC_GET_VARA(TYPE)
+dnl
+define(`TEST_NC_GET_VARA',dnl
+`dnl
+int
+test_ncmpi_get_vara_$1(void)
+{
+    int ncid;
+    int d;
+    int i;
+    int j;
+    int k;
+    int err;
+    int allInExtRange;        /* all values within external range? */
+    int allInIntRange;        /* all values within internal range? */
+    int nels;
+    int nslabs;
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    int canConvert;     /* Both text or both numeric */
+    double expect[MAX_NELS];
+    $1 value[MAX_NELS];
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+        }
+        err = ncmpi_get_vara_$1_all(BAD_ID, i, start, edge, value);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        err = ncmpi_get_vara_$1_all(ncid, BAD_VARID, start, edge, value);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = var_shape[i][j]; /* causes NC_EINVALCOORDS */
+            err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value);
+            IF (canConvert && err != NC_EINVALCOORDS)
+                error("bad index: err = %d", err);
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1; /* causes NC_EEDGE */
+            err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value);
+            IF (canConvert && err != NC_EEDGE)
+                error("bad edge: err = %d", err);
+            edge[j] = 1;
+        }
+        /* Check non-scalars for correct error returned even when */
+        /* there is nothing to get (edge[j]==0) */
+        if (var_rank[i] > 0) {
+            for (j = 0; j < var_rank[i]; j++) {
+                edge[j] = 0;
+            }
+            err = ncmpi_get_vara_$1_all(BAD_ID, i, start, edge, value);
+            IF (err != NC_EBADID) 
+                error("bad ncid: err = %d", err);
+            err = ncmpi_get_vara_$1_all(ncid, BAD_VARID, start, edge, value);
+            IF (err != NC_ENOTVAR) 
+                error("bad var id: err = %d", err);
+            for (j = 0; j < var_rank[i]; j++) {
+                if (var_dimid[i][j] > 0) {                /* skip record dim */
+                    start[j] = var_shape[i][j];
+                    err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value);
+                    IF (canConvert && err != NC_EINVALCOORDS)
+                        error("bad start: err = %d", err);
+                    start[j] = 0;
+                }
+            }
+            err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value);
+            if (canConvert) {
+                IF (err != NC_NOERR) 
+                    error("%s", ncmpi_strerror(err));
+            } else {
+                IF (err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+            }
+            for (j = 0; j < var_rank[i]; j++) {
+                edge[j] = 1;
+            }
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+        for (k = 0; k < nslabs; k++) {
+            nels = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                nels *= edge[j];
+            }
+            allInExtRange = allInIntRange = 1;
+            for (j = 0; j < nels; j++) {
+                err = toMixedBase(j, var_rank[i], edge, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase 1");
+                for (d = 0; d < var_rank[i]; d++)
+                    index[d] += start[d];
+                expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+                if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) {
+		    IfCheckTextChar($1, var_type[i])
+                        allInIntRange &= CheckRange($1,expect[j]);
+                } else {
+                    allInExtRange = 0;
+                }
+            }
+            if (var_rank[i] == 0 && i%2)
+                err = ncmpi_get_vara_$1_all(ncid, i, NULL, NULL, value);
+            else
+                err = ncmpi_get_vara_$1_all(ncid, i, start, edge, value);
+            if (canConvert) {
+                if (allInExtRange) {
+                    if (allInIntRange) {
+                        IF (err != NC_NOERR)
+                            error("%s", ncmpi_strerror(err));
+                    } else {
+                        IF (err != NC_ERANGE)
+                            error("Range error: err = %d", err);
+                    }
+                } else {
+                    IF (err != NC_NOERR && err != NC_ERANGE)
+                        error("OK or Range error: err = %d", err);
+                }
+                for (j = 0; j < nels; j++) {
+                    if (CheckNumRange($1, expect[j], var_type[i])) {
+                        IF (!equal(value[j],expect[j],var_type[i],NCT_ITYPE($1))){
+                            error("value read not that expected");
+                            if (verbose) {
+                                error("\n");
+                                error("varid: %d, ", i);
+                                error("var_name: %s, ", var_name[i]);
+                                error("var_type: %s, ", s_nc_type(var_type[i]));
+                                error("element number: %d, ", j);
+                                error("expect: %g, ", expect[j]);
+                                error("got: %g", (double) value[j]);
+                            }
+                        } else {
+                            nok++;
+                        }
+                    }
+                }
+            } else {
+                IF (nels > 0 && err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+            }
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+TEST_NC_GET_VARA(text)
+TEST_NC_GET_VARA(uchar)
+TEST_NC_GET_VARA(schar)
+TEST_NC_GET_VARA(short)
+TEST_NC_GET_VARA(int)
+TEST_NC_GET_VARA(long)
+TEST_NC_GET_VARA(float)
+TEST_NC_GET_VARA(double)
+TEST_NC_GET_VARA(ushort)
+TEST_NC_GET_VARA(uint)
+TEST_NC_GET_VARA(longlong)
+TEST_NC_GET_VARA(ulonglong)
+
+
+dnl TEST_NC_GET_VARS(TYPE)
+dnl
+define(`TEST_NC_GET_VARS',dnl
+`dnl
+int
+test_ncmpi_get_vars_$1(void)
+{
+    int ncid;
+    int d;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err;
+    int allInExtRange;        /* all values within external range? */
+    int allInIntRange;        /* all values within internal range? */
+    int nels;
+    int nslabs;
+    int nstarts;        /* number of different starts */
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    int canConvert;     /* Both text or both numeric */
+    double expect[MAX_NELS];
+    $1 value[MAX_NELS];
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+        }
+        err = ncmpi_get_vars_$1_all(BAD_ID, i, start, edge, stride, value);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        err = ncmpi_get_vars_$1_all(ncid, BAD_VARID, start, edge, stride, value);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = var_shape[i][j];
+            err = ncmpi_get_vars_$1_all(ncid, i, start, edge, stride, value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    error("conversion: err = %d", err);
+            } else {
+                IF (err != NC_EINVALCOORDS)
+                    error("bad index: err = %d", err);
+                start[j] = 0;
+                edge[j] = var_shape[i][j] + 1;
+                err = ncmpi_get_vars_$1_all(ncid, i, start, edge, stride, value);
+                IF (err != NC_EEDGE)
+                    error("bad edge: err = %d", err);
+                edge[j] = 1;
+                stride[j] = 0;
+                err = ncmpi_get_vars_$1_all(ncid, i, start, edge, stride, value);
+                IF (err != NC_ESTRIDE)
+                    error("bad stride: err = %d", err);
+                stride[j] = 1;
+            }
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+*/
+                allInExtRange = allInIntRange = 1;
+                for (j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != NC_NOERR)
+                        error("error in toMixedBase 1");
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * stride[d];
+                    expect[j] = hash4(var_type[i], var_rank[i], index2, 
+                        NCT_ITYPE($1));
+                    if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) {
+		        IfCheckTextChar($1, var_type[i])
+                            allInIntRange &= CheckRange($1,expect[j]);
+                    } else {
+                        allInExtRange = 0;
+                    }
+                }
+                if (var_rank[i] == 0 && i%2 )
+                    err = ncmpi_get_vars_$1_all(ncid, i, NULL, NULL, NULL, value);
+                else
+                    err = ncmpi_get_vars_$1_all(ncid, i, index, count, stride, value);
+                if (canConvert) {
+                    if (allInExtRange) {
+                        if (allInIntRange) {
+                            IF (err != NC_NOERR)
+                                error("%s", ncmpi_strerror(err));
+                        } else {
+                            IF (err != NC_ERANGE)
+                                error("Range error: err = %d", err);
+                        }
+                    } else {
+                        IF (err != NC_NOERR && err != NC_ERANGE)
+                            error("OK or Range error: err = %d", err);
+                    }
+                    for (j = 0; j < nels; j++) {
+                        if (CheckNumRange($1, expect[j], var_type[i])) {
+                            IF (!equal(value[j],expect[j],var_type[i], NCT_ITYPE($1))){
+                                error("value read not that expected");
+                                if (verbose) {
+                                    error("\n");
+                                    error("varid: %d, ", i);
+                                    error("var_name: %s, ", var_name[i]);
+                                    error("var_type: %s, ", s_nc_type(var_type[i]));
+                                    error("element number: %d, ", j);
+                                    error("expect: %g, ", expect[j]);
+                                    error("got: %g", (double) value[j]);
+                                }
+                            } else {
+                                nok++;
+                            }
+                        }
+                    }
+                } else {
+                    IF (nels > 0 && err != NC_ECHAR)
+                        error("wrong type: err = %d", err);
+                }
+            }
+        }
+
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+TEST_NC_GET_VARS(text)
+TEST_NC_GET_VARS(uchar)
+TEST_NC_GET_VARS(schar)
+TEST_NC_GET_VARS(short)
+TEST_NC_GET_VARS(int)
+TEST_NC_GET_VARS(long)
+TEST_NC_GET_VARS(float)
+TEST_NC_GET_VARS(double)
+TEST_NC_GET_VARS(ushort)
+TEST_NC_GET_VARS(uint)
+TEST_NC_GET_VARS(longlong)
+TEST_NC_GET_VARS(ulonglong)
+
+
+dnl TEST_NC_GET_VARM(TYPE)
+dnl
+define(`TEST_NC_GET_VARM',dnl
+`dnl
+int
+test_ncmpi_get_varm_$1(void)
+{
+    int ncid;
+    int d;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err;
+    int allInExtRange;        /* all values within external range? */
+    int allInIntRange;        /* all values within internal range? */
+    int nels;
+    int nslabs;
+    int nstarts;        /* number of different starts */
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    MPI_Offset imap[MAX_RANK];
+    int canConvert;     /* Both text or both numeric */
+    double expect[MAX_NELS];
+    $1 value[MAX_NELS];
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+            imap[j] = 1;
+        }
+        err = ncmpi_get_varm_$1_all(BAD_ID, i, start, edge, stride, imap, value);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        err = ncmpi_get_varm_$1_all(ncid, BAD_VARID, start, edge, stride, imap, value);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = var_shape[i][j];
+            err = ncmpi_get_varm_$1_all(ncid, i, start, edge, stride, imap, value);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    error("conversion: err = %d", err);
+            } else {
+                IF (err != NC_EINVALCOORDS)
+                    error("bad index: err = %d", err);
+                start[j] = 0;
+                edge[j] = var_shape[i][j] + 1;
+                err = ncmpi_get_varm_$1_all(ncid, i, start, edge, stride, imap, value);
+                IF (err != NC_EEDGE)
+                    error("bad edge: err = %d", err);
+                edge[j] = 1;
+                stride[j] = 0;
+                err = ncmpi_get_varm_$1_all(ncid, i, start, edge, stride, imap, value);
+                IF (err != NC_ESTRIDE)
+                    error("bad stride: err = %d", err);
+                stride[j] = 1;
+            }
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+ */
+                if (var_rank[i] > 0) {
+                    j = var_rank[i] - 1;
+                    imap[j] = 1;
+                    for (; j > 0; j--)
+                        imap[j-1] = imap[j] * count[j];
+                }
+                allInExtRange = allInIntRange = 1;
+                for (j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != NC_NOERR)
+                        error("error in toMixedBase 1");
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * stride[d];
+                    expect[j] = hash4(var_type[i], var_rank[i], index2,
+                        NCT_ITYPE($1));
+                    if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) {
+		        IfCheckTextChar($1, var_type[i])
+                            allInIntRange &= CheckRange($1,expect[j]);
+                    } else {
+                        allInExtRange = 0;
+                    }
+                }
+                if (var_rank[i] == 0 && i%2 )
+                    err = ncmpi_get_varm_$1_all(ncid,i,NULL,NULL,NULL,NULL,value);
+                else
+                    err = ncmpi_get_varm_$1_all(ncid,i,index,count,stride,imap,value);
+                if (canConvert) {
+                    if (allInExtRange) {
+                        if (allInIntRange) {
+                            IF (err != NC_NOERR)
+                                error("%s", ncmpi_strerror(err));
+                        } else {
+                            IF (err != NC_ERANGE)
+                                error("Range error: err = %d", err);
+                        }
+                    } else {
+                        IF (err != NC_NOERR && err != NC_ERANGE)
+                            error("OK or Range error: err = %d", err);
+                    }
+                    for (j = 0; j < nels; j++) {
+                        if (CheckNumRange($1, expect[j], var_type[i])) {
+                            IF (!equal(value[j],expect[j],var_type[i], NCT_ITYPE($1))){
+                                error("value read not that expected");
+                                if (verbose) {
+                                    error("\n");
+                                    error("varid: %d, ", i);
+                                    error("var_name: %s, ", var_name[i]);
+                                    error("var_type: %s, ", s_nc_type(var_type[i]));
+                                    error("element number: %d, ", j);
+                                    error("expect: %g, ", expect[j]);
+                                    error("got: %g", (double) value[j]);
+                                }
+                            } else {
+                                nok++;
+                            }
+                        }
+                    }
+                } else {
+                    IF (nels > 0 && err != NC_ECHAR)
+                        error("wrong type: err = %d", err);
+                }
+            }
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+TEST_NC_GET_VARM(text)
+TEST_NC_GET_VARM(uchar)
+TEST_NC_GET_VARM(schar)
+TEST_NC_GET_VARM(short)
+TEST_NC_GET_VARM(int)
+TEST_NC_GET_VARM(long)
+TEST_NC_GET_VARM(float)
+TEST_NC_GET_VARM(double)
+TEST_NC_GET_VARM(ushort)
+TEST_NC_GET_VARM(uint)
+TEST_NC_GET_VARM(longlong)
+TEST_NC_GET_VARM(ulonglong)
+
+
+dnl TEST_NC_GET_ATT(TYPE)
+dnl
+define(`TEST_NC_GET_ATT',dnl
+`dnl
+int
+test_ncmpi_get_att_$1(void)
+{
+    int ncid;
+    int i;
+    int j;
+    MPI_Offset k;
+    int err;
+    int allInExtRange;
+    int allInIntRange;
+    int canConvert;     /* Both text or both numeric */
+    int nok = 0;        /* count of valid comparisons */
+    double expect[MAX_NELS];
+    $1 value[MAX_NELS];
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = -1; i < numVars; i++) {
+        for (j = 0; j < NATTS(i); j++) {
+            canConvert = (ATT_TYPE(i,j) == NC_CHAR) CheckText($1);
+            err = ncmpi_get_att_$1(BAD_ID, i, ATT_NAME(i,j), value);
+            IF (err != NC_EBADID) 
+                error("bad ncid: err = %d", err);
+            err = ncmpi_get_att_$1(ncid, BAD_VARID, ATT_NAME(i,j), value);
+            IF (err != NC_ENOTVAR) 
+                error("bad var id: err = %d", err);
+            err = ncmpi_get_att_$1(ncid, i, "noSuch", value);
+            IF (err != NC_ENOTATT) 
+                error("Bad attribute name: err = %d", err);
+            allInExtRange = allInIntRange = 1;
+            for (k = 0; k < ATT_LEN(i,j); k++) {
+                expect[k] = hash4(ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1));
+                if (inRange3(expect[k],ATT_TYPE(i,j),NCT_ITYPE($1))) {
+		    /* netCDF specification make a special case for type
+		     * conversion between uchar and scahr: do not check for
+		     * range error. See
+		     * http://www.unidata.ucar.edu/software/netcdf/docs_rc/data_type.html#type_conversion
+                     */
+		    IfCheckTextChar($1, ATT_TYPE(i,j))
+		    ifelse(`$1',`uchar', `if (ATT_TYPE(i,j) != NC_BYTE)')
+                        allInIntRange &= CheckRange($1,expect[k]);
+                } else {
+                    allInExtRange = 0;
+                }
+            }
+            err = ncmpi_get_att_$1(ncid, i, ATT_NAME(i,j), value);
+            if (canConvert || ATT_LEN(i,j) == 0) {
+                if (allInExtRange) {
+                    if (allInIntRange) {
+                        IF (err != NC_NOERR)
+                            error("%s", ncmpi_strerror(err));
+                    } else {
+                        IF (err != NC_ERANGE)
+                            error("Range error: err = %d", err);
+                    }
+                } else {
+                    IF (err != NC_NOERR && err != NC_ERANGE)
+                        error("OK or Range error: err = %d", err);
+                }
+                for (k = 0; k < ATT_LEN(i,j); k++) {
+                    if (CheckNumRange($1, expect[k], ATT_TYPE(i,j))) {
+                        IF (!equal(value[k],expect[k],ATT_TYPE(i,j), NCT_ITYPE($1))){
+                            error("value read not that expected");
+                            if (verbose) {
+                                error("\n");
+                                error("varid: %d, ", i);
+                                error("att_name: %s, ", ATT_NAME(i,j));
+                                error("var_type: %s, ", s_nc_type(var_type[i]));
+                                error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
+                                error("element number: %d, ", k);
+                                error("expect: %g, ", expect[k]);
+                                error("got: %g", (double) value[k]);
+                            }
+                        } else {
+                            nok++;
+                        }
+                    }
+                }
+            } else {
+                IF (err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+TEST_NC_GET_ATT(text)
+TEST_NC_GET_ATT(uchar)
+TEST_NC_GET_ATT(schar)
+TEST_NC_GET_ATT(short)
+TEST_NC_GET_ATT(int)
+TEST_NC_GET_ATT(long)
+TEST_NC_GET_ATT(float)
+TEST_NC_GET_ATT(double)
+TEST_NC_GET_ATT(ushort)
+TEST_NC_GET_ATT(uint)
+TEST_NC_GET_ATT(longlong)
+TEST_NC_GET_ATT(ulonglong)
+
diff --git a/test/nc_test/test_iget.m4 b/test/nc_test/test_iget.m4
new file mode 100644
index 0000000..d54a30b
--- /dev/null
+++ b/test/nc_test/test_iget.m4
@@ -0,0 +1,1547 @@
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: test_iget.m4 2293 2016-01-06 03:43:04Z wkliao $ */
+
+
+undefine(`index')dnl
+dnl dnl dnl
+dnl
+dnl Macros
+dnl
+dnl dnl dnl
+dnl
+dnl Upcase(str)
+dnl
+define(`Upcase',dnl
+`dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)')dnl
+dnl dnl dnl
+dnl
+dnl NCT_ITYPE(type)
+dnl
+define(`NCT_ITYPE', ``NCT_'Upcase($1)')dnl
+dnl
+
+define(`CheckText', `ifelse(`$1',`text', , `== (NCT_ITYPE($1) == NCT_TEXT)')')dnl
+define(`CheckRange',`ifelse(`$1',`text', `1', `($2 >= $1_min && $2 <= $1_max)')')dnl
+define(`IfCheckTextChar', `ifelse(`$1',`text', `if ($2 != NC_CHAR)')')dnl
+define(`CheckNumRange',
+       `ifelse(`$1',`text', `1',
+               `inRange3($2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl
+
+#include "tests.h"
+
+int
+test_ncmpi_iget_var1(void)
+{
+    int i, j, err, ncid, nok = 0; /* count of valid comparisons */
+    MPI_Offset index[MAX_RANK];
+    double expect, value, buf[1];
+    int reqid, status;
+    MPI_Datatype datatype;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        for (j = 0; j < var_rank[i]; j++) index[j] = 0;
+        datatype = nc_mpi_type(var_type[i]);
+
+        /* check if pnetcdf can detect a bad file ID */
+        err = ncmpi_iget_var1(BAD_ID, i, index, buf, 1, datatype, &reqid);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iget_var1(ncid, BAD_VARID, index, buf, 1, datatype, &reqid);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        /* check if pnetcdf can detect out of boundary requests */
+        for (j = 0; j < var_rank[i]; j++) {
+            index[j] = var_shape[i][j]; /* make an out-of-boundary starts[] */
+            err = ncmpi_iget_var1(ncid, i, index, buf, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                error("bad index: err = %d", err);
+            ELSE_NOK
+            index[j] = 0;
+        }
+        /* check if the contents are supposed to be */
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR)
+                error("error in toMixedBase 1");
+
+            /* when file is created the variable contents are generated by
+             * hash functions */
+            expect = hash(var_type[i], var_rank[i], index);
+            if (var_rank[i] == 0 && i%2 )
+                err = ncmpi_iget_var1(ncid, i, NULL, buf, 1, datatype, &reqid);
+            else
+                err = ncmpi_iget_var1(ncid, i, index, buf, 1, datatype, &reqid);
+            IF (err != NC_NOERR)
+                error("ncmpi_iget_var: %s", ncmpi_strerror(err));
+            ELSE_NOK
+
+            err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+            IF (err != NC_NOERR)
+                error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+            ELSE_NOK
+
+            err = nc2dbl( var_type[i], buf, &value );
+            IF (err)
+                error("error in nc2dbl");
+            if (inRange(expect,var_type[i])) {
+                IF (!equal2(value,expect,var_type[i])) {
+                    error("expected: %G, got: %G", expect, value);
+                } else {
+                    nok++;
+                }   
+            }
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+dnl TEST_NC_IGET_VAR1(TYPE)
+dnl
+define(`TEST_NC_IGET_VAR1',dnl
+`dnl
+int
+test_ncmpi_iget_var1_$1(void)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset index[MAX_RANK];
+    int canConvert;     /* Both text or both numeric */
+    double expect;
+    $1 value;
+    int reqid, status;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        for (j = 0; j < var_rank[i]; j++)
+            index[j] = 0;
+
+        /* check if pnetcdf can detect a bad file ID */
+        err = ncmpi_iget_var1_$1(BAD_ID, i, index, &value, &reqid);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iget_var1_$1(ncid, BAD_VARID, index, &value, &reqid);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        /* check if pnetcdf can detect out of boundary requests */
+        for (j = 0; j < var_rank[i]; j++) {
+            index[j] = var_shape[i][j]; /* make an out-of-boundary starts[] */
+            err = ncmpi_iget_var1_$1(ncid, i, index, &value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    error("conversion: err = %d", err);
+            } else IF (err != NC_EINVALCOORDS)
+                error("bad index: err = %d", err);
+            ELSE_NOK
+            index[j] = 0;
+        }
+        /* check if the contents are supposed to be */
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR)
+                error("error in toMixedBase 1");
+
+            /* when file is created the variable contents are generated by
+             * hash functions */
+            expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1) );
+
+            if (var_rank[i] == 0 && i%2 )
+                err = ncmpi_iget_var1_$1(ncid, i, NULL, &value, &reqid);
+            else
+                err = ncmpi_iget_var1_$1(ncid, i, index, &value, &reqid);
+            if (err == NC_NOERR)
+                ncmpi_wait_all(ncid, 1, &reqid, &status);
+
+            if (canConvert) {
+                if (inRange3(expect,var_type[i], NCT_ITYPE($1))) {
+                    if (CheckRange($1, expect)) {
+                        IF (status != NC_NOERR) {
+                            error("%s", ncmpi_strerror(status));
+                        } else {
+                            IF (!equal(value,expect,var_type[i],NCT_ITYPE($1)))
+                                error("expected: %G, got: %G", expect,
+                                    (double) value);
+                            ELSE_NOK
+                        }
+                    } else {
+                        IF (status != NC_ERANGE)
+                            error("Range error: status = %d", status);
+                        ELSE_NOK
+                    }
+                } else {
+                    IF (status != NC_NOERR && status != NC_ERANGE)
+                        error("OK or Range error: status = %d", status);
+                    ELSE_NOK
+                }
+            } else {
+                IF (err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+                ELSE_NOK
+            }
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+TEST_NC_IGET_VAR1(text)
+TEST_NC_IGET_VAR1(uchar)
+TEST_NC_IGET_VAR1(schar)
+TEST_NC_IGET_VAR1(short)
+TEST_NC_IGET_VAR1(int)
+TEST_NC_IGET_VAR1(long)
+TEST_NC_IGET_VAR1(float)
+TEST_NC_IGET_VAR1(double)
+TEST_NC_IGET_VAR1(ushort)
+TEST_NC_IGET_VAR1(uint)
+TEST_NC_IGET_VAR1(longlong)
+TEST_NC_IGET_VAR1(ulonglong)
+
+int
+test_ncmpi_iget_var(void)
+{
+    int ncid;
+    int i;
+    int j;
+    int err, num_err;
+    int nels;
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset index[MAX_RANK];
+    double expect[MAX_NELS];
+    double buf[MAX_NELS];
+    int reqid, status;
+    MPI_Datatype datatype;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        /* check if pnetcdf can detect a bad file ID */
+        err = ncmpi_iget_var(BAD_ID, i, buf, 1, datatype, &reqid);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        /* check if pnetcdf can detect a bad variable ID */
+        err = ncmpi_iget_var(ncid, BAD_VARID, buf, 1, datatype, &reqid);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+
+        /* check if the contents are supposed to be */
+        nels = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            nels *= var_shape[i][j];
+        }
+        for (j = 0; j < nels; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR)
+                error("error in toMixedBase 1");
+            expect[j] = hash(var_type[i], var_rank[i], index);
+        }
+        err = ncmpi_iget_var(ncid, i, buf, nels, datatype, &reqid);
+        IF (err != NC_NOERR)
+            error("ncmpi_iget_var: %s", ncmpi_strerror(err));
+        ELSE_NOK
+
+        err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+        IF (err != NC_NOERR)
+            error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+        ELSE_NOK
+
+        num_err = 0;
+        for (j = 0; j < nels; j++) {
+            double got;
+            char *p = (char *) buf;
+            p += j * nctypelen(var_type[i]);
+            if (inRange(expect[j],var_type[i])) {
+                err = nc2dbl(var_type[i], p, &got);
+                IF (err != NC_NOERR)
+                    error("error in nc2dbl");
+                IF (!equal2(got,expect[j],var_type[i])) {
+                    error("value read not that expected");
+                    if (verbose) {
+                        error("\n");
+                        error("varid: %d, ", i);
+                        error("var_name: %s, ", var_name[i]);
+                        error("element number: %d ", j);
+                        error("expect: %g", expect[j]);
+                        error("got: %g", got);
+                    }
+                    num_err++;
+                }
+            }
+            if (num_err == 0) nok++;
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+dnl TEST_NC_IGET_VAR(TYPE)
+dnl
+define(`TEST_NC_IGET_VAR',dnl
+`dnl
+int
+test_ncmpi_iget_var_$1(void)
+{
+    int ncid;
+    int i;
+    int j;
+    int err, num_err;
+    int allInExtRange;        /* all values within external range? */
+    int allInIntRange;        /* all values within internal range? */
+    int nels;
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset index[MAX_RANK];
+    int canConvert;     /* Both text or both numeric */
+    double expect[MAX_NELS];
+    $1 value[MAX_NELS];
+    int reqid, status;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+
+        /* check if pnetcdf can detect a bad file ID */
+        err = ncmpi_iget_var_$1(BAD_ID, i, value, &reqid);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        /* check if pnetcdf can detect a bad variable ID */
+        err = ncmpi_iget_var_$1(ncid, BAD_VARID, value, &reqid);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+
+        /* check if the contents are supposed to be */
+        nels = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            nels *= var_shape[i][j];
+        }
+        allInExtRange = allInIntRange = 1;
+        for (j = 0; j < nels; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR)
+                error("error in toMixedBase 1");
+            expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+            if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) {
+                IfCheckTextChar($1, var_type[i])
+                    allInIntRange &= CheckRange($1, expect[j]);
+            } else {
+                allInExtRange = 0;
+            }
+        }
+        err = ncmpi_iget_var_$1(ncid, i, value, &reqid);
+        if (err == NC_NOERR)
+            ncmpi_wait_all(ncid, 1, &reqid, &status);
+        ELSE_NOK
+        if (canConvert) {
+            if (allInExtRange) {
+                if (allInIntRange) {
+                    IF (status != NC_NOERR)
+                        error("%s", ncmpi_strerror(status));
+                    ELSE_NOK
+                } else {
+                    IF (status != NC_ERANGE)
+                        error("Range error: status = %d", status);
+                    ELSE_NOK
+                }
+            } else {
+                IF (status != NC_NOERR && status != NC_ERANGE)
+                    error("OK or Range error: status = %d", status);
+                ELSE_NOK
+            }
+            num_err = 0;
+            for (j = 0; j < nels; j++) {
+                if (CheckNumRange($1, expect[j], var_type[i])) {
+                    IF (!equal(value[j],expect[j],var_type[i],NCT_ITYPE($1))){
+                        error("value read not that expected");
+                        if (verbose) {
+                            error("\n");
+                            error("varid: %d, ", i);
+                            error("var_name: %s, ", var_name[i]);
+                            error("element number: %d ", j);
+                            error("expect: %g", expect[j]);
+                            error("got: %g", (double) value[j]);
+                        }
+                        num_err++;
+                    }
+                }
+            }
+            if (num_err == 0) nok++;
+        } else {
+            IF (nels > 0 && err != NC_ECHAR)
+                error("wrong type: err = %d", err);
+            ELSE_NOK
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+TEST_NC_IGET_VAR(text)
+TEST_NC_IGET_VAR(uchar)
+TEST_NC_IGET_VAR(schar)
+TEST_NC_IGET_VAR(short)
+TEST_NC_IGET_VAR(int)
+TEST_NC_IGET_VAR(long)
+TEST_NC_IGET_VAR(float)
+TEST_NC_IGET_VAR(double)
+TEST_NC_IGET_VAR(ushort)
+TEST_NC_IGET_VAR(uint)
+TEST_NC_IGET_VAR(longlong)
+TEST_NC_IGET_VAR(ulonglong)
+
+
+int
+test_ncmpi_iget_vara(void)
+{
+    int ncid, d, i, j, k, err, num_err, nels, nslabs;
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Datatype datatype;
+    double buf[MAX_NELS];
+    double expect[MAX_NELS];
+    int reqid, status;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+        }
+        err = ncmpi_iget_vara(BAD_ID, i, start, edge, buf, 1, datatype, &reqid);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iget_vara(ncid, BAD_VARID, start, edge, buf, 1, datatype, &reqid);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = var_shape[i][j];  /* out of boundary check */
+            err = ncmpi_iget_vara(ncid, i, start, edge, buf, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                error("bad index: err = %d", err);
+            ELSE_NOK
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = ncmpi_iget_vara(ncid, i, start, edge, buf, 1, datatype, &reqid);
+            IF (err != NC_EEDGE)
+                error("bad index/edge: err = %d", err);
+            ELSE_NOK
+            edge[j] = 1;
+        }
+        /* Check non-scalars for correct error returned even when */
+        /* there is nothing to get (edge[j]==0) */
+        if (var_rank[i] > 0) {
+            for (j = 0; j < var_rank[i]; j++)
+                edge[j] = 0;
+            err = ncmpi_iget_vara(BAD_ID, i, start, edge, buf, 1, datatype, &reqid);
+            IF (err != NC_EBADID) 
+                error("bad ncid: err = %d", err);
+            ELSE_NOK
+            err = ncmpi_iget_vara(ncid, BAD_VARID, start, edge, buf, 1, datatype, &reqid);
+            IF (err != NC_ENOTVAR) 
+                error("bad var id: err = %d", err);
+            ELSE_NOK
+            for (j = 0; j < var_rank[i]; j++) {
+                if (var_dimid[i][j] > 0) {                /* skip record dim */
+                    start[j] = var_shape[i][j];     /* out of boundary check */
+                    err = ncmpi_iget_vara(ncid, i, start, edge, buf, 1, datatype, &reqid);
+                    IF (err != NC_EINVALCOORDS)
+                        error("bad start: err = %d", err);
+                    ELSE_NOK
+                    start[j] = 0;
+                }
+            }
+            for (j = 0; j < var_rank[i]; j++)
+                edge[j] = 1;
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+        for (k = 0; k < nslabs; k++) {
+            nels = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                nels *= edge[j];
+            }
+            for (j = 0; j < nels; j++) {
+                err = toMixedBase(j, var_rank[i], edge, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase 1");
+                for (d = 0; d < var_rank[i]; d++)
+                    index[d] += start[d];
+                expect[j] = hash(var_type[i], var_rank[i], index);
+            }
+            if (var_rank[i] == 0 && i%2)
+                err = ncmpi_iget_vara(ncid, i, NULL, NULL, buf, 1, datatype, &reqid);
+            else
+                err = ncmpi_iget_vara(ncid, i, start, edge, buf, nels, datatype, &reqid);
+            IF (err != NC_NOERR)
+                error("ncmpi_iget_vara %s", ncmpi_strerror(err));
+            ELSE_NOK
+
+            err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+            IF (err != NC_NOERR)
+                error("ncmpi_wait_all %s", ncmpi_strerror(err));
+            ELSE_NOK
+
+            num_err = 0;
+            for (j = 0; j < nels; j++) {
+                double got;
+                char *p = (char *) buf;
+                p += j * nctypelen(var_type[i]);
+                if (inRange(expect[j],var_type[i])) {
+                    err = nc2dbl(var_type[i], p, &got);
+                    IF (err != NC_NOERR)
+                        error("error in nc2dbl");
+                    IF (!equal2(got,expect[j],var_type[i])) {
+                        error("value read not that expected");
+                        if (verbose) {
+                            error("\n");
+                            error("varid: %d, ", i);
+                            error("var_name: %s, ", var_name[i]);
+                            error("element number: %d ", j);
+                            error("expect: %g", expect[j]);
+                            error("got: %g", got);
+                        }
+                        num_err++;
+                    }
+                }
+                if (num_err == 0) nok++;
+            }
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+dnl TEST_NC_IGET_VARA(TYPE)
+dnl
+define(`TEST_NC_IGET_VARA',dnl
+`dnl
+int
+test_ncmpi_iget_vara_$1(void)
+{
+    int ncid;
+    int d;
+    int i;
+    int j;
+    int k;
+    int err, num_err;
+    int allInExtRange;        /* all values within external range? */
+    int allInIntRange;        /* all values within internal range? */
+    int nels;
+    int nslabs;
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    int canConvert;     /* Both text or both numeric */
+    double expect[MAX_NELS];
+    $1 value[MAX_NELS];
+    int reqid, status;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+        }
+        err = ncmpi_iget_vara_$1(BAD_ID, i, start, edge, value, &reqid);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iget_vara_$1(ncid, BAD_VARID, start, edge, value, &reqid);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = var_shape[i][j];  /* out of boundary check */
+            err = ncmpi_iget_vara_$1(ncid, i, start, edge, value, &reqid);
+            IF (canConvert && err != NC_EINVALCOORDS)
+                error("bad index: err = %d", err);
+            ELSE_NOK
+            if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = ncmpi_iget_vara_$1(ncid, i, start, edge, value, &reqid);
+            IF (canConvert && err != NC_EEDGE)
+                error("bad index/edge: err = %d", err);
+            ELSE_NOK
+            if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
+            edge[j] = 1;
+        }
+        /* Check non-scalars for correct error returned even when */
+        /* there is nothing to get (edge[j]==0) */
+        if (var_rank[i] > 0) {
+            for (j = 0; j < var_rank[i]; j++) {
+                edge[j] = 0;
+            }
+            err = ncmpi_iget_vara_$1(BAD_ID, i, start, edge, value, &reqid);
+            IF (err != NC_EBADID) 
+                error("bad ncid: err = %d", err);
+            ELSE_NOK
+            err = ncmpi_iget_vara_$1(ncid, BAD_VARID, start, edge, value, &reqid);
+            IF (err != NC_ENOTVAR) 
+                error("bad var id: err = %d", err);
+            ELSE_NOK
+            for (j = 0; j < var_rank[i]; j++) {
+                if (var_dimid[i][j] > 0) {                /* skip record dim */
+                    start[j] = var_shape[i][j];     /* out of boundary check */
+                    err = ncmpi_iget_vara_$1(ncid, i, start, edge, value, &reqid);
+                    IF (canConvert && err != NC_EINVALCOORDS)
+                        error("bad start: err = %d", err);
+                    ELSE_NOK
+                    if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
+                    start[j] = 0;
+                }
+            }
+            err = ncmpi_iget_vara_$1(ncid, i, start, edge, value, &reqid);
+            if (canConvert) {
+                IF (err != NC_NOERR)
+                    error("Error: ncmpi_iget_vara_$1 %s",ncmpi_strerror(err));
+            } else {
+                IF (err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+                ELSE_NOK
+            }
+            if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
+            for (j = 0; j < var_rank[i]; j++) {
+                edge[j] = 1;
+            }
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+        for (k = 0; k < nslabs; k++) {
+            nels = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                nels *= edge[j];
+            }
+            allInExtRange = allInIntRange = 1;
+            for (j = 0; j < nels; j++) {
+                err = toMixedBase(j, var_rank[i], edge, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase 1");
+                for (d = 0; d < var_rank[i]; d++)
+                    index[d] += start[d];
+                expect[j] = hash4(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+                if (inRange3(expect[j],var_type[i], NCT_ITYPE($1))) {
+                    IfCheckTextChar($1, var_type[i])
+                        allInIntRange &= CheckRange($1, expect[j]);
+                } else {
+                    allInExtRange = 0;
+                }
+            }
+            if (var_rank[i] == 0 && i%2)
+                err = ncmpi_iget_vara_$1(ncid, i, NULL, NULL, value, &reqid);
+            else
+                err = ncmpi_iget_vara_$1(ncid, i, start, edge, value, &reqid);
+            if (err == NC_NOERR)
+                ncmpi_wait_all(ncid, 1, &reqid, &status);
+            if (canConvert) {
+                if (allInExtRange) {
+                    if (allInIntRange) {
+                        IF (status != NC_NOERR)
+                            error("%s", ncmpi_strerror(status));
+                        ELSE_NOK
+                    } else {
+                        IF (status != NC_ERANGE)
+                            error("Range error: status = %d", status);
+                        ELSE_NOK
+                    }
+                } else {
+                    IF (status != NC_NOERR && status != NC_ERANGE)
+                        error("OK or Range error: status = %d", status);
+                    ELSE_NOK
+                }
+                num_err = 0;
+                for (j = 0; j < nels; j++) {
+                    if (CheckNumRange($1, expect[j], var_type[i])) {
+                        IF (!equal(value[j],expect[j],var_type[i],NCT_ITYPE($1))){
+                            error("value read not that expected");
+                            if (verbose) {
+                                error("\n");
+                                error("varid: %d, ", i);
+                                error("var_name: %s, ", var_name[i]);
+                                error("element number: %d ", j);
+                                error("expect: %g", expect[j]);
+                                error("got: %g", (double) value[j]);
+                            }
+                            num_err++;
+                        }
+                    }
+                }
+                if (num_err == 0) nok++;
+            } else {
+                IF (nels > 0 && err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+                ELSE_NOK
+            }
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+TEST_NC_IGET_VARA(text)
+TEST_NC_IGET_VARA(uchar)
+TEST_NC_IGET_VARA(schar)
+TEST_NC_IGET_VARA(short)
+TEST_NC_IGET_VARA(int)
+TEST_NC_IGET_VARA(long)
+TEST_NC_IGET_VARA(float)
+TEST_NC_IGET_VARA(double)
+TEST_NC_IGET_VARA(ushort)
+TEST_NC_IGET_VARA(uint)
+TEST_NC_IGET_VARA(longlong)
+TEST_NC_IGET_VARA(ulonglong)
+
+int
+test_ncmpi_iget_vars(void)
+{
+    int ncid;
+    int d;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err, num_err;
+    int nels;
+    int nslabs;
+    int nstarts;        /* number of different starts */
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    double buf[MAX_NELS];
+    double expect[MAX_NELS];
+    int reqid, status;
+    MPI_Datatype datatype;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+        }
+        err = ncmpi_iget_vars(BAD_ID, i, start, edge, stride, buf, 1, datatype, &reqid);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iget_vars(ncid, BAD_VARID, start, edge, stride, buf, 1, datatype, &reqid);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = var_shape[i][j];    /* out of boundary check */
+            err = ncmpi_iget_vars(ncid, i, start, edge, stride, buf, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                error("bad index: err = %d", err);
+            ELSE_NOK
+
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = ncmpi_iget_vars(ncid, i, start, edge, stride, buf, 1, datatype, &reqid);
+            IF (err != NC_EEDGE)
+                error("bad edge: err = %d", err);
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;
+            err = ncmpi_iget_vars(ncid, i, start, edge, stride, buf, 1, datatype, &reqid);
+            IF (err != NC_ESTRIDE)
+                error("bad stride: err = %d", err);
+            ELSE_NOK
+            stride[j] = 1;
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                ELSE_NOK
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+*/
+                for (j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != NC_NOERR)
+                        error("error in toMixedBase 1");
+                    ELSE_NOK
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * stride[d];
+                    expect[j] = hash(var_type[i], var_rank[i], index2);
+                }
+                if (var_rank[i] == 0 && i%2 )
+                    err = ncmpi_iget_vars(ncid, i, NULL, NULL, NULL, buf, 1, datatype, &reqid);
+                else
+                    err = ncmpi_iget_vars(ncid, i, index, count, stride, buf, nels, datatype, &reqid);
+                IF (err != NC_NOERR)
+                    error("%s", ncmpi_strerror(err));
+                ELSE_NOK
+
+                err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+                IF (err != NC_NOERR)
+                    error("%s", ncmpi_strerror(err));
+                ELSE_NOK
+
+                num_err = 0;
+                for (j = 0; j < nels; j++) {
+                    double got;
+                    char *p = (char *) buf;
+                    p += j * nctypelen(var_type[i]);
+                    if (inRange(expect[j],var_type[i])) {
+                        err = nc2dbl(var_type[i], p, &got);
+                        IF (err != NC_NOERR)
+                            error("error in nc2dbl");
+                        IF (!equal2(got,expect[j],var_type[i])) {
+                            error("value read not that expected");
+                            if (verbose) {
+                                error("\n");
+                                error("varid: %d, ", i);
+                                error("var_name: %s, ", var_name[i]);
+                                error("element number: %d ", j);
+                                error("expect: %g, ", expect[j]);
+                                error("got: %g", got);
+                            }
+                            num_err++;
+                        }
+                    }
+                }
+                if (num_err == 0) nok++;
+            }
+        }
+
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+dnl TEST_NC_IGET_VARS(TYPE)
+dnl
+define(`TEST_NC_IGET_VARS',dnl
+`dnl
+int
+test_ncmpi_iget_vars_$1(void)
+{
+    int ncid;
+    int d;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err, num_err;
+    int allInExtRange;        /* all values within external range? */
+    int allInIntRange;        /* all values within internal range? */
+    int nels;
+    int nslabs;
+    int nstarts;        /* number of different starts */
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    int canConvert;     /* Both text or both numeric */
+    double expect[MAX_NELS];
+    $1 value[MAX_NELS];
+    int reqid, status;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+        }
+        err = ncmpi_iget_vars_$1(BAD_ID, i, start, edge, stride, value, &reqid);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iget_vars_$1(ncid, BAD_VARID, start, edge, stride, value, &reqid);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = var_shape[i][j];    /* out of boundary check */
+            err = ncmpi_iget_vars_$1(ncid, i, start, edge, stride, value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    error("conversion: err = %d", err);
+            } else {
+                IF (err != NC_EINVALCOORDS)
+                    error("bad index: err = %d", err);
+                ELSE_NOK
+
+                start[j] = 0;
+                edge[j] = var_shape[i][j] + 1;  /* edge error check */
+                err = ncmpi_iget_vars_$1(ncid, i, start, edge, stride, value, &reqid);
+                IF (err != NC_EEDGE)
+                    error("bad edge: err = %d", err);
+                ELSE_NOK
+                edge[j] = 1;
+                stride[j] = 0;
+                err = ncmpi_iget_vars_$1(ncid, i, start, edge, stride, value, &reqid);
+                IF (err != NC_ESTRIDE)
+                    error("bad stride: err = %d", err);
+                ELSE_NOK
+                stride[j] = 1;
+            }
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                ELSE_NOK
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+*/
+                allInExtRange = allInIntRange = 1;
+                for (j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != NC_NOERR)
+                        error("error in toMixedBase 1");
+                    ELSE_NOK
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * stride[d];
+                    expect[j] = hash4(var_type[i], var_rank[i], index2, 
+                        NCT_ITYPE($1));
+                    if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) {
+                        IfCheckTextChar($1, var_type[i])
+                            allInIntRange &= CheckRange($1, expect[j]);
+                    } else {
+                        allInExtRange = 0;
+                    }
+                }
+                if (var_rank[i] == 0 && i%2 )
+                    err = ncmpi_iget_vars_$1(ncid, i, NULL, NULL, NULL, value, &reqid);
+                else
+                    err = ncmpi_iget_vars_$1(ncid, i, index, count, stride, value, &reqid);
+                if (err == NC_NOERR)
+                    ncmpi_wait_all(ncid, 1, &reqid, &status);
+                if (canConvert) {
+                    if (allInExtRange) {
+                        if (allInIntRange) {
+                            IF (status != NC_NOERR)
+                                error("%s", ncmpi_strerror(status));
+                            ELSE_NOK
+                        } else {
+                            IF (status != NC_ERANGE)
+                                error("Range error: status = %d", status);
+                            ELSE_NOK
+                        }
+                    } else {
+                        IF (status != NC_NOERR && status != NC_ERANGE)
+                            error("OK or Range error: status = %d", status);
+                        ELSE_NOK
+                    }
+                    num_err = 0;
+                    for (j = 0; j < nels; j++) {
+                        if (CheckNumRange($1, expect[j], var_type[i])) {
+                            IF (!equal(value[j],expect[j],var_type[i], NCT_ITYPE($1))){
+                                error("value read not that expected");
+                                if (verbose) {
+                                    error("\n");
+                                    error("varid: %d, ", i);
+                                    error("var_name: %s, ", var_name[i]);
+                                    error("element number: %d ", j);
+                                    error("expect: %g, ", expect[j]);
+                                    error("got: %g", (double) value[j]);
+                                }
+                                num_err++;
+                            }
+                        }
+                    }
+                    if (num_err == 0) nok++;
+                } else {
+                    IF (nels > 0 && err != NC_ECHAR)
+                        error("wrong type: err = %d", err);
+                    ELSE_NOK
+                }
+            }
+        }
+
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+TEST_NC_IGET_VARS(text)
+TEST_NC_IGET_VARS(uchar)
+TEST_NC_IGET_VARS(schar)
+TEST_NC_IGET_VARS(short)
+TEST_NC_IGET_VARS(int)
+TEST_NC_IGET_VARS(long)
+TEST_NC_IGET_VARS(float)
+TEST_NC_IGET_VARS(double)
+TEST_NC_IGET_VARS(ushort)
+TEST_NC_IGET_VARS(uint)
+TEST_NC_IGET_VARS(longlong)
+TEST_NC_IGET_VARS(ulonglong)
+
+int
+test_ncmpi_iget_varm(void)
+{
+    int ncid;
+    int d;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err, num_err;
+    int nels;
+    int nslabs;
+    int nstarts;        /* number of different starts */
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    MPI_Offset imap[MAX_RANK];
+    double buf[MAX_NELS], expect[MAX_NELS];
+    int reqid, status;
+    MPI_Datatype datatype;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+            imap[j] = 1;
+        }
+        err = ncmpi_iget_varm(BAD_ID, i, start, edge, stride, imap, buf, 1, datatype, &reqid);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iget_varm(ncid, BAD_VARID, start, edge, stride, imap, buf, 1, datatype, &reqid);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = var_shape[i][j];    /* out of boundary check */
+            err = ncmpi_iget_varm(ncid, i, start, edge, stride, imap, buf, 1, datatype, &reqid);
+            IF (err != NC_EINVALCOORDS)
+                error("bad index: err = %d", err);
+            ELSE_NOK
+
+            start[j] = 0;
+            edge[j] = var_shape[i][j] + 1;  /* edge error check */
+            err = ncmpi_iget_varm(ncid, i, start, edge, stride, imap, buf, 1, datatype, &reqid);
+            IF (err != NC_EEDGE)
+                error("bad edge: err = %d", err);
+            ELSE_NOK
+            edge[j] = 1;
+            stride[j] = 0;
+            err = ncmpi_iget_varm(ncid, i, start, edge, stride, imap, buf, 1, datatype, &reqid);
+            IF (err != NC_ESTRIDE)
+                error("bad stride: err = %d", err);
+            ELSE_NOK
+            stride[j] = 1;
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                ELSE_NOK
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    index[j] += start[j];
+                    nels *= count[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+ */
+                if (var_rank[i] > 0) {
+                    j = var_rank[i] - 1;
+                    imap[j] = 1;
+                    for (; j > 0; j--)
+                        imap[j-1] = imap[j] * count[j];
+                }
+                for (j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != NC_NOERR)
+                        error("error in toMixedBase 1");
+                    ELSE_NOK
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * stride[d];
+                    expect[j] = hash(var_type[i], var_rank[i], index2);
+                }
+                if (var_rank[i] == 0 && i%2 )
+                    err = ncmpi_iget_varm(ncid,i,NULL,NULL,NULL,NULL,buf, 1, datatype, &reqid);
+                else
+                    err = ncmpi_iget_varm(ncid,i,index,count,stride,imap,buf, nels, datatype, &reqid);
+                IF (err != NC_NOERR)
+                    error("%s", ncmpi_strerror(err));
+                ELSE_NOK
+
+                err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+                IF (err != NC_NOERR)
+                    error("%s", ncmpi_strerror(err));
+                ELSE_NOK
+
+                num_err = 0;
+                for (j = 0; j < nels; j++) {
+                    double got;
+                    char *p = (char *) buf;
+                    p += j * nctypelen(var_type[i]);
+                    if (inRange(expect[j],var_type[i])) {
+                        err = nc2dbl(var_type[i], p, &got);
+                        IF (err != NC_NOERR)
+                            error("error in nc2dbl");
+                        IF (!equal2(got,expect[j],var_type[i])) {
+                            error("value read not that expected");
+                            if (verbose) {
+                                error("\n");
+                                error("varid: %d, ", i);
+                                error("var_name: %s, ", var_name[i]);
+                                error("element number: %d ", j);
+                                error("expect: %g, ", expect[j]);
+                                error("got: %g", got);
+                            }
+                            num_err++;
+                        }
+                    }
+                    if (num_err == 0) nok++;
+                }
+            }
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+dnl TEST_NC_IGET_VARM(TYPE)
+dnl
+define(`TEST_NC_IGET_VARM',dnl
+`dnl
+int
+test_ncmpi_iget_varm_$1(void)
+{
+    int ncid;
+    int d;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err, num_err;
+    int allInExtRange;        /* all values within external range? */
+    int allInIntRange;        /* all values within internal range? */
+    int nels;
+    int nslabs;
+    int nstarts;        /* number of different starts */
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    MPI_Offset imap[MAX_RANK];
+    int canConvert;     /* Both text or both numeric */
+    double expect[MAX_NELS];
+    $1 value[MAX_NELS];
+    int reqid, status;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+            imap[j] = 1;
+        }
+        err = ncmpi_iget_varm_$1(BAD_ID, i, start, edge, stride, imap, value, &reqid);
+        IF (err != NC_EBADID)
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iget_varm_$1(ncid, BAD_VARID, start, edge, stride, imap, value, &reqid);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = var_shape[i][j];    /* out of boundary check */
+            err = ncmpi_iget_varm_$1(ncid, i, start, edge, stride, imap, value, &reqid);
+            if (!canConvert) {
+                IF (err != NC_ECHAR)
+                    error("conversion: err = %d", err);
+            } else {
+                IF (err != NC_EINVALCOORDS)
+                    error("bad index: err = %d", err);
+                ELSE_NOK
+
+                start[j] = 0;
+                edge[j] = var_shape[i][j] + 1;  /* edge error check */
+                err = ncmpi_iget_varm_$1(ncid, i, start, edge, stride, imap, value, &reqid);
+                IF (err != NC_EEDGE)
+                    error("bad edge: err = %d", err);
+                ELSE_NOK
+                edge[j] = 1;
+                stride[j] = 0;
+                err = ncmpi_iget_varm_$1(ncid, i, start, edge, stride, imap, value, &reqid);
+                IF (err != NC_ESTRIDE)
+                    error("bad stride: err = %d", err);
+                ELSE_NOK
+                stride[j] = 1;
+            }
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                ELSE_NOK
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+ */
+                if (var_rank[i] > 0) {
+                    j = var_rank[i] - 1;
+                    imap[j] = 1;
+                    for (; j > 0; j--)
+                        imap[j-1] = imap[j] * count[j];
+                }
+                allInExtRange = allInIntRange = 1;
+                for (j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != NC_NOERR)
+                        error("error in toMixedBase 1");
+                    ELSE_NOK
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * stride[d];
+                    expect[j] = hash4(var_type[i], var_rank[i], index2,
+                        NCT_ITYPE($1));
+                    if (inRange3(expect[j],var_type[i],NCT_ITYPE($1))) {
+                        IfCheckTextChar($1, var_type[i])
+                            allInIntRange &= CheckRange($1, expect[j]);
+                    } else {
+                        allInExtRange = 0;
+                    }
+                }
+                if (var_rank[i] == 0 && i%2 )
+                    err = ncmpi_iget_varm_$1(ncid,i,NULL,NULL,NULL,NULL,value, &reqid);
+                else
+                    err = ncmpi_iget_varm_$1(ncid,i,index,count,stride,imap,value, &reqid);
+                if (err == NC_NOERR)
+                    ncmpi_wait_all(ncid, 1, &reqid, &status);
+                if (canConvert) {
+                    if (allInExtRange) {
+                        if (allInIntRange) {
+                            IF (status != NC_NOERR)
+                                error("%s", ncmpi_strerror(status));
+                            ELSE_NOK
+                        } else {
+                            IF (status != NC_ERANGE)
+                                error("Range error: status = %d", status);
+                            ELSE_NOK
+                        }
+                    } else {
+                        IF (status != NC_NOERR && status != NC_ERANGE)
+                            error("OK or Range error: status = %d", status);
+                        ELSE_NOK
+                    }
+                    num_err = 0;
+                    for (j = 0; j < nels; j++) {
+                        if (CheckNumRange($1, expect[j], var_type[i])) {
+                            IF (!equal(value[j],expect[j],var_type[i], NCT_ITYPE($1))){
+                                error("value read not that expected");
+                                if (verbose) {
+                                    error("\n");
+                                    error("varid: %d, ", i);
+                                    error("var_name: %s, ", var_name[i]);
+                                    error("element number: %d ", j);
+                                    error("expect: %g, ", expect[j]);
+                                    error("got: %g", (double) value[j]);
+                                }
+                                num_err++;
+                            }
+                        }
+                    }
+                    if (num_err == 0) nok++;
+                } else {
+                    IF (nels > 0 && err != NC_ECHAR)
+                        error("wrong type: err = %d", err);
+                    ELSE_NOK
+                }
+            }
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+TEST_NC_IGET_VARM(text)
+TEST_NC_IGET_VARM(uchar)
+TEST_NC_IGET_VARM(schar)
+TEST_NC_IGET_VARM(short)
+TEST_NC_IGET_VARM(int)
+TEST_NC_IGET_VARM(long)
+TEST_NC_IGET_VARM(float)
+TEST_NC_IGET_VARM(double)
+TEST_NC_IGET_VARM(ushort)
+TEST_NC_IGET_VARM(uint)
+TEST_NC_IGET_VARM(longlong)
+TEST_NC_IGET_VARM(ulonglong)
+
+
diff --git a/test/nc_test/test_iput.m4 b/test/nc_test/test_iput.m4
new file mode 100644
index 0000000..9a5423e
--- /dev/null
+++ b/test/nc_test/test_iput.m4
@@ -0,0 +1,1732 @@
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: test_iput.m4 2295 2016-01-06 20:28:09Z wkliao $ */
+
+
+undefine(`index')dnl
+dnl dnl dnl
+dnl
+dnl Macros
+dnl
+dnl dnl dnl
+dnl
+dnl Upcase(str)
+dnl
+define(`Upcase',dnl
+`dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)')dnl
+dnl dnl dnl
+dnl
+dnl NCT_ITYPE(type)
+dnl
+define(`NCT_ITYPE', ``NCT_'Upcase($1)')dnl
+dnl
+
+define(`CheckText', `ifelse(`$1',`text', , `== (NCT_ITYPE($1) == NCT_TEXT)')')dnl
+define(`IfCheckTextChar', `ifelse(`$1',`text', `if ($2 != NC_CHAR)')')dnl
+define(`CheckNumRange',
+       `ifelse(`$1',`text', `1',
+               `inRange3($2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl
+define(`CheckRange3',
+       `ifelse(`$1',`text', `1',
+               `inRange3($2,$3,NCT_ITYPE($1))')')dnl
+
+
+#include "tests.h"
+
+dnl HASH(TYPE)
+dnl
+define(`HASH',dnl
+`dnl
+/*
+ *  ensure hash value within range for internal TYPE
+ */
+static
+double
+hash_$1(
+    const nc_type type,
+    const int rank,
+    const MPI_Offset *index,
+    const nct_itype itype)
+{
+    const double min = $1_min;
+    const double max = $1_max;
+
+    return MAX(min, MIN(max, hash4( type, rank, index, itype)));
+}
+')dnl
+
+dnl HASH(text)
+#define hash_text hash4
+
+HASH(uchar)
+HASH(schar)
+HASH(short)
+HASH(int)
+HASH(long)
+HASH(float)
+HASH(double)
+HASH(ushort)
+HASH(uint)
+HASH(longlong)
+HASH(ulonglong)
+
+
+dnl CHECK_VARS(TYPE)
+dnl
+define(`CHECK_VARS',dnl
+`dnl
+/* 
+ *  check all vars in file which are (text/numeric) compatible with TYPE
+ */
+static
+int
+check_vars_$1(const char *filename)
+{
+    int  ncid;                  /* netCDF id */
+    MPI_Offset index[MAX_RANK];
+    int  err;           /* status */
+    int  d;
+    int  i;
+    size_t  j;
+    $1 value;
+    nc_type datatype;
+    int ndims;
+    int dimids[MAX_RANK];
+    char name[NC_MAX_NAME];
+    MPI_Offset length;
+    int canConvert;     /* Both text or both numeric */
+    int nok = 0;      /* count of valid comparisons */
+    double expect;
+
+    err = ncmpi_open(comm, filename, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        if (canConvert) {
+            err = ncmpi_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
+            IF (err != NC_NOERR)
+                error("ncmpi_inq_var: %s", ncmpi_strerror(err));
+            IF (strcmp(name, var_name[i]) != 0)
+                error("Unexpected var_name");
+            IF (datatype != var_type[i])
+                error("Unexpected type");
+            IF (ndims != var_rank[i])
+                error("Unexpected rank");
+            for (j = 0; j < ndims; j++) {
+                err = ncmpi_inq_dim(ncid, dimids[j], 0, &length);
+                IF (err != NC_NOERR)
+                    error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
+                IF (length != var_shape[i][j])
+                    error("Unexpected shape");
+            }
+            for (j = 0; j < var_nels[i]; j++) {
+                err = toMixedBase(j, var_rank[i], var_shape[i], index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase 2");
+                expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1));
+                err = ncmpi_get_var1_$1_all(ncid, i, index, &value);
+                if (CheckNumRange($1, expect, datatype)) {
+                    IF (err != NC_NOERR) {
+                        error("error in ncmpi_get_var1_$1_all $s",__func__);
+                    } else IF (!equal(value,expect,var_type[i],NCT_ITYPE($1))) {
+                        error("Var value read not that expected");
+                        if (verbose) {
+                            error("\n");
+                            error("varid: %d, ", i);
+                            error("var_name: %s, ", var_name[i]);
+                            error("var_type: %s, ", s_nc_type(var_type[i]));
+                            error("put type: $1, ");
+                            error("index:");
+                            for (d = 0; d < var_rank[i]; d++)
+                                error(" %d", index[d]);
+                            error(", expect: %g, ", expect);
+                            error("got: %g", (double) value);
+                        }
+                    } else {
+                        ++nok;
+                    }
+                }
+            }
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+CHECK_VARS(text)
+CHECK_VARS(uchar)
+CHECK_VARS(schar)
+CHECK_VARS(short)
+CHECK_VARS(int)
+CHECK_VARS(long)
+CHECK_VARS(float)
+CHECK_VARS(double)
+CHECK_VARS(ushort)
+CHECK_VARS(uint)
+CHECK_VARS(longlong)
+CHECK_VARS(ulonglong)
+
+static double
+hash2nc(const nc_type var_type, int var_rank, MPI_Offset *index)
+{
+    double min;
+    double max;
+
+    switch (var_type) {
+        case NC_CHAR:   min = X_CHAR_MIN;   max = X_CHAR_MAX;   break;
+        case NC_BYTE:   min = X_BYTE_MIN;   max = X_BYTE_MAX;   break;
+        case NC_SHORT:  min = X_SHORT_MIN;  max = X_SHORT_MAX;  break;
+        case NC_INT:    min = X_INT_MIN;    max = X_INT_MAX;    break;
+        case NC_FLOAT:  min = X_FLOAT_MIN;  max = X_FLOAT_MAX;  break;
+        case NC_DOUBLE: min = X_DOUBLE_MIN; max = X_DOUBLE_MAX; break;
+        case NC_UBYTE:  min = 0;            max = X_UCHAR_MAX;  break;
+        case NC_USHORT: min = 0;            max = X_USHORT_MAX; break;
+        case NC_UINT:   min = 0;            max = X_UINT_MAX;   break;
+        case NC_INT64:  min = X_INT64_MIN;  max = X_INT64_MAX;  break;
+        case NC_UINT64: min = 0;            max = X_UINT64_MAX; break;
+        default:
+            return NC_EBADTYPE;
+    }
+
+    return MAX(min, MIN(max, hash(var_type, var_rank, index)));
+}
+
+static int
+dbls2ncs(int nels, int var_type, double *inBuf, void *outBuf)
+{
+    int i;
+    char *p = (char*)outBuf;
+    for (i=0; i<nels; i++) {
+        switch (var_type) {
+            case NC_CHAR:   {char      a = inBuf[i]; memcpy(p, &a, 1); break;}
+            case NC_BYTE:   {schar     a = inBuf[i]; memcpy(p, &a, 1); break;}
+            case NC_SHORT:  {short     a = inBuf[i]; memcpy(p, &a, 2); break;}
+            case NC_INT:    {int       a = inBuf[i]; memcpy(p, &a, 4); break;}
+            case NC_FLOAT:  {float     a = inBuf[i]; memcpy(p, &a, 4); break;}
+            case NC_DOUBLE: {double    a = inBuf[i]; memcpy(p, &a, 8); break;}
+            case NC_UBYTE:  {uchar     a = inBuf[i]; memcpy(p, &a, 1); break;}
+            case NC_USHORT: {ushort    a = inBuf[i]; memcpy(p, &a, 2); break;}
+            case NC_UINT:   {uint      a = inBuf[i]; memcpy(p, &a, 4); break;}
+            case NC_INT64:  {longlong  a = inBuf[i]; memcpy(p, &a, 8); break;}
+            case NC_UINT64: {ulonglong a = inBuf[i]; memcpy(p, &a, 8); break;}
+            default:
+                return NC_EBADTYPE;
+        }
+        p += nctypelen(var_type);
+    }
+    return NC_NOERR;
+}
+
+int
+test_ncmpi_iput_var1(void)
+{
+    int ncid, nok=0;
+    int i;
+    int j;
+    int err;
+    MPI_Offset index[MAX_RANK];
+    double value = 5;        /* any value would do - only for error cases */
+    int reqid, status=NC_NOERR;
+    MPI_Datatype datatype;
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+        for (j = 0; j < var_rank[i]; j++)
+            index[j] = 0;
+        err = ncmpi_iput_var1(BAD_ID, i, index, &value, 1, datatype, &reqid);
+        IF (err != NC_EBADID) 
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iput_var1(ncid, BAD_VARID, index, &value, 1, datatype, &reqid);
+        IF (err != NC_ENOTVAR) 
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                index[j] = var_shape[i][j];     /* out of boundary check */
+                err = ncmpi_iput_var1(ncid, i, index, &value, 1, datatype, &reqid);
+                IF (err != NC_EINVALCOORDS)
+                    error("bad index: err = %d", err);
+                ELSE_NOK
+                index[j] = 0;
+            }
+        }
+        for (j = 0; j < var_nels[i]; j++) {
+            double buf;
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR) 
+                error("error in toMixedBase 1");
+            value = hash2nc(var_type[i], var_rank[i], index);
+            err = dbl2nc(value, var_type[i], &buf);
+            IF (err != NC_NOERR)
+                error("error in dbl2nc");
+
+            if (var_rank[i] == 0 && i%2 == 0)
+                err = ncmpi_iput_var1(ncid, i, NULL, &buf, 1, datatype, &reqid);
+            else
+                err = ncmpi_iput_var1(ncid, i, index, &buf, 1, datatype, &reqid);
+            IF (err != NC_NOERR)
+                error("ncmpi_iput_var1: %s", ncmpi_strerror(err));
+            ELSE_NOK
+
+            err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+            IF (err != NC_NOERR)
+                error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+            ELSE_NOK
+        }
+    }
+
+    check_vars(ncid);
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+dnl TEST_NC_IPUT_VAR1(TYPE)
+dnl
+define(`TEST_NC_IPUT_VAR1',dnl
+`dnl
+int
+test_ncmpi_iput_var1_$1(void)
+{
+    int ncid, nok=0;
+    int i;
+    int j;
+    int err;
+    MPI_Offset index[MAX_RANK];
+    int canConvert;        /* Both text or both numeric */
+    $1 value = 5;        /* any value would do - only for error cases */
+    int reqid, status=NC_NOERR;
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        for (j = 0; j < var_rank[i]; j++)
+            index[j] = 0;
+        err = ncmpi_iput_var1_$1(BAD_ID, i, index, &value, &reqid);
+        IF (err != NC_EBADID) 
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iput_var1_$1(ncid, BAD_VARID, index, &value, &reqid);
+        IF (err != NC_ENOTVAR) 
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                index[j] = var_shape[i][j];     /* out of boundary check */
+                err = ncmpi_iput_var1_$1(ncid, i, index, &value, &reqid);
+                IF (canConvert && err != NC_EINVALCOORDS)
+                    error("bad index: err = %d", err);
+                ELSE_NOK
+                if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
+                index[j] = 0;
+            }
+        }
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR) 
+                error("error in toMixedBase 1");
+            value = hash_$1( var_type[i], var_rank[i], index, NCT_ITYPE($1));
+            if (var_rank[i] == 0 && i%2 == 0)
+                err = ncmpi_iput_var1_$1(ncid, i, NULL, &value, &reqid);
+            else
+                err = ncmpi_iput_var1_$1(ncid, i, index, &value, &reqid);
+            if (err == NC_NOERR || err == NC_ERANGE)
+                /* NC_ERANGE is not fatal, must continue */
+                ncmpi_wait_all(ncid, 1, &reqid, &status);
+            if (canConvert) {
+                if (CheckRange3($1, value, var_type[i])) {
+                    IF (err != NC_NOERR)
+                        error("%s", ncmpi_strerror(err));
+                    ELSE_NOK
+                    IF (status != NC_NOERR)
+                        error("%s", ncmpi_strerror(status));
+                    ELSE_NOK
+                } else {
+                    /* NC_ERANGE is checked at ncmpi_iput_var1_$1() */
+                    IF (err != NC_ERANGE) {
+                        error("Range error: err = %d", err);
+                        error("\n\t\tfor type %s value %.17e %ld",
+                                s_nc_type(var_type[i]),
+                                (double)value, (long)value, &reqid);
+                    }
+                    ELSE_NOK
+                }
+            } else {
+                /* NC_ECHAR is checked at ncmpi_iput_var1_$1() */
+                IF (err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    nok += check_vars_$1(scratch);
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+')dnl
+
+TEST_NC_IPUT_VAR1(text)
+TEST_NC_IPUT_VAR1(uchar)
+TEST_NC_IPUT_VAR1(schar)
+TEST_NC_IPUT_VAR1(short)
+TEST_NC_IPUT_VAR1(int)
+TEST_NC_IPUT_VAR1(long)
+TEST_NC_IPUT_VAR1(float)
+TEST_NC_IPUT_VAR1(double)
+TEST_NC_IPUT_VAR1(ushort)
+TEST_NC_IPUT_VAR1(uint)
+TEST_NC_IPUT_VAR1(longlong)
+TEST_NC_IPUT_VAR1(ulonglong)
+
+int
+test_ncmpi_iput_var(void)
+{
+    int ncid, nok=0, varid, i, j, err, nels;
+    MPI_Offset index[MAX_RANK];
+    double value[MAX_NELS];
+    int reqid, status=NC_NOERR;
+    MPI_Datatype datatype;
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    /* Because var API is writing the entire variables. We need at first
+     * make sure there are non-zero records to write */
+
+    /* Write record number NRECS to force writing of preceding records */
+    /* Assumes variable cr is char vector with UNLIMITED dimension */
+    err = ncmpi_inq_varid(ncid, "cr", &varid);
+    IF (err != NC_NOERR)
+        error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
+    index[0] = NRECS-1;
+    err = ncmpi_iput_var1_text(ncid, varid, index, "x", &reqid);
+    IF (err != NC_NOERR)
+        error("ncmpi_iput_var1_text: %s", ncmpi_strerror(err));
+    err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+    IF (err != NC_NOERR)
+        error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        err = ncmpi_iput_var(BAD_ID, i, value, 1, datatype, &reqid);
+        IF (err != NC_EBADID) 
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iput_var(ncid, BAD_VARID, value, 1, datatype, &reqid);
+        IF (err != NC_ENOTVAR) 
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+
+        nels = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            nels *= var_shape[i][j];
+            index[j] = 0;
+        }
+        double ncbuf[MAX_NELS];
+        for (j = 0; j < nels; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR) 
+                error("error in toMixedBase 1");
+            ncbuf[j] = hash2nc(var_type[i], var_rank[i], index);
+        }
+        /* type convert ncbuf[] to value[] */
+        err = dbls2ncs(nels, var_type[i], ncbuf, value);
+        IF (err != NC_NOERR) 
+            error("error in dbls2ncs");
+        err = ncmpi_iput_var(ncid, i, value, nels, datatype, &reqid);
+        IF (err != NC_NOERR)
+            error("ncmpi_iput_var: %s", ncmpi_strerror(err));
+        ELSE_NOK
+
+        err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+        IF (err != NC_NOERR)
+            error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+        ELSE_NOK
+    }
+
+    check_vars(ncid);
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+
+    return nok;
+}
+
+dnl TEST_NC_IPUT_VAR(TYPE)
+dnl
+define(`TEST_NC_IPUT_VAR',dnl
+`dnl
+int
+test_ncmpi_iput_var_$1(void)
+{
+    int ncid, nok=0;
+    int varid;
+    int i;
+    int j;
+    int err;
+    int nels;
+    MPI_Offset index[MAX_RANK];
+    int canConvert;        /* Both text or both numeric */
+    int allInExtRange;        /* all values within external range? */
+    $1 value[MAX_NELS];
+    int reqid, status=NC_NOERR;
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        err = ncmpi_iput_var_$1(BAD_ID, i, value, &reqid);
+        IF (err != NC_EBADID) 
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iput_var_$1(ncid, BAD_VARID, value, &reqid);
+        IF (err != NC_ENOTVAR) 
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+
+        nels = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            nels *= var_shape[i][j];
+        }
+        for (allInExtRange = 1, j = 0; j < nels; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR) 
+                error("error in toMixedBase 1");
+            value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+            IfCheckTextChar($1, var_type[i])
+                allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+        }
+        err = ncmpi_iput_var_$1(ncid, i, value, &reqid);
+        if (err == NC_NOERR || err == NC_ERANGE)
+            /* NC_ERANGE is not fatal, must continue */
+            ncmpi_wait_all(ncid, 1, &reqid, &status);
+
+        if (canConvert) {
+            if (allInExtRange) {
+                IF (err != NC_NOERR) 
+                    error("%s", ncmpi_strerror(err));
+                ELSE_NOK
+                IF (status != NC_NOERR) 
+                    error("%s", ncmpi_strerror(status));
+                ELSE_NOK
+            } else {
+                /* NC_ERANGE is checked at ncmpi_iput_var_$1() */
+                IF (err != NC_ERANGE && var_dimid[i][0] != RECDIM)
+                    error("expecting range error, but err = %d", err);
+                ELSE_NOK
+            }
+        } else { /* should flag wrong type even if nothing to write */
+            /* NC_ECHAR is checked at ncmpi_iput_var_$1() */
+            IF (nels > 0 && err != NC_ECHAR)
+                error("wrong type: err = %d", err);
+            ELSE_NOK
+        }
+    }
+
+    /* Preceeding has written nothing for record variables, now try */
+    /* again with more than 0 records */
+
+    /* Write record number NRECS to force writing of preceding records */
+    /* Assumes variable cr is char vector with UNLIMITED dimension */
+    err = ncmpi_inq_varid(ncid, "cr", &varid);
+    IF (err != NC_NOERR)
+        error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
+    index[0] = NRECS-1;
+    err = ncmpi_iput_var1_text(ncid, varid, index, "x", &reqid);
+    IF (err != NC_NOERR)
+        error("ncmpi_iput_var1_text: %s", ncmpi_strerror(err));
+    else
+        ncmpi_wait_all(ncid, 1, &reqid, &status);
+
+    for (i = 0; i < numVars; i++) {
+        if (var_dimid[i][0] == RECDIM) {  /* only test record variables here */
+            canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+            assert(var_rank[i] <= MAX_RANK);
+            assert(var_nels[i] <= MAX_NELS);
+            err = ncmpi_iput_var_$1(BAD_ID, i, value, &reqid);
+            IF (err != NC_EBADID) 
+                error("expecting bad ncid, but err = %d", err);
+            ELSE_NOK
+
+            nels = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                nels *= var_shape[i][j];
+            }
+            for (allInExtRange = 1, j = 0; j < nels; j++) {
+                err = toMixedBase(j, var_rank[i], var_shape[i], index);
+                IF (err != NC_NOERR) 
+                    error("error in toMixedBase 1");
+                ELSE_NOK
+                value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+                IfCheckTextChar($1, var_type[i])
+                    allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+            }
+            err = ncmpi_iput_var_$1(ncid, i, value, &reqid);
+            if (err == NC_NOERR || err == NC_ERANGE)
+                /* NC_ERANGE is not fatal, must continue */
+                ncmpi_wait_all(ncid, 1, &reqid, &status);
+            if (canConvert) {
+                if (allInExtRange) {
+                    IF (err != NC_NOERR) 
+                        error("%s", ncmpi_strerror(err));
+                    ELSE_NOK
+                    IF (status != NC_NOERR) 
+                        error("%s", ncmpi_strerror(status));
+                    ELSE_NOK
+                } else {
+                    /* NC_ERANGE is checked at ncmpi_iput_var_$1() */
+                    IF (err != NC_ERANGE)
+                        error("range error: err = %d", err);
+                    ELSE_NOK
+                }
+            } else {
+                /* NC_ECHAR is checked at ncmpi_iput_var_$1() */
+                IF (nels > 0 && err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    nok += check_vars_$1(scratch);
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+
+    return nok;
+}
+')dnl
+
+TEST_NC_IPUT_VAR(text)
+TEST_NC_IPUT_VAR(uchar)
+TEST_NC_IPUT_VAR(schar)
+TEST_NC_IPUT_VAR(short)
+TEST_NC_IPUT_VAR(int)
+TEST_NC_IPUT_VAR(long)
+TEST_NC_IPUT_VAR(float)
+TEST_NC_IPUT_VAR(double)
+TEST_NC_IPUT_VAR(ushort)
+TEST_NC_IPUT_VAR(uint)
+TEST_NC_IPUT_VAR(longlong)
+TEST_NC_IPUT_VAR(ulonglong)
+
+int
+test_ncmpi_iput_vara(void)
+{
+    int ncid, nok=0, d, i, j, k, err, nslabs, nels;
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    double value[MAX_NELS];
+    int reqid, status=NC_NOERR;
+    MPI_Datatype datatype;
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    value[0] = 0;
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+        }
+        err = ncmpi_iput_vara(BAD_ID, i, start, edge, value, 1, datatype, &reqid);
+        IF (err != NC_EBADID) 
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iput_vara(ncid, BAD_VARID, start, edge, value, 1, datatype, &reqid);
+        IF (err != NC_ENOTVAR) 
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                start[j] = var_shape[i][j];      /* out of bundary check */
+                err = ncmpi_iput_vara(ncid, i, start, edge, value, 1, datatype, &reqid);
+                IF (err != NC_EINVALCOORDS)
+                    error("expecting bad start, but err = %d", err);
+                ELSE_NOK
+                start[j] = 0;
+                edge[j] = var_shape[i][j] + 1;  /* edge error check */
+                err = ncmpi_iput_vara(ncid, i, start, edge, value, 1, datatype, &reqid);
+                IF (err != NC_EEDGE)
+                    error("expecting bad edge, but err = %d", err);
+                ELSE_NOK
+                edge[j] = 1;
+            }
+        }
+        /* Check correct error returned even when nothing to put */
+        for (j = 0; j < var_rank[i]; j++) {
+            edge[j] = 0;
+        }
+        err = ncmpi_iput_vara(BAD_ID, i, start, edge, value, 1, datatype, &reqid);
+        IF (err != NC_EBADID) 
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iput_vara(ncid, BAD_VARID, start, edge, value, 1, datatype, &reqid);
+        IF (err != NC_ENOTVAR) 
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                start[j] = var_shape[i][j];     /* out of boundary check */
+                err = ncmpi_iput_vara(ncid, i, start, edge, value, 1, datatype, &reqid);
+                IF (err != NC_EINVALCOORDS)
+                    error("bad start: err = %d", err);
+                ELSE_NOK
+                start[j] = 0;
+            }
+        }
+
+        for (j = 0; j < var_rank[i]; j++) {
+            edge[j] = 1;
+        }
+
+        /* Choose a random point dividing each dim into 2 parts */
+        /* Put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to put lower or upper part of dim */
+        for (k = 0; k < nslabs; k++) {
+            nels = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                nels *= edge[j];
+            }
+            double ncbuf[MAX_NELS];
+            for (j = 0; j < nels; j++) {
+                err = toMixedBase(j, var_rank[i], edge, index);
+                IF (err != NC_NOERR) 
+                    error("error in toMixedBase 1");
+                ELSE_NOK
+                for (d = 0; d < var_rank[i]; d++) 
+                    index[d] += start[d];
+                ncbuf[j] = hash2nc(var_type[i], var_rank[i], index);
+            }
+            /* type convert ncbuf[] to value[] */
+            err = dbls2ncs(nels, var_type[i], ncbuf, value);
+            IF (err != NC_NOERR)
+                error("error in dbls2ncs");
+
+            if (var_rank[i] == 0 && i%2 == 0)
+                err = ncmpi_iput_vara(ncid, i, NULL, NULL, value, nels, datatype, &reqid);
+            else
+                err = ncmpi_iput_vara(ncid, i, start, edge, value, nels, datatype, &reqid);
+            IF (err != NC_NOERR)
+                error("ncmpi_iput_var1: %s", ncmpi_strerror(err));
+            ELSE_NOK
+
+            err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+            IF (err != NC_NOERR)
+                error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+            ELSE_NOK
+        }
+    }
+
+    check_vars(ncid);
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+dnl TEST_NC_IPUT_VARA(TYPE)
+dnl
+define(`TEST_NC_IPUT_VARA',dnl
+`dnl
+int
+test_ncmpi_iput_vara_$1(void)
+{
+    int ncid, nok=0;
+    int d;
+    int i;
+    int j;
+    int k;
+    int err;
+    int nslabs;
+    int nels;
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    int canConvert;        /* Both text or both numeric */
+    int allInExtRange;        /* all values within external range? */
+    $1 value[MAX_NELS];
+    int reqid, status=NC_NOERR;
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    value[0] = 0;
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+        }
+        err = ncmpi_iput_vara_$1(BAD_ID, i, start, edge, value, &reqid);
+        IF (err != NC_EBADID) 
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iput_vara_$1(ncid, BAD_VARID, start, edge, value, &reqid);
+        IF (err != NC_ENOTVAR) 
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                start[j] = var_shape[i][j];      /* out of bundary check */
+                err = ncmpi_iput_vara_$1(ncid, i, start, edge, value, &reqid);
+                IF (canConvert && err != NC_EINVALCOORDS)
+                    error("expecting bad start, but err = %d", err);
+                ELSE_NOK
+                if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
+                start[j] = 0;
+                edge[j] = var_shape[i][j] + 1;  /* edge error check */
+                err = ncmpi_iput_vara_$1(ncid, i, start, edge, value, &reqid);
+                IF (canConvert && err != NC_EEDGE)
+                    error("expecting bad edge, but err = %d", err);
+                ELSE_NOK
+                if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
+                edge[j] = 1;
+            }
+        }
+        /* Check correct error returned even when nothing to put */
+        for (j = 0; j < var_rank[i]; j++) {
+            edge[j] = 0;
+        }
+        err = ncmpi_iput_vara_$1(BAD_ID, i, start, edge, value, &reqid);
+        IF (err != NC_EBADID) 
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iput_vara_$1(ncid, BAD_VARID, start, edge, value, &reqid);
+        IF (err != NC_ENOTVAR) 
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                start[j] = var_shape[i][j];     /* out of boundary check */
+                err = ncmpi_iput_vara_$1(ncid, i, start, edge, value, &reqid);
+                IF (canConvert && err != NC_EINVALCOORDS)
+                    error("bad start: err = %d", err);
+                ELSE_NOK
+                if (err == NC_NOERR) ncmpi_wait_all(ncid, 1, &reqid, &status);
+                start[j] = 0;
+            }
+        }
+
+        for (j = 0; j < var_rank[i]; j++) {
+            edge[j] = 1;
+        }
+
+        /* Choose a random point dividing each dim into 2 parts */
+        /* Put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to put lower or upper part of dim */
+        for (k = 0; k < nslabs; k++) {
+            nels = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                nels *= edge[j];
+            }
+            for (allInExtRange = 1, j = 0; j < nels; j++) {
+                err = toMixedBase(j, var_rank[i], edge, index);
+                IF (err != NC_NOERR) 
+                    error("error in toMixedBase 1");
+                ELSE_NOK
+                for (d = 0; d < var_rank[i]; d++) 
+                    index[d] += start[d];
+                value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+                IfCheckTextChar($1, var_type[i])
+                    allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+            }
+            if (var_rank[i] == 0 && i%2 == 0)
+                err = ncmpi_iput_vara_$1(ncid, i, NULL, NULL, value, &reqid);
+            else
+                err = ncmpi_iput_vara_$1(ncid, i, start, edge, value, &reqid);
+            if (err == NC_NOERR || err == NC_ERANGE)
+                /* NC_ERANGE is not fatal, must continue */
+                ncmpi_wait_all(ncid, 1, &reqid, &status);
+            if (canConvert) {
+                if (allInExtRange) {
+                    IF (err != NC_NOERR) 
+                        error("%s", ncmpi_strerror(err));
+                    ELSE_NOK
+                    IF (status != NC_NOERR) 
+                        error("%s", ncmpi_strerror(status));
+                    ELSE_NOK
+                } else {
+                    /* NC_ERANGE is checked at ncmpi_iput_vara_$1() */
+                    IF (err != NC_ERANGE)
+                        error("range error: err = %d", err);
+                    ELSE_NOK
+                }
+            } else {
+                /* NC_ECHAR is checked at ncmpi_iput_vara_$1() */
+                IF (nels > 0 && err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    nok += check_vars_$1(scratch);
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+')dnl
+
+TEST_NC_IPUT_VARA(text)
+TEST_NC_IPUT_VARA(uchar)
+TEST_NC_IPUT_VARA(schar)
+TEST_NC_IPUT_VARA(short)
+TEST_NC_IPUT_VARA(int)
+TEST_NC_IPUT_VARA(long)
+TEST_NC_IPUT_VARA(float)
+TEST_NC_IPUT_VARA(double)
+TEST_NC_IPUT_VARA(ushort)
+TEST_NC_IPUT_VARA(uint)
+TEST_NC_IPUT_VARA(longlong)
+TEST_NC_IPUT_VARA(ulonglong)
+
+int
+test_ncmpi_iput_vars(void)
+{
+    int ncid, nok=0, d, i, j, k, m, err, nels, nslabs;
+    int nstarts;        /* number of different starts */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    double value[MAX_NELS];
+    int reqid, status=NC_NOERR;
+    MPI_Datatype datatype;
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+        }
+        err = ncmpi_iput_vars(BAD_ID, i, start, edge, stride, value, 1, datatype, &reqid);
+        IF (err != NC_EBADID) 
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iput_vars(ncid, BAD_VARID, start, edge, stride, value, 1, datatype, &reqid);
+        IF (err != NC_ENOTVAR) 
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                start[j] = var_shape[i][j];     /* out of boundary check */
+                err = ncmpi_iput_vars(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
+                IF (err != NC_EINVALCOORDS)
+                    error("expecting bad start, but err = %d", err);
+                ELSE_NOK
+                start[j] = 0;
+                edge[j] = var_shape[i][j] + 1;  /* edge error check */
+                err = ncmpi_iput_vars(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
+                IF (err != NC_EEDGE)
+                    error("expecting bad edge, but err = %d", err);
+                ELSE_NOK
+                edge[j] = 1;
+                stride[j] = 0;  /* strided edge error check */
+                err = ncmpi_iput_vars(ncid, i, start, edge, stride, value, 1, datatype, &reqid);
+                IF (err != NC_ESTRIDE)
+                    error("expecting bad stride, but err = %d", err);
+                ELSE_NOK
+                stride[j] = 1;
+            }
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* Put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to put lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+*/
+                double ncbuf[MAX_NELS];
+                for (j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != NC_NOERR)
+                        error("error in toMixedBase");
+                    ELSE_NOK
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * stride[d];
+                    ncbuf[j] = hash2nc(var_type[i], var_rank[i], index2);
+                }
+                /* type convert ncbuf[] to value[] */
+                err = dbls2ncs(nels, var_type[i], ncbuf, value);
+                IF (err != NC_NOERR)
+                    error("error in dbls2ncs");
+
+                if (var_rank[i] == 0 && i%2 == 0)
+                    err = ncmpi_iput_vars(ncid, i, NULL, NULL, stride, value, nels, datatype, &reqid);
+                else
+                    err = ncmpi_iput_vars(ncid, i, index, count, stride, value, nels, datatype, &reqid);
+                IF (err != NC_NOERR)
+                    error("ncmpi_iput_var1: %s", ncmpi_strerror(err));
+                ELSE_NOK
+
+                err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+                IF (err != NC_NOERR)
+                    error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+                ELSE_NOK
+            }
+        }
+    }
+
+    check_vars(ncid);
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+dnl TEST_NC_IPUT_VARS(TYPE)
+dnl
+define(`TEST_NC_IPUT_VARS',dnl
+`dnl
+int
+test_ncmpi_iput_vars_$1(void)
+{
+    int ncid, nok=0;
+    int d;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err;
+    int nels;
+    int nslabs;
+    int nstarts;        /* number of different starts */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    int canConvert;        /* Both text or both numeric */
+    int allInExtRange;        /* all values within external range? */
+    $1 value[MAX_NELS];
+    int reqid, status=NC_NOERR;
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+        }
+        err = ncmpi_iput_vars_$1(BAD_ID, i, start, edge, stride, value, &reqid);
+        IF (err != NC_EBADID) 
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iput_vars_$1(ncid, BAD_VARID, start, edge, stride, value, &reqid);
+        IF (err != NC_ENOTVAR) 
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                start[j] = var_shape[i][j];     /* out of boundary check */
+                err = ncmpi_iput_vars_$1(ncid, i, start, edge, stride, value, &reqid);
+                if (!canConvert) {
+                    IF (err != NC_ECHAR)
+                        error("conversion: err = %d", err);
+                    ELSE_NOK
+                } else {
+                    IF (err != NC_EINVALCOORDS)
+                        error("expecting bad start, but err = %d", err);
+                    ELSE_NOK
+                    start[j] = 0;
+                    edge[j] = var_shape[i][j] + 1;  /* edge error check */
+                    err = ncmpi_iput_vars_$1(ncid, i, start, edge, stride, value, &reqid);
+                    IF (err != NC_EEDGE)
+                        error("expecting bad edge, but err = %d", err);
+                    ELSE_NOK
+                    edge[j] = 1;
+                    stride[j] = 0;  /* strided edge error check */
+                    err = ncmpi_iput_vars_$1(ncid, i, start, edge, stride, value, &reqid);
+                    IF (err != NC_ESTRIDE)
+                        error("expecting bad stride, but err = %d", err);
+                    ELSE_NOK
+                    stride[j] = 1;
+                }
+            }
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* Put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to put lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+*/
+                for (allInExtRange = 1, j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != NC_NOERR)
+                        error("error in toMixedBase");
+                    ELSE_NOK
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * stride[d];
+                    value[j] = hash_$1(var_type[i], var_rank[i], index2, NCT_ITYPE($1));
+                    IfCheckTextChar($1, var_type[i])
+                        allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+                }
+                if (var_rank[i] == 0 && i%2 == 0)
+                    err = ncmpi_iput_vars_$1(ncid, i, NULL, NULL, stride, value, &reqid);
+                else
+                    err = ncmpi_iput_vars_$1(ncid, i, index, count, stride, value, &reqid);
+                if (err == NC_NOERR || err == NC_ERANGE)
+                    /* NC_ERANGE is not fatal, must continue */
+                    ncmpi_wait_all(ncid, 1, &reqid, &status);
+                if (canConvert) {
+                    if (allInExtRange) {
+                        IF (err != NC_NOERR) 
+                            error("%s", ncmpi_strerror(err));
+                        ELSE_NOK
+                        IF (status != NC_NOERR) 
+                            error("%s", ncmpi_strerror(status));
+                        ELSE_NOK
+                    } else {
+                        /* NC_ERANGE is checked at ncmpi_iput_vars_$1() */
+                        IF (err != NC_ERANGE)
+                            error("range error: err = %d", err);
+                        ELSE_NOK
+                    }
+                } else {
+                    /* NC_ECHAR is checked at ncmpi_iput_vars_$1() */
+                    IF (nels > 0 && err != NC_ECHAR)
+                        error("wrong type: err = %d", err);
+                    ELSE_NOK
+                }
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    nok += check_vars_$1(scratch);
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+')dnl
+
+TEST_NC_IPUT_VARS(text)
+TEST_NC_IPUT_VARS(uchar)
+TEST_NC_IPUT_VARS(schar)
+TEST_NC_IPUT_VARS(short)
+TEST_NC_IPUT_VARS(int)
+TEST_NC_IPUT_VARS(long)
+TEST_NC_IPUT_VARS(float)
+TEST_NC_IPUT_VARS(double)
+TEST_NC_IPUT_VARS(ushort)
+TEST_NC_IPUT_VARS(uint)
+TEST_NC_IPUT_VARS(longlong)
+TEST_NC_IPUT_VARS(ulonglong)
+
+int
+test_ncmpi_iput_varm(void)
+{
+    int ncid, nok=0, d, i, j, k, m, err, nels, nslabs;
+    int nstarts;        /* number of different starts */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    MPI_Offset imap[MAX_RANK];
+    double value[MAX_NELS];
+    int reqid, status=NC_NOERR;
+    MPI_Datatype datatype;
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+            imap[j] = 1;
+        }
+        err = ncmpi_iput_varm(BAD_ID, i, start, edge, stride, imap, value, 1, datatype, &reqid);
+        IF (err != NC_EBADID) 
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iput_varm(ncid, BAD_VARID, start, edge, stride, imap, value, 1, datatype, &reqid);
+        IF (err != NC_ENOTVAR) 
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                start[j] = var_shape[i][j];     /* out of boundary check */
+                err = ncmpi_iput_varm(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
+                IF (err != NC_EINVALCOORDS)
+                    error("expecting bad start, but err = %d", err);
+                ELSE_NOK
+                start[j] = 0;
+                edge[j] = var_shape[i][j] + 1;  /* edge error check */
+                err = ncmpi_iput_varm(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
+                IF (err != NC_EEDGE)
+                    error("expecting bad edge, but err = %d", err);
+                ELSE_NOK
+                edge[j] = 1;
+                stride[j] = 0;  /* strided edge error check */
+                err = ncmpi_iput_varm(ncid, i, start, edge, stride, imap, value, 1, datatype, &reqid);
+                IF (err != NC_ESTRIDE)
+                    error("expecting bad stride, but err = %d", err);
+                ELSE_NOK
+                stride[j] = 1;
+            }
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* Put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to put lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                ELSE_NOK
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+*/
+                if (var_rank[i] > 0) {
+                    j = var_rank[i] - 1;
+                    imap[j] = 1;
+                    for (; j > 0; j--)
+                        imap[j-1] = imap[j] * count[j];
+                }
+                double ncbuf[MAX_NELS];
+                for (j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != NC_NOERR)
+                        error("error in toMixedBase");
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * stride[d];
+                    ncbuf[j] = hash2nc(var_type[i], var_rank[i], index2);
+                }
+                /* type convert ncbuf[] to value[] */
+                err = dbls2ncs(nels, var_type[i], ncbuf, value);
+                IF (err != NC_NOERR)
+                    error("error in dbls2ncs");
+
+                if (var_rank[i] == 0 && i%2 == 0)
+                    err = ncmpi_iput_varm(ncid,i,NULL,NULL,NULL,NULL,value, nels, datatype, &reqid);
+                else
+                    err = ncmpi_iput_varm(ncid,i,index,count,stride,imap,value, nels, datatype,&reqid);
+                IF (err != NC_NOERR)
+                    error("ncmpi_iput_var1: %s", ncmpi_strerror(err));
+                ELSE_NOK
+
+                err = ncmpi_wait_all(ncid, 1, &reqid, &status);
+                IF (err != NC_NOERR)
+                    error("ncmpi_wait_all: %s", ncmpi_strerror(err));
+                ELSE_NOK
+            }
+        }
+    }
+
+    check_vars(ncid);
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+dnl TEST_NC_IPUT_VARM(TYPE)
+dnl
+define(`TEST_NC_IPUT_VARM',dnl
+`dnl
+int
+test_ncmpi_iput_varm_$1(void)
+{
+    int ncid, nok=0;
+    int d;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err;
+    int nels;
+    int nslabs;
+    int nstarts;        /* number of different starts */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    MPI_Offset imap[MAX_RANK];
+    int canConvert;        /* Both text or both numeric */
+    int allInExtRange;        /* all values within external range? */
+    $1 value[MAX_NELS];
+    int reqid, status=NC_NOERR;
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+            imap[j] = 1;
+        }
+        err = ncmpi_iput_varm_$1(BAD_ID, i, start, edge, stride, imap, value, &reqid);
+        IF (err != NC_EBADID) 
+            error("bad ncid: err = %d", err);
+        ELSE_NOK
+        err = ncmpi_iput_varm_$1(ncid, BAD_VARID, start, edge, stride, imap, value, &reqid);
+        IF (err != NC_ENOTVAR) 
+            error("bad var id: err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                start[j] = var_shape[i][j];     /* out of boundary check */
+                err = ncmpi_iput_varm_$1(ncid, i, start, edge, stride, imap, value, &reqid);
+                if (!canConvert) {
+                    IF (err != NC_ECHAR)
+                        error("conversion: err = %d", err);
+                    ELSE_NOK
+                } else {
+                    IF (err != NC_EINVALCOORDS)
+                        error("expecting bad start, but err = %d", err);
+                    ELSE_NOK
+                    start[j] = 0;
+                    edge[j] = var_shape[i][j] + 1;  /* edge error check */
+                    err = ncmpi_iput_varm_$1(ncid, i, start, edge, stride, imap, value, &reqid);
+                    IF (err != NC_EEDGE)
+                        error("expecting bad edge, but err = %d", err);
+                    ELSE_NOK
+                    edge[j] = 1;
+                    stride[j] = 0;  /* strided edge error check */
+                    err = ncmpi_iput_varm_$1(ncid, i, start, edge, stride, imap, value, &reqid);
+                    IF (err != NC_ESTRIDE)
+                        error("expecting bad stride, but err = %d", err);
+                    ELSE_NOK
+                    stride[j] = 1;
+                }
+            }
+        }
+        /* Choose a random point dividing each dim into 2 parts */
+        /* Put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to put lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                ELSE_NOK
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+*/
+                if (var_rank[i] > 0) {
+                    j = var_rank[i] - 1;
+                    imap[j] = 1;
+                    for (; j > 0; j--)
+                        imap[j-1] = imap[j] * count[j];
+                }
+                for (allInExtRange = 1, j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != NC_NOERR)
+                        error("error in toMixedBase");
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * stride[d];
+                    value[j] = hash_$1(var_type[i], var_rank[i], index2, NCT_ITYPE($1));
+                    IfCheckTextChar($1, var_type[i])
+                        allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+                }
+                if (var_rank[i] == 0 && i%2 == 0)
+                    err = ncmpi_iput_varm_$1(ncid,i,NULL,NULL,NULL,NULL,value, &reqid);
+                else
+                    err = ncmpi_iput_varm_$1(ncid,i,index,count,stride,imap,value,&reqid);
+                if (err == NC_NOERR || err == NC_ERANGE)
+                    /* NC_ERANGE is not fatal, must continue */
+                    ncmpi_wait_all(ncid, 1, &reqid, &status);
+                if (canConvert) {
+                    if (allInExtRange) {
+                        IF (err != NC_NOERR)
+                            error("%s", ncmpi_strerror(err));
+                        ELSE_NOK
+                        IF (status != NC_NOERR)
+                            error("%s", ncmpi_strerror(status));
+                        ELSE_NOK
+                    } else {
+                        /* NC_ERANGE is checked at ncmpi_iput_varm_$1() */
+                        IF (err != NC_ERANGE)
+                            error("range error: err = %d", err);
+                        ELSE_NOK
+                    }
+                } else {
+                    /* NC_ECHAR is checked at ncmpi_iput_varm_$1() */
+                    IF (nels > 0 && err != NC_ECHAR)
+                        error("wrong type: err = %d", err);
+                    ELSE_NOK
+                }
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    nok += check_vars_$1(scratch);
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+')dnl
+
+TEST_NC_IPUT_VARM(text)
+TEST_NC_IPUT_VARM(uchar)
+TEST_NC_IPUT_VARM(schar)
+TEST_NC_IPUT_VARM(short)
+TEST_NC_IPUT_VARM(int)
+TEST_NC_IPUT_VARM(long)
+TEST_NC_IPUT_VARM(float)
+TEST_NC_IPUT_VARM(double)
+TEST_NC_IPUT_VARM(ushort)
+TEST_NC_IPUT_VARM(uint)
+TEST_NC_IPUT_VARM(longlong)
+TEST_NC_IPUT_VARM(ulonglong)
+
+
diff --git a/test/nc_test/test_put.m4 b/test/nc_test/test_put.m4
new file mode 100644
index 0000000..cb0391b
--- /dev/null
+++ b/test/nc_test/test_put.m4
@@ -0,0 +1,1265 @@
+dnl This is m4 source.
+dnl Process using m4 to produce 'C' language file.
+dnl
+dnl If you see this line, you can ignore the next one.
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+dnl
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: test_put.m4 2295 2016-01-06 20:28:09Z wkliao $ */
+
+
+undefine(`index')dnl
+dnl dnl dnl
+dnl
+dnl Macros
+dnl
+dnl dnl dnl
+dnl
+dnl Upcase(str)
+dnl
+define(`Upcase',dnl
+`dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)')dnl
+dnl dnl dnl
+dnl
+dnl NCT_ITYPE(type)
+dnl
+define(`NCT_ITYPE',    ``NCT_'Upcase($1)')dnl
+define(`NC_TYPE',      ``NC_'Upcase($1)')dnl
+define(`X_MIN',        ``X_'Upcase($1)_MIN')dnl
+define(`X_MAX',        ``X_'Upcase($1)_MAX')dnl
+dnl
+
+define(`CheckText', `ifelse(`$1',`text', , `== (NCT_ITYPE($1) == NCT_TEXT)')')dnl
+define(`IfCheckTextChar', `ifelse(`$1',`text', `if ($2 != NC_CHAR)')')dnl
+define(`CheckNumRange',
+       `ifelse(`$1',`text', `1',
+               `inRange3($2,$3,NCT_ITYPE($1)) && ($2 >= $1_min && $2 <= $1_max)')')dnl
+define(`CheckRange',
+       `ifelse(`$1',`text', `0', `($2 >= $1_min && $2 <= $1_max)')')dnl
+define(`CheckRange3',
+       `ifelse(`$1',`text', `1',
+               `inRange3($2,$3,NCT_ITYPE($1))')')dnl
+
+#include "tests.h"
+
+dnl HASH(TYPE)
+dnl
+define(`HASH',dnl
+`dnl
+/*
+ *  ensure hash value within range for internal TYPE
+ */
+static
+double
+hash_$1(
+    const nc_type type,
+    const int rank,
+    const MPI_Offset *index,
+    const nct_itype itype)
+{
+    const double min = $1_min;
+    const double max = $1_max;
+
+    return MAX(min, MIN(max, hash4( type, rank, index, itype)));
+}
+')dnl
+
+dnl HASH(text)
+#define hash_text hash4
+
+HASH(uchar)
+HASH(schar)
+HASH(short)
+HASH(int)
+HASH(long)
+HASH(float)
+HASH(double)
+HASH(ushort)
+HASH(uint)
+HASH(longlong)
+HASH(ulonglong)
+
+
+dnl CHECK_VARS(TYPE)
+dnl
+define(`CHECK_VARS',dnl
+`dnl
+/* 
+ *  check all vars in file which are (text/numeric) compatible with TYPE
+ */
+static
+int
+check_vars_$1(const char *filename)
+{
+    int  ncid;                  /* netCDF id */
+    MPI_Offset index[MAX_RANK];
+    int  err;
+    int  d;
+    int  i;
+    size_t  j;
+    $1 value;
+    nc_type datatype;
+    int ndims;
+    int dimids[MAX_RANK];
+    char name[NC_MAX_NAME];
+    MPI_Offset length;
+    int canConvert;     /* Both text or both numeric */
+    int nok = 0;      /* count of valid comparisons */
+    double expect;
+
+    err = ncmpi_open(comm, filename, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        if (canConvert) {
+            err = ncmpi_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
+            IF (err != NC_NOERR)
+                error("ncmpi_inq_var: %s", ncmpi_strerror(err));
+            IF (strcmp(name, var_name[i]) != 0)
+                error("Unexpected var_name");
+            IF (datatype != var_type[i])
+                error("Unexpected type");
+            IF (ndims != var_rank[i])
+                error("Unexpected rank");
+            for (j = 0; j < ndims; j++) {
+                err = ncmpi_inq_dim(ncid, dimids[j], 0, &length);
+                IF (err != NC_NOERR)
+                    error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
+                IF (length != var_shape[i][j])
+                    error("Unexpected shape");
+            }
+            for (j = 0; j < var_nels[i]; j++) {
+                err = toMixedBase(j, var_rank[i], var_shape[i], index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase 2");
+                expect = hash4( var_type[i], var_rank[i], index, NCT_ITYPE($1));
+                err = ncmpi_get_var1_$1_all(ncid, i, index, &value);
+                if (CheckNumRange($1, expect, datatype)) {
+                    IF (err != NC_NOERR) {
+                        error("ncmpi_get_var1_$1_all: %s", ncmpi_strerror(err));
+                    } else {
+                        IF (!equal(value,expect,var_type[i],NCT_ITYPE($1))) {
+                            error("Var value read not that expected");
+                            if (verbose) {
+                                error("\n");
+                                error("varid: %d, ", i);
+                                error("var_name: %s, ", var_name[i]);
+                                error("var_type: %s, ", s_nc_type(var_type[i]));
+                                error("index:");
+                                for (d = 0; d < var_rank[i]; d++)
+                                    error(" %d", index[d]);
+                                error(", expect: %g, ", expect);
+                                error("got: %g", (double) value);
+                            }
+                        } else {
+                            ++nok;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+')dnl
+
+CHECK_VARS(text)
+CHECK_VARS(uchar)
+CHECK_VARS(schar)
+CHECK_VARS(short)
+CHECK_VARS(int)
+CHECK_VARS(long)
+CHECK_VARS(float)
+CHECK_VARS(double)
+CHECK_VARS(ushort)
+CHECK_VARS(uint)
+CHECK_VARS(longlong)
+CHECK_VARS(ulonglong)
+
+
+dnl CHECK_ATTS(TYPE)         numeric only
+dnl
+define(`CHECK_ATTS',dnl
+`dnl
+/* 
+ *  check all attributes in file which are (text/numeric) compatible with TYPE
+ *  ignore any attributes containing values outside range of TYPE
+ */
+static
+int
+check_atts_$1(int  ncid)
+{
+    int  err;
+    int  i;
+    int  j;
+    MPI_Offset  k;
+    $1 value[MAX_NELS];
+    nc_type datatype;
+    MPI_Offset length;
+    size_t nInExtRange;  /* number values within external range */
+    size_t nInIntRange;  /* number values within internal range */
+    int canConvert;     /* Both text or both numeric */
+    int nok = 0;      /* count of valid comparisons */
+    double expect[MAX_NELS];
+
+    for (i = -1; i < numVars; i++) {
+        for (j = 0; j < NATTS(i); j++) {
+            canConvert = (ATT_TYPE(i,j) == NC_CHAR) CheckText($1);
+            if (!canConvert) continue;
+
+            err = ncmpi_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
+            IF (err != NC_NOERR)
+                error("ncmpi_inq_att: %s", ncmpi_strerror(err));
+            IF (datatype != ATT_TYPE(i,j))
+            error("ncmpi_inq_att: unexpected type");
+            IF (length != ATT_LEN(i,j))
+                error("ncmpi_inq_att: unexpected length");
+            assert(length <= MAX_NELS);
+            nInIntRange = nInExtRange = 0;
+            for (k = 0; k < length; k++) {
+                expect[k] = hash4( datatype, -1, &k, NCT_ITYPE($1));
+                if (inRange3(expect[k], datatype, NCT_ITYPE($1))) {
+                    ++nInExtRange;
+                    if (CheckRange($1, expect[k]))
+                        ++nInIntRange;
+                }
+            }
+            err = ncmpi_get_att_$1(ncid, i, ATT_NAME(i,j), value);
+            if (nInExtRange == length && nInIntRange == length) {
+                IF (err != NC_NOERR)
+                    error("%s", ncmpi_strerror(err));
+            } else {
+                IF (err != NC_NOERR && err != NC_ERANGE)
+                    error("OK or Range error: err = %d", err);
+            }
+            for (k = 0; k < length; k++) {
+                if (CheckNumRange($1, expect[k], datatype)) {
+                    IF (!equal(value[k],expect[k],datatype,NCT_ITYPE($1))) {
+                        error("att. value read not that expected");
+                        if (verbose) {
+                            error("\n");
+                            error("varid: %d, ", i);
+                            error("att_name: %s, ", ATT_NAME(i,j));
+                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
+                            error("element number: %d ", k);
+                            error("expect: %g, ", expect[k]);
+                            error("got: %g", (double) value[k]);
+                        }
+                    } else {
+                        nok++;
+                    }
+                }
+            }                                               
+        }                                               
+    }
+    return nok;
+}
+')dnl
+
+CHECK_ATTS(text)
+CHECK_ATTS(uchar)
+CHECK_ATTS(schar)
+CHECK_ATTS(short)
+CHECK_ATTS(int)
+CHECK_ATTS(long)
+CHECK_ATTS(float)
+CHECK_ATTS(double)
+CHECK_ATTS(ushort)
+CHECK_ATTS(uint)
+CHECK_ATTS(longlong)
+CHECK_ATTS(ulonglong)
+
+
+dnl TEST_NC_PUT_VAR1(TYPE)
+dnl
+define(`TEST_NC_PUT_VAR1',dnl
+`dnl
+int
+test_ncmpi_put_var1_$1(void)
+{
+    int ncid, nok=0;
+    int i;
+    int j;
+    int err;
+    MPI_Offset index[MAX_RANK];
+    int canConvert;        /* Both text or both numeric */
+    $1 value = 5;        /* any value would do - only for error cases */
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        for (j = 0; j < var_rank[i]; j++)
+            index[j] = 0;
+        err = ncmpi_put_var1_$1_all(BAD_ID, i, index, &value);
+        IF (err != NC_EBADID) 
+            error("expecting NC_EBADID (bad ncid), but err = %s", nc_err_code_name(err));
+        ELSE_NOK
+        err = ncmpi_put_var1_$1_all(ncid, BAD_VARID, index, &value);
+        IF (err != NC_ENOTVAR) 
+            error("expecting NC_ENOTVAR (bad var id), but err = %s", nc_err_code_name(err));
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                index[j] = var_shape[i][j];     /* out of boundary check */
+                err = ncmpi_put_var1_$1_all(ncid, i, index, &value);
+                IF (canConvert && err != NC_EINVALCOORDS)
+                    error("expecting NC_EINVALCOORDS (bad index), but err = %s", nc_err_code_name(err));
+                ELSE_NOK
+                index[j] = 0;
+            }
+        }
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR) 
+                error("error in toMixedBase 1");
+            value = hash_$1( var_type[i], var_rank[i], index, NCT_ITYPE($1));
+            if (var_rank[i] == 0 && i%2 == 0)
+                err = ncmpi_put_var1_$1_all(ncid, i, NULL, &value);
+            else
+                err = ncmpi_put_var1_$1_all(ncid, i, index, &value);
+            if (canConvert) {
+                if (CheckRange3($1, value, var_type[i])) {
+                    IF (err != NC_NOERR)
+                        error("%s", ncmpi_strerror(err));
+                    ELSE_NOK
+                } else {
+                    IF (err != NC_ERANGE) {
+                        error("Range error: err = %d", err);
+                        error("\n\t\tfor type %s value %.17e %ld",
+                                s_nc_type(var_type[i]),
+                                (double)value, (long)value);
+                    }
+                    ELSE_NOK
+                }
+            } else {
+                IF (err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    nok += check_vars_$1(scratch);
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+')dnl
+
+TEST_NC_PUT_VAR1(text)
+TEST_NC_PUT_VAR1(uchar)
+TEST_NC_PUT_VAR1(schar)
+TEST_NC_PUT_VAR1(short)
+TEST_NC_PUT_VAR1(int)
+TEST_NC_PUT_VAR1(long)
+TEST_NC_PUT_VAR1(float)
+TEST_NC_PUT_VAR1(double)
+TEST_NC_PUT_VAR1(ushort)
+TEST_NC_PUT_VAR1(uint)
+TEST_NC_PUT_VAR1(longlong)
+TEST_NC_PUT_VAR1(ulonglong)
+
+
+dnl TEST_NC_PUT_VAR(TYPE)
+dnl
+define(`TEST_NC_PUT_VAR',dnl
+`dnl
+int
+test_ncmpi_put_var_$1(void)
+{
+    int ncid, nok=0;
+    int varid;
+    int i;
+    int j;
+    int err;
+    int nels;
+    MPI_Offset index[MAX_RANK];
+    int canConvert;        /* Both text or both numeric */
+    int allInExtRange;        /* all values within external range? */
+    $1 value[MAX_NELS];
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        err = ncmpi_put_var_$1_all(BAD_ID, i, value);
+        IF (err != NC_EBADID) 
+            error("expecting bad ncid, but err = %d", err);
+        ELSE_NOK
+        err = ncmpi_put_var_$1_all(ncid, BAD_VARID, value);
+        IF (err != NC_ENOTVAR) 
+            error("expecting bad var id, but err = %d", err);
+        ELSE_NOK
+
+        nels = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            nels *= var_shape[i][j];
+        }
+        for (allInExtRange = 1, j = 0; j < nels; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR) 
+                error("error in toMixedBase 1");
+            value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+            IfCheckTextChar($1, var_type[i])
+                allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+        }
+        err = ncmpi_put_var_$1_all(ncid, i, value);
+        if (canConvert) {
+            if (allInExtRange) {
+                IF (err != NC_NOERR) 
+                    error("%s", ncmpi_strerror(err));
+                ELSE_NOK
+            } else {
+                IF (err != NC_ERANGE && var_dimid[i][0] != RECDIM)
+                    error("expecting range error, but err = %d", err);
+                ELSE_NOK
+            }
+        } else { /* should flag wrong type even if nothing to write */
+            IF (nels > 0 && err != NC_ECHAR)
+                error("wrong type: err = %d", err);
+            ELSE_NOK
+        }
+    }
+
+    /* Preceeding has written nothing for record variables, now try */
+    /* again with more than 0 records */
+
+    /* Write record number NRECS to force writing of preceding records */
+    /* Assumes variable cr is char vector with UNLIMITED dimension */
+    err = ncmpi_inq_varid(ncid, "cr", &varid);
+    IF (err != NC_NOERR)
+        error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
+    index[0] = NRECS-1;
+    err = ncmpi_put_var1_text_all(ncid, varid, index, "x");
+    IF (err != NC_NOERR)
+        error("ncmpi_put_var1_text_all: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        if (var_dimid[i][0] == RECDIM) {  /* only test record variables here */
+            canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+            assert(var_rank[i] <= MAX_RANK);
+            assert(var_nels[i] <= MAX_NELS);
+            err = ncmpi_put_var_$1_all(BAD_ID, i, value);
+            IF (err != NC_EBADID) 
+                error("expecting bad ncid, but err = %d", err);
+            ELSE_NOK
+
+            nels = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                nels *= var_shape[i][j];
+            }
+            for (allInExtRange = 1, j = 0; j < nels; j++) {
+                err = toMixedBase(j, var_rank[i], var_shape[i], index);
+                IF (err != NC_NOERR) 
+                    error("error in toMixedBase 1");
+                ELSE_NOK
+                value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+                IfCheckTextChar($1, var_type[i])
+                    allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+            }
+            err = ncmpi_put_var_$1_all(ncid, i, value);
+            if (canConvert) {
+                if (allInExtRange) {
+                    IF (err != NC_NOERR) 
+                        error("%s", ncmpi_strerror(err));
+                    ELSE_NOK
+                } else {
+                    IF (err != NC_ERANGE)
+                        error("expecting range error, but err = %d", err);
+                    ELSE_NOK
+                }
+            } else {
+                IF (nels > 0 && err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    nok += check_vars_$1(scratch);
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+')dnl
+
+TEST_NC_PUT_VAR(text)
+TEST_NC_PUT_VAR(uchar)
+TEST_NC_PUT_VAR(schar)
+TEST_NC_PUT_VAR(short)
+TEST_NC_PUT_VAR(int)
+TEST_NC_PUT_VAR(long)
+TEST_NC_PUT_VAR(float)
+TEST_NC_PUT_VAR(double)
+TEST_NC_PUT_VAR(ushort)
+TEST_NC_PUT_VAR(uint)
+TEST_NC_PUT_VAR(longlong)
+TEST_NC_PUT_VAR(ulonglong)
+
+
+dnl TEST_NC_PUT_VARA(TYPE)
+dnl
+define(`TEST_NC_PUT_VARA',dnl
+`dnl
+int
+test_ncmpi_put_vara_$1(void)
+{
+    int ncid, nok=0;
+    int d;
+    int i;
+    int j;
+    int k;
+    int err;
+    int nslabs;
+    int nels;
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    int canConvert;        /* Both text or both numeric */
+    int allInExtRange;        /* all values within external range? */
+    $1 value[MAX_NELS];
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    value[0] = 0;
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+        }
+        err = ncmpi_put_vara_$1_all(BAD_ID, i, start, edge, value);
+        IF (err != NC_EBADID) 
+            error("expecting bad ncid, but err = %d", err);
+        ELSE_NOK
+        err = ncmpi_put_vara_$1_all(ncid, BAD_VARID, start, edge, value);
+        IF (err != NC_ENOTVAR) 
+            error("expecting bad var id, but err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                start[j] = var_shape[i][j];
+                err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value);
+                IF (canConvert && err != NC_EINVALCOORDS)
+                    error("expecting bad start, but err = %d", err);
+                ELSE_NOK
+                start[j] = 0;
+                edge[j] = var_shape[i][j] + 1;
+                err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value);
+                IF (canConvert && err != NC_EEDGE)
+                    error("expecting bad edge, but err = %d", err);
+                ELSE_NOK
+                edge[j] = 1;
+            }
+        }
+
+        /* Check correct error returned even when nothing to put */
+        for (j = 0; j < var_rank[i]; j++) {
+            edge[j] = 0;
+        }
+        err = ncmpi_put_vara_$1_all(BAD_ID, i, start, edge, value);
+        IF (err != NC_EBADID) 
+            error("expecting bad ncid, but err = %d", err);
+        ELSE_NOK
+        err = ncmpi_put_vara_$1_all(ncid, BAD_VARID, start, edge, value);
+        IF (err != NC_ENOTVAR) 
+            error("expecting bad var id, but err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                start[j] = var_shape[i][j];
+                err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value);
+                IF (canConvert && err != NC_EINVALCOORDS)
+                    error("expecting bad start, but err = %d", err);
+                ELSE_NOK
+                start[j] = 0;
+            }
+        }
+
+/* wkliao: this test below of put_vara is redundant and incorrectly uses the
+           value[] set from the previously iteration. There is no such test
+           in put_vars and put_varm.
+
+        err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value);
+        if (canConvert) {
+            IF (err != NC_NOERR)
+                error("%s", ncmpi_strerror(err));
+            ELSE_NOK
+        } else {
+            IF (err != NC_ECHAR)
+                error("wrong type: err = %d", err);
+            ELSE_NOK
+        }
+*/
+        for (j = 0; j < var_rank[i]; j++) {
+            edge[j] = 1;
+        }
+
+        /* Choose a random point dividing each dim into 2 parts */
+        /* Put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to put lower or upper part of dim */
+        for (k = 0; k < nslabs; k++) {
+            nels = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                nels *= edge[j];
+            }
+            for (allInExtRange = 1, j = 0; j < nels; j++) {
+                err = toMixedBase(j, var_rank[i], edge, index);
+                IF (err != NC_NOERR) 
+                    error("error in toMixedBase 1");
+                for (d = 0; d < var_rank[i]; d++) 
+                    index[d] += start[d];
+                value[j]= hash_$1(var_type[i], var_rank[i], index, NCT_ITYPE($1));
+                IfCheckTextChar($1, var_type[i])
+                    allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+            }
+            if (var_rank[i] == 0 && i%2 == 0)
+                err = ncmpi_put_vara_$1_all(ncid, i, NULL, NULL, value);
+            else
+                err = ncmpi_put_vara_$1_all(ncid, i, start, edge, value);
+            if (canConvert) {
+                if (allInExtRange) {
+                    IF (err != NC_NOERR) 
+                        error("%s", ncmpi_strerror(err));
+                    ELSE_NOK
+                } else {
+                    IF (err != NC_ERANGE)
+                        error("expecting range error, but err = %d", err);
+                    ELSE_NOK
+                }
+            } else {
+                IF (nels > 0 && err != NC_ECHAR)
+                    error("wrong type: err = %d", err);
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    nok += check_vars_$1(scratch);
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+')dnl
+
+TEST_NC_PUT_VARA(text)
+TEST_NC_PUT_VARA(uchar)
+TEST_NC_PUT_VARA(schar)
+TEST_NC_PUT_VARA(short)
+TEST_NC_PUT_VARA(int)
+TEST_NC_PUT_VARA(long)
+TEST_NC_PUT_VARA(float)
+TEST_NC_PUT_VARA(double)
+TEST_NC_PUT_VARA(ushort)
+TEST_NC_PUT_VARA(uint)
+TEST_NC_PUT_VARA(longlong)
+TEST_NC_PUT_VARA(ulonglong)
+
+
+dnl TEST_NC_PUT_VARS(TYPE)
+dnl
+define(`TEST_NC_PUT_VARS',dnl
+`dnl
+int
+test_ncmpi_put_vars_$1(void)
+{
+    int ncid, nok=0;
+    int d;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err;
+    int nels;
+    int nslabs;
+    int nstarts;        /* number of different starts */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    int canConvert;        /* Both text or both numeric */
+    int allInExtRange;        /* all values within external range? */
+    $1 value[MAX_NELS];
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+        }
+        err = ncmpi_put_vars_$1_all(BAD_ID, i, start, edge, stride, value);
+        IF (err != NC_EBADID) 
+            error("expecting bad ncid, but err = %d", err);
+        ELSE_NOK
+        err = ncmpi_put_vars_$1_all(ncid, BAD_VARID, start, edge, stride, value);
+        IF (err != NC_ENOTVAR) 
+            error("expecting bad var id, but err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                start[j] = var_shape[i][j];
+                err = ncmpi_put_vars_$1_all(ncid, i, start, edge, stride, value);
+                if (!canConvert) {
+                    IF (err != NC_ECHAR)
+                        error("conversion: err = %d", err);
+                    ELSE_NOK
+                } else {
+                    IF (err != NC_EINVALCOORDS)
+                        error("expecting bad start, but err = %d", err);
+                    ELSE_NOK
+                    start[j] = 0;
+                    edge[j] = var_shape[i][j] + 1;
+                    err = ncmpi_put_vars_$1_all(ncid, i, start, edge, stride, value);
+                    IF (err != NC_EEDGE)
+                        error("expecting bad edge, but err = %d", err);
+                    ELSE_NOK
+                    edge[j] = 1;
+                    stride[j] = 0;
+                    err = ncmpi_put_vars_$1_all(ncid, i, start, edge, stride, value);
+                    IF (err != NC_ESTRIDE)
+                        error("expecting bad stride, but err = %d", err);
+                    ELSE_NOK
+                    stride[j] = 1;
+                }
+            }
+        }
+
+        /* Choose a random point dividing each dim into 2 parts */
+        /* Put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to put lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+*/
+                for (allInExtRange = 1, j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != NC_NOERR)
+                        error("error in toMixedBase");
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * stride[d];
+                    value[j] = hash_$1(var_type[i], var_rank[i], index2, 
+                        NCT_ITYPE($1));
+                    IfCheckTextChar($1, var_type[i])
+                        allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+                }
+                if (var_rank[i] == 0 && i%2 == 0)
+                    err = ncmpi_put_vars_$1_all(ncid, i, NULL, NULL, stride, value);
+                else
+                    err = ncmpi_put_vars_$1_all(ncid, i, index, count, stride, value);
+                if (canConvert) {
+                    if (allInExtRange) {
+                        IF (err != NC_NOERR) 
+                            error("%s", ncmpi_strerror(err));
+                        ELSE_NOK
+                    } else {
+                        IF (err != NC_ERANGE)
+                            error("expecting range error, but err = %d", err);
+                        ELSE_NOK
+                    }
+                } else {
+                    IF (nels > 0 && err != NC_ECHAR)
+                        error("wrong type: err = %d", err);
+                    ELSE_NOK
+                }
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    nok += check_vars_$1(scratch);
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+')dnl
+
+TEST_NC_PUT_VARS(text)
+TEST_NC_PUT_VARS(uchar)
+TEST_NC_PUT_VARS(schar)
+TEST_NC_PUT_VARS(short)
+TEST_NC_PUT_VARS(int)
+TEST_NC_PUT_VARS(long)
+TEST_NC_PUT_VARS(float)
+TEST_NC_PUT_VARS(double)
+TEST_NC_PUT_VARS(ushort)
+TEST_NC_PUT_VARS(uint)
+TEST_NC_PUT_VARS(longlong)
+TEST_NC_PUT_VARS(ulonglong)
+
+
+dnl TEST_NC_PUT_VARM(TYPE)
+dnl
+define(`TEST_NC_PUT_VARM',dnl
+`dnl
+int
+test_ncmpi_put_varm_$1(void)
+{
+    int ncid, nok=0;
+    int d;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err;
+    int nels;
+    int nslabs;
+    int nstarts;        /* number of different starts */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    MPI_Offset imap[MAX_RANK];
+    int canConvert;        /* Both text or both numeric */
+    int allInExtRange;        /* all values within external range? */
+    $1 value[MAX_NELS];
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        canConvert = (var_type[i] == NC_CHAR) CheckText($1);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+            imap[j] = 1;
+        }
+        err = ncmpi_put_varm_$1_all(BAD_ID, i, start, edge, stride, imap, value);
+        IF (err != NC_EBADID) 
+            error("expecting bad ncid, but err = %d", err);
+        ELSE_NOK
+        err = ncmpi_put_varm_$1_all(ncid, BAD_VARID, start, edge, stride, imap, value);
+        IF (err != NC_ENOTVAR) 
+            error("expecting bad var id, but err = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {                /* skip record dim */
+                start[j] = var_shape[i][j];
+                err = ncmpi_put_varm_$1_all(ncid, i, start, edge, stride, imap, value);
+                if (!canConvert) {
+                    IF (err != NC_ECHAR)
+                        error("conversion: err = %d", err);
+                    ELSE_NOK
+                } else {
+                    IF (err != NC_EINVALCOORDS)
+                        error("expecting bad start, but err = %d", err);
+                    ELSE_NOK
+                    start[j] = 0;
+                    edge[j] = var_shape[i][j] + 1;
+                    err = ncmpi_put_varm_$1_all(ncid, i, start, edge, stride, imap, value);
+                    IF (err != NC_EEDGE)
+                        error("expecting bad edge, but err = %d", err);
+                    ELSE_NOK
+                    edge[j] = 1;
+                    stride[j] = 0;
+                    err = ncmpi_put_varm_$1_all(ncid, i, start, edge, stride, imap, value);
+                    IF (err != NC_ESTRIDE)
+                        error("expecting bad stride, but err = %d", err);
+                    ELSE_NOK
+                    stride[j] = 1;
+                }
+            }
+        }
+
+        /* Choose a random point dividing each dim into 2 parts */
+        /* Put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to put lower or upper part of dim */
+        /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                } else {
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+*/
+                if (var_rank[i] > 0) {
+                    j = var_rank[i] - 1;
+                    imap[j] = 1;
+                    for (; j > 0; j--)
+                        imap[j-1] = imap[j] * count[j];
+                }
+                for (allInExtRange = 1, j = 0; j < nels; j++) {
+                    err = toMixedBase(j, var_rank[i], count, index2);
+                    IF (err != NC_NOERR)
+                        error("error in toMixedBase");
+                    for (d = 0; d < var_rank[i]; d++)
+                        index2[d] = index[d] + index2[d] * stride[d];
+                    value[j] = hash_$1(var_type[i], var_rank[i], index2,
+                        NCT_ITYPE($1));
+                    IfCheckTextChar($1, var_type[i])
+                        allInExtRange &= inRange3(value[j], var_type[i], NCT_ITYPE($1));
+                }
+                if (var_rank[i] == 0 && i%2 == 0)
+                    err = ncmpi_put_varm_$1_all(ncid,i,NULL,NULL,NULL,NULL,value);
+                else
+                    err = ncmpi_put_varm_$1_all(ncid,i,index,count,stride,imap,value);
+                if (canConvert) {
+                    if (allInExtRange) {
+                        IF (err != NC_NOERR)
+                            error("%s", ncmpi_strerror(err));
+                        ELSE_NOK
+                    } else {
+                        IF (err != NC_ERANGE)
+                            error("expecting range error, but err = %d", err);
+                        ELSE_NOK
+                    }
+                } else {
+                    IF (nels > 0 && err != NC_ECHAR)
+                        error("wrong type: err = %d", err);
+                    ELSE_NOK
+                }
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    nok += check_vars_$1(scratch);
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+')dnl
+
+TEST_NC_PUT_VARM(text)
+TEST_NC_PUT_VARM(uchar)
+TEST_NC_PUT_VARM(schar)
+TEST_NC_PUT_VARM(short)
+TEST_NC_PUT_VARM(int)
+TEST_NC_PUT_VARM(long)
+TEST_NC_PUT_VARM(float)
+TEST_NC_PUT_VARM(double)
+TEST_NC_PUT_VARM(ushort)
+TEST_NC_PUT_VARM(uint)
+TEST_NC_PUT_VARM(longlong)
+TEST_NC_PUT_VARM(ulonglong)
+
+
+int
+test_ncmpi_put_att_text(void)
+{
+    int ncid, nok=0;
+    int i;
+    int j;
+    MPI_Offset k;
+    int err;
+    text value[MAX_NELS];
+
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+
+    {
+        const char *const tval = "value for bad name";
+        const size_t tval_len = strlen(tval);
+        
+        err = ncmpi_put_att_text(ncid, 0, "", tval_len, tval);
+        IF (err != NC_EBADNAME)
+           error("should be NC_EBADNAME: err = %d", err);
+        ELSE_NOK
+    }
+    for (i = -1; i < numVars; i++) {
+        for (j = 0; j < NATTS(i); j++) {
+            if (ATT_TYPE(i,j) == NC_CHAR) {
+                assert(ATT_LEN(i,j) <= MAX_NELS);
+                err = ncmpi_put_att_text(BAD_ID, i, ATT_NAME(i,j), ATT_LEN(i,j), 
+                    value);
+                IF (err != NC_EBADID)
+                    error("expecting bad ncid, but err = %d", err);
+                ELSE_NOK
+                err = ncmpi_put_att_text(ncid, BAD_VARID, ATT_NAME(i,j), 
+                    ATT_LEN(i,j), value);
+                IF (err != NC_ENOTVAR)
+                    error("expecting bad var id, but err = %d", err);
+                ELSE_NOK
+                for (k = 0; k < ATT_LEN(i,j); k++) {
+                    value[k] = hash(ATT_TYPE(i,j), -1, &k);
+                }
+                err = ncmpi_put_att_text(ncid, i, ATT_NAME(i,j), 
+                    ATT_LEN(i,j), value);
+                IF (err != NC_NOERR)
+                    error("%s", ncmpi_strerror(err));
+                ELSE_NOK
+            }
+        }
+    }
+
+    nok += check_atts_text(ncid);
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+dnl TEST_NC_PUT_ATT(TYPE)         numeric only
+dnl
+define(`TEST_NC_PUT_ATT',dnl
+`dnl
+int
+test_ncmpi_put_att_$1(void)
+{
+    int ncid, nok=0;
+    int i;
+    int j;
+    MPI_Offset k;
+    int err;
+    $1 value[MAX_NELS];
+    int allInExtRange;  /* all values within external range? */
+
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+
+    for (i = -1; i < numVars; i++) {
+        for (j = 0; j < NATTS(i); j++) {
+            if (!(ATT_TYPE(i,j) == NC_CHAR)) {
+                assert(ATT_LEN(i,j) <= MAX_NELS);
+                err = ncmpi_put_att_$1(BAD_ID, i, ATT_NAME(i,j), ATT_TYPE(i,j), 
+                    ATT_LEN(i,j), value);
+                IF (err != NC_EBADID)
+                    error("expecting bad ncid, but err = %d", err);
+                ELSE_NOK
+                err = ncmpi_put_att_$1(ncid, BAD_VARID, ATT_NAME(i,j), 
+                    ATT_TYPE(i,j), ATT_LEN(i,j), value);
+                IF (err != NC_ENOTVAR)
+                    error("expecting bad var id, but err = %d", err);
+                ELSE_NOK
+                err = ncmpi_put_att_$1(ncid, i, ATT_NAME(i,j), BAD_TYPE, 
+                    ATT_LEN(i,j), value);
+                IF (err != NC_EBADTYPE)
+                    error("expecting bad type, but err = %d", err);
+                ELSE_NOK
+                for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
+                    value[k] = hash_$1(ATT_TYPE(i,j), -1, &k, NCT_ITYPE($1));
+                    IfCheckTextChar($1, ATT_TYPE(i,j))
+                        allInExtRange &= inRange3(value[k], ATT_TYPE(i,j), NCT_ITYPE($1));
+                }
+                err = ncmpi_put_att_$1(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j),
+                    ATT_LEN(i,j), value);
+                if (allInExtRange) {
+                    IF (err != NC_NOERR)
+                        error("%s", ncmpi_strerror(err));
+                    ELSE_NOK
+                } else {
+                    IF (err != NC_ERANGE)
+                        error("expecting range error, but err = %d", err);
+                    ELSE_NOK
+                }
+            }
+        }
+    }
+
+    nok += check_atts_$1(ncid);
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+')dnl
+
+TEST_NC_PUT_ATT(uchar)
+TEST_NC_PUT_ATT(schar)
+TEST_NC_PUT_ATT(short)
+TEST_NC_PUT_ATT(int)
+TEST_NC_PUT_ATT(long)
+TEST_NC_PUT_ATT(float)
+TEST_NC_PUT_ATT(double)
+TEST_NC_PUT_ATT(ushort)
+TEST_NC_PUT_ATT(uint)
+TEST_NC_PUT_ATT(longlong)
+TEST_NC_PUT_ATT(ulonglong)
+
diff --git a/test/nc_test/test_read.c b/test/nc_test/test_read.c
new file mode 100644
index 0000000..18c9169
--- /dev/null
+++ b/test/nc_test/test_read.c
@@ -0,0 +1,1792 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: test_read.c 2297 2016-01-06 22:22:33Z wkliao $
+ */
+
+#include <sys/types.h> /* open() */
+#include <sys/stat.h> /* open() */
+#include <fcntl.h> /* open() */
+#include <unistd.h> /* unlink(), write() */
+#include "tests.h"
+
+/* 
+ * Test ncmpi_strerror.
+ *    Try on a bad error status.
+ *    Test for each defined error status.
+ */
+int
+test_ncmpi_strerror(void)
+{
+    int i;
+    const char *message, *expected_msg;
+    int nok=0;
+
+    static const struct {
+	int status;
+	const char *msg;
+    } ncerrs[] = {
+        {NC_NOERR, "No error"},
+        {NC_EBADID, "NetCDF: Not a valid ID"},
+        {NC_ENFILE, "NetCDF: Too many files open"},
+        {NC_EEXIST, "NetCDF: File exists && NC_NOCLOBBER"},
+        {NC_EINVAL, "NetCDF: Invalid argument"},
+        {NC_EPERM, "NetCDF: Write to read only"},
+        {NC_ENOTINDEFINE, "NetCDF: Operation not allowed in data mode"},
+        {NC_EINDEFINE, "NetCDF: Operation not allowed in define mode"},
+        {NC_EINVALCOORDS, "NetCDF: Index exceeds dimension bound"},
+        {NC_EMAXDIMS, "NetCDF: NC_MAX_DIMS exceeded"},
+        {NC_ENAMEINUSE, "NetCDF: String match to name in use"},
+        {NC_ENOTATT, "NetCDF: Attribute not found"},
+        {NC_EMAXATTS, "NetCDF: NC_MAX_ATTRS exceeded"},
+        {NC_EBADTYPE, "NetCDF: Not a valid data type or _FillValue type mismatch"},
+        {NC_EBADDIM, "NetCDF: Invalid dimension ID or name"},
+        {NC_EUNLIMPOS, "NetCDF: NC_UNLIMITED in the wrong index"},
+        {NC_EMAXVARS, "NetCDF: NC_MAX_VARS exceeded"},
+        {NC_ENOTVAR, "NetCDF: Variable not found"},
+        {NC_EGLOBAL, "NetCDF: Action prohibited on NC_GLOBAL varid"},
+        {NC_ENOTNC, "NetCDF: Unknown file format"},
+        {NC_ESTS, "NetCDF: In Fortran, string too short"},
+        {NC_EMAXNAME, "NetCDF: NC_MAX_NAME exceeded"},
+        {NC_EUNLIMIT, "NetCDF: NC_UNLIMITED size already in use"},
+        {NC_ENORECVARS, "NetCDF: nc_rec op when there are no record vars"},
+        {NC_ECHAR, "NetCDF: Attempt to convert between text & numbers"},
+        {NC_EEDGE, "NetCDF: Start+count exceeds dimension bound"},
+        {NC_ESTRIDE, "NetCDF: Illegal stride"},
+        {NC_EBADNAME, "NetCDF: Name contains illegal characters"},
+        {NC_ERANGE, "NetCDF: Numeric conversion not representable"},
+        {NC_ENOMEM, "NetCDF: Memory allocation (malloc) failure"},
+        {NC_EVARSIZE, "NetCDF: One or more variable sizes violate format constraints"},
+        {NC_EDIMSIZE, "NetCDF: Invalid dimension size"}
+    };
+
+    /* Try on a bad error status */
+    message = ncmpi_strerror(-666);/* should fail */
+    expected_msg = "Unknown Error";
+    IF (strncmp(message, expected_msg, strlen(expected_msg)) != 0)
+	error("ncmpi_strerror on bad error status returned: %s", message);
+    ELSE_NOK
+
+    /* Try on each legitimate error status */
+    for (i=0; i<LEN_OF(ncerrs); i++) {
+	const char *message = ncmpi_strerror(ncerrs[i].status);
+	IF (strcmp(message, ncerrs[i].msg) != 0)
+	    error("ncmpi_strerror(%d) should return `%s', not `%s'",
+		  ncerrs[i].status, ncerrs[i].msg, message);
+        ELSE_NOK
+    }
+    return nok;
+}
+
+
+/* 
+ * Test ncmpi_open.
+ * If in read-only section of tests,
+ *    Try to open a non-existent netCDF file, check error return.
+ *    Open a file that is not a netCDF file, check error return.
+ *    Open a netCDF file with a bad mode argument, check error return.
+ *    Open a netCDF file with NC_NOWRITE, info mode, try to write, check error.
+ *    Try to open a netcdf twice, check whether returned netcdf ids different.
+ * If in writable section of tests,
+ *    Open a netCDF file with NC_WRITE mode, write something, close it.
+ * On exit, any open netCDF files are closed.
+ */
+#define NOT_NC_FILE "dummy_not_nc_file"
+int
+test_ncmpi_open(void)
+{
+    int err, fd;
+    int ncid;
+    int ncid2;
+    int nok=0;
+    ssize_t w_len;
+    
+    /* Try to open a nonexistent file */
+    err = ncmpi_open(comm, "tooth-fairy.nc", NC_NOWRITE, info, &ncid);/* should fail */
+
+    /* on some systems, opening an nonexisting file will actually create the
+     * file. In this case, we print the error messages on screen and move on
+     * to the next test, instead of aborting the entire test.
+     */
+    if (err == NC_NOERR)
+ 	fprintf(stderr, "opening a nonexistent file expects to fail, but got NC_NOERR\n");
+    else if (err != NC_ENOENT)
+	fprintf(stderr, "opening a nonexistent file expects NC_ENOENT, but got %s\n",nc_err_code_name(err));
+    else {
+        /* printf("Expected error message complaining: \"File tooth-fairy.nc does not exist\"\n"); */
+        nok++;
+    }
+
+    /* create a not-nc file */
+    fd = open(NOT_NC_FILE, O_CREAT|O_WRONLY, 0600);
+    w_len = write(fd, "0123456789abcdefghijklmnopqrstuvwxyz", 36);
+    assert(w_len >= 0);
+    close(fd);
+
+    /* Open a file that is not a netCDF file. */
+    err = ncmpi_open(comm, NOT_NC_FILE, NC_NOWRITE, info, &ncid);/* should fail */
+    IF (err != NC_ENOTNC)
+	error("ncmpi_open of non-netCDF file: expecting NC_ENOTNC but got %s", nc_err_code_name(err));
+    ELSE_NOK
+
+    /* delete the not-nc file */
+    unlink(NOT_NC_FILE);
+
+    /* Open a netCDF file in read-only mode, check that write fails */
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    ELSE_NOK
+    err = ncmpi_redef(ncid);	/* should fail */
+    IF (err != NC_EPERM)
+	error("ncmpi_redef of read-only file should fail");
+    /* Opened OK, see if can open again and get a different netCDF ID */
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid2);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    else {
+	ncmpi_close(ncid2);
+        nok++;
+    }
+    IF (ncid2 == ncid)
+	error("netCDF IDs for first and second ncmpi_open calls should differ");
+
+    if (! read_only) {		/* tests using netCDF scratch file */
+	err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid2);
+	IF (err != NC_NOERR) 
+	    error("ncmpi_create: %s", ncmpi_strerror(err));
+	else 
+	    ncmpi_close(ncid2);
+	err = ncmpi_open(comm, scratch, NC_WRITE, info, &ncid2);
+	IF (err != NC_NOERR) 
+	    error("ncmpi_open: %s", ncmpi_strerror(err));
+	else {
+	    ncmpi_close(ncid2);
+            nok++;
+        }
+	err = ncmpi_delete(scratch, info);
+	IF (err != NC_NOERR) 
+	    error("remove of %s failed", scratch);
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+/* 
+ * Test ncmpi_close.
+ *    Try to close a netCDF file twice, check whether second close fails.
+ *    Try on bad handle, check error return.
+ *    Try in define mode and data mode.
+ */
+int
+test_ncmpi_close(void)
+{
+    int ncid, nok=0;
+    int err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    /* Close a netCDF file twice, second time should fail */
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close failed: %s", ncmpi_strerror(err));
+    ELSE_NOK
+    err = ncmpi_close(ncid);
+    IF (err != NC_EBADID)
+	error("ncmpi_close of closed file should have failed");
+    ELSE_NOK
+    
+    /* Try with a bad netCDF ID */
+    err = ncmpi_close(BAD_ID);/* should fail */
+    IF (err != NC_EBADID)
+	error("ncmpi_close with bad netCDF ID returned wrong error (%d)", err);
+    ELSE_NOK
+
+    /* Close in data mode */
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close in data mode failed: %s", ncmpi_strerror(err));
+    ELSE_NOK
+
+    if (! read_only) {		/* tests using netCDF scratch file */
+        err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+        IF (err != NC_NOERR) 
+            error("ncmpi_create: %s", ncmpi_strerror(err));
+	err = ncmpi_close(ncid);
+	IF (err != NC_NOERR)
+	    error("ncmpi_close in define mode: %s", ncmpi_strerror(err));
+        ELSE_NOK
+        err = ncmpi_delete(scratch, info);
+        IF (err != NC_NOERR)
+            error("remove of %s failed", scratch);
+    }
+    return nok;
+}
+
+
+/* 
+ * Test ncmpi_inq.
+ *    Try on bad handle, check error return.
+ *    Try in data mode, check returned values.
+ *    Try asking for subsets of info.
+ * If in writable section of tests,
+ *    Try in define mode, after adding an unlimited dimension, variable.
+ * On exit, any open netCDF files are closed.
+ */
+int
+test_ncmpi_inq(void)
+{
+    int ncid;
+    int ndims;			/* number of dimensions */
+    int nvars;			/* number of variables */
+    int ngatts;			/* number of global attributes */
+    int recdim;			/* id of unlimited dimension */
+    int err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    int nok=0;
+
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    
+    /* Try on bad handle */
+    err = ncmpi_inq(BAD_ID, 0, 0, 0, 0);
+    IF (err != NC_EBADID)
+	error("bad ncid: status = %d", err);
+    ELSE_NOK
+    
+    err = ncmpi_inq(ncid, &ndims, &nvars, &ngatts, &recdim);
+    IF (err != NC_NOERR)
+	error("ncmpi_inq: %s", ncmpi_strerror(err));
+    else IF (ndims != NDIMS)
+	error("ncmpi_inq: wrong number of dimensions returned, %d", ndims);
+    else IF (nvars != numVars)
+	error("ncmpi_inq: wrong number of variables returned, %d", nvars);
+    else IF (ngatts != numGatts)
+	error("ncmpi_inq: wrong number of global atts returned, %d", ngatts);
+    else IF (recdim != RECDIM)
+	error("ncmpi_inq: wrong record dimension ID returned, %d", recdim);
+    ELSE_NOK
+    
+    /* Inguire for no info (useless, but should still work) */
+    err = ncmpi_inq(ncid, 0, 0, 0, 0);
+    IF (err != NC_NOERR)
+	error("ncmpi_inq for no info failed: %s", ncmpi_strerror(err));
+    ELSE_NOK
+
+    /* Inguire for subsets of info */
+    ngatts = numGatts - 1;	/* wipe out previous correct value */
+    err = ncmpi_inq(ncid, 0, 0, &ngatts, 0);
+    IF (err != NC_NOERR)
+	error("ncmpi_inq for one item failed: %s", ncmpi_strerror(err));
+    else IF (ngatts != numGatts)
+	error("ncmpi_inq subset: wrong number of global atts returned, %d", ngatts);
+    ELSE_NOK
+    ndims = NDIMS - 1;
+    nvars = numVars - 1;
+    err = ncmpi_inq(ncid, &ndims, &nvars, 0, 0);
+    IF (err != NC_NOERR)
+	error("ncmpi_inq for two items failed: %s", ncmpi_strerror(err));
+    else IF (ndims != NDIMS)
+	error("ncmpi_inq subset: wrong number of dimensions returned, %d", ndims);
+    else IF (nvars != numVars)
+	error("ncmpi_inq subset: wrong number of variables returned, %d", nvars);
+    ELSE_NOK
+
+    if (! read_only) {		/* tests using netCDF scratch file */
+	int ncid2;		/* for scratch netCDF dataset */
+
+        err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid2);
+        IF (err != NC_NOERR) {
+            error("ncmpi_create: %s", ncmpi_strerror(err));
+	} else {		/* add dim, var, gatt, check inq */
+	    int ndims0;
+	    int nvars0;
+	    int ngatts0;
+	    int recdim0;
+	    err = ncmpi_enddef(ncid2); /* enter data mode */
+	    err = ncmpi_inq(ncid2, &ndims0, &nvars0, &ngatts0, &recdim0);
+	    IF (err != NC_NOERR)
+		error("ncmpi_inq: %s", ncmpi_strerror(err));
+            ELSE_NOK
+	    err = ncmpi_redef(ncid2); /* enter define mode */
+	    /* Check that inquire still works in define mode */
+	    err = ncmpi_inq(ncid2, &ndims, &nvars, &ngatts, &recdim);
+	    IF (err != NC_NOERR)
+		error("ncmpi_inq in define mode: %s", ncmpi_strerror(err));
+	    else IF (ndims != ndims0)
+		error("ncmpi_inq in define mode: ndims wrong, %d", ndims);
+	    else IF (nvars != nvars0)
+		error("ncmpi_inq in define mode: nvars wrong, %d", nvars);
+	    else IF (ngatts != ngatts0)
+		error("ncmpi_inq in define mode: ngatts wrong, %d", ngatts);
+	    else IF (recdim != recdim0)
+		error("ncmpi_inq in define mode: recdim wrong, %d", recdim);
+            ELSE_NOK
+
+	    {
+		int did, vid;
+		/* Add dim, var, global att */
+		err = ncmpi_def_dim(ncid2, "inqd", 1L, &did);
+		IF (err != NC_NOERR)
+		    error("ncmpi_def_dim: %s", ncmpi_strerror(err));
+		err = ncmpi_def_var(ncid2, "inqv", NC_FLOAT, 0, 0, &vid);
+		IF (err != NC_NOERR)
+		    error("ncmpi_def_var: %s", ncmpi_strerror(err));
+	    }
+	    err = ncmpi_put_att_text(ncid2, NC_GLOBAL, "inqa", 1+strlen("stuff"),
+				   "stuff");
+	    IF (err != NC_NOERR)
+		error("ncmpi_put_att_text: %s", ncmpi_strerror(err));
+
+	    /* Make sure ncmpi_inq sees the additions while in define mode */
+	    err = ncmpi_inq(ncid2, &ndims, &nvars, &ngatts, &recdim);
+	    IF (err != NC_NOERR)
+		error("ncmpi_inq in define mode: %s", ncmpi_strerror(err));
+	    else IF (ndims != ndims0 + 1)
+		error("ncmpi_inq in define mode: ndims wrong, %d", ndims);
+	    else IF (nvars != nvars0 + 1)
+		error("ncmpi_inq in define mode: nvars wrong, %d", nvars);
+	    else IF (ngatts != ngatts0 + 1)
+		error("ncmpi_inq in define mode: ngatts wrong, %d", ngatts);
+            ELSE_NOK
+	    err = ncmpi_enddef(ncid2);
+	    IF (err != NC_NOERR)
+		error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+	    /* Make sure ncmpi_inq stills sees additions in data mode */
+	    err = ncmpi_inq(ncid2, &ndims, &nvars, &ngatts, &recdim);
+	    IF (err != NC_NOERR)
+		error("ncmpi_inq failed in data mode: %s", ncmpi_strerror(err));
+	    else IF (ndims != ndims0 + 1)
+		error("ncmpi_inq in define mode: ndims wrong, %d", ndims);
+	    else IF (nvars != nvars0 + 1)
+		error("ncmpi_inq in define mode: nvars wrong, %d", nvars);
+	    else IF (ngatts != ngatts0 + 1)
+		error("ncmpi_inq in define mode: ngatts wrong, %d", ngatts);
+            ELSE_NOK
+	    ncmpi_close(ncid2);
+	    err = ncmpi_delete(scratch, info);
+	    IF (err != NC_NOERR)
+		error("remove of %s failed", scratch);
+	}
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_natts(void)
+{
+    int ncid;
+    int ngatts;			/* number of global attributes */
+    int err, nok=0;
+
+    err = ncmpi_inq_natts(BAD_ID, &ngatts);
+    IF (err != NC_EBADID)
+	error("bad ncid: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_inq_natts(ncid, &ngatts);
+    IF (err != NC_NOERR)
+	error("ncmpi_inq_natts: %s", ncmpi_strerror(err));
+    else IF (ngatts != numGatts)
+	error("ncmpi_inq_natts: wrong number of global atts returned, %d", ngatts);
+    ELSE_NOK
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_ndims(void)
+{
+    int ncid;
+    int ndims;
+    int err;
+    int nok=0;
+
+    err = ncmpi_inq_ndims(BAD_ID, &ndims);
+    IF (err != NC_EBADID)
+	error("bad ncid: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_inq_ndims(ncid, &ndims);
+    IF (err != NC_NOERR)
+	error("ncmpi_inq_ndims: %s", ncmpi_strerror(err));
+    else IF (ndims != NDIMS)
+	error("ncmpi_inq_ndims: wrong number returned, %d", ndims);
+    ELSE_NOK
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_nvars(void)
+{
+    int ncid;
+    int nvars;
+    int err;
+    int nok=0;
+
+    err = ncmpi_inq_nvars(BAD_ID, &nvars);
+    IF (err != NC_EBADID)
+	error("bad ncid: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_inq_nvars(ncid, &nvars);
+    IF (err != NC_NOERR)
+	error("ncmpi_inq_nvars: %s", ncmpi_strerror(err));
+    else IF (nvars != numVars)
+	error("ncmpi_inq_nvars: wrong number returned, %d", nvars);
+    ELSE_NOK
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_unlimdim(void)
+{
+    int ncid;
+    int unlimdim;
+    int err;
+    int nok=0;
+
+    err = ncmpi_inq_unlimdim(BAD_ID, &unlimdim);
+    IF (err != NC_EBADID)
+	error("bad ncid: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_inq_unlimdim(ncid, &unlimdim);
+    IF (err != NC_NOERR)
+	error("ncmpi_inq_unlimdim: %s", ncmpi_strerror(err));
+    else IF (unlimdim != RECDIM)
+	error("ncmpi_inq_unlimdim: wrong number returned, %d", unlimdim);
+    ELSE_NOK
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_dimid(void)
+{
+    int ncid;
+    int dimid;
+    int i;
+    int err;
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_inq_dimid(ncid, "noSuch", &dimid);
+    IF (err != NC_EBADDIM)
+	error("bad dim name: status = %d", err);
+    ELSE_NOK
+    for (i = 0; i < NDIMS; i++) {
+	err = ncmpi_inq_dimid(BAD_ID, dim_name[i], &dimid);
+	IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_dimid(ncid, dim_name[i], &dimid);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_dimid: %s", ncmpi_strerror(err));
+	else IF (dimid != i)
+	    error("expected %d, got %d", i, dimid);
+        ELSE_NOK
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_dim(void)
+{
+    int ncid;
+    int i;
+    int err;
+    char name[NC_MAX_NAME];
+    MPI_Offset length;
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < NDIMS; i++) {
+	err = ncmpi_inq_dim(BAD_ID, i, name, &length);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_dim(ncid, BAD_DIMID, name, &length);
+        IF (err != NC_EBADDIM)
+	    error("bad dimid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_dim(ncid, i, 0, 0);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
+        ELSE_NOK
+	err = ncmpi_inq_dim(ncid, i, name, &length);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
+	else IF (strcmp(dim_name[i],name)) 
+	    error("name expected: %s, got: %s",dim_name[i],name);
+	else IF (dim_len[i] != length)
+	    error("size expected: %d, got: %d",dim_len[i],length);
+        ELSE_NOK
+	err = ncmpi_inq_dim(ncid, i, name, 0);
+        IF (err != NC_NOERR)
+	    error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
+	else IF (strcmp(dim_name[i],name)) 
+	    error("name expected: %s, got: %s",dim_name[i],name);
+        ELSE_NOK
+	err = ncmpi_inq_dim(ncid, i, 0, &length);
+        IF (err != NC_NOERR)
+	    error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
+	else IF (dim_len[i] != length)
+	    error("size expected: %d, got: %d",dim_len[i],length);
+        ELSE_NOK
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_dimlen(void)
+{
+    int ncid;
+    int i;
+    int err;
+    MPI_Offset  length;
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < NDIMS; i++) {
+	err = ncmpi_inq_dimlen(BAD_ID, i, &length);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_dimlen(ncid, BAD_DIMID, &length);
+        IF (err != NC_EBADDIM)
+	    error("bad dimid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_dimlen(ncid, i, &length);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_dimlen: %s", ncmpi_strerror(err));
+	else IF (dim_len[i] != length)
+	    error("size expected: %d, got: %d",dim_len[i],length);
+        ELSE_NOK
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_dimname(void)
+{
+    int ncid;
+    int i;
+    int err;
+    char name[NC_MAX_NAME];
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < NDIMS; i++) {
+	err = ncmpi_inq_dimname(BAD_ID, i, name);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_dimname(ncid, BAD_DIMID, name);
+        IF (err != NC_EBADDIM)
+	    error("bad dimid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_dimname(ncid, i, name);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_dimname: %s", ncmpi_strerror(err));
+	else IF (strcmp(dim_name[i],name)) 
+	    error("name expected: %s, got: %s",dim_name[i],name);
+        ELSE_NOK
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_varid(void)
+{
+    int ncid;
+    int varid;
+    int i;
+    int err;
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    err = ncmpi_inq_varid(ncid, "noSuch", &varid);
+    IF (err != NC_ENOTVAR)
+	error("bad ncid: status = %d", err);
+    ELSE_NOK
+
+    for (i = 0; i < numVars; i++) {
+	err = ncmpi_inq_varid(BAD_ID, var_name[i], &varid);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_varid(ncid, var_name[i], &varid);
+        IF (err != NC_NOERR)
+	    error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
+	else IF (varid != i)
+	    error("expected %d, got %d", i, varid);
+        ELSE_NOK
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_var(void)
+{
+    int ncid;
+    int i;
+    int err;
+    char name[NC_MAX_NAME];
+    nc_type datatype;
+    int ndims;
+    int dimids[MAX_RANK];
+    int natts;
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+	err = ncmpi_inq_var(BAD_ID, i, name, &datatype, &ndims, dimids, &natts);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_var(ncid,BAD_VARID,name,&datatype,&ndims,dimids,&natts);
+        IF (err != NC_ENOTVAR)
+	    error("bad var id: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_var(ncid, i, 0, 0, 0, 0, 0);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
+        ELSE_NOK
+	err = ncmpi_inq_var(ncid, i, name, &datatype, &ndims, dimids, &natts);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
+	else IF (strcmp(var_name[i],name)) 
+	    error("name expected: %s, got: %s",var_name[i],name);
+	else IF (var_type[i] != datatype)
+	    error("type expected: %d, got: %d",var_type[i],datatype);
+	else IF (var_rank[i] != ndims)
+	    error("ndims expected: %d, got: %d",var_rank[i],ndims);
+	else IF (!int_vec_eq(var_dimid[i],dimids,ndims))
+	    error("unexpected dimid");
+	else IF (var_natts[i] != natts)
+	    error("natts expected: %d, got: %d",var_natts[i],natts);
+        ELSE_NOK
+	err = ncmpi_inq_var(ncid, i, name, 0, 0, 0, 0);
+        IF (err != NC_NOERR)
+	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
+	else IF (strcmp(var_name[i],name)) 
+	    error("name expected: %s, got: %s",var_name[i],name);
+        ELSE_NOK
+	err = ncmpi_inq_var(ncid, i, 0, &datatype, 0, 0, 0);
+        IF (err != NC_NOERR)
+	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
+        else IF (var_type[i] != datatype)
+            error("type expected: %d, got: %d",var_type[i],datatype);
+        ELSE_NOK
+	err = ncmpi_inq_var(ncid, i, 0, 0, &ndims, 0, 0);
+        IF (err != NC_NOERR)
+	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
+        else IF (var_rank[i] != ndims)
+            error("ndims expected: %d, got: %d",var_rank[i],ndims);
+        ELSE_NOK
+	err = ncmpi_inq_var(ncid, i, 0, 0, 0, dimids, 0);
+        IF (err != NC_NOERR)
+	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
+        else IF (!int_vec_eq(var_dimid[i],dimids,ndims))
+            error("unexpected dimid");
+        ELSE_NOK
+	err = ncmpi_inq_var(ncid, i, 0, 0, 0, 0, &natts);
+        IF (err != NC_NOERR)
+	    error("ncmpi_inq_var: %s", ncmpi_strerror(err));
+        else IF (var_natts[i] != natts)
+            error("natts expected: %d, got: %d",var_natts[i],natts);
+        ELSE_NOK
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_vardimid(void)
+{
+    int ncid;
+    int i;
+    int err;
+    int dimids[MAX_RANK];
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+	err = ncmpi_inq_vardimid(BAD_ID, i, dimids);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_vardimid(ncid, BAD_VARID, dimids);
+        IF (err != NC_ENOTVAR)
+	    error("bad var id: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_vardimid(ncid, i, dimids);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_vardimid: %s", ncmpi_strerror(err));
+	else IF (!int_vec_eq(var_dimid[i], dimids, var_rank[i]))
+	    error("unexpected dimid");
+        ELSE_NOK
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_varname(void)
+{
+    int ncid;
+    int i;
+    int err;
+    char name[NC_MAX_NAME];
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+	err = ncmpi_inq_varname(BAD_ID, i, name);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        nok++;
+	err = ncmpi_inq_varname(ncid, BAD_VARID, name);
+        IF (err != NC_ENOTVAR)
+	    error("bad var id: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_varname(ncid, i, name);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_varname: %s", ncmpi_strerror(err));
+	else IF (strcmp(var_name[i],name)) 
+	    error("name expected: %s, got: %s",var_name[i],name);
+        ELSE_NOK
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_varnatts(void)
+{
+    int ncid;
+    int i;
+    int err;
+    int natts;
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = -1; i < numVars; i++) {
+	err = ncmpi_inq_varnatts(BAD_ID, i, &natts);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_varnatts(ncid, BAD_VARID, &natts);
+        IF (err != NC_ENOTVAR)
+	    error("bad var id: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_varnatts(ncid, VARID(i), &natts);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_varnatts: %s", ncmpi_strerror(err));
+        else IF (NATTS(i) != natts)
+            error("natts expected: %d, got: %d",NATTS(i),natts);
+        ELSE_NOK
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_varndims(void)
+{
+    int ncid;
+    int i;
+    int err;
+    int ndims;
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+	err = ncmpi_inq_varndims(BAD_ID, i, &ndims);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_varndims(ncid, BAD_VARID, &ndims);
+        IF (err != NC_ENOTVAR)
+	    error("bad var id: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_varndims(ncid, i, &ndims);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_varndims: %s", ncmpi_strerror(err));
+        else IF (var_rank[i] != ndims)
+            error("ndims expected: %d, got: %d",var_rank[i],ndims);
+        ELSE_NOK
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_vartype(void)
+{
+    int ncid;
+    int i;
+    int err;
+    nc_type datatype;
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+	err = ncmpi_inq_vartype(BAD_ID, i, &datatype);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_vartype(ncid, BAD_VARID, &datatype);
+        IF (err != NC_ENOTVAR)
+	    error("bad var id: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_vartype(ncid, i, &datatype);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_vartype: %s", ncmpi_strerror(err));
+        else IF (var_type[i] != datatype)
+            error("type expected: %d, got: %d", var_type[i], datatype);
+        ELSE_NOK
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_put_var1
+ */
+int
+test_ncmpi_get_var1(void)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    double expect;
+    int nok = 0;		/* count of valid comparisons */
+    double buf[1];		/* (void *) buffer */
+    double value;
+    MPI_Offset index[MAX_RANK];
+    MPI_Datatype datatype;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_begin_indep_data(ncid);
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+	for (j = 0; j < var_rank[i]; j++)
+	    index[j] = 0;
+        err = ncmpi_get_var1(BAD_ID, i, index, buf, 1, datatype);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+        err = ncmpi_get_var1(ncid, BAD_VARID, index, buf, 1, datatype);
+        IF (err != NC_ENOTVAR)
+	    error("bad var id: status = %d", err);
+        ELSE_NOK
+	for (j = 0; j < var_rank[i]; j++) {
+	    index[j] = var_shape[i][j];
+	    err = ncmpi_get_var1(ncid, i, index, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                error("bad index: status = %d", err);
+            ELSE_NOK
+	    index[j] = 0;
+	}
+        for (j = 0; j < var_nels[i]; j++) {
+	    err = toMixedBase(j, var_rank[i], var_shape[i], index);
+	    IF (err != NC_NOERR)
+		error("error in toMixedBase 2");
+	    expect = hash( var_type[i], var_rank[i], index );
+            if (var_rank[i] == 0 && i%2 )
+		err = ncmpi_get_var1(ncid, i, NULL, buf, 1, datatype);
+	    else
+		err = ncmpi_get_var1(ncid, i, index, buf, 1, datatype);
+	    IF (err != NC_NOERR)
+		error("%s", ncmpi_strerror(err));
+            ELSE_NOK
+	    err = nc2dbl( var_type[i], buf, &value );
+	    IF (err != NC_NOERR)
+		error("error in nc2dbl");
+	    if (inRange(expect,var_type[i])) {
+		IF (!equal2(value,expect,var_type[i]))
+		    error("expected: %G, got: %G", expect, value);
+                ELSE_NOK
+	    }
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_get_vara
+ * Choose a random point dividing each dim into 2 parts
+ * Get 2^rank (nslabs) slabs so defined
+ * Each get overwrites buffer, so check after each get.
+ */
+int
+test_ncmpi_get_vara(void)
+{
+    int ncid, d, i, j, k, err, nels, nslabs;
+    int nok = 0;      /* count of valid comparisons */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Datatype datatype;
+    double buf[MAX_NELS];	/* (void *) buffer */
+    double expect;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_begin_indep_data(ncid);
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+        }
+        err = ncmpi_get_vara(BAD_ID, i, start, edge, buf, 1, datatype);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+        err = ncmpi_get_vara(ncid, BAD_VARID, start, edge, buf, 1, datatype);
+        IF (err != NC_ENOTVAR)
+	    error("bad var id: status = %d", err);
+        ELSE_NOK
+	for (j = 0; j < var_rank[i]; j++) {
+	    start[j] = var_shape[i][j];
+	    err = ncmpi_get_vara(ncid, i, start, edge, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                error("bad index: status = %d", err);
+            ELSE_NOK
+	    start[j] = 0;
+	    edge[j] = var_shape[i][j] + 1;
+	    err = ncmpi_get_vara(ncid, i, start, edge, buf, 1, datatype);
+            IF (err != NC_EEDGE)
+		error("bad edge: status = %d", err);
+            ELSE_NOK
+	    edge[j] = 1;
+	}
+            /* Choose a random point dividing each dim into 2 parts */
+            /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+            /* bits of k determine whether to get lower or upper part of dim */
+        for (k = 0; k < nslabs; k++) {
+            nels = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                }else{
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                nels *= edge[j];
+            }
+            if (var_rank[i] == 0 && i%2 )
+		err = ncmpi_get_vara(ncid, i, NULL, NULL, buf, nels, datatype);
+	    else
+		err = ncmpi_get_vara(ncid, i, start, edge, buf, nels, datatype);
+	    IF (err != NC_NOERR) {
+		error("%s", ncmpi_strerror(err));
+	    } else {
+	        nok++;
+		for (j = 0; j < nels; j++) {
+                    double got;
+                    char *p = (char *) buf;
+                    p += j * nctypelen(var_type[i]);
+		    err = nc2dbl( var_type[i], p, & got );
+		    IF (err != NC_NOERR)
+			error("error in nc2dbl");
+		    err = toMixedBase(j, var_rank[i], edge, index);
+		    IF (err != NC_NOERR)
+			error("error in toMixedBase 1");
+		    for (d = 0; d < var_rank[i]; d++)
+			index[d] += start[d];
+		    expect = hash(var_type[i], var_rank[i], index);
+		    if (inRange(expect,var_type[i])) {
+			IF (!equal2(got,expect,var_type[i])) {
+			    error("value read not that expected");
+			    if (verbose) {
+				error("\n");
+				error("varid: %d, ", i);
+				error("var_name: %s, ", var_name[i]);
+				error("element number: %d ", j);
+				error("expect: %g", expect);
+				error("got: %g", got);
+			    }
+			}
+		    }
+		}
+	    }
+	}
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_get_vars
+ * Choose a random point dividing each dim into 2 parts
+ * Get 2^rank (nslabs) slabs so defined
+ * Each get overwrites buffer, so check after each get.
+ */
+int
+test_ncmpi_get_vars(void)
+{
+    int ncid;
+    int d;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err;
+    int nels;
+    int nslabs;
+    int nstarts;	/* number of different starts */
+    int nok = 0;	/* total count of valid comparisons */
+    int n;		/* count of valid comparisons within var */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    MPI_Datatype datatype;
+    double buf[MAX_NELS];     /* (void *) buffer */
+    char *p;			/* (void *) pointer */
+    double expect;
+    double got;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_begin_indep_data(ncid);
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+        }
+        err = ncmpi_get_vars(BAD_ID, i, start, edge, stride, buf, 1, datatype);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+        err = ncmpi_get_vars(ncid, BAD_VARID, start, edge, stride, buf, 1, datatype);
+        IF (err != NC_ENOTVAR)
+	    error("bad var id: status = %d", err);
+        ELSE_NOK
+	for (j = 0; j < var_rank[i]; j++) {
+	    start[j] = var_shape[i][j];
+	    err = ncmpi_get_vars(ncid, i, start, edge, stride, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                error("bad index: status = %d", err);
+            ELSE_NOK
+	    start[j] = 0;
+	    edge[j] = var_shape[i][j] + 1;
+	    err = ncmpi_get_vars(ncid, i, start, edge, stride, buf, 1, datatype);
+            IF (err != NC_EEDGE)
+		error("bad edge: status = %d", err);
+            ELSE_NOK
+	    edge[j] = 1;
+	    stride[j] = 0;
+	    err = ncmpi_get_vars(ncid, i, start, edge, stride, buf, 1, datatype);
+            IF (err != NC_ESTRIDE)
+		error("bad stride: status = %d", err);
+            ELSE_NOK
+	    stride[j] = 1;
+	}
+        /* Choose a random point dividing each dim into 2 parts */
+        /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+        /* bits of k determine whether to get lower or upper part of dim */
+	/* choose random stride from 1 to edge */
+	n = 0;
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                }else{
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+		sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+	    for (m = 0; m < nstarts; m++) {
+		err = toMixedBase(m, var_rank[i], sstride, index);
+		IF (err != NC_NOERR)
+		    error("error in toMixedBase");
+		nels = 1;
+		for (j = 0; j < var_rank[i]; j++) {
+		    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+		    nels *= count[j];
+		    index[j] += start[j];
+		}
+		/* Random choice of forward or backward */
+/* TODO
+		if ( roll(2) ) {
+		    for (j = 0; j < var_rank[i]; j++) {
+			index[j] += (count[j] - 1) * stride[j];
+			stride[j] = -stride[j];
+		    }
+		}
+ */
+		if (var_rank[i] == 0 && i%2 )
+		    err = ncmpi_get_vars(ncid, i, NULL, NULL, NULL, buf, 1, datatype);
+		else
+		    err = ncmpi_get_vars(ncid, i, index, count, stride, buf, nels, datatype);
+		IF (err != NC_NOERR) {
+		    error("%s", ncmpi_strerror(err));
+		} else {
+		    nok++;
+		    for (j = 0; j < nels; j++) {
+			p = (char *) buf;
+			p += j * nctypelen(var_type[i]);
+			err = nc2dbl( var_type[i], p, & got );
+			IF (err != NC_NOERR)
+			    error("error in nc2dbl");
+			err = toMixedBase(j, var_rank[i], count, index2);
+			IF (err != NC_NOERR)
+			    error("error in toMixedBase 1");
+			for (d = 0; d < var_rank[i]; d++)
+			    index2[d] = index[d] + index2[d] * stride[d];
+			expect = hash(var_type[i], var_rank[i], index2);
+			if (inRange(expect,var_type[i])) {
+			    IF (!equal2(got,expect,var_type[i])) {
+				error("value read not that expected");
+				if (verbose) {
+				    error("\n");
+				    error("varid: %d, ", i);
+				    error("var_name: %s, ", var_name[i]);
+				    error("element number: %d ", j);
+				    error("expect: %g, ", expect);
+				    error("got: %g ", got);
+				}
+			    }
+			}
+			n++;
+		    }
+		}
+	    }
+	}
+	IF (n != var_nels[i]) {
+	    error("count != nels");
+	    if (verbose) {
+		error("\n");
+		error("varid: %d, ", i);
+		error("var_name: %s, ", var_name[i]);
+		error("count: %d, ", n);
+		error("nels: %d ", var_nels[i]);
+	    }
+	}
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_get_varm
+ * Choose a random point dividing each dim into 2 parts
+ * Get 2^rank (nslabs) slabs so defined
+ * Choose random stride from 1 to edge
+ * Buffer should end up being bit image of external variable.
+ * So all gets for a variable store in different elements of buffer
+ */
+int
+test_ncmpi_get_varm(void)
+{
+    int ncid;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err;
+    int nslabs;
+    int nstarts;	/* number of different starts */
+    int nok = 0;	/* total count of valid comparisons */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    MPI_Offset imap[MAX_RANK];
+    MPI_Offset imap2[MAX_RANK];
+    MPI_Offset nels;
+    MPI_Datatype datatype;
+    double buf[MAX_NELS];	/* (void *) buffer */
+    char *p;			/* (void *) pointer */
+    double expect;
+    double got;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_begin_indep_data(ncid);
+    for (i = 0; i < numVars; i++) {
+        datatype = nc_mpi_type(var_type[i]);
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+        }
+        if (var_rank[i] > 0) {
+            j = var_rank[i] - 1;
+            /* imap[j] = nctypelen(var_type[i]); */
+            imap[j] = 1; /* in numbers of elements */
+            for (; j > 0; j--)
+                imap[j-1] = imap[j] * var_shape[i][j];
+        }
+        err = ncmpi_get_varm(BAD_ID, i, start, edge, stride, imap, buf, 1, datatype);
+        IF (err != NC_EBADID)
+	    error("bad ncid: status = %d", err);
+        ELSE_NOK
+        err = ncmpi_get_varm(ncid, BAD_VARID, start, edge, stride, imap, buf, 1, datatype);
+        IF (err != NC_ENOTVAR)
+	    error("bad var id: status = %d", err);
+        ELSE_NOK
+	for (j = 0; j < var_rank[i]; j++) {
+	    start[j] = var_shape[i][j];
+	    err = ncmpi_get_varm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
+            IF (err != NC_EINVALCOORDS)
+                error("bad index: status = %d", err);
+            ELSE_NOK
+	    start[j] = 0;
+	    edge[j] = var_shape[i][j] + 1;
+	    err = ncmpi_get_varm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
+            IF (err != NC_EEDGE)
+		error("bad edge: status = %d", err);
+            ELSE_NOK
+	    edge[j] = 1;
+	    stride[j] = 0;
+	    err = ncmpi_get_varm(ncid, i, start, edge, stride, imap, buf, 1, datatype);
+            IF (err != NC_ESTRIDE)
+		error("bad stride: status = %d", err);
+            ELSE_NOK
+	    stride[j] = 1;
+	}
+            /* Choose a random point dividing each dim into 2 parts */
+            /* get 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+            /* bits of k determine whether to get lower or upper part of dim */
+	    /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                }else{
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+		sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+		imap2[j] = imap[j] * sstride[j];
+                nstarts *= stride[j];
+            }
+	    for (m = 0; m < nstarts; m++) {
+		if (var_rank[i] == 0 && i%2 ) {
+		    err = ncmpi_get_varm(ncid, i, NULL, NULL, NULL, NULL, buf, var_nels[i], datatype);
+		} else {
+		    err = toMixedBase(m, var_rank[i], sstride, index);
+		    IF (err != NC_NOERR)
+			error("error in toMixedBase");
+                    nels = 1;
+		    for (j = 0; j < var_rank[i]; j++) {
+			count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+			index[j] += start[j];
+                        nels *= count[j];
+		    }
+			    /* Random choice of forward or backward */
+/* TODO
+		    if ( roll(2) ) {
+			for (j = 0; j < var_rank[i]; j++) {
+			    index[j] += (count[j] - 1) * stride[j];
+			    stride[j] = -stride[j];
+			}
+		    }
+ */
+		    j = fromMixedBase(var_rank[i], index, var_shape[i]);
+		    p = (char *) buf + j * nctypelen(var_type[i]);
+		    err = ncmpi_get_varm(ncid, i, index, count, stride, imap2, p, nels, datatype);
+		}
+		IF (err != NC_NOERR)
+		    error("%s", ncmpi_strerror(err));
+                ELSE_NOK
+	    }
+	}
+        p = (char *) buf;
+	for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR)
+                error("error in toMixedBase");
+            expect = hash( var_type[i], var_rank[i], index);
+	    err = nc2dbl( var_type[i], p, & got );
+	    IF (err != NC_NOERR)
+		error("error in nc2dbl");
+	    if (inRange(expect,var_type[i])) {
+		IF (!equal2(got,expect,var_type[i])) {
+		    error("value read not that expected");
+		    if (verbose) {
+			error("\n");
+			error("varid: %d, ", i);
+			error("var_name: %s, ", var_name[i]);
+			error("element number: %d ", j);
+			error("expect: %g, ", expect);
+			error("got: %g ", got);
+		    }
+		}
+                ELSE_NOK
+	    }
+            p += nctypelen(var_type[i]);
+	}
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_get_att(void)
+{
+    int ncid;
+    int i;
+    int j;
+    MPI_Offset k;
+    int err;
+    double buf[MAX_NELS];	/* (void *) buffer */
+    char *p;			/* (void *) pointer */
+    double expect;
+    double got;
+    int nok = 0;      /* count of valid comparisons */
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR) 
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = -1; i < numVars; i++) {
+        for (j = 0; j < NATTS(i); j++) {
+	    err = ncmpi_get_att(BAD_ID, i, ATT_NAME(i,j), buf);
+	    IF (err != NC_EBADID) 
+		error("bad ncid: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_get_att(ncid, BAD_VARID, ATT_NAME(i,j), buf);
+	    IF (err != NC_ENOTVAR) 
+		error("bad var id: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_get_att(ncid, i, "noSuch", buf);
+	    IF (err != NC_ENOTATT) 
+		error("Bad attribute name: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_get_att(ncid, i, ATT_NAME(i,j), buf);
+	    IF (err != NC_NOERR) {
+		error("%s", ncmpi_strerror(err));
+	    } else {
+		nok++;
+		for (k = 0; k < ATT_LEN(i,j); k++) {
+		    expect = hash(ATT_TYPE(i,j), -1, &k );
+		    p = (char *) buf;
+		    p += k * nctypelen(ATT_TYPE(i,j));
+		    err = nc2dbl( ATT_TYPE(i,j), p, &got );
+		    IF (err != NC_NOERR)
+			error("error in nc2dbl");
+		    if (inRange(expect,ATT_TYPE(i,j))) {
+			IF (!equal2(got,expect,ATT_TYPE(i,j))) {
+			    error("value read not that expected");
+			    if (verbose) {
+				error("\n");
+				error("varid: %d, ", i);
+				error("var_name: %s, ",
+					i >= 0 ? var_name[i] : "Global");
+				error("att_name: %s, ", ATT_NAME(i,j));
+				error("element number: %d\n", k);
+				error("expect: %-23.16e\n", expect);
+				error("   got: %-23.16e", got);
+			    }
+			}
+		    }
+                }
+	    }
+	}
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_att(void)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    nc_type t;
+    MPI_Offset n;
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR) 
+	error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = -1; i < numVars; i++) {
+        for (j = 0; j < NATTS(i); j++) {
+	    err = ncmpi_inq_att(BAD_ID, i, ATT_NAME(i,j), &t, &n);
+	    IF (err != NC_EBADID) 
+		error("bad ncid: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_inq_att(ncid, BAD_VARID, ATT_NAME(i,j), &t, &n);
+	    IF (err != NC_ENOTVAR) 
+		error("bad var id: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_inq_att(ncid, i, "noSuch", &t, &n);
+	    IF (err != NC_ENOTATT) 
+		error("Bad attribute name: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_inq_att(ncid, i, ATT_NAME(i,j), &t, &n);
+	    IF (err != NC_NOERR) {
+		error("%s", ncmpi_strerror(err));
+	    } else {
+		IF (t != ATT_TYPE(i,j))
+		    error("type not that expected");
+		else IF (n != ATT_LEN(i,j)) 
+		    error("length not that expected");
+                ELSE_NOK
+	    }
+	}
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_attlen(void)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    MPI_Offset len;
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = -1; i < numVars; i++) {
+	err = ncmpi_inq_attlen(ncid, i, "noSuch", &len);
+	IF (err != NC_ENOTATT)
+	    error("Bad attribute name: status = %d", err);
+        ELSE_NOK
+        for (j = 0; j < NATTS(i); j++) {
+            err = ncmpi_inq_attlen(BAD_ID, i, ATT_NAME(i,j), &len);
+            IF (err != NC_EBADID)
+                error("bad ncid: status = %d", err);
+            ELSE_NOK
+            err = ncmpi_inq_attlen(ncid, BAD_VARID, ATT_NAME(i,j), &len);
+            IF (err != NC_ENOTVAR)
+                error("bad varid: status = %d", err);
+            ELSE_NOK
+            err = ncmpi_inq_attlen(ncid, i, ATT_NAME(i,j), &len);
+            IF (err != NC_NOERR) {
+                error("%s", ncmpi_strerror(err));
+            } else {
+		IF (len != ATT_LEN(i,j))
+		    error("len not that expected");
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_atttype(void)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    nc_type datatype;
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = -1; i < numVars; i++) {
+	err = ncmpi_inq_atttype(ncid, i, "noSuch", &datatype);
+	IF (err != NC_ENOTATT)
+	    error("Bad attribute name: status = %d", err);
+        ELSE_NOK
+        for (j = 0; j < NATTS(i); j++) {
+            err = ncmpi_inq_atttype(BAD_ID, i, ATT_NAME(i,j), &datatype);
+            IF (err != NC_EBADID)
+                error("bad ncid: status = %d", err);
+            ELSE_NOK
+            err = ncmpi_inq_atttype(ncid, BAD_VARID, ATT_NAME(i,j), &datatype);
+            IF (err != NC_ENOTVAR)
+                error("bad varid: status = %d", err);
+            ELSE_NOK
+            err = ncmpi_inq_atttype(ncid, i, ATT_NAME(i,j), &datatype);
+            IF (err != NC_NOERR) {
+                error("%s", ncmpi_strerror(err));
+            } else {
+		IF (datatype != ATT_TYPE(i,j))
+		    error("type not that expected");
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_attname(void)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    char name[NC_MAX_NAME];
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = -1; i < numVars; i++) {
+	err = ncmpi_inq_attname(ncid, i, BAD_ATTNUM, name);
+	IF (err != NC_ENOTATT)
+	    error("Bad attribute number: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_inq_attname(ncid, i, NATTS(i), name);
+	IF (err != NC_ENOTATT)
+	    error("Bad attribute number: status = %d", err);
+        ELSE_NOK
+        for (j = 0; j < NATTS(i); j++) {
+            err = ncmpi_inq_attname(BAD_ID, i, j, name);
+            IF (err != NC_EBADID)
+                error("bad ncid: status = %d", err);
+            ELSE_NOK
+            err = ncmpi_inq_attname(ncid, BAD_VARID, j, name);
+            IF (err != NC_ENOTVAR)
+                error("bad var id: status = %d", err);
+            ELSE_NOK
+            err = ncmpi_inq_attname(ncid, i, j, name);
+            IF (err != NC_NOERR) {
+                error("%s", ncmpi_strerror(err));
+            } else {
+		IF (strcmp(ATT_NAME(i,j), name) != 0)
+		    error("name not that expected");
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
+
+int
+test_ncmpi_inq_attid(void)
+{
+    int ncid;
+    int i;
+    int j;
+    int err;
+    int attnum;
+    int nok=0;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = -1; i < numVars; i++) {
+	err = ncmpi_inq_attid(ncid, i, "noSuch", &attnum);
+	IF (err != NC_ENOTATT)
+	    error("Bad attribute name: status = %d", err);
+        ELSE_NOK
+        for (j = 0; j < NATTS(i); j++) {
+            err = ncmpi_inq_attid(BAD_ID, i, ATT_NAME(i,j), &attnum);
+            IF (err != NC_EBADID)
+                error("bad ncid: status = %d", err);
+            ELSE_NOK
+            err = ncmpi_inq_attid(ncid, BAD_VARID, ATT_NAME(i,j), &attnum);
+            IF (err != NC_ENOTVAR)
+                error("bad varid: status = %d", err);
+            ELSE_NOK
+            err = ncmpi_inq_attid(ncid, i, ATT_NAME(i,j), &attnum);
+            IF (err != NC_NOERR) {
+                error("%s", ncmpi_strerror(err));
+            } else {
+		IF (attnum != j)
+		    error("attnum not that expected");
+                ELSE_NOK
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    return nok;
+}
+
diff --git a/test/nc_test/test_write.c b/test/nc_test/test_write.c
new file mode 100644
index 0000000..604601e
--- /dev/null
+++ b/test/nc_test/test_write.c
@@ -0,0 +1,2185 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: test_write.c 2289 2016-01-02 08:26:40Z wkliao $
+ */
+
+#include "tests.h"
+#include "math.h"
+
+
+/*
+ * Test ncmpi_create
+ *    For mode in NC_NOCLOBBER|extra_flags, NC_CLOBBER, info do:
+ *       create netcdf file 'scratch.nc' with no data, close it
+ *       test that it can be opened, do ncmpi_inq to check nvars = 0, etc.
+ *    Try again in NC_NOCLOBBER|extra_flags mode, check error return
+ * On exit, delete this file
+ */
+int
+test_ncmpi_create(void)
+{
+    int clobber; /* 0 for NC_NOCLOBBER|extra_flags, 1 for NC_CLOBBER, info */
+    int err;
+    int ncid;
+    int ndims;   /* number of dimensions */
+    int nvars;   /* number of variables */
+    int ngatts;  /* number of global attributes */
+    int recdim;  /* id of unlimited dimension */
+    int nok=0;
+
+    for (clobber = 0; clobber < 2; clobber++) {
+	err = ncmpi_create(comm, scratch, clobber ? NC_CLOBBER|extra_flags : NC_NOCLOBBER, info, &ncid);
+	IF (err != NC_NOERR)
+	    error("ncmpi_create: %s", ncmpi_strerror(err));
+        ELSE_NOK
+	err = ncmpi_close(ncid);
+	IF (err != NC_NOERR)
+	    error("ncmpi_close: %s", ncmpi_strerror(err));
+	err = ncmpi_open(comm, scratch, NC_NOWRITE, info, &ncid);
+	IF (err != NC_NOERR)
+	    error("ncmpi_open: %s", ncmpi_strerror(err));
+	err = ncmpi_inq(ncid, &ndims, &nvars, &ngatts, &recdim);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq: %s", ncmpi_strerror(err));
+	else IF (ndims != 0)
+	    error("ncmpi_inq: wrong number of dimensions returned, %d", ndims);
+	else IF (nvars != 0)
+	    error("ncmpi_inq: wrong number of variables returned, %d", nvars);
+	else IF (ngatts != 0)
+	    error("ncmpi_inq: wrong number of global atts returned, %d", ngatts);
+	else IF (recdim != -1)
+	    error("ncmpi_inq: wrong record dimension ID returned, %d", recdim);
+        ELSE_NOK
+	err = ncmpi_close(ncid);
+	IF (err != NC_NOERR)
+	    error("ncmpi_close: %s", ncmpi_strerror(err));
+    }
+
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_EEXIST)
+	error("attempt to overwrite file: status = %d", err);
+    ELSE_NOK
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+	error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_redef 
+ * (In fact also tests ncmpi_enddef - called from test_ncmpi_enddef)
+ *    BAD_ID
+ *    attempt redef (error) & enddef on read-only file
+ *    create file, define dims & vars. 
+ *    attempt put var (error)
+ *    attempt redef (error) & enddef.
+ *    put vars
+ *    attempt def new dims (error)
+ *    redef
+ *    def new dims, vars.
+ *    put atts
+ *    enddef
+ *    put vars
+ *    close
+ *    check file: vars & atts
+ */
+int
+test_ncmpi_redef(void)
+{
+    int ncid;                   /* netcdf id */
+    /* used to force effective test of ncio->move() in redef */
+    size_t sizehint = 8192;
+    int dimid;         /* dimension id */
+    int varid;         /* variable id */
+    int varid1;        /* variable id */
+    int nok=0, err;
+    const char * title = "Not funny";
+    double var;
+    char name[NC_MAX_NAME];
+    MPI_Offset length;
+
+    /* BAD_ID tests */
+    err = ncmpi_redef(BAD_ID);
+    IF (err != NC_EBADID)
+	error("bad ncid: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_enddef(BAD_ID);
+    IF (err != NC_EBADID)
+	error("bad ncid: status = %d", err);
+    ELSE_NOK
+
+    /* read-only tests */
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_redef(ncid);
+    IF (err != NC_EPERM)
+	error("ncmpi_redef in NC_NOWRITE, info mode: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_ENOTINDEFINE)
+	error("ncmpi_endfef in NC_NOWRITE, info mode: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    /* tests using scratch file */
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    /* err = ncmpi__create(scratch, NC_NOCLOBBER|extra_flags, 0, &sizehint, &ncid); */
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    /* limit for ncio implementations which which have infinite chunksize */
+    if(sizehint > 32768)
+	sizehint = 16384;
+    def_dims(ncid);
+    def_vars(ncid);
+    put_atts(ncid);
+    err = ncmpi_inq_varid(ncid, "d", &varid);
+    IF (err != NC_NOERR) 
+	error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
+    var = 1.0;
+    err = ncmpi_begin_indep_data(ncid);
+    IF (err != NC_EINDEFINE)
+        error("ncmpi_begin_indep_data... in define mode: status = %d", err);
+    err = ncmpi_put_var1_double(ncid, varid, NULL, &var);
+    IF (err != NC_EINDEFINE)
+        error("ncmpi_put_var... in define mode: status = %d", err);
+    err = ncmpi_end_indep_data(ncid);
+    IF (err != NC_ENOTINDEP)
+        error("ncmpi_end_indep_data... not in indep mode: status = %d", err);
+    err = ncmpi_redef(ncid);
+    IF (err != NC_EINDEFINE)
+        error("ncmpi_redef in define mode: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+    ELSE_NOK
+    put_vars(ncid);
+    err = ncmpi_def_dim(ncid, "abc", sizehint, &dimid);
+    IF (err != NC_ENOTINDEFINE)
+        error("ncmpi_def_dim in define mode: status = %d", err);
+    err = ncmpi_redef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_redef: %s", ncmpi_strerror(err));
+    ELSE_NOK
+    err = ncmpi_set_fill(ncid, NC_NOFILL, NULL);
+    IF (err != NC_NOERR)
+        error("ncmpi_set_fill: %s", ncmpi_strerror(err));
+    err = ncmpi_def_dim(ncid, "abc", sizehint, &dimid);
+    IF (err != NC_NOERR)
+        error("ncmpi_def_dim: %s", ncmpi_strerror(err));
+    err = ncmpi_def_var(ncid, "abcScalar", NC_INT, 0, NULL, &varid);
+    IF (err != NC_NOERR)
+        error("ncmpi_def_var: %s", ncmpi_strerror(err));
+    err = ncmpi_def_var(ncid, "abc", NC_INT, 1, &dimid, &varid1);
+    IF (err != NC_NOERR)
+        error("ncmpi_def_var: %s", ncmpi_strerror(err));
+    {
+	int dimids[NDIMS +1];
+	int ii = 0;
+	for(ii = 0; ii < NDIMS; ii++)
+		dimids[ii] = ii;
+	dimids[NDIMS] = dimid;
+    	err = ncmpi_def_var(ncid, "abcRec", NC_INT, NDIMS, dimids, &varid1);
+    	IF (err != NC_NOERR)
+        	error("ncmpi_def_var: %s", ncmpi_strerror(err));
+    }
+    err = ncmpi_put_att_text(ncid, NC_GLOBAL, "title", 1+strlen(title), title);
+    IF (err != NC_NOERR)
+        error("ncmpi_put_att_text: %s", ncmpi_strerror(err));
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+    ELSE_NOK
+    var = 1.0;
+    err = ncmpi_end_indep_data(ncid);
+    IF (err != NC_ENOTINDEP)
+        error("ncmpi_end_indep_data: in collective mode status = %s", ncmpi_strerror(err));
+    err = ncmpi_begin_indep_data(ncid);
+    IF (err != NC_NOERR) 
+	error("ncmpi_begin_indep_data: %s", ncmpi_strerror(err));
+    err = ncmpi_put_var1_double(ncid, varid, NULL, &var);
+    IF (err != NC_NOERR)
+        error("ncmpi_put_var1_double: %s", ncmpi_strerror(err));
+    err = ncmpi_end_indep_data(ncid);
+    IF (err != NC_NOERR) 
+	error("ncmpi_begin_indep_data: %s", ncmpi_strerror(err));
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR) 
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+
+	/* check scratch file written as expected */
+    check_file(scratch);
+    err = ncmpi_open(comm, scratch, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_inq_dim(ncid, dimid, name, &length);
+    IF (err != NC_NOERR) 
+	error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
+    IF (strcmp(name, "abc") != 0) 
+	error("Unexpected dim name");
+    IF (length != sizehint) 
+	error("Unexpected dim length");
+    ncmpi_begin_indep_data(ncid);
+    err = ncmpi_get_var1_double(ncid, varid, NULL, &var);
+    IF (err != NC_NOERR)
+        error("ncmpi_get_var1_double: %s", ncmpi_strerror(err));
+    ncmpi_end_indep_data(ncid);
+    IF (var != 1.0)
+        error("ncmpi_get_var1_double: unexpected value");
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_enddef 
+ * Simply calls test_ncmpi_redef which tests both ncmpi_redef & ncmpi_enddef
+ */
+int
+test_ncmpi_enddef(void)
+{
+    return test_ncmpi_redef();
+}
+
+
+/*
+ * Test ncmpi_sync
+ *    try with bad handle, check error
+ *    try in define mode, check error
+ *    try writing with one handle, reading with another on same netCDF
+ */
+int
+test_ncmpi_sync(void)
+{
+    int ncidw;         /* netcdf id for writing */
+    int ncidr;         /* netcdf id for reading */
+    int nok=0, err;
+
+    /* BAD_ID test */
+    err = ncmpi_sync(BAD_ID);
+    IF (err != NC_EBADID)
+        error("bad ncid: status = %d", err);
+    ELSE_NOK
+
+        /* create scratch file & try ncmpi_sync in define mode */
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncidw);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+	return nok;
+    }
+    err = ncmpi_sync(ncidw);
+    IF (err != NC_EINDEFINE)
+        error("ncmpi_sync called in define mode: status = %d", err);
+    ELSE_NOK
+
+    /* write using same handle */
+    def_dims(ncidw);
+    def_vars(ncidw);
+    put_atts(ncidw);
+    err = ncmpi_enddef(ncidw);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+    put_vars(ncidw);
+    err = ncmpi_sync(ncidw);
+    IF (err != NC_NOERR)
+        error("ncmpi_sync of ncidw failed: %s", ncmpi_strerror(err));
+    ELSE_NOK
+
+    /* open another handle, ncmpi_sync, read (check) */
+    err = ncmpi_open(comm, scratch, NC_NOWRITE, info, &ncidr);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_sync(ncidr);
+    IF (err != NC_NOERR)
+        error("ncmpi_sync of ncidr failed: %s", ncmpi_strerror(err));
+    ELSE_NOK
+    check_dims(ncidr);
+    check_atts(ncidr);
+    check_vars(ncidr);
+
+    /* close both handles */
+    err = ncmpi_close(ncidr);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = ncmpi_close(ncidw);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_abort
+ *    try with bad handle, check error
+ *    try in define mode before anything written, check that file was deleted
+ *    try after ncmpi_enddef, ncmpi_redef, define new dims, vars, atts
+ *    try after writing variable
+ */
+int
+test_ncmpi_abort(void)
+{
+    int ncid;          /* netcdf id */
+    int err;
+    int ndims;
+    int nvars;
+    int ngatts;
+    int nok=0;
+
+    /* BAD_ID test */
+    err = ncmpi_abort(BAD_ID);
+    IF (err != NC_EBADID)
+        error("bad ncid: status = %d", err);
+    ELSE_NOK
+
+        /* create scratch file & try ncmpi_abort in define mode */
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    put_atts(ncid);
+    err = ncmpi_abort(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_abort of ncid failed: %s", ncmpi_strerror(err));
+    ELSE_NOK
+    err = ncmpi_close(ncid);	/* should already be closed */
+    IF (err != NC_EBADID)
+        error("bad ncid: status = %d", err);
+    err = ncmpi_delete(scratch, info);	/* should already be deleted */
+    IF (!err) /* err is expected to be NC_ENOENT */
+        error("file %s should not exist", scratch);
+
+        /* 
+         * create scratch file
+	 * do ncmpi_enddef & ncmpi_redef
+	 * define new dims, vars, atts
+	 * try ncmpi_abort: should restore previous state (no dims, vars, atts)
+	 */ 
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+    err = ncmpi_redef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_redef: %s", ncmpi_strerror(err));
+    def_dims(ncid);
+    def_vars(ncid);
+    put_atts(ncid);
+    err = ncmpi_abort(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_abort of ncid failed: %s", ncmpi_strerror(err));
+    ELSE_NOK
+    err = ncmpi_close(ncid);	/* should already be closed */
+    IF (err != NC_EBADID)
+        error("bad ncid: status = %d", err);
+    err = ncmpi_open(comm, scratch, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_inq (ncid, &ndims, &nvars, &ngatts, NULL);
+    IF (err != NC_NOERR)
+        error("ncmpi_inq: %s", ncmpi_strerror(err));
+    IF (ndims != 0)
+        error("ndims should be 0");
+    IF (nvars != 0)
+        error("nvars should be 0");
+    IF (ngatts != 0)
+        error("ngatts should be 0");
+    err = ncmpi_close (ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    /* try ncmpi_abort in data mode - should just close */
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    put_atts(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+    put_vars(ncid);
+    err = ncmpi_abort(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_abort of ncid failed: %s", ncmpi_strerror(err));
+    ELSE_NOK
+    err = ncmpi_close(ncid);       /* should already be closed */
+    IF (err != NC_EBADID)
+        error("bad ncid: status = %d", err);
+    check_file(scratch);
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_def_dim
+ *    try with bad netCDF handle, check error
+ *    try in data mode, check error
+ *    check that returned id is one more than previous id
+ *    try adding same dimension twice, check error
+ *    try with illegal sizes, check error
+ *    make sure unlimited size works, shows up in ncmpi_inq_unlimdim
+ *    try to define a second unlimited dimension, check error
+ */
+int
+test_ncmpi_def_dim(void)
+{
+    int ncid;
+    int  err;             /* status */
+    int  i, nok=0;
+    int  dimid;         /* dimension id */
+    MPI_Offset length;
+
+        /* BAD_ID test */
+    err = ncmpi_def_dim(BAD_ID, "abc", 8, &dimid);
+    IF (err != NC_EBADID)
+        error("bad ncid: status = %d", err);
+    ELSE_NOK
+
+        /* data mode test */
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+    err = ncmpi_def_dim(ncid, "abc", 8, &dimid);
+    IF (err != NC_ENOTINDEFINE)
+        error("bad ncid: status = %d", err);
+    ELSE_NOK
+
+    /* define-mode tests: unlimited dim */
+    err = ncmpi_redef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_redef: %s", ncmpi_strerror(err));
+    err = ncmpi_def_dim(ncid, dim_name[0], NC_UNLIMITED, &dimid);
+    IF (err != NC_NOERR) 
+	error("ncmpi_def_dim: %s", ncmpi_strerror(err));
+    ELSE_NOK
+    IF (dimid != 0) 
+	error("Unexpected dimid");
+    ELSE_NOK
+    err = ncmpi_inq_unlimdim(ncid, &dimid);
+    IF (err != NC_NOERR) 
+	error("ncmpi_inq_unlimdim: %s", ncmpi_strerror(err));
+    IF (dimid != 0) 
+	error("Unexpected recdim");
+    err = ncmpi_inq_dimlen(ncid, dimid, &length);
+    IF (length != 0) 
+	error("Unexpected length");
+    err = ncmpi_def_dim(ncid, "abc", NC_UNLIMITED, &dimid);
+    IF (err != NC_EUNLIMIT)
+        error("2nd unlimited dimension: status = %d", err);
+    ELSE_NOK
+
+    /* define-mode tests: remaining dims */
+    for (i = 1; i < NDIMS; i++) {
+        err = ncmpi_def_dim(ncid, dim_name[i-1], dim_len[i], &dimid);
+	IF (err != NC_ENAMEINUSE)
+	    error("duplicate name: status = %d", err);
+        ELSE_NOK
+	err = ncmpi_def_dim(ncid, BAD_NAME, dim_len[i], &dimid);
+	IF (err != NC_EBADNAME)
+	    error("bad name: status = %d", err);
+        ELSE_NOK
+        err = ncmpi_def_dim(ncid, dim_name[i], NC_UNLIMITED-1, &dimid);
+	IF (err != NC_EDIMSIZE)
+	    error("bad size: status = %d", err);
+        ELSE_NOK
+        err = ncmpi_def_dim(ncid, dim_name[i], dim_len[i], &dimid);
+        IF (err != NC_NOERR) 
+	    error("ncmpi_def_dim: %s", ncmpi_strerror(err));
+        ELSE_NOK
+	IF (dimid != i) 
+	    error("Unexpected dimid");
+    }
+
+        /* Following just to expand unlimited dim */
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+    put_vars(ncid);
+
+        /* Check all dims */
+    check_dims(ncid);
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_rename_dim
+ *    try with bad netCDF handle, check error
+ *    check that proper rename worked with ncmpi_inq_dim
+ *    try renaming to existing dimension name, check error
+ *    try with bad dimension handle, check error
+ */
+int
+test_ncmpi_rename_dim(void)
+{
+    int ncid;
+    int  err, nok=0;             /* status */
+    char name[NC_MAX_NAME];
+
+        /* BAD_ID test */
+    err = ncmpi_rename_dim(BAD_ID, 0, "abc");
+    IF (err != NC_EBADID)
+        error("bad ncid: status = %d", err);
+    ELSE_NOK
+
+        /* main tests */
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    err = ncmpi_rename_dim(ncid, BAD_DIMID, "abc");
+    IF (err != NC_EBADDIM)
+        error("bad dimid: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_rename_dim(ncid, 2, "abc");
+    IF (err != NC_NOERR)
+        error("ncmpi_rename_dim: %s", ncmpi_strerror(err));
+    ELSE_NOK
+    err = ncmpi_inq_dimname(ncid, 2, name);
+    IF (strcmp(name, "abc") != 0)
+        error("Unexpected name: %s", name);
+    err = ncmpi_rename_dim(ncid, 0, "abc");
+    IF (err != NC_ENAMEINUSE)
+        error("duplicate name: status = %d", err);
+    ELSE_NOK
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_def_var
+ *    try with bad netCDF handle, check error
+ *    try with bad name, check error
+ *    scalar tests:
+ *      check that proper define worked with ncmpi_inq_var
+ *      try redefining an existing variable, check error
+ *      try with bad datatype, check error
+ *      try with bad number of dimensions, check error
+ *      try in data mode, check error
+ *    check that returned id is one more than previous id
+ *    try with bad dimension ids, check error
+ */
+int
+test_ncmpi_def_var(void)
+{
+    int  ncid;
+    int  varid;
+    int  err, nok=0;             /* status */
+    int  i;
+    int  ndims;
+    int  natts;
+    char name[NC_MAX_NAME];
+    int dimids[MAX_RANK];
+    nc_type datatype;
+
+        /* BAD_ID test */
+    err = ncmpi_def_var(BAD_ID, "abc", NC_SHORT, 0, NULL, &varid);
+    IF (err != NC_EBADID)
+        error("bad ncid: status = %d", err);
+    ELSE_NOK
+
+        /* scalar tests */
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    err = ncmpi_def_var(ncid, "abc", NC_SHORT, 0, NULL, &varid);
+    IF (err != NC_NOERR)
+        error("ncmpi_def_var: %s", ncmpi_strerror(err));
+    ELSE_NOK
+    err = ncmpi_inq_var(ncid, varid, name, &datatype, &ndims, dimids, &natts);
+    IF (err != NC_NOERR)
+        error("ncmpi_inq_var: %s", ncmpi_strerror(err));
+    IF (strcmp(name, "abc") != 0)
+        error("Unexpected name: %s", name);
+    IF (datatype != NC_SHORT)
+        error("Unexpected datatype");
+    IF (ndims != 0)
+        error("Unexpected rank");
+    err = ncmpi_def_var(ncid, BAD_NAME, NC_SHORT, 0, NULL, &varid);
+    IF (err != NC_EBADNAME)
+        error("bad name: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_def_var(ncid, "abc", NC_SHORT, 0, NULL, &varid);
+    IF (err != NC_ENAMEINUSE)
+        error("duplicate name: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_def_var(ncid, "ABC", BAD_TYPE, -1, dimids, &varid);
+    IF (err != NC_EBADTYPE)
+        error("bad type: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_def_var(ncid, "ABC", NC_SHORT, -1, dimids, &varid);
+    IF (err != NC_EINVAL)
+        error("bad rank: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+	error("ncmpi_enddef: %s", ncmpi_strerror(err));
+    err = ncmpi_def_var(ncid, "ABC", NC_SHORT, 0, dimids, &varid);
+    IF (err != NC_ENOTINDEFINE)
+        error("ncmpi_def_var called in data mode: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+
+    /* general tests using global vars */
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    for (i = 0; i < numVars; i++) {
+        err = ncmpi_def_var(ncid, var_name[i], var_type[i], var_rank[i],
+            var_dimid[i], &varid);
+        IF (err != NC_NOERR) 
+	    error("ncmpi_def_var: %s", ncmpi_strerror(err));
+        ELSE_NOK
+	IF (varid != i)
+	    error("Unexpected varid");
+        ELSE_NOK
+    }
+
+    /* try bad dim ids */
+    dimids[0] = BAD_DIMID;
+    err = ncmpi_def_var(ncid, "abc", NC_SHORT, 1, dimids, &varid);
+    IF (err != NC_EBADDIM)
+        error("bad dim ids: status = %d", err);
+    ELSE_NOK
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_put_var1
+ */
+int
+test_ncmpi_put_var1(void)
+{
+    int i, j, err, ncid, nok=0;
+    MPI_Offset index[MAX_RANK];
+    MPI_Datatype buftype;
+    double value;
+    double buf[1];		/* (void *) buffer */
+
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    /* var1 is only available for indep mode */
+    err = ncmpi_begin_indep_data(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_begin_indep_data: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        buftype = nc_mpi_type(var_type[i]);
+        for (j = 0; j < var_rank[i]; j++)
+            index[j] = 0;
+        err = ncmpi_put_var1(BAD_ID, i, index, buf, 1, buftype);
+        IF (err != NC_EBADID)
+            error("bad ncid: status = %d", err);
+        ELSE_NOK
+        err = ncmpi_put_var1(ncid, BAD_VARID, index, buf, 1, buftype);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: status = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {          /* skip record dim */
+                index[j] = var_shape[i][j];
+                err = ncmpi_put_var1(ncid, i, index, buf, 1, buftype);
+                IF (err != NC_EINVALCOORDS)
+                    error("bad index: status = %d", err);
+                ELSE_NOK
+                index[j] = 0;
+            }
+        }
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR)
+                error("error in toMixedBase");
+            value = hash(var_type[i], var_rank[i], index);
+	    if (inRange(value, var_type[i])) {
+		err = dbl2nc(value, var_type[i], buf);
+		IF (err != NC_NOERR)
+		    error("error in dbl2nc");
+		if (var_rank[i] == 0 && i%2 == 0)
+		    err = ncmpi_put_var1(ncid, i, NULL, buf, 1, buftype);
+		else
+		    err = ncmpi_put_var1(ncid, i, index, buf, 1, buftype);
+		IF (err != NC_NOERR)
+		    error("%s", ncmpi_strerror(err));
+                ELSE_NOK
+	    }
+        }
+    }
+    err = ncmpi_end_indep_data(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_end_indep_data: %s", ncmpi_strerror(err));
+
+    check_vars(ncid);
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_put_vara
+ * Choose a random point dividing each dim into 2 parts
+ * Put 2^rank (nslabs) slabs so defined
+ * Redefine buffer for each put.
+ * At end check all variables using check_vars
+ */
+int
+test_ncmpi_put_vara(void)
+{
+    int d, i, j, k, err, nels,nslabs, ncid, nok=0;
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset bufcount;
+    MPI_Datatype buftype;
+    double buf[MAX_NELS]; 	/* (void *) buffer */
+    char *p;			/* (void *) pointer */
+    double value;
+
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+        }
+        buftype = nc_mpi_type(var_type[i]);
+        for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= edge[j];
+        err = ncmpi_put_vara_all(BAD_ID, i, start, edge, buf, bufcount, buftype);
+        IF (err != NC_EBADID)
+            error("expecting bad ncid: status = %d", err);
+        ELSE_NOK
+        err = ncmpi_put_vara_all(ncid, BAD_VARID, start, edge, buf, bufcount, buftype);
+        IF (err != NC_ENOTVAR)
+            error("expecting bad var id: status = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {          /* skip record dim */
+		start[j] = var_shape[i][j];
+                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
+		err = ncmpi_put_vara_all(ncid, i, start, edge, buf, bufcount, buftype);
+                IF (err != NC_EINVALCOORDS)
+                    error("expecting bad start, but err = %d", err);
+                ELSE_NOK
+		start[j] = 0;
+		edge[j] = var_shape[i][j] + 1;
+                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
+		err = ncmpi_put_vara_all(ncid, i, start, edge, buf, bufcount, buftype);
+                IF (err != NC_EEDGE)
+                    error("expecting bad edge, but err = %d", err);
+                ELSE_NOK
+		edge[j] = 1;
+	    }
+        }
+            /* Choose a random point dividing each dim into 2 parts */
+            /* put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+            /* bits of k determine whether to put lower or upper part of dim */
+        for (k = 0; k < nslabs; k++) {
+            nels = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                }else{
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                nels *= edge[j];
+            }
+	    p = (char *) buf;
+	    for (j = 0; j < nels; j++) {
+		err = toMixedBase(j, var_rank[i], edge, index);
+		IF (err != NC_NOERR)
+		    error("error in toMixedBase");
+		for (d = 0; d < var_rank[i]; d++)
+		    index[d] += start[d];
+		value = hash(var_type[i], var_rank[i], index);
+		if (!inRange(value, var_type[i]))
+		    value = 0;
+		err = dbl2nc(value, var_type[i], p);
+		IF (err != NC_NOERR)
+		    error("error in dbl2nc");
+		p += nctypelen(var_type[i]);
+            }
+            for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= edge[j];
+            if (var_rank[i] == 0 && i%2 == 0)
+		err = ncmpi_put_vara_all(ncid, i, NULL, NULL, buf, bufcount, buftype);
+            else
+		err = ncmpi_put_vara_all(ncid, i, start, edge, buf, bufcount, buftype);
+            IF (err != NC_NOERR)
+                error("%s", ncmpi_strerror(err));
+            ELSE_NOK
+        }
+    }
+
+    check_vars(ncid);
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_put_vars
+ * Choose a random point dividing each dim into 2 parts
+ * Put 2^rank (nslabs) slabs so defined
+ * Choose random stride from 1 to edge
+ * Redefine buffer for each put.
+ * At end check all variables using check_vars
+ */
+int
+test_ncmpi_put_vars(void)
+{
+    int ncid, d, i, j, k, m, err, nels, nslabs, nok=0;
+    int nstarts;        /* number of different starts */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset index2[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    MPI_Offset bufcount;
+    MPI_Datatype buftype;
+    double buf[MAX_NELS]; /* (void *) buffer */
+    char *p;			/* (void *) pointer */
+    double value;
+
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+        }
+        buftype = nc_mpi_type(var_type[i]);
+        for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= edge[j];
+        err = ncmpi_put_vars_all(BAD_ID, i, start, edge, stride, buf, bufcount, buftype);
+        IF (err != NC_EBADID)
+            error("bad ncid: status = %d", err);
+        ELSE_NOK
+        err = ncmpi_put_vars_all(ncid, BAD_VARID, start, edge, stride, buf, bufcount, buftype);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: status = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {          /* skip record dim */
+		start[j] = var_shape[i][j];
+                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
+		err = ncmpi_put_vars_all(ncid, i, start, edge, stride, buf, bufcount, buftype);
+		IF (err != NC_EINVALCOORDS)
+		    error("bad index: status = %d", err);
+                ELSE_NOK
+		start[j] = 0;
+		edge[j] = var_shape[i][j] + 1;
+                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
+		err = ncmpi_put_vars_all(ncid, i, start, edge, stride, buf, bufcount, buftype);
+		IF (err != NC_EEDGE)
+		    error("bad edge: status = %d", err);
+                ELSE_NOK
+		edge[j] = 1;
+		stride[j] = 0;
+                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
+		err = ncmpi_put_vars_all(ncid, i, start, edge, stride, buf, bufcount, buftype);
+		IF (err != NC_ESTRIDE)
+		    error("bad stride: status = %d", err);
+                ELSE_NOK
+		stride[j] = 1;
+	    }
+        }
+            /* Choose a random point dividing each dim into 2 parts */
+            /* put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+            /* bits of k determine whether to put lower or upper part of dim */
+            /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                }else{
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+                err = toMixedBase(m, var_rank[i], sstride, index);
+                IF (err != NC_NOERR)
+                    error("error in toMixedBase");
+                nels = 1;
+                for (j = 0; j < var_rank[i]; j++) {
+                    count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+                    nels *= count[j];
+                    index[j] += start[j];
+                }
+                        /* Random choice of forward or backward */
+/* TODO
+                if ( roll(2) ) {
+                    for (j = 0; j < var_rank[i]; j++) {
+                        index[j] += (count[j] - 1) * stride[j];
+                        stride[j] = -stride[j];
+                    }
+                }
+ */
+		p = (char *) buf;
+		for (j = 0; j < nels; j++) {
+		    err = toMixedBase(j, var_rank[i], count, index2);
+		    IF (err != NC_NOERR)
+			error("error in toMixedBase");
+		    for (d = 0; d < var_rank[i]; d++)
+			index2[d] = index[d] + index2[d] * stride[d];
+		    value = hash(var_type[i], var_rank[i], index2);
+		    if (!inRange(value, var_type[i]))
+			value = 0;
+		    err = dbl2nc(value, var_type[i], p);
+		    IF (err != NC_NOERR)
+			error("error in dbl2nc");
+		    p += nctypelen(var_type[i]);
+		}
+                for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= count[j];
+		if (var_rank[i] == 0 && i%2 == 0)
+		    err = ncmpi_put_vars_all(ncid, i, NULL, NULL, NULL, buf, bufcount, buftype);
+		else
+		    err = ncmpi_put_vars_all(ncid, i, index, count, stride, buf, bufcount, buftype);
+		IF (err != NC_NOERR)
+		    error("%s", ncmpi_strerror(err));
+                ELSE_NOK
+            }
+        }
+    }
+
+    check_vars(ncid);
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_put_varm
+ * Choose a random point dividing each dim into 2 parts
+ * Put 2^rank (nslabs) slabs so defined
+ * Choose random stride from 1 to edge
+ * Buffer is bit image of whole external variable.
+ * So all puts for a variable put different elements of buffer
+ * At end check all variables using check_vars
+ */
+int
+test_ncmpi_put_varm(void)
+{
+    int ncid, nok=0;
+    int i;
+    int j;
+    int k;
+    int m;
+    int err;
+    int nslabs;
+    int nstarts;        /* number of different starts */
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset edge[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    MPI_Offset mid[MAX_RANK];
+    MPI_Offset count[MAX_RANK];
+    MPI_Offset sstride[MAX_RANK];
+    MPI_Offset stride[MAX_RANK];
+    MPI_Offset imap[MAX_RANK];
+    MPI_Offset imap2[MAX_RANK];
+    MPI_Offset bufcount;
+    MPI_Datatype buftype;
+    double buf[MAX_NELS];       /* (void *) buffer */
+    char *p;			/* (void *) pointer */
+    double value;
+
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = 0; i < numVars; i++) {
+        assert(var_rank[i] <= MAX_RANK);
+        assert(var_nels[i] <= MAX_NELS);
+        for (j = 0; j < var_rank[i]; j++) {
+            start[j] = 0;
+            edge[j] = 1;
+            stride[j] = 1;
+        }
+	if (var_rank[i] > 0) {
+	    j = var_rank[i] - 1; 
+	    imap[j] = nctypelen(var_type[i]); /*  netCDF considers imap in bytes */
+	    imap[j] = 1;                      /* PnetCDF considers imap in elements */
+	    for (; j > 0; j--)
+		imap[j-1] = imap[j] * var_shape[i][j];
+	}
+	p = (char *) buf;
+	for (j = 0; j < var_nels[i]; j++) {
+	    err = toMixedBase(j, var_rank[i], var_shape[i], index);
+	    IF (err != NC_NOERR)
+		error("error in toMixedBase");
+	    value = hash(var_type[i], var_rank[i], index);
+	    if (!inRange(value, var_type[i]))
+		value = 0;
+	    err = dbl2nc(value, var_type[i], p);
+	    IF (err != NC_NOERR)
+		error("error in dbl2nc");
+	    p += nctypelen(var_type[i]);
+	}
+        buftype = nc_mpi_type(var_type[i]);
+        for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= edge[j];
+        err = ncmpi_put_varm_all(BAD_ID, i, start, edge, stride, imap, buf, bufcount, buftype);
+        IF (err != NC_EBADID)
+            error("bad ncid: status = %d", err);
+        ELSE_NOK
+        err = ncmpi_put_varm_all(ncid, BAD_VARID, start, edge, stride, imap, buf, bufcount, buftype);
+        IF (err != NC_ENOTVAR)
+            error("bad var id: status = %d", err);
+        ELSE_NOK
+        for (j = 0; j < var_rank[i]; j++) {
+            if (var_dimid[i][j] > 0) {          /* skip record dim */
+		start[j] = var_shape[i][j];
+                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
+		err = ncmpi_put_varm_all(ncid, i, start, edge, stride, imap, buf, bufcount, buftype);
+		IF (err != NC_EINVALCOORDS)
+		    error("bad index: status = %d", err);
+                ELSE_NOK
+		start[j] = 0;
+		edge[j] = var_shape[i][j] + 1;
+                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
+		err = ncmpi_put_varm_all(ncid, i, start, edge, stride, imap, buf, bufcount, buftype);
+		IF (err != NC_EEDGE)
+		    error("bad edge: status = %d", err);
+                ELSE_NOK
+		edge[j] = 1;
+		stride[j] = 0;
+                for (bufcount=1,k=0; k<var_rank[i]; k++) bufcount *= edge[k];
+		err = ncmpi_put_varm_all(ncid, i, start, edge, stride, imap, buf, bufcount, buftype);
+		IF (err != NC_ESTRIDE)
+		    error("bad stride: status = %d", err);
+                ELSE_NOK
+		stride[j] = 1;
+	    }
+        }
+            /* Choose a random point dividing each dim into 2 parts */
+            /* put 2^rank (nslabs) slabs so defined */
+        nslabs = 1;
+        for (j = 0; j < var_rank[i]; j++) {
+            mid[j] = roll( var_shape[i][j] );
+            nslabs *= 2;
+        }
+            /* bits of k determine whether to put lower or upper part of dim */
+            /* choose random stride from 1 to edge */
+        for (k = 0; k < nslabs; k++) {
+            nstarts = 1;
+            for (j = 0; j < var_rank[i]; j++) {
+                if ((k >> j) & 1) {
+                    start[j] = 0;
+                    edge[j] = mid[j];
+                }else{
+                    start[j] = mid[j];
+                    edge[j] = var_shape[i][j] - mid[j];
+                }
+                sstride[j] = stride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
+                imap2[j] = imap[j] * sstride[j];
+                nstarts *= stride[j];
+            }
+            for (m = 0; m < nstarts; m++) {
+		if (var_rank[i] == 0 && i%2 == 0) {
+		    err = ncmpi_put_varm_all(ncid, i, NULL, NULL, NULL, NULL, buf, 1, buftype);
+		} else {
+		    err = toMixedBase(m, var_rank[i], sstride, index);
+		    IF (err != NC_NOERR)
+			error("error in toMixedBase");
+		    for (j = 0; j < var_rank[i]; j++) {
+			count[j] = 1 + (edge[j] - index[j] - 1) / stride[j];
+			index[j] += start[j];
+		    }
+			    /* Random choice of forward or backward */
+/* TODO
+		    if ( roll(2) ) {
+			for (j = 0; j < var_rank[i]; j++) {
+			    index[j] += (count[j] - 1) * stride[j];
+			    stride[j] = -stride[j];
+			}
+		    }
+ */
+		    j = fromMixedBase(var_rank[i], index, var_shape[i]);
+                    p = (char *) buf + j * nctypelen(var_type[i]);
+                    for (bufcount=1,j=0; j<var_rank[i]; j++) bufcount *= count[j];
+		    err = ncmpi_put_varm_all(ncid, i, index, count, stride, imap2, p, bufcount, buftype);
+		}
+		IF (err != NC_NOERR)
+		    error("i=%d var_rank[i]=%d %s", i,var_rank[i],ncmpi_strerror(err));
+                ELSE_NOK
+            }
+        }
+    }
+
+    check_vars(ncid);
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_rename_var
+ *    try with bad netCDF handle, check error
+ *    try with bad variable handle, check error
+ *    try renaming to existing variable name, check error
+ *    check that proper rename worked with ncmpi_inq_varid
+ *    try in data mode, check error
+ */
+int
+test_ncmpi_rename_var(void)
+{
+    int ncid;
+    int varid;
+    int err, nok=0;
+    int i;
+    char name[NC_MAX_NAME];
+
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    err = ncmpi_rename_var(ncid, BAD_VARID, "newName");
+    IF (err != NC_ENOTVAR)
+	error("bad var id: status = %d", err);
+    ELSE_NOK
+    def_dims(ncid);
+    def_vars(ncid);
+
+	/* Prefix "new_" to each name */
+    for (i = 0; i < numVars; i++) {
+        err = ncmpi_rename_var(BAD_ID, i, "newName");
+        IF (err != NC_EBADID)
+            error("bad ncid: status = %d", err);
+        ELSE_NOK
+        err = ncmpi_rename_var(ncid, i, var_name[numVars-1]);
+        IF (err != NC_ENAMEINUSE)
+            error("duplicate name: status = %d", err);
+        ELSE_NOK
+	strcpy(name, "new_");
+	strcat(name, var_name[i]);
+        err = ncmpi_rename_var(ncid, i, name);
+        IF (err != NC_NOERR)
+	    error("ncmpi_rename_var: %s", ncmpi_strerror(err));
+        ELSE_NOK
+        err = ncmpi_inq_varid(ncid, name, &varid);
+        IF (err != NC_NOERR)
+	    error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
+        IF (varid != i)
+	    error("Unexpected varid");
+    }
+
+	/* Change to data mode */
+	/* Try making names even longer. Then restore original names */
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+	strcpy(name, "even_longer_");
+	strcat(name, var_name[i]);
+        err = ncmpi_rename_var(ncid, i, name);
+        IF (err != NC_ENOTINDEFINE)
+            error("longer name in data mode: status = %d", err);
+        ELSE_NOK
+        err = ncmpi_rename_var(ncid, i, var_name[i]);
+        IF (err != NC_NOERR)
+	    error("ncmpi_rename_var: %s", ncmpi_strerror(err));
+        ELSE_NOK
+        err = ncmpi_inq_varid(ncid, var_name[i], &varid);
+        IF (err != NC_NOERR)
+	    error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
+        IF (varid != i)
+	    error("Unexpected varid");
+    }
+
+    put_vars(ncid);
+    check_vars(ncid);
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+int
+test_ncmpi_put_att(void)
+{
+    int ncid, nok=0;
+    int varid;
+    int i;
+    int j;
+    MPI_Offset k;
+    int err;
+    double buf[MAX_NELS];       /* (void *) buffer */
+    char *p;                    /* (void *) pointer */
+    char *name;			/* of att */
+    nc_type datatype;		/* of att */
+    MPI_Offset length;		/* of att */
+    double value;
+
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+
+    for (i = -1; i < numVars; i++) {
+	varid = VARID(i);
+        for (j = 0; j < NATTS(i); j++) {
+	    name = ATT_NAME(i,j);
+	    datatype = ATT_TYPE(i,j);
+	    length = ATT_LEN(i,j);
+            err = ncmpi_put_att(BAD_ID, varid, name, datatype, length, buf);
+            IF (err != NC_EBADID)
+                error("bad ncid: status = %d", err);
+            ELSE_NOK
+            err = ncmpi_put_att(ncid, varid, BAD_NAME, datatype, length, buf);
+	    IF (err != NC_EBADNAME)
+		error("bad name: status = %d", err);
+            ELSE_NOK
+            err = ncmpi_put_att(ncid, BAD_VARID, name, datatype, length, buf);
+            IF (err != NC_ENOTVAR)
+                error("bad var id: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_put_att(ncid, varid, name, BAD_TYPE, length, buf);
+	    IF (err != NC_EBADTYPE)
+		error("bad type: status = %d", err);
+            ELSE_NOK
+	    p = (char *) buf;
+	    for (k=0; k<length; k++) {
+		value = hash(datatype, -1, &k);
+		if (!inRange(value, datatype))
+		    value = 0;
+		err = dbl2nc(value, datatype, p);
+		IF (err != NC_NOERR)
+		    error("error in dbl2nc");
+		p += nctypelen(datatype);
+	    }
+            err = ncmpi_put_att(ncid, varid, name, datatype, length, buf);
+            IF (err != NC_NOERR)
+                error("%s", ncmpi_strerror(err));
+            ELSE_NOK
+        }
+    }
+
+    check_atts(ncid);
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_copy_att
+ *    try with bad source or target netCDF handles, check error
+ *    try with bad source or target variable handle, check error
+ *    try with nonexisting attribute, check error
+ *    check that NC_GLOBAL variable for source or target works
+ *    check that new attribute put works with target in define mode
+ *    check that old attribute put works with target in data mode
+ *    check that changing type and length of an attribute work OK
+ *    try with same ncid for source and target, different variables
+ *    try with same ncid for source and target, same variable
+ */
+int
+test_ncmpi_copy_att(void)
+{
+    int ncid_in;
+    int ncid_out;
+    int varid;
+    int err, nok=0;
+    int i;
+    int j=0;
+    char *name;                 /* of att */
+    nc_type datatype;           /* of att */
+    MPI_Offset length;          /* of att */
+    char  value;
+
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid_in);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid_out);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid_out);
+    def_vars(ncid_out);
+
+    for (i = -1; i < numVars; i++) {
+        varid = VARID(i);
+        for (j = 0; j < NATTS(i); j++) {
+            name = ATT_NAME(i,j);
+	    err = ncmpi_copy_att(ncid_in, BAD_VARID, name, ncid_out, varid);
+	    IF (err != NC_ENOTVAR)
+		error("bad var id: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_copy_att(ncid_in, varid, name, ncid_out, BAD_VARID);
+	    IF (err != NC_ENOTVAR)
+		error("bad var id: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_copy_att(BAD_ID, varid, name, ncid_out, varid);
+	    IF (err != NC_EBADID)
+		error("bad ncid: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_copy_att(ncid_in, varid, name, BAD_ID, varid);
+	    IF (err != NC_EBADID)
+		error("bad ncid: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_copy_att(ncid_in, varid, "noSuch", ncid_out, varid);
+	    IF (err != NC_ENOTATT)
+		error("bad attname: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_copy_att(ncid_in, varid, name, ncid_out, varid);
+	    IF (err != NC_NOERR)
+		error("ncmpi_copy_att: %s", ncmpi_strerror(err));
+            ELSE_NOK
+	    err = ncmpi_copy_att(ncid_out, varid, name, ncid_out, varid);
+	    IF (err != NC_NOERR)
+		error("source = target: %s", ncmpi_strerror(err));
+            ELSE_NOK
+	}
+    }
+
+    err = ncmpi_close(ncid_in);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+        /* Close scratch. Reopen & check attributes */
+    err = ncmpi_close(ncid_out);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = ncmpi_open(comm, scratch, NC_WRITE, info, &ncid_out);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    check_atts(ncid_out);
+
+       /* 
+	* change to define mode
+	* define single char. global att. ':a' with value 'A'
+	* This will be used as source for following copies
+	*/
+    err = ncmpi_redef(ncid_out);
+    IF (err != NC_NOERR)
+        error("ncmpi_redef: %s", ncmpi_strerror(err));
+    err = ncmpi_put_att_text(ncid_out, NC_GLOBAL, "a", 1, "A");
+    IF (err != NC_NOERR)
+	error("ncmpi_put_att_text: %s", ncmpi_strerror(err));
+
+       /* 
+	* change to data mode
+	* Use scratch as both source & dest.
+	* try copy to existing att. change type & decrease length
+	* rename 1st existing att of each var (if any) 'a'
+	* if this att. exists them copy ':a' to it
+	*/
+    err = ncmpi_enddef(ncid_out);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+	if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
+	    err = ncmpi_rename_att(ncid_out, i, att_name[i][0], "a");
+	    IF (err != NC_NOERR)
+		error("ncmpi_rename_att: %s", ncmpi_strerror(err));
+	    err = ncmpi_copy_att(ncid_out, NC_GLOBAL, "a", ncid_out, i);
+	    IF (err != NC_NOERR)
+		error("ncmpi_copy_att: %s", ncmpi_strerror(err));
+            ELSE_NOK
+	}
+    }
+    err = ncmpi_close(ncid_out);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+	/* Reopen & check */
+    err = ncmpi_open(comm, scratch, NC_WRITE, info, &ncid_out);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    for (i = 0; i < numVars; i++) {
+	if (NATTS(i) > 0 && ATT_LEN(i,j) > 0) {
+	    err = ncmpi_inq_att(ncid_out, i, "a", &datatype, &length);
+	    IF (err != NC_NOERR)
+		error("ncmpi_inq_att: %s", ncmpi_strerror(err));
+	    IF (datatype != NC_CHAR)
+		error("Unexpected type");
+	    IF (length != 1)
+		error("Unexpected length");
+	    err = ncmpi_get_att_text(ncid_out, i, "a", &value);
+	    IF (err != NC_NOERR)
+		error("ncmpi_get_att_text: %s", ncmpi_strerror(err));
+	    IF (value != 'A')
+		error("Unexpected value");
+	}                                                   
+    }                                                   
+
+    err = ncmpi_close(ncid_out);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_rename_att
+ *    try with bad netCDF handle, check error
+ *    try with bad variable handle, check error
+ *    try with nonexisting att name, check error
+ *    try renaming to existing att name, check error
+ *    check that proper rename worked with ncmpi_inq_attid
+ *    try in data mode, check error
+ */
+int
+test_ncmpi_rename_att(void)
+{
+    int ncid;
+    int varid;
+    int err;
+    int i;
+    int j;
+    MPI_Offset  k;
+    int attnum;
+    char *attname;
+    char name[NC_MAX_NAME];
+    char oldname[NC_MAX_NAME];
+    char newname[NC_MAX_NAME];
+    int nok = 0;      /* count of valid comparisons */
+    nc_type datatype;
+    nc_type atttype;
+    MPI_Offset length;
+    size_t attlength;
+    char  text[MAX_NELS];
+    double value[MAX_NELS];
+    double expect;
+
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    err = ncmpi_rename_att(ncid, BAD_VARID, "abc", "newName");
+    IF (err != NC_ENOTVAR)
+	error("bad var id: status = %d", err);
+    ELSE_NOK
+    def_dims(ncid);
+    def_vars(ncid);
+    put_atts(ncid);
+
+    for (i = -1; i < numVars; i++) {
+        varid = VARID(i);
+        for (j = 0; j < NATTS(i); j++) {
+	    attname = ATT_NAME(i,j);
+	    err = ncmpi_rename_att(BAD_ID, varid, attname, "newName");
+	    IF (err != NC_EBADID)
+		error("bad ncid: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_rename_att(ncid, varid, "noSuch", "newName");
+	    IF (err != NC_ENOTATT)
+		error("bad attname: status = %d", err);
+            ELSE_NOK
+	    strcpy(newname, "new_");
+	    strcat(newname, attname);
+	    err = ncmpi_rename_att(ncid, varid, attname, newname);
+	    IF (err != NC_NOERR)
+		error("ncmpi_rename_att: %s", ncmpi_strerror(err));
+            ELSE_NOK
+	    err = ncmpi_inq_attid(ncid, varid, newname, &attnum);
+	    IF (err != NC_NOERR)
+		error("ncmpi_inq_attid: %s", ncmpi_strerror(err));
+	    IF (attnum != j)
+		error("Unexpected attnum");
+	}
+    }
+
+    /* Close. Reopen & check */
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = ncmpi_open(comm, scratch, NC_WRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+
+    for (i = -1; i < numVars; i++) {
+        varid = VARID(i);
+        for (j = 0; j < NATTS(i); j++) {
+	    attname = ATT_NAME(i,j);
+	    atttype = ATT_TYPE(i,j);
+	    attlength = ATT_LEN(i,j);
+            strcpy(newname, "new_");
+            strcat(newname, attname);
+            err = ncmpi_inq_attname(ncid, varid, j, name);
+            IF (err != NC_NOERR)
+                error("ncmpi_inq_attname: %s", ncmpi_strerror(err));
+            IF (strcmp(name, newname) != 0)
+                error("ncmpi_inq_attname: unexpected name");
+            err = ncmpi_inq_att(ncid, varid, name, &datatype, &length);
+            IF (err != NC_NOERR)
+                error("ncmpi_inq_att: %s", ncmpi_strerror(err));
+            IF (datatype != atttype)
+                error("ncmpi_inq_att: unexpected type");
+            IF (length != attlength)
+                error("ncmpi_inq_att: unexpected length");
+            if (datatype == NC_CHAR) {
+                err = ncmpi_get_att_text(ncid, varid, name, text);
+                IF (err != NC_NOERR)
+                    error("ncmpi_get_att_text: %s", ncmpi_strerror(err));
+                for (k = 0; k < attlength; k++) {
+                    expect = hash(datatype, -1, &k);
+                    IF (text[k] != (char)expect)
+                        error("ncmpi_get_att_text: unexpected value");
+                }
+            } else {
+                err = ncmpi_get_att_double(ncid, varid, name, value);
+                IF (err != NC_NOERR)
+                    error("ncmpi_get_att_double: %s", ncmpi_strerror(err));
+                for (k = 0; k < attlength; k++) {
+                    expect = hash(datatype, -1, &k);
+		    if (inRange(expect, datatype)) {
+			IF (!equal(value[k],expect,datatype,NCT_DOUBLE))
+			    error("ncmpi_get_att_double: unexpected value");
+                    }
+                }
+            }
+        }
+    }
+
+	/* Now in data mode */
+	/* Try making names even longer. Then restore original names */
+
+    for (i = -1; i < numVars; i++) {
+        varid = VARID(i);
+        for (j = 0; j < NATTS(i); j++) {
+	    attname = ATT_NAME(i,j);
+	    strcpy(oldname, "new_");
+	    strcat(oldname, attname);
+	    strcpy(newname, "even_longer_");
+	    strcat(newname, attname);
+	    err = ncmpi_rename_att(ncid, varid, oldname, newname);
+	    IF (err != NC_ENOTINDEFINE)
+		error("longer name in data mode: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_rename_att(ncid, varid, oldname, attname);
+	    IF (err != NC_NOERR)
+		error("ncmpi_rename_att: %s", ncmpi_strerror(err));
+            ELSE_NOK
+	    err = ncmpi_inq_attid(ncid, varid, attname, &attnum);
+	    IF (err != NC_NOERR)
+		error("ncmpi_inq_attid: %s", ncmpi_strerror(err));
+	    IF (attnum != j)
+		error("Unexpected attnum");
+	}
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_del_att
+ *    try with bad netCDF handle, check error
+ *    try with bad variable handle, check error
+ *    try with nonexisting att name, check error
+ *    check that proper delete worked using:
+ *      ncmpi_inq_attid, ncmpi_inq_natts, ncmpi_inq_varnatts
+ */
+int
+test_ncmpi_del_att(void)
+{
+    int ncid;
+    int err, nok=0;
+    int i;
+    int j;
+    int attnum;
+    int natts;
+    int numatts;
+    int varid;
+    char *name;                 /* of att */
+
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    err = ncmpi_del_att(ncid, BAD_VARID, "abc");
+    IF (err != NC_ENOTVAR)
+	error("bad var id: status = %d", err);
+    ELSE_NOK
+    def_dims(ncid);
+    def_vars(ncid);
+    put_atts(ncid);
+
+    for (i = -1; i < numVars; i++) {
+	varid = VARID(i);
+	numatts = NATTS(i);
+        for (j = 0; j < numatts; j++) {
+	    name = ATT_NAME(i,j);
+	    err = ncmpi_del_att(BAD_ID, varid, name);
+	    IF (err != NC_EBADID)
+		error("bad ncid: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_del_att(ncid, varid, "noSuch");
+	    IF (err != NC_ENOTATT)
+		error("bad attname: status = %d", err);
+            ELSE_NOK
+	    err = ncmpi_del_att(ncid, varid, name);
+	    IF (err != NC_NOERR)
+		error("ncmpi_del_att: %s", ncmpi_strerror(err));
+            ELSE_NOK
+	    err = ncmpi_inq_attid(ncid, varid, name, &attnum);
+	    IF (err != NC_ENOTATT)
+		error("bad attname: status = %d", err);
+	    if (i < 0) {
+		err = ncmpi_inq_natts(ncid, &natts);
+		IF (err != NC_NOERR)
+		    error("ncmpi_inq_natts: %s", ncmpi_strerror(err));
+		IF (natts != numatts-j-1)
+		    error("natts: expected %d, got %d", numatts-j-1, natts);
+	    }
+	    err = ncmpi_inq_varnatts(ncid, varid, &natts);
+	    IF (err != NC_NOERR)
+		error("ncmpi_inq_natts: %s", ncmpi_strerror(err));
+	    IF (natts != numatts-j-1)
+		error("natts: expected %d, got %d", numatts-j-1, natts);
+	}
+    }
+
+        /* Close. Reopen & check no attributes left */
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = ncmpi_open(comm, scratch, NC_WRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_inq_natts(ncid, &natts);
+    IF (err != NC_NOERR)
+	error("ncmpi_inq_natts: %s", ncmpi_strerror(err));
+    IF (natts != 0)
+	error("natts: expected %d, got %d", 0, natts);
+    for (i = -1; i < numVars; i++) {
+	varid = VARID(i);
+	err = ncmpi_inq_varnatts(ncid, varid, &natts);
+	IF (err != NC_NOERR)
+	    error("ncmpi_inq_natts: %s", ncmpi_strerror(err));
+	IF (natts != 0)
+	    error("natts: expected %d, got %d", 0, natts);
+    }
+
+	/* restore attributes. change to data mode. try to delete */
+    err = ncmpi_redef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_redef: %s", ncmpi_strerror(err));
+    put_atts(ncid);
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    for (i = -1; i < numVars; i++) {
+	varid = VARID(i);
+	numatts = NATTS(i);
+        for (j = 0; j < numatts; j++) {
+	    name = ATT_NAME(i,j);
+	    err = ncmpi_del_att(ncid, varid, name);
+	    IF (err != NC_ENOTINDEFINE)
+		error("in data mode: status = %d", err);
+            ELSE_NOK
+	}
+    }
+
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+/*
+ * Test ncmpi_set_fill
+ *    try with bad netCDF handle, check error
+ *    try in read-only mode, check error
+ *    try with bad new_fillmode, check error
+ *    try in data mode, check error
+ *    check that proper set to NC_FILL works for record & non-record variables
+ *    (note that it is not possible to test NC_NOFILL mode!)
+ *    close file & create again for test using attribute _FillValue
+ */
+int
+test_ncmpi_set_fill(void)
+{
+    int ncid;
+    int varid;
+    int err;
+    int i;
+    int j;
+    int old_fillmode;
+    int nok = 0;      /* count of valid comparisons */
+    char text = 0;
+    double value = 0;
+    double fill;
+    MPI_Offset index[MAX_RANK];
+
+	/* bad ncid */
+    err = ncmpi_set_fill(BAD_ID, NC_NOFILL, &old_fillmode);
+    IF (err != NC_EBADID)
+	error("bad ncid: status = %d", err);
+
+	/* try in read-only mode */
+    err = ncmpi_open(comm, testfile, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    err = ncmpi_set_fill(ncid, NC_NOFILL, &old_fillmode);
+    IF (err != NC_EPERM)
+	error("read-only: status = %d", err);
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+
+	/* create scratch */
+    err = ncmpi_create(comm, scratch, NC_NOCLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+
+	/* BAD_FILLMODE */
+    err = ncmpi_set_fill(ncid, BAD_FILLMODE, &old_fillmode);
+    IF (err != NC_EINVAL)
+        error("bad fillmode: status = %d", err);
+
+	/* proper calls */
+    err = ncmpi_set_fill(ncid, NC_NOFILL, &old_fillmode);
+    IF (err != NC_NOERR)
+        error("ncmpi_set_fill: %s", ncmpi_strerror(err));
+    IF (old_fillmode != NC_NOFILL)
+        error("Unexpected old fill mode: %d", old_fillmode);
+    err = ncmpi_set_fill(ncid, NC_FILL, &old_fillmode);
+    IF (err != NC_NOERR)
+        error("ncmpi_set_fill: %s", ncmpi_strerror(err));
+    IF (old_fillmode != NC_NOFILL)
+        error("Unexpected old fill mode: %d", old_fillmode);
+
+	/* define dims & vars */
+    def_dims(ncid);
+    def_vars(ncid);
+
+	/* Change to data mode. Set fillmode again */
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+    err = ncmpi_set_fill(ncid, NC_FILL, &old_fillmode);
+    IF (err != NC_ENOTINDEFINE)
+        error("ncmpi_set_fill: %s", ncmpi_strerror(err));
+
+	/* Write record number NRECS to force writing of preceding records */
+	/* Assumes variable cr is char vector with UNLIMITED dimension */
+    err = ncmpi_inq_varid(ncid, "cr", &varid);
+    IF (err != NC_NOERR)
+        error("ncmpi_inq_varid: %s", ncmpi_strerror(err));
+    index[0] = NRECS;
+    for (i=0; i<=index[0]; i++)
+        err = ncmpi_fill_var_rec(ncid, varid, i);
+    err = ncmpi_put_var1_text_all(ncid, varid, index, &text);
+    IF (err != NC_NOERR)
+        error("ncmpi_put_var1_text_all: %s", ncmpi_strerror(err));
+
+	/* get all variables & check all values equal default fill */
+    for (i = 0; i < numVars; i++) {
+        if (var_dimid[i][0] == RECDIM) continue; /* skip record variables */
+	switch (var_type[i]) {
+	    case NC_CHAR:   fill = NC_FILL_CHAR; break;
+	    case NC_BYTE:   fill = NC_FILL_BYTE; break;
+	    case NC_SHORT:  fill = NC_FILL_SHORT; break;
+	    case NC_INT:   fill = NC_FILL_INT; break;
+	    case NC_FLOAT:  fill = NC_FILL_FLOAT; break;
+	    case NC_DOUBLE: fill = NC_FILL_DOUBLE; break;
+	    case NC_UBYTE: fill = NC_FILL_UBYTE; break;
+	    case NC_USHORT: fill = NC_FILL_USHORT; break;
+	    case NC_UINT: fill = NC_FILL_UINT; break;
+	    case NC_INT64: fill = NC_FILL_INT64; break;
+	    case NC_UINT64: fill = NC_FILL_UINT64; break;
+	    default: assert(0);
+	}
+	for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR)
+                error("error in toMixedBase");
+	    if (var_type[i] == NC_CHAR) {
+		err = ncmpi_get_var1_text_all(ncid, i, index, &text);
+		IF (err != NC_NOERR)
+		    error("ncmpi_get_var1_text_all failed: %s", ncmpi_strerror(err));
+		value = text;
+	    } else {
+		err = ncmpi_get_var1_double_all(ncid, i, index, &value);
+		IF (err != NC_NOERR)
+		    error("ncmpi_get_var1_double_all failed: %s", ncmpi_strerror(err));
+	    }
+	    IF (value != fill && fabs((fill - value)/fill) > DBL_EPSILON)
+		error("\n\t\t%s Value expected: %-23.17e,\n\t\t          read: %-23.17e\n",
+			var_name[i],fill, value);
+	    ELSE_NOK
+        }
+    }
+
+	/* close scratch & create again for test using attribute _FillValue */
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_create: %s", ncmpi_strerror(err));
+        return nok;
+    }
+    def_dims(ncid);
+    def_vars(ncid);
+
+	/* set _FillValue = 42 for all vars */
+    text = fill = 42;
+    for (i = 0; i < numVars; i++) {
+	if (var_type[i] == NC_CHAR) {
+	    err = ncmpi_put_att_text(ncid, i, "_FillValue", 1, &text);
+	    IF (err != NC_NOERR)
+		error("ncmpi_put_att_text: %s", ncmpi_strerror(err));
+	} else {
+	    err = ncmpi_put_att_double(ncid, i, "_FillValue",var_type[i],1,&fill);
+	    IF (err != NC_NOERR)
+		error("ncmpi_put_att_double: %s", ncmpi_strerror(err));
+	}
+    }
+
+	/* data mode. write records */
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_enddef: %s", ncmpi_strerror(err));
+    index[0] = NRECS;
+    for (i=0; i<=index[0]; i++)
+        err = ncmpi_fill_var_rec(ncid, varid, i);
+    err = ncmpi_put_var1_text_all(ncid, varid, index, &text);
+    IF (err != NC_NOERR)
+        error("ncmpi_put_var1_text_all: %s", ncmpi_strerror(err));
+
+	/* get all variables & check all values equal 42 */
+    for (i = 0; i < numVars; i++) {
+        if (var_dimid[i][0] == RECDIM) continue; /* skip record variables */
+	for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR)
+                error("error in toMixedBase");
+	    if (var_type[i] == NC_CHAR) {
+		err = ncmpi_get_var1_text_all(ncid, i, index, &text);
+		IF (err != NC_NOERR)
+		    error("ncmpi_get_var1_text_all failed: %s", ncmpi_strerror(err));
+		value = text;
+	    } else {
+		err = ncmpi_get_var1_double_all(ncid, i, index, &value);
+		IF (err != NC_NOERR)
+		    error("ncmpi_get_var1_double_all failed: %s", ncmpi_strerror(err));
+	    }
+	    IF (value != fill)
+		error(" %s Value expected: %g, read: %g\n", var_name[i],fill, value);
+	    ELSE_NOK
+        }
+    }
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+        error("remove of %s failed", scratch);
+
+    return nok;
+}
+
+
+/* This function gets the version of a netCDF file, 1 is for netCDF
+   classic, 2 for 64-bit offset format, (someday) 3 for HDF5 format.
+*/
+#define MAGIC_NUM_LEN 4
+static
+int ncmpi_get_file_version(char *path, int *version)
+{
+   FILE *fp;
+   char magic[MAGIC_NUM_LEN];
+
+   /* Need two valid pointers - check for NULL. */
+   if (!version || !path)
+      return NC_EINVAL;
+
+   /* Figure out if this is a netcdf or hdf5 file. */
+   if (!(fp = fopen(path, "r")) ||
+       fread(magic, MAGIC_NUM_LEN, 1, fp) != 1)
+      return errno;
+   fclose(fp);
+   if (strncmp(magic, "CDF", MAGIC_NUM_LEN-1)==0)
+   {
+      if (magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CLASSIC || 
+         magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CDF2 ||
+         magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CDF2)
+        *version = magic[MAGIC_NUM_LEN-1];
+      else
+        return NC_ENOTNC;
+   }
+   /*   tomorrow, tomorrow, I love you tomorrow, you're always a day
+       away! */
+   /*if (magic[1] == 'H' && magic[2] == 'D' && magic[3] == 'F')
+      *version = 3;*/
+   return NC_NOERR;
+}
+
+/*
+ * Test nc_set_default_format
+ *    try with bad default format
+ *    try with NULL old_formatp
+ *    try in data mode, check error
+ *    check that proper set to NC_FILL works for record & non-record variables
+ *    (note that it is not possible to test NC_NOFILL mode!)
+ *    close file & create again for test using attribute _FillValue
+ */
+int
+test_ncmpi_set_default_format(void)
+{
+    int ncid, nok=0;
+    int err;
+    int i;
+    int version=1;
+    int old_format;
+
+    /* bad format */
+    err = ncmpi_set_default_format(BAD_DEFAULT_FORMAT, &old_format);
+    IF (err != NC_EINVAL)
+       error("bad default format: status = %d", err);
+    ELSE_NOK
+
+    /* NULL old_formatp */
+    err = ncmpi_set_default_format(NC_FORMAT_CDF2, NULL);
+    IF (err != NC_NOERR)
+       error("null old_fortmatp: status = %d", err);
+    ELSE_NOK
+
+    /* Cycle through available formats. */
+    for(i=1; i<5; i++)
+    {
+       if (i == 3 || i == 4) continue; /* test classic formats only */
+
+       if ((err = ncmpi_set_default_format(i, NULL)))
+         error("setting classic format: status = %d", err);
+       ELSE_NOK
+       if ((err=ncmpi_create(comm, scratch, NC_CLOBBER, info, &ncid)))
+         error("bad nc_create: status = %d", err);
+       if ((err=ncmpi_put_att_text(ncid, NC_GLOBAL, "testatt", 
+                               sizeof("blah"), "blah")))
+         error("bad put_att: status = %d", err);
+       if ( (err=ncmpi_close(ncid)))
+         error("bad close: status = %d", err);
+       if ( (err = ncmpi_get_file_version(scratch, &version)) )
+         error("bad file version = %d", err);
+       if (version != i) {
+          if (i == 4) {
+              if (version == 3) continue;
+              printf("expect version 3 but got %d (file=%s)",version,scratch);
+              continue;
+          }
+          printf("expect version %d but got %d (file=%s)",i,version,scratch);
+          error("bad file version = %d", version);
+        }
+    }
+
+    /* Remove the left-over file. */
+    if ((err = ncmpi_delete(scratch, info)))
+       error("remove of %s failed", scratch);
+    return nok;
+}
+
+
+
+
+/*
+ * Test ncmpi_delete
+ * 	create netcdf file 'scratch.nc' with no data, close it
+ * 	delete the file
+ */
+int
+test_ncmpi_delete(void)
+{
+    int err, nok=0;;
+    int ncid;
+
+    err = ncmpi_create(comm, scratch, NC_CLOBBER|extra_flags, info, &ncid);
+    IF (err != NC_NOERR)
+	error("error creating scratch file %s, status = %d\n", scratch,err);
+    err = ncmpi_close(ncid);
+    IF (err != NC_NOERR)
+        error("ncmpi_close: %s", ncmpi_strerror(err));
+    err = ncmpi_delete(scratch, info);
+    IF (err != NC_NOERR)
+	error("remove of %s failed", scratch);
+    ELSE_NOK
+    return nok;
+}
diff --git a/test/nc_test/tests.h b/test/nc_test/tests.h
new file mode 100644
index 0000000..ffcead3
--- /dev/null
+++ b/test/nc_test/tests.h
@@ -0,0 +1,793 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: tests.h 2293 2016-01-06 03:43:04Z wkliao $ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <limits.h>
+#include <float.h>
+#define NO_NETCDF_2 1
+#include <errno.h>
+#include <mpi.h>
+
+#include <pnetcdf.h>
+#include <testutils.h>
+#include "error.h"
+
+#include "ncconfig.h" /* output of 'configure' */
+
+#if defined(_CRAY) && !defined(_CRAYIEEE)
+#define CRAYFLOAT 1 /* CRAY Floating point */
+#elif defined(_SX) && defined(_FLOAT2)	/* NEC SUPER-UX in CRAY mode */
+#define CRAYFLOAT 1 /* CRAY Floating point */
+#endif
+
+/* Limits of external types (based on those in ncx.h) */
+
+/* Note: In CDF format specification, NC_CHAR is for text characters, which
+ * is considered an 8-bit unsigned integer. Since it is for printable text
+ * characters, its values should range from 0 (X_CHAR_MIN) to 255 (X_CHAR_MAX).
+ */
+#define X_CHAR_MIN	0
+#define X_CHAR_MAX	255
+
+#define X_SCHAR_MIN     (-128)
+#define X_SCHAR_MAX     127
+#define X_UCHAR_MAX     255
+#define X_UCHAR_MIN     0
+#define X_BYTE_MIN	X_SCHAR_MIN
+#define X_BYTE_MAX	X_SCHAR_MAX
+#define X_SHORT_MIN	(-32768)
+#define X_SHORT_MAX	32767
+#define X_INT_MIN	(-2147483647-1)
+#define X_INT_MAX	2147483647
+#if defined(FLT_MAX_EXP) && FLT_MAX_EXP < 128
+/* FLT_MAX < X_FLOAT_MAX */
+#define X_FLOAT_MAX	FLT_MAX
+#else
+#define X_FLOAT_MAX	3.40282347e+38f
+#endif
+#define X_FLOAT_MIN	(-X_FLOAT_MAX)
+#if defined(CRAYFLOAT) && CRAYFLOAT != 0
+/* ldexp(1. - ldexp(.5 , -46), 1024) */
+#define X_DOUBLE_MAX    1.79769313486230e+308
+#else
+/* scalb(1. - scalb(.5 , -52), 1024) */
+#define X_DOUBLE_MAX	DBL_MAX
+#endif
+#define X_DOUBLE_MIN	-(DBL_MAX)
+
+#define X_UBYTE_MAX     X_UCHAR_MAX
+#define X_UBYTE_MIN     X_UCHAR_MIN
+#define X_USHORT_MAX    65535U
+#define X_USHORT_MIN    0
+#define X_UINT_MAX      4294967295U
+#define X_UINT_MIN      0
+
+#ifndef LLONG_MAX
+#define LLONG_MAX  0x7fffffffffffffffLL
+#endif
+#ifndef LLONG_MIN
+#define LLONG_MIN (-0x7fffffffffffffffLL-1)
+#endif
+#ifndef ULLONG_MAX
+#define ULLONG_MAX  0xffffffffffffffffULL
+#endif
+
+#ifndef X_INT64_MAX
+#define X_INT64_MAX    LLONG_MAX
+#endif
+#ifndef X_INT64_MIN
+#define X_INT64_MIN    LLONG_MIN
+#endif
+#ifndef X_UINT64_MAX
+#define X_UINT64_MAX  ULLONG_MAX
+#endif
+#ifndef X_UINT64_MIN
+#define X_UINT64_MIN  ULLONG_MIN
+#endif
+
+
+#if defined(_SX) && _SX != 0 /* NEC SUPER UX */
+#if _INT64
+#undef  INT_MAX /* workaround cpp bug */
+#define INT_MAX  X_INT_MAX
+#undef  INT_MIN /* workaround cpp bug */
+#define INT_MIN  X_INT_MIN
+#undef  LONG_MAX /* workaround cpp bug */
+#define LONG_MAX  X_INT_MAX
+#undef  LONG_MIN /* workaround cpp bug */
+#define LONG_MIN  X_INT_MIN
+#elif _LONG64
+#undef  LONG_MAX /* workaround cpp bug */
+#define LONG_MAX  4294967295L
+#undef  LONG_MIN /* workaround cpp bug */
+#define LONG_MIN -4294967295L
+#endif
+#endif /* _SX */
+
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif /* MAX */
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif /* MIN */
+
+#ifndef ABS
+#define ABS(x)  ((x) < 0 ? -(x) : (x))
+#endif /* ABS */
+
+    /* Parameters of test data */
+
+#define NTYPES      11   /* number of nc_types to test */
+#define NDIMS        5
+#define NRECS        2
+#define NGATTS       NTYPES
+#define RECDIM       0
+#define MAX_RANK     3
+#define MAX_NELS    64
+#define MAX_DIM_LEN  4
+#define MAX_NATTS    3
+/*
+ *  #define NVARS 136   when NTYPES==6
+ *  #define NVARS 142   when NTYPES==7
+ *  #define NVARS 148   when NTYPES==8
+ *  #define NVARS 154   when NTYPES==9
+ *  #define NVARS 160   when NTYPES==10
+ *  #define NVARS 166   when NTYPES==11
+ *  c:char, b:byte, s:short, i:int, f:float, d:double, y:ubyte, t:ushort,
+ *  u:uint, x:int64, z:uint64
+ */
+#define NVARS 166
+
+/*
+ *  * global variables (defined by command line processing in main())
+ *   * related use of CDF-1 vs CDF-2 file formats
+ *    */
+extern int cdf_format;  /* 1: CDF-1, 2: CDF-2 5: CDF-5 */
+extern int extra_flags; /* if using CDF-2 format, will be set to NC_64BIT_OFFSET
+                           if using CDF-5 format, will be set to NC_64BIT_DATA */
+extern int numGatts;  /* number of global attributes */
+extern int numVars;   /* number of variables */
+extern int numTypes;  /* number of netCDF data types to test */
+
+
+/* Here is how NVARS is acalculated in init_gvars().
+MAX_RANK=3
+MAX_DIM_LEN==4
+max_dim_len[MAX_RANK] = {MAX_DIM_LEN +1, MAX_DIM_LEN, MAX_DIM_LEN };
+rank==0, nvars=1      ntypes=NTYPES  (if rank < 2)
+rank==1, nvars=5      ntypes=NTYPES  (if rank < 2)
+rank==2, nvars=5*4    ntypes=1       (if rank >= 2)
+rank==3, nvars=5*4*4  ntypes=1       (if rank >= 2)
+nv=1* 6+5* 6+5*4+5*4*4= 6+30+20+80 = 136 (if NTYPES==6)
+nv=1* 7+5* 7+5*4+5*4*4= 7+35+20+80 = 142 (if NTYPES==7)
+nv=1* 8+5* 8+5*4+5*4*4= 8+40+20+80 = 148 (if NTYPES==8)
+nv=1* 9+5* 9+5*4+5*4*4= 9+45+20+80 = 154 (if NTYPES==9)
+nv=1*10+5*10+5*4+5*4*4=10+50+20+80 = 160 (if NTYPES==10)
+nv=1*11+5*11+5*4+5*4*4=11+55+20+80 = 166 (if NTYPES==11)
+*/
+
+/* Limits of internal types */
+
+/* Remove the use of text_min and text_max, becuase in NetCDF, there is no
+ * situation that would cause to check the range of a text or NC_CHAR value.
+ * In netCDF, a NC_CHAR variable must be read/written/created by netCDF text
+ * APIs. Otherwise, NC_ECHAR error will return. In the text APIs, the user
+ * buffers will be treated as a text array. For put APIs, a local signed char
+ * value (if the local char is signed) will be type-casted to an unsigned char
+ * value before writing to the file. For get APIs, an external unsigned char
+ * (NC_CHAR) value will be type-casted to a local signed char value. If the
+ * local char is unsigned, then no type casting will even happen. Also note
+ * that netCDF text APIs never returns NC_ERANGE error code.
+
+#define text_min CHAR_MIN
+#define text_max CHAR_MAX
+*/
+
+#define uchar_min     0
+#define schar_min     SCHAR_MIN
+#define short_min     SHRT_MIN
+#define int_min       INT_MIN
+#define long_min      LONG_MIN
+#define float_min     (-FLT_MAX)
+#define double_min    (-DBL_MAX)
+#define ushort_min    0
+#define uint_min      0
+#define ulong_min     0
+#define int64_min     LLONG_MIN
+#define longlong_min  int64_min
+#define uint64_min    0
+#define ulonglong_min uint64_min
+
+#define uchar_max     UCHAR_MAX
+#define schar_max     SCHAR_MAX
+#define short_max     SHRT_MAX
+#define int_max       INT_MAX
+#define long_max      LONG_MAX
+#define float_max     FLT_MAX
+#define double_max    DBL_MAX
+#define ushort_max    USHRT_MAX
+#define uint_max      UINT_MAX
+#define ulong_max     ULONG_MAX
+#define int64_max     LLONG_MAX
+#define longlong_max  int64_max
+#define uint64_max    ULLONG_MAX
+#define ulonglong_max uint64_max
+
+
+
+    /* Examples of invalid argument values */
+
+#define BAD_ID -1               /* invalid netCDF ID */
+#define BAD_DIMID -1            /* invalid dim ID */
+#define BAD_VARID -2            /* invalid var ID */
+#define BAD_ATTNUM -1           /* invalid att number */
+#define BAD_TYPE (nc_type) 0    /* invalid data type */
+#define BAD_FILLMODE -1         /* invalid fill mode */
+#define BAD_NAME "a/b"		/* invalid name */
+#define BAD_DEFAULT_FORMAT 12	/* invalid default format */
+
+#define LEN_OF(array) ((sizeof array) / (sizeof array[0]))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+    /* Non-standard internal types */
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+typedef char text;
+typedef signed char schar;
+#if !defined(HAVE_UCHAR) && !defined(__osf__) && !defined(_AIX)
+typedef unsigned char uchar;
+#endif
+
+#ifndef HAVE_USHORT
+typedef unsigned short int  ushort;
+#endif
+
+#ifndef HAVE_UINT
+typedef unsigned int  uint;
+#endif
+
+#ifndef HAVE_INT64
+typedef long long  int64;
+#endif
+
+#ifndef HAVE_UINT64
+typedef unsigned long long  uint64;
+#endif
+
+typedef long long longlong;
+typedef unsigned long long ulonglong;
+
+
+    /* Global variables - filenames */
+
+extern char testfile[128];		/* netCDF read-only test data */
+extern char scratch[128];		/* netCDF test file for writing */
+
+    /* Global variables - command-line arguments */
+
+extern int read_only;	/* if 1, don't try to change files */
+extern int verbose;	/* if 1, print details of tests */
+extern int nfails;	/* number of failures in specific test */
+extern int use_cdf2;	/* if 1, use CDF-2 format (offset >2GB ) */
+extern int extra_flags;	/* if using CDF-2, need extra flags for create*/
+extern int max_nmpt;	/* max number of messages per test */
+
+
+    /* Global variables - test data */
+
+extern char       dim_name[NDIMS][3];
+extern MPI_Offset dim_len[NDIMS];
+extern char       var_name[NVARS][2+MAX_RANK];
+extern nc_type    var_type[NVARS];
+extern size_t     var_rank[NVARS];
+extern int        var_dimid[NVARS][MAX_RANK];
+extern MPI_Offset var_shape[NVARS][MAX_RANK];
+extern size_t     var_nels[NVARS];
+extern size_t     var_natts[NVARS];
+extern char       att_name[NVARS][MAX_NATTS][2];
+extern char       gatt_name[NGATTS][3];
+extern nc_type    att_type[NVARS][NGATTS];
+extern nc_type    gatt_type[NGATTS];
+extern size_t     att_len[NVARS][MAX_NATTS];
+extern size_t     gatt_len[NGATTS];
+
+/* Global variables: MPI data */
+extern MPI_Comm comm;
+extern MPI_Info info;
+
+    /* Macros for accessing attribute test data */
+    /* varid is -1 for NC_GLOBAL so can do global atts in same loop */
+
+#define VARID(varid)      (varid < 0 ? NC_GLOBAL : varid)
+#define NATTS(varid)      (varid < 0 ? numGatts : var_natts[varid])
+#define ATT_NAME(varid,j) (varid < 0 ? gatt_name[j] : att_name[varid][j])
+#define ATT_TYPE(varid,j) (varid < 0 ? gatt_type[j] : att_type[varid][j])
+#define ATT_LEN(varid,j)  (varid < 0 ? gatt_len[j] : att_len[varid][j])
+
+extern const char *s_nc_type(nc_type);
+
+extern int test_ncmpi_strerror(void);
+extern int test_ncmpi_open(void);
+extern int test_ncmpi_close(void);
+extern int test_ncmpi_delete(void);
+
+extern int test_ncmpi_inq(void);
+extern int test_ncmpi_inq_natts(void);
+extern int test_ncmpi_inq_ndims(void);
+extern int test_ncmpi_inq_nvars(void);
+extern int test_ncmpi_inq_unlimdim(void);
+
+extern int test_ncmpi_inq_dimid(void);
+extern int test_ncmpi_inq_dim(void);
+extern int test_ncmpi_inq_dimlen(void);
+extern int test_ncmpi_inq_dimname(void);
+
+extern int test_ncmpi_inq_varid(void);
+extern int test_ncmpi_inq_vardimid(void);
+extern int test_ncmpi_inq_varname(void);
+extern int test_ncmpi_inq_varnatts(void);
+extern int test_ncmpi_inq_varndims(void);
+extern int test_ncmpi_inq_vartype(void);
+extern int test_ncmpi_inq_var(void);
+
+extern int test_ncmpi_get_var(void);
+extern int test_ncmpi_get_var_text(void);
+extern int test_ncmpi_get_var_schar(void);
+extern int test_ncmpi_get_var_uchar(void);
+extern int test_ncmpi_get_var_short(void);
+extern int test_ncmpi_get_var_int(void);
+extern int test_ncmpi_get_var_long(void);
+extern int test_ncmpi_get_var_float(void);
+extern int test_ncmpi_get_var_double(void);
+extern int test_ncmpi_get_var_ushort(void);
+extern int test_ncmpi_get_var_uint(void);
+extern int test_ncmpi_get_var_longlong(void);
+extern int test_ncmpi_get_var_ulonglong(void);
+
+extern int test_ncmpi_get_var1(void);
+extern int test_ncmpi_get_var1_text(void);
+extern int test_ncmpi_get_var1_schar(void);
+extern int test_ncmpi_get_var1_uchar(void);
+extern int test_ncmpi_get_var1_short(void);
+extern int test_ncmpi_get_var1_int(void);
+extern int test_ncmpi_get_var1_long(void);
+extern int test_ncmpi_get_var1_float(void);
+extern int test_ncmpi_get_var1_double(void);
+extern int test_ncmpi_get_var1_ushort(void);
+extern int test_ncmpi_get_var1_uint(void);
+extern int test_ncmpi_get_var1_longlong(void);
+extern int test_ncmpi_get_var1_ulonglong(void);
+
+extern int test_ncmpi_get_vara(void);
+extern int test_ncmpi_get_vara_text(void);
+extern int test_ncmpi_get_vara_schar(void);
+extern int test_ncmpi_get_vara_uchar(void);
+extern int test_ncmpi_get_vara_short(void);
+extern int test_ncmpi_get_vara_int(void);
+extern int test_ncmpi_get_vara_long(void);
+extern int test_ncmpi_get_vara_float(void);
+extern int test_ncmpi_get_vara_double(void);
+extern int test_ncmpi_get_vara_ushort(void);
+extern int test_ncmpi_get_vara_uint(void);
+extern int test_ncmpi_get_vara_longlong(void);
+extern int test_ncmpi_get_vara_ulonglong(void);
+
+extern int test_ncmpi_get_vars(void);
+extern int test_ncmpi_get_vars_text(void);
+extern int test_ncmpi_get_vars_schar(void);
+extern int test_ncmpi_get_vars_uchar(void);
+extern int test_ncmpi_get_vars_short(void);
+extern int test_ncmpi_get_vars_int(void);
+extern int test_ncmpi_get_vars_long(void);
+extern int test_ncmpi_get_vars_float(void);
+extern int test_ncmpi_get_vars_double(void);
+extern int test_ncmpi_get_vars_ushort(void);
+extern int test_ncmpi_get_vars_uint(void);
+extern int test_ncmpi_get_vars_longlong(void);
+extern int test_ncmpi_get_vars_ulonglong(void);
+
+extern int test_ncmpi_get_varm(void);
+extern int test_ncmpi_get_varm_text(void);
+extern int test_ncmpi_get_varm_schar(void);
+extern int test_ncmpi_get_varm_uchar(void);
+extern int test_ncmpi_get_varm_short(void);
+extern int test_ncmpi_get_varm_int(void);
+extern int test_ncmpi_get_varm_long(void);
+extern int test_ncmpi_get_varm_float(void);
+extern int test_ncmpi_get_varm_double(void);
+extern int test_ncmpi_get_varm_ushort(void);
+extern int test_ncmpi_get_varm_uint(void);
+extern int test_ncmpi_get_varm_longlong(void);
+extern int test_ncmpi_get_varm_ulonglong(void);
+
+extern int test_ncmpi_iget_var(void);
+extern int test_ncmpi_iget_var_text(void);
+extern int test_ncmpi_iget_var_schar(void);
+extern int test_ncmpi_iget_var_uchar(void);
+extern int test_ncmpi_iget_var_short(void);
+extern int test_ncmpi_iget_var_int(void);
+extern int test_ncmpi_iget_var_long(void);
+extern int test_ncmpi_iget_var_float(void);
+extern int test_ncmpi_iget_var_double(void);
+extern int test_ncmpi_iget_var_ushort(void);
+extern int test_ncmpi_iget_var_uint(void);
+extern int test_ncmpi_iget_var_longlong(void);
+extern int test_ncmpi_iget_var_ulonglong(void);
+
+extern int test_ncmpi_iget_var1(void);
+extern int test_ncmpi_iget_var1_text(void);
+extern int test_ncmpi_iget_var1_schar(void);
+extern int test_ncmpi_iget_var1_uchar(void);
+extern int test_ncmpi_iget_var1_short(void);
+extern int test_ncmpi_iget_var1_int(void);
+extern int test_ncmpi_iget_var1_long(void);
+extern int test_ncmpi_iget_var1_float(void);
+extern int test_ncmpi_iget_var1_double(void);
+extern int test_ncmpi_iget_var1_ushort(void);
+extern int test_ncmpi_iget_var1_uint(void);
+extern int test_ncmpi_iget_var1_longlong(void);
+extern int test_ncmpi_iget_var1_ulonglong(void);
+
+extern int test_ncmpi_iget_vara(void);
+extern int test_ncmpi_iget_vara_text(void);
+extern int test_ncmpi_iget_vara_schar(void);
+extern int test_ncmpi_iget_vara_uchar(void);
+extern int test_ncmpi_iget_vara_short(void);
+extern int test_ncmpi_iget_vara_int(void);
+extern int test_ncmpi_iget_vara_long(void);
+extern int test_ncmpi_iget_vara_float(void);
+extern int test_ncmpi_iget_vara_double(void);
+extern int test_ncmpi_iget_vara_ushort(void);
+extern int test_ncmpi_iget_vara_uint(void);
+extern int test_ncmpi_iget_vara_longlong(void);
+extern int test_ncmpi_iget_vara_ulonglong(void);
+
+extern int test_ncmpi_iget_vars(void);
+extern int test_ncmpi_iget_vars_text(void);
+extern int test_ncmpi_iget_vars_schar(void);
+extern int test_ncmpi_iget_vars_uchar(void);
+extern int test_ncmpi_iget_vars_short(void);
+extern int test_ncmpi_iget_vars_int(void);
+extern int test_ncmpi_iget_vars_long(void);
+extern int test_ncmpi_iget_vars_float(void);
+extern int test_ncmpi_iget_vars_double(void);
+extern int test_ncmpi_iget_vars_ushort(void);
+extern int test_ncmpi_iget_vars_uint(void);
+extern int test_ncmpi_iget_vars_longlong(void);
+extern int test_ncmpi_iget_vars_ulonglong(void);
+
+extern int test_ncmpi_iget_varm(void);
+extern int test_ncmpi_iget_varm_text(void);
+extern int test_ncmpi_iget_varm_schar(void);
+extern int test_ncmpi_iget_varm_uchar(void);
+extern int test_ncmpi_iget_varm_short(void);
+extern int test_ncmpi_iget_varm_int(void);
+extern int test_ncmpi_iget_varm_long(void);
+extern int test_ncmpi_iget_varm_float(void);
+extern int test_ncmpi_iget_varm_double(void);
+extern int test_ncmpi_iget_varm_ushort(void);
+extern int test_ncmpi_iget_varm_uint(void);
+extern int test_ncmpi_iget_varm_longlong(void);
+extern int test_ncmpi_iget_varm_ulonglong(void);
+
+extern int test_ncmpi_get_att(void);
+extern int test_ncmpi_get_att_text(void);
+extern int test_ncmpi_get_att_schar(void);
+extern int test_ncmpi_get_att_uchar(void);
+extern int test_ncmpi_get_att_short(void);
+extern int test_ncmpi_get_att_int(void);
+extern int test_ncmpi_get_att_long(void);
+extern int test_ncmpi_get_att_float(void);
+extern int test_ncmpi_get_att_double(void);
+extern int test_ncmpi_get_att_ushort(void);
+extern int test_ncmpi_get_att_uint(void);
+extern int test_ncmpi_get_att_longlong(void);
+extern int test_ncmpi_get_att_ulonglong(void);
+
+extern int test_ncmpi_put_var(void);
+extern int test_ncmpi_put_var_text(void);
+extern int test_ncmpi_put_var_schar(void);
+extern int test_ncmpi_put_var_uchar(void);
+extern int test_ncmpi_put_var_short(void);
+extern int test_ncmpi_put_var_int(void);
+extern int test_ncmpi_put_var_long(void);
+extern int test_ncmpi_put_var_float(void);
+extern int test_ncmpi_put_var_double(void);
+extern int test_ncmpi_put_var_ushort(void);
+extern int test_ncmpi_put_var_uint(void);
+extern int test_ncmpi_put_var_longlong(void);
+extern int test_ncmpi_put_var_ulonglong(void);
+
+extern int test_ncmpi_put_var1(void);
+extern int test_ncmpi_put_var1_text(void);
+extern int test_ncmpi_put_var1_schar(void);
+extern int test_ncmpi_put_var1_uchar(void);
+extern int test_ncmpi_put_var1_short(void);
+extern int test_ncmpi_put_var1_int(void);
+extern int test_ncmpi_put_var1_long(void);
+extern int test_ncmpi_put_var1_float(void);
+extern int test_ncmpi_put_var1_double(void);
+extern int test_ncmpi_put_var1_ushort(void);
+extern int test_ncmpi_put_var1_uint(void);
+extern int test_ncmpi_put_var1_longlong(void);
+extern int test_ncmpi_put_var1_ulonglong(void);
+
+extern int test_ncmpi_put_vara(void);
+extern int test_ncmpi_put_vara_text(void);
+extern int test_ncmpi_put_vara_schar(void);
+extern int test_ncmpi_put_vara_uchar(void);
+extern int test_ncmpi_put_vara_short(void);
+extern int test_ncmpi_put_vara_int(void);
+extern int test_ncmpi_put_vara_long(void);
+extern int test_ncmpi_put_vara_float(void);
+extern int test_ncmpi_put_vara_double(void);
+extern int test_ncmpi_put_vara_ushort(void);
+extern int test_ncmpi_put_vara_uint(void);
+extern int test_ncmpi_put_vara_longlong(void);
+extern int test_ncmpi_put_vara_ulonglong(void);
+
+extern int test_ncmpi_put_vars(void);
+extern int test_ncmpi_put_vars_text(void);
+extern int test_ncmpi_put_vars_schar(void);
+extern int test_ncmpi_put_vars_uchar(void);
+extern int test_ncmpi_put_vars_short(void);
+extern int test_ncmpi_put_vars_int(void);
+extern int test_ncmpi_put_vars_long(void);
+extern int test_ncmpi_put_vars_float(void);
+extern int test_ncmpi_put_vars_double(void);
+extern int test_ncmpi_put_vars_ushort(void);
+extern int test_ncmpi_put_vars_uint(void);
+extern int test_ncmpi_put_vars_longlong(void);
+extern int test_ncmpi_put_vars_ulonglong(void);
+
+extern int test_ncmpi_put_varm(void);
+extern int test_ncmpi_put_varm_text(void);
+extern int test_ncmpi_put_varm_schar(void);
+extern int test_ncmpi_put_varm_uchar(void);
+extern int test_ncmpi_put_varm_short(void);
+extern int test_ncmpi_put_varm_int(void);
+extern int test_ncmpi_put_varm_long(void);
+extern int test_ncmpi_put_varm_float(void);
+extern int test_ncmpi_put_varm_double(void);
+extern int test_ncmpi_put_varm_ushort(void);
+extern int test_ncmpi_put_varm_uint(void);
+extern int test_ncmpi_put_varm_longlong(void);
+extern int test_ncmpi_put_varm_ulonglong(void);
+
+extern int test_ncmpi_iput_var(void);
+extern int test_ncmpi_iput_var_text(void);
+extern int test_ncmpi_iput_var_schar(void);
+extern int test_ncmpi_iput_var_uchar(void);
+extern int test_ncmpi_iput_var_short(void);
+extern int test_ncmpi_iput_var_int(void);
+extern int test_ncmpi_iput_var_long(void);
+extern int test_ncmpi_iput_var_float(void);
+extern int test_ncmpi_iput_var_double(void);
+extern int test_ncmpi_iput_var_ushort(void);
+extern int test_ncmpi_iput_var_uint(void);
+extern int test_ncmpi_iput_var_longlong(void);
+extern int test_ncmpi_iput_var_ulonglong(void);
+
+extern int test_ncmpi_iput_var1(void);
+extern int test_ncmpi_iput_var1_text(void);
+extern int test_ncmpi_iput_var1_schar(void);
+extern int test_ncmpi_iput_var1_uchar(void);
+extern int test_ncmpi_iput_var1_short(void);
+extern int test_ncmpi_iput_var1_int(void);
+extern int test_ncmpi_iput_var1_long(void);
+extern int test_ncmpi_iput_var1_float(void);
+extern int test_ncmpi_iput_var1_double(void);
+extern int test_ncmpi_iput_var1_ushort(void);
+extern int test_ncmpi_iput_var1_uint(void);
+extern int test_ncmpi_iput_var1_longlong(void);
+extern int test_ncmpi_iput_var1_ulonglong(void);
+
+extern int test_ncmpi_iput_vara(void);
+extern int test_ncmpi_iput_vara_text(void);
+extern int test_ncmpi_iput_vara_schar(void);
+extern int test_ncmpi_iput_vara_uchar(void);
+extern int test_ncmpi_iput_vara_short(void);
+extern int test_ncmpi_iput_vara_int(void);
+extern int test_ncmpi_iput_vara_long(void);
+extern int test_ncmpi_iput_vara_float(void);
+extern int test_ncmpi_iput_vara_double(void);
+extern int test_ncmpi_iput_vara_ushort(void);
+extern int test_ncmpi_iput_vara_uint(void);
+extern int test_ncmpi_iput_vara_longlong(void);
+extern int test_ncmpi_iput_vara_ulonglong(void);
+
+extern int test_ncmpi_iput_vars(void);
+extern int test_ncmpi_iput_vars_text(void);
+extern int test_ncmpi_iput_vars_schar(void);
+extern int test_ncmpi_iput_vars_uchar(void);
+extern int test_ncmpi_iput_vars_short(void);
+extern int test_ncmpi_iput_vars_int(void);
+extern int test_ncmpi_iput_vars_long(void);
+extern int test_ncmpi_iput_vars_float(void);
+extern int test_ncmpi_iput_vars_double(void);
+extern int test_ncmpi_iput_vars_ushort(void);
+extern int test_ncmpi_iput_vars_uint(void);
+extern int test_ncmpi_iput_vars_longlong(void);
+extern int test_ncmpi_iput_vars_ulonglong(void);
+
+extern int test_ncmpi_iput_varm(void);
+extern int test_ncmpi_iput_varm_text(void);
+extern int test_ncmpi_iput_varm_schar(void);
+extern int test_ncmpi_iput_varm_uchar(void);
+extern int test_ncmpi_iput_varm_short(void);
+extern int test_ncmpi_iput_varm_int(void);
+extern int test_ncmpi_iput_varm_long(void);
+extern int test_ncmpi_iput_varm_float(void);
+extern int test_ncmpi_iput_varm_double(void);
+extern int test_ncmpi_iput_varm_ushort(void);
+extern int test_ncmpi_iput_varm_uint(void);
+extern int test_ncmpi_iput_varm_longlong(void);
+extern int test_ncmpi_iput_varm_ulonglong(void);
+
+extern int test_ncmpi_put_att(void);
+extern int test_ncmpi_put_att_text(void);
+extern int test_ncmpi_put_att_schar(void);
+extern int test_ncmpi_put_att_uchar(void);
+extern int test_ncmpi_put_att_short(void);
+extern int test_ncmpi_put_att_int(void);
+extern int test_ncmpi_put_att_long(void);
+extern int test_ncmpi_put_att_float(void);
+extern int test_ncmpi_put_att_double(void);
+extern int test_ncmpi_put_att_ushort(void);
+extern int test_ncmpi_put_att_uint(void);
+extern int test_ncmpi_put_att_longlong(void);
+extern int test_ncmpi_put_att_ulonglong(void);
+
+extern int test_ncmpi_create(void);
+extern int test_ncmpi_redef(void);
+extern int test_ncmpi_enddef(void);
+extern int test_ncmpi_sync(void);
+extern int test_ncmpi_abort(void);
+extern int test_ncmpi_def_dim(void);
+extern int test_ncmpi_rename_dim(void);
+extern int test_ncmpi_def_var(void);
+extern int test_ncmpi_rename_var(void);
+extern int test_ncmpi_copy_att(void);
+
+extern int test_ncmpi_inq_att(void);
+extern int test_ncmpi_inq_attname(void);
+extern int test_ncmpi_inq_attid(void);
+extern int test_ncmpi_inq_attlen(void);
+extern int test_ncmpi_inq_atttype(void);
+
+extern int test_ncmpi_rename_att(void);
+extern int test_ncmpi_del_att(void);
+extern int test_ncmpi_set_fill(void);
+extern int test_ncmpi_set_default_format(void);
+
+extern void print_nok(int nok);
+
+#define PRINT_NOK(nok) if (verbose) print("%4d good comparisons.\n",nok);
+
+
+/*
+ * internal types
+ */
+typedef enum {
+	NCT_UNSPECIFIED = 0,
+	NCT_UCHAR =	1,	/* unsigned char */
+	NCT_TEXT =	16,	/* char */
+#define NCT_CHAR NCT_TEXT
+	NCT_SCHAR =	17,	/* signed char */
+	NCT_SHORT =	18,	/* short */
+	NCT_INT =	20,	/* int */
+	NCT_LONG =	22,	/* long */
+	NCT_FLOAT =	36,	/* float */
+	NCT_DOUBLE =	40,	/* double */
+	NCT_USHORT =	41,
+	NCT_UINT =	42,
+	NCT_INT64 =	43,
+#define NCT_LONGLONG NCT_INT64
+	NCT_UINT64 =	44
+#define NCT_ULONGLONG NCT_UINT64
+} nct_itype;
+
+extern int
+inRange(const double value, const nc_type datatype);
+
+extern int
+inRange3(const double value, const nc_type datatype, const nct_itype itype);
+
+extern int
+equal(double x, double y, nc_type extType, nct_itype itype);
+
+extern int
+equal2(double x, double y, nc_type extType);
+
+extern int
+int_vec_eq(const int *v1, const int *v2, const int n);
+
+extern int
+roll(int n);
+
+extern int
+toMixedBase(
+    size_t number,           /* number to be converted to mixed base */
+    size_t length,
+    const MPI_Offset base[], /* dimensioned [length], base[0] ignored */
+    MPI_Offset result[]);    /* dimensioned [length] */
+
+extern size_t
+fromMixedBase(
+    size_t length,
+    MPI_Offset number[],     /* dimensioned [length] */
+    MPI_Offset base[]);      /* dimensioned [length], base[0] ignored */
+
+extern int
+nc2dbl ( const nc_type datatype, const void *p, double *result);
+
+extern int
+dbl2nc ( const double d, const nc_type datatype, void *p);
+
+extern double
+hash( const nc_type type, const int rank, const MPI_Offset *index );
+
+extern long long
+hashx_llong(const int rank, const MPI_Offset *index);
+
+extern double
+hash4(const nc_type type, const int rank, const MPI_Offset *index, const nct_itype itype);
+
+extern void
+init_gvars(void);
+
+extern void
+def_dims(int ncid);
+
+extern void
+def_vars(int ncid);
+
+extern void
+put_atts(int ncid);
+
+extern void
+put_vars(int ncid);
+
+extern void
+write_file(char *filename);
+
+extern void
+check_dims(int ncid);
+
+extern void
+check_vars(int ncid);
+
+extern void
+check_atts(int ncid);
+
+extern void
+check_file(char *filename);
+
+extern int
+nctypelen(nc_type type);
+
+extern MPI_Datatype
+nc_mpi_type(nc_type type);
+
+extern char*
+ncmpii_err_code_name(int err);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/test/nc_test/tst_atts.c b/test/nc_test/tst_atts.c
new file mode 100644
index 0000000..25ae1fd
--- /dev/null
+++ b/test/nc_test/tst_atts.c
@@ -0,0 +1,2246 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: tst_atts.c 2270 2015-12-23 19:14:45Z wkliao $ */
+
+/* This program is based on the test program tst_atts.c of the netCDF package */
+
+/* This is part of the netCDF package.
+   Copyright 2006 University Corporation for Atmospheric Research/Unidata.
+   See COPYRIGHT file for conditions of use.
+
+   This is a very simple example which writes a netCDF file with
+   Unicode names encoded with UTF-8. It is the NETCDF3 equivalent
+   of tst_unicode.c
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h> /* INT_MIN */
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+static int verbose;
+
+#define ERR {if (err != NC_NOERR) {printf("Error at %s line %d: %s\n",__func__,__LINE__,ncmpi_strerror(err)); return 1;}}
+#define ERRV {printf("Unexpected result at %s line %d\n",__func__,__LINE__); return 1;}
+
+
+#if 0
+static void
+check_err(const int stat, const int line, const char *file) {
+   if (stat != NC_NOERR) {
+      (void)fprintf(stderr,"line %d of %s: %s\n", line, file, ncmpi_strerror(stat));
+      fflush(stderr);
+      exit(1);
+   }
+}
+#endif
+
+static int
+create_file(char *filename, int cmode)
+{
+    int  err;  /* return status */
+    int  ncid;  /* netCDF id */
+
+    /* dimension ids */
+    int Dr_dim;
+    int D1_dim;
+    int D2_dim;
+    int D3_dim;
+    int D4_dim;
+
+    /* dimension lengths */
+    MPI_Offset Dr_len = NC_UNLIMITED;
+    MPI_Offset D1_len = 1;
+    MPI_Offset D2_len = 2;
+    MPI_Offset D3_len = 3;
+    MPI_Offset D4_len = 4;
+
+    /* variable ids */
+    int c_id;
+    int b_id;
+    int s_id;
+    int i_id;
+    int f_id;
+    int d_id;
+    int cr_id;
+    int br_id;
+    int sr_id;
+    int ir_id;
+    int fr_id;
+    int dr_id;
+    int c1_id;
+    int b1_id;
+    int s1_id;
+    int i1_id;
+    int f1_id;
+    int d1_id;
+    int c2_id;
+    int b2_id;
+    int s2_id;
+    int i2_id;
+    int f2_id;
+    int d2_id;
+    int c3_id;
+    int b3_id;
+    int s3_id;
+    int i3_id;
+    int f3_id;
+    int d3_id;
+    int c4_id;
+    int b4_id;
+    int s4_id;
+    int i4_id;
+    int f4_id;
+    int d4_id;
+    int cr1_id;
+    int br2_id;
+    int sr3_id;
+    int ir4_id;
+    int f11_id;
+    int d12_id;
+    int c13_id;
+    int b14_id;
+    int s21_id;
+    int i22_id;
+    int f23_id;
+    int d24_id;
+    int c31_id;
+    int b32_id;
+    int s33_id;
+    int i34_id;
+    int f41_id;
+    int d42_id;
+    int c43_id;
+    int b44_id;
+    int sr11_id;
+    int ir12_id;
+    int fr13_id;
+    int dr14_id;
+    int cr21_id;
+    int br22_id;
+    int sr23_id;
+    int ir24_id;
+    int fr31_id;
+    int dr32_id;
+    int cr33_id;
+    int br34_id;
+    int sr41_id;
+    int ir42_id;
+    int fr43_id;
+    int dr44_id;
+    int c111_id;
+    int b112_id;
+    int s113_id;
+    int i114_id;
+    int f121_id;
+    int d122_id;
+    int c123_id;
+    int b124_id;
+    int s131_id;
+    int i132_id;
+    int f133_id;
+    int d134_id;
+    int c141_id;
+    int b142_id;
+    int s143_id;
+    int i144_id;
+    int f211_id;
+    int d212_id;
+    int c213_id;
+    int b214_id;
+    int s221_id;
+    int i222_id;
+    int f223_id;
+    int d224_id;
+    int c231_id;
+    int b232_id;
+    int s233_id;
+    int i234_id;
+    int f241_id;
+    int d242_id;
+    int c243_id;
+    int b244_id;
+    int s311_id;
+    int i312_id;
+    int f313_id;
+    int d314_id;
+    int c321_id;
+    int b322_id;
+    int s323_id;
+    int i324_id;
+    int f331_id;
+    int d332_id;
+    int c333_id;
+    int b334_id;
+    int s341_id;
+    int i342_id;
+    int f343_id;
+    int d344_id;
+    int c411_id;
+    int b412_id;
+    int s413_id;
+    int i414_id;
+    int f421_id;
+    int d422_id;
+    int c423_id;
+    int b424_id;
+    int s431_id;
+    int i432_id;
+    int f433_id;
+    int d434_id;
+    int c441_id;
+    int b442_id;
+    int s443_id;
+    int i444_id;
+
+    /* rank (number of dimensions) for each variable */
+#   define RANK_c 0
+#   define RANK_b 0
+#   define RANK_s 0
+#   define RANK_i 0
+#   define RANK_f 0
+#   define RANK_d 0
+#   define RANK_cr 1
+#   define RANK_br 1
+#   define RANK_sr 1
+#   define RANK_ir 1
+#   define RANK_fr 1
+#   define RANK_dr 1
+#   define RANK_c1 1
+#   define RANK_b1 1
+#   define RANK_s1 1
+#   define RANK_i1 1
+#   define RANK_f1 1
+#   define RANK_d1 1
+#   define RANK_c2 1
+#   define RANK_b2 1
+#   define RANK_s2 1
+#   define RANK_i2 1
+#   define RANK_f2 1
+#   define RANK_d2 1
+#   define RANK_c3 1
+#   define RANK_b3 1
+#   define RANK_s3 1
+#   define RANK_i3 1
+#   define RANK_f3 1
+#   define RANK_d3 1
+#   define RANK_c4 1
+#   define RANK_b4 1
+#   define RANK_s4 1
+#   define RANK_i4 1
+#   define RANK_f4 1
+#   define RANK_d4 1
+#   define RANK_cr1 2
+#   define RANK_br2 2
+#   define RANK_sr3 2
+#   define RANK_ir4 2
+#   define RANK_f11 2
+#   define RANK_d12 2
+#   define RANK_c13 2
+#   define RANK_b14 2
+#   define RANK_s21 2
+#   define RANK_i22 2
+#   define RANK_f23 2
+#   define RANK_d24 2
+#   define RANK_c31 2
+#   define RANK_b32 2
+#   define RANK_s33 2
+#   define RANK_i34 2
+#   define RANK_f41 2
+#   define RANK_d42 2
+#   define RANK_c43 2
+#   define RANK_b44 2
+#   define RANK_sr11 3
+#   define RANK_ir12 3
+#   define RANK_fr13 3
+#   define RANK_dr14 3
+#   define RANK_cr21 3
+#   define RANK_br22 3
+#   define RANK_sr23 3
+#   define RANK_ir24 3
+#   define RANK_fr31 3
+#   define RANK_dr32 3
+#   define RANK_cr33 3
+#   define RANK_br34 3
+#   define RANK_sr41 3
+#   define RANK_ir42 3
+#   define RANK_fr43 3
+#   define RANK_dr44 3
+#   define RANK_c111 3
+#   define RANK_b112 3
+#   define RANK_s113 3
+#   define RANK_i114 3
+#   define RANK_f121 3
+#   define RANK_d122 3
+#   define RANK_c123 3
+#   define RANK_b124 3
+#   define RANK_s131 3
+#   define RANK_i132 3
+#   define RANK_f133 3
+#   define RANK_d134 3
+#   define RANK_c141 3
+#   define RANK_b142 3
+#   define RANK_s143 3
+#   define RANK_i144 3
+#   define RANK_f211 3
+#   define RANK_d212 3
+#   define RANK_c213 3
+#   define RANK_b214 3
+#   define RANK_s221 3
+#   define RANK_i222 3
+#   define RANK_f223 3
+#   define RANK_d224 3
+#   define RANK_c231 3
+#   define RANK_b232 3
+#   define RANK_s233 3
+#   define RANK_i234 3
+#   define RANK_f241 3
+#   define RANK_d242 3
+#   define RANK_c243 3
+#   define RANK_b244 3
+#   define RANK_s311 3
+#   define RANK_i312 3
+#   define RANK_f313 3
+#   define RANK_d314 3
+#   define RANK_c321 3
+#   define RANK_b322 3
+#   define RANK_s323 3
+#   define RANK_i324 3
+#   define RANK_f331 3
+#   define RANK_d332 3
+#   define RANK_c333 3
+#   define RANK_b334 3
+#   define RANK_s341 3
+#   define RANK_i342 3
+#   define RANK_f343 3
+#   define RANK_d344 3
+#   define RANK_c411 3
+#   define RANK_b412 3
+#   define RANK_s413 3
+#   define RANK_i414 3
+#   define RANK_f421 3
+#   define RANK_d422 3
+#   define RANK_c423 3
+#   define RANK_b424 3
+#   define RANK_s431 3
+#   define RANK_i432 3
+#   define RANK_f433 3
+#   define RANK_d434 3
+#   define RANK_c441 3
+#   define RANK_b442 3
+#   define RANK_s443 3
+#   define RANK_i444 3
+
+    /* variable shapes */
+    int cr_dims[RANK_cr];
+    int br_dims[RANK_br];
+    int sr_dims[RANK_sr];
+    int ir_dims[RANK_ir];
+    int fr_dims[RANK_fr];
+    int dr_dims[RANK_dr];
+    int c1_dims[RANK_c1];
+    int b1_dims[RANK_b1];
+    int s1_dims[RANK_s1];
+    int i1_dims[RANK_i1];
+    int f1_dims[RANK_f1];
+    int d1_dims[RANK_d1];
+    int c2_dims[RANK_c2];
+    int b2_dims[RANK_b2];
+    int s2_dims[RANK_s2];
+    int i2_dims[RANK_i2];
+    int f2_dims[RANK_f2];
+    int d2_dims[RANK_d2];
+    int c3_dims[RANK_c3];
+    int b3_dims[RANK_b3];
+    int s3_dims[RANK_s3];
+    int i3_dims[RANK_i3];
+    int f3_dims[RANK_f3];
+    int d3_dims[RANK_d3];
+    int c4_dims[RANK_c4];
+    int b4_dims[RANK_b4];
+    int s4_dims[RANK_s4];
+    int i4_dims[RANK_i4];
+    int f4_dims[RANK_f4];
+    int d4_dims[RANK_d4];
+    int cr1_dims[RANK_cr1];
+    int br2_dims[RANK_br2];
+    int sr3_dims[RANK_sr3];
+    int ir4_dims[RANK_ir4];
+    int f11_dims[RANK_f11];
+    int d12_dims[RANK_d12];
+    int c13_dims[RANK_c13];
+    int b14_dims[RANK_b14];
+    int s21_dims[RANK_s21];
+    int i22_dims[RANK_i22];
+    int f23_dims[RANK_f23];
+    int d24_dims[RANK_d24];
+    int c31_dims[RANK_c31];
+    int b32_dims[RANK_b32];
+    int s33_dims[RANK_s33];
+    int i34_dims[RANK_i34];
+    int f41_dims[RANK_f41];
+    int d42_dims[RANK_d42];
+    int c43_dims[RANK_c43];
+    int b44_dims[RANK_b44];
+    int sr11_dims[RANK_sr11];
+    int ir12_dims[RANK_ir12];
+    int fr13_dims[RANK_fr13];
+    int dr14_dims[RANK_dr14];
+    int cr21_dims[RANK_cr21];
+    int br22_dims[RANK_br22];
+    int sr23_dims[RANK_sr23];
+    int ir24_dims[RANK_ir24];
+    int fr31_dims[RANK_fr31];
+    int dr32_dims[RANK_dr32];
+    int cr33_dims[RANK_cr33];
+    int br34_dims[RANK_br34];
+    int sr41_dims[RANK_sr41];
+    int ir42_dims[RANK_ir42];
+    int fr43_dims[RANK_fr43];
+    int dr44_dims[RANK_dr44];
+    int c111_dims[RANK_c111];
+    int b112_dims[RANK_b112];
+    int s113_dims[RANK_s113];
+    int i114_dims[RANK_i114];
+    int f121_dims[RANK_f121];
+    int d122_dims[RANK_d122];
+    int c123_dims[RANK_c123];
+    int b124_dims[RANK_b124];
+    int s131_dims[RANK_s131];
+    int i132_dims[RANK_i132];
+    int f133_dims[RANK_f133];
+    int d134_dims[RANK_d134];
+    int c141_dims[RANK_c141];
+    int b142_dims[RANK_b142];
+    int s143_dims[RANK_s143];
+    int i144_dims[RANK_i144];
+    int f211_dims[RANK_f211];
+    int d212_dims[RANK_d212];
+    int c213_dims[RANK_c213];
+    int b214_dims[RANK_b214];
+    int s221_dims[RANK_s221];
+    int i222_dims[RANK_i222];
+    int f223_dims[RANK_f223];
+    int d224_dims[RANK_d224];
+    int c231_dims[RANK_c231];
+    int b232_dims[RANK_b232];
+    int s233_dims[RANK_s233];
+    int i234_dims[RANK_i234];
+    int f241_dims[RANK_f241];
+    int d242_dims[RANK_d242];
+    int c243_dims[RANK_c243];
+    int b244_dims[RANK_b244];
+    int s311_dims[RANK_s311];
+    int i312_dims[RANK_i312];
+    int f313_dims[RANK_f313];
+    int d314_dims[RANK_d314];
+    int c321_dims[RANK_c321];
+    int b322_dims[RANK_b322];
+    int s323_dims[RANK_s323];
+    int i324_dims[RANK_i324];
+    int f331_dims[RANK_f331];
+    int d332_dims[RANK_d332];
+    int c333_dims[RANK_c333];
+    int b334_dims[RANK_b334];
+    int s341_dims[RANK_s341];
+    int i342_dims[RANK_i342];
+    int f343_dims[RANK_f343];
+    int d344_dims[RANK_d344];
+    int c411_dims[RANK_c411];
+    int b412_dims[RANK_b412];
+    int s413_dims[RANK_s413];
+    int i414_dims[RANK_i414];
+    int f421_dims[RANK_f421];
+    int d422_dims[RANK_d422];
+    int c423_dims[RANK_c423];
+    int b424_dims[RANK_b424];
+    int s431_dims[RANK_s431];
+    int i432_dims[RANK_i432];
+    int f433_dims[RANK_f433];
+    int d434_dims[RANK_d434];
+    int c441_dims[RANK_c441];
+    int b442_dims[RANK_b442];
+    int s443_dims[RANK_s443];
+    int i444_dims[RANK_i444];
+
+    /* enter define mode */
+    err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+
+    /* define dimensions */
+    err=ncmpi_def_dim(ncid, "Dr", Dr_len, &Dr_dim); ERR
+    err=ncmpi_def_dim(ncid, "D1", D1_len, &D1_dim); ERR
+    err=ncmpi_def_dim(ncid, "D2", D2_len, &D2_dim); ERR
+    err=ncmpi_def_dim(ncid, "D3", D3_len, &D3_dim); ERR
+    err=ncmpi_def_dim(ncid, "D4", D4_len, &D4_dim); ERR
+
+    /* define variables */
+
+    err=ncmpi_def_var(ncid, "c", NC_CHAR, RANK_c, 0, &c_id); ERR
+
+    err=ncmpi_def_var(ncid, "b", NC_BYTE, RANK_b, 0, &b_id); ERR
+
+    err=ncmpi_def_var(ncid, "s", NC_SHORT, RANK_s, 0, &s_id); ERR
+
+    err=ncmpi_def_var(ncid, "i", NC_INT, RANK_i, 0, &i_id); ERR
+
+    err=ncmpi_def_var(ncid, "f", NC_FLOAT, RANK_f, 0, &f_id); ERR
+
+    err=ncmpi_def_var(ncid, "d", NC_DOUBLE, RANK_d, 0, &d_id); ERR
+
+    cr_dims[0] = Dr_dim;
+    err=ncmpi_def_var(ncid, "cr", NC_CHAR, RANK_cr, cr_dims, &cr_id); ERR
+
+    br_dims[0] = Dr_dim;
+    err=ncmpi_def_var(ncid, "br", NC_BYTE, RANK_br, br_dims, &br_id); ERR
+
+    sr_dims[0] = Dr_dim;
+    err=ncmpi_def_var(ncid, "sr", NC_SHORT, RANK_sr, sr_dims, &sr_id); ERR
+
+    ir_dims[0] = Dr_dim;
+    err=ncmpi_def_var(ncid, "ir", NC_INT, RANK_ir, ir_dims, &ir_id); ERR
+
+    fr_dims[0] = Dr_dim;
+    err=ncmpi_def_var(ncid, "fr", NC_FLOAT, RANK_fr, fr_dims, &fr_id); ERR
+
+    dr_dims[0] = Dr_dim;
+    err=ncmpi_def_var(ncid, "dr", NC_DOUBLE, RANK_dr, dr_dims, &dr_id); ERR
+
+    c1_dims[0] = D1_dim;
+    err=ncmpi_def_var(ncid, "c1", NC_CHAR, RANK_c1, c1_dims, &c1_id); ERR
+
+    b1_dims[0] = D1_dim;
+    err=ncmpi_def_var(ncid, "b1", NC_BYTE, RANK_b1, b1_dims, &b1_id); ERR
+
+    s1_dims[0] = D1_dim;
+    err=ncmpi_def_var(ncid, "s1", NC_SHORT, RANK_s1, s1_dims, &s1_id); ERR
+
+    i1_dims[0] = D1_dim;
+    err=ncmpi_def_var(ncid, "i1", NC_INT, RANK_i1, i1_dims, &i1_id); ERR
+
+    f1_dims[0] = D1_dim;
+    err=ncmpi_def_var(ncid, "f1", NC_FLOAT, RANK_f1, f1_dims, &f1_id); ERR
+
+    d1_dims[0] = D1_dim;
+    err=ncmpi_def_var(ncid, "d1", NC_DOUBLE, RANK_d1, d1_dims, &d1_id); ERR
+
+    c2_dims[0] = D2_dim;
+    err=ncmpi_def_var(ncid, "c2", NC_CHAR, RANK_c2, c2_dims, &c2_id); ERR
+
+    b2_dims[0] = D2_dim;
+    err=ncmpi_def_var(ncid, "b2", NC_BYTE, RANK_b2, b2_dims, &b2_id); ERR
+
+    s2_dims[0] = D2_dim;
+    err=ncmpi_def_var(ncid, "s2", NC_SHORT, RANK_s2, s2_dims, &s2_id); ERR
+
+    i2_dims[0] = D2_dim;
+    err=ncmpi_def_var(ncid, "i2", NC_INT, RANK_i2, i2_dims, &i2_id); ERR
+
+    f2_dims[0] = D2_dim;
+    err=ncmpi_def_var(ncid, "f2", NC_FLOAT, RANK_f2, f2_dims, &f2_id); ERR
+
+    d2_dims[0] = D2_dim;
+    err=ncmpi_def_var(ncid, "d2", NC_DOUBLE, RANK_d2, d2_dims, &d2_id); ERR
+
+    c3_dims[0] = D3_dim;
+    err=ncmpi_def_var(ncid, "c3", NC_CHAR, RANK_c3, c3_dims, &c3_id); ERR
+
+    b3_dims[0] = D3_dim;
+    err=ncmpi_def_var(ncid, "b3", NC_BYTE, RANK_b3, b3_dims, &b3_id); ERR
+
+    s3_dims[0] = D3_dim;
+    err=ncmpi_def_var(ncid, "s3", NC_SHORT, RANK_s3, s3_dims, &s3_id); ERR
+
+    i3_dims[0] = D3_dim;
+    err=ncmpi_def_var(ncid, "i3", NC_INT, RANK_i3, i3_dims, &i3_id); ERR
+
+    f3_dims[0] = D3_dim;
+    err=ncmpi_def_var(ncid, "f3", NC_FLOAT, RANK_f3, f3_dims, &f3_id); ERR
+
+    d3_dims[0] = D3_dim;
+    err=ncmpi_def_var(ncid, "d3", NC_DOUBLE, RANK_d3, d3_dims, &d3_id); ERR
+
+    c4_dims[0] = D4_dim;
+    err=ncmpi_def_var(ncid, "c4", NC_CHAR, RANK_c4, c4_dims, &c4_id); ERR
+
+    b4_dims[0] = D4_dim;
+    err=ncmpi_def_var(ncid, "b4", NC_BYTE, RANK_b4, b4_dims, &b4_id); ERR
+
+    s4_dims[0] = D4_dim;
+    err=ncmpi_def_var(ncid, "s4", NC_SHORT, RANK_s4, s4_dims, &s4_id); ERR
+
+    i4_dims[0] = D4_dim;
+    err=ncmpi_def_var(ncid, "i4", NC_INT, RANK_i4, i4_dims, &i4_id); ERR
+
+    f4_dims[0] = D4_dim;
+    err=ncmpi_def_var(ncid, "f4", NC_FLOAT, RANK_f4, f4_dims, &f4_id); ERR
+
+    d4_dims[0] = D4_dim;
+    err=ncmpi_def_var(ncid, "d4", NC_DOUBLE, RANK_d4, d4_dims, &d4_id); ERR
+
+    cr1_dims[0] = Dr_dim;
+    cr1_dims[1] = D1_dim;
+    err=ncmpi_def_var(ncid, "cr1", NC_CHAR, RANK_cr1, cr1_dims, &cr1_id); ERR
+
+    br2_dims[0] = Dr_dim;
+    br2_dims[1] = D2_dim;
+    err=ncmpi_def_var(ncid, "br2", NC_BYTE, RANK_br2, br2_dims, &br2_id); ERR
+
+    sr3_dims[0] = Dr_dim;
+    sr3_dims[1] = D3_dim;
+    err=ncmpi_def_var(ncid, "sr3", NC_SHORT, RANK_sr3, sr3_dims, &sr3_id); ERR
+
+    ir4_dims[0] = Dr_dim;
+    ir4_dims[1] = D4_dim;
+    err=ncmpi_def_var(ncid, "ir4", NC_INT, RANK_ir4, ir4_dims, &ir4_id); ERR
+
+    f11_dims[0] = D1_dim;
+    f11_dims[1] = D1_dim;
+    err=ncmpi_def_var(ncid, "f11", NC_FLOAT, RANK_f11, f11_dims, &f11_id); ERR
+
+    d12_dims[0] = D1_dim;
+    d12_dims[1] = D2_dim;
+    err=ncmpi_def_var(ncid, "d12", NC_DOUBLE, RANK_d12, d12_dims, &d12_id); ERR
+
+    c13_dims[0] = D1_dim;
+    c13_dims[1] = D3_dim;
+    err=ncmpi_def_var(ncid, "c13", NC_CHAR, RANK_c13, c13_dims, &c13_id); ERR
+
+    b14_dims[0] = D1_dim;
+    b14_dims[1] = D4_dim;
+    err=ncmpi_def_var(ncid, "b14", NC_BYTE, RANK_b14, b14_dims, &b14_id); ERR
+
+    s21_dims[0] = D2_dim;
+    s21_dims[1] = D1_dim;
+    err=ncmpi_def_var(ncid, "s21", NC_SHORT, RANK_s21, s21_dims, &s21_id); ERR
+
+    i22_dims[0] = D2_dim;
+    i22_dims[1] = D2_dim;
+    err=ncmpi_def_var(ncid, "i22", NC_INT, RANK_i22, i22_dims, &i22_id); ERR
+
+    f23_dims[0] = D2_dim;
+    f23_dims[1] = D3_dim;
+    err=ncmpi_def_var(ncid, "f23", NC_FLOAT, RANK_f23, f23_dims, &f23_id); ERR
+
+    d24_dims[0] = D2_dim;
+    d24_dims[1] = D4_dim;
+    err=ncmpi_def_var(ncid, "d24", NC_DOUBLE, RANK_d24, d24_dims, &d24_id); ERR
+
+    c31_dims[0] = D3_dim;
+    c31_dims[1] = D1_dim;
+    err=ncmpi_def_var(ncid, "c31", NC_CHAR, RANK_c31, c31_dims, &c31_id); ERR
+
+    b32_dims[0] = D3_dim;
+    b32_dims[1] = D2_dim;
+    err=ncmpi_def_var(ncid, "b32", NC_BYTE, RANK_b32, b32_dims, &b32_id); ERR
+
+    s33_dims[0] = D3_dim;
+    s33_dims[1] = D3_dim;
+    err=ncmpi_def_var(ncid, "s33", NC_SHORT, RANK_s33, s33_dims, &s33_id); ERR
+
+    i34_dims[0] = D3_dim;
+    i34_dims[1] = D4_dim;
+    err=ncmpi_def_var(ncid, "i34", NC_INT, RANK_i34, i34_dims, &i34_id); ERR
+
+    f41_dims[0] = D4_dim;
+    f41_dims[1] = D1_dim;
+    err=ncmpi_def_var(ncid, "f41", NC_FLOAT, RANK_f41, f41_dims, &f41_id); ERR
+
+    d42_dims[0] = D4_dim;
+    d42_dims[1] = D2_dim;
+    err=ncmpi_def_var(ncid, "d42", NC_DOUBLE, RANK_d42, d42_dims, &d42_id); ERR
+
+    c43_dims[0] = D4_dim;
+    c43_dims[1] = D3_dim;
+    err=ncmpi_def_var(ncid, "c43", NC_CHAR, RANK_c43, c43_dims, &c43_id); ERR
+
+    b44_dims[0] = D4_dim;
+    b44_dims[1] = D4_dim;
+    err=ncmpi_def_var(ncid, "b44", NC_BYTE, RANK_b44, b44_dims, &b44_id); ERR
+
+    sr11_dims[0] = Dr_dim;
+    sr11_dims[1] = D1_dim;
+    sr11_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "sr11", NC_SHORT, RANK_sr11, sr11_dims, &sr11_id); ERR
+
+    ir12_dims[0] = Dr_dim;
+    ir12_dims[1] = D1_dim;
+    ir12_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "ir12", NC_INT, RANK_ir12, ir12_dims, &ir12_id); ERR
+
+    fr13_dims[0] = Dr_dim;
+    fr13_dims[1] = D1_dim;
+    fr13_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "fr13", NC_FLOAT, RANK_fr13, fr13_dims, &fr13_id); ERR
+
+    dr14_dims[0] = Dr_dim;
+    dr14_dims[1] = D1_dim;
+    dr14_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "dr14", NC_DOUBLE, RANK_dr14, dr14_dims, &dr14_id); ERR
+
+    cr21_dims[0] = Dr_dim;
+    cr21_dims[1] = D2_dim;
+    cr21_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "cr21", NC_CHAR, RANK_cr21, cr21_dims, &cr21_id); ERR
+
+    br22_dims[0] = Dr_dim;
+    br22_dims[1] = D2_dim;
+    br22_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "br22", NC_BYTE, RANK_br22, br22_dims, &br22_id); ERR
+
+    sr23_dims[0] = Dr_dim;
+    sr23_dims[1] = D2_dim;
+    sr23_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "sr23", NC_SHORT, RANK_sr23, sr23_dims, &sr23_id); ERR
+
+    ir24_dims[0] = Dr_dim;
+    ir24_dims[1] = D2_dim;
+    ir24_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "ir24", NC_INT, RANK_ir24, ir24_dims, &ir24_id); ERR
+
+    fr31_dims[0] = Dr_dim;
+    fr31_dims[1] = D3_dim;
+    fr31_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "fr31", NC_FLOAT, RANK_fr31, fr31_dims, &fr31_id); ERR
+
+    dr32_dims[0] = Dr_dim;
+    dr32_dims[1] = D3_dim;
+    dr32_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "dr32", NC_DOUBLE, RANK_dr32, dr32_dims, &dr32_id); ERR
+
+    cr33_dims[0] = Dr_dim;
+    cr33_dims[1] = D3_dim;
+    cr33_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "cr33", NC_CHAR, RANK_cr33, cr33_dims, &cr33_id); ERR
+
+    br34_dims[0] = Dr_dim;
+    br34_dims[1] = D3_dim;
+    br34_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "br34", NC_BYTE, RANK_br34, br34_dims, &br34_id); ERR
+
+    sr41_dims[0] = Dr_dim;
+    sr41_dims[1] = D4_dim;
+    sr41_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "sr41", NC_SHORT, RANK_sr41, sr41_dims, &sr41_id); ERR
+
+    ir42_dims[0] = Dr_dim;
+    ir42_dims[1] = D4_dim;
+    ir42_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "ir42", NC_INT, RANK_ir42, ir42_dims, &ir42_id); ERR
+
+    fr43_dims[0] = Dr_dim;
+    fr43_dims[1] = D4_dim;
+    fr43_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "fr43", NC_FLOAT, RANK_fr43, fr43_dims, &fr43_id); ERR
+
+    dr44_dims[0] = Dr_dim;
+    dr44_dims[1] = D4_dim;
+    dr44_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "dr44", NC_DOUBLE, RANK_dr44, dr44_dims, &dr44_id); ERR
+
+    c111_dims[0] = D1_dim;
+    c111_dims[1] = D1_dim;
+    c111_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "c111", NC_CHAR, RANK_c111, c111_dims, &c111_id); ERR
+
+    b112_dims[0] = D1_dim;
+    b112_dims[1] = D1_dim;
+    b112_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "b112", NC_BYTE, RANK_b112, b112_dims, &b112_id); ERR
+
+    s113_dims[0] = D1_dim;
+    s113_dims[1] = D1_dim;
+    s113_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "s113", NC_SHORT, RANK_s113, s113_dims, &s113_id); ERR
+
+    i114_dims[0] = D1_dim;
+    i114_dims[1] = D1_dim;
+    i114_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "i114", NC_INT, RANK_i114, i114_dims, &i114_id); ERR
+
+    f121_dims[0] = D1_dim;
+    f121_dims[1] = D2_dim;
+    f121_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "f121", NC_FLOAT, RANK_f121, f121_dims, &f121_id); ERR
+
+    d122_dims[0] = D1_dim;
+    d122_dims[1] = D2_dim;
+    d122_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "d122", NC_DOUBLE, RANK_d122, d122_dims, &d122_id); ERR
+
+    c123_dims[0] = D1_dim;
+    c123_dims[1] = D2_dim;
+    c123_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "c123", NC_CHAR, RANK_c123, c123_dims, &c123_id); ERR
+
+    b124_dims[0] = D1_dim;
+    b124_dims[1] = D2_dim;
+    b124_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "b124", NC_BYTE, RANK_b124, b124_dims, &b124_id); ERR
+
+    s131_dims[0] = D1_dim;
+    s131_dims[1] = D3_dim;
+    s131_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "s131", NC_SHORT, RANK_s131, s131_dims, &s131_id); ERR
+
+    i132_dims[0] = D1_dim;
+    i132_dims[1] = D3_dim;
+    i132_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "i132", NC_INT, RANK_i132, i132_dims, &i132_id); ERR
+
+    f133_dims[0] = D1_dim;
+    f133_dims[1] = D3_dim;
+    f133_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "f133", NC_FLOAT, RANK_f133, f133_dims, &f133_id); ERR
+
+    d134_dims[0] = D1_dim;
+    d134_dims[1] = D3_dim;
+    d134_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "d134", NC_DOUBLE, RANK_d134, d134_dims, &d134_id); ERR
+
+    c141_dims[0] = D1_dim;
+    c141_dims[1] = D4_dim;
+    c141_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "c141", NC_CHAR, RANK_c141, c141_dims, &c141_id); ERR
+
+    b142_dims[0] = D1_dim;
+    b142_dims[1] = D4_dim;
+    b142_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "b142", NC_BYTE, RANK_b142, b142_dims, &b142_id); ERR
+
+    s143_dims[0] = D1_dim;
+    s143_dims[1] = D4_dim;
+    s143_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "s143", NC_SHORT, RANK_s143, s143_dims, &s143_id); ERR
+
+    i144_dims[0] = D1_dim;
+    i144_dims[1] = D4_dim;
+    i144_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "i144", NC_INT, RANK_i144, i144_dims, &i144_id); ERR
+
+    f211_dims[0] = D2_dim;
+    f211_dims[1] = D1_dim;
+    f211_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "f211", NC_FLOAT, RANK_f211, f211_dims, &f211_id); ERR
+
+    d212_dims[0] = D2_dim;
+    d212_dims[1] = D1_dim;
+    d212_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "d212", NC_DOUBLE, RANK_d212, d212_dims, &d212_id); ERR
+
+    c213_dims[0] = D2_dim;
+    c213_dims[1] = D1_dim;
+    c213_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "c213", NC_CHAR, RANK_c213, c213_dims, &c213_id); ERR
+
+    b214_dims[0] = D2_dim;
+    b214_dims[1] = D1_dim;
+    b214_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "b214", NC_BYTE, RANK_b214, b214_dims, &b214_id); ERR
+
+    s221_dims[0] = D2_dim;
+    s221_dims[1] = D2_dim;
+    s221_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "s221", NC_SHORT, RANK_s221, s221_dims, &s221_id); ERR
+
+    i222_dims[0] = D2_dim;
+    i222_dims[1] = D2_dim;
+    i222_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "i222", NC_INT, RANK_i222, i222_dims, &i222_id); ERR
+
+    f223_dims[0] = D2_dim;
+    f223_dims[1] = D2_dim;
+    f223_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "f223", NC_FLOAT, RANK_f223, f223_dims, &f223_id); ERR
+
+    d224_dims[0] = D2_dim;
+    d224_dims[1] = D2_dim;
+    d224_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "d224", NC_DOUBLE, RANK_d224, d224_dims, &d224_id); ERR
+
+    c231_dims[0] = D2_dim;
+    c231_dims[1] = D3_dim;
+    c231_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "c231", NC_CHAR, RANK_c231, c231_dims, &c231_id); ERR
+
+    b232_dims[0] = D2_dim;
+    b232_dims[1] = D3_dim;
+    b232_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "b232", NC_BYTE, RANK_b232, b232_dims, &b232_id); ERR
+
+    s233_dims[0] = D2_dim;
+    s233_dims[1] = D3_dim;
+    s233_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "s233", NC_SHORT, RANK_s233, s233_dims, &s233_id); ERR
+
+    i234_dims[0] = D2_dim;
+    i234_dims[1] = D3_dim;
+    i234_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "i234", NC_INT, RANK_i234, i234_dims, &i234_id); ERR
+
+    f241_dims[0] = D2_dim;
+    f241_dims[1] = D4_dim;
+    f241_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "f241", NC_FLOAT, RANK_f241, f241_dims, &f241_id); ERR
+
+    d242_dims[0] = D2_dim;
+    d242_dims[1] = D4_dim;
+    d242_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "d242", NC_DOUBLE, RANK_d242, d242_dims, &d242_id); ERR
+
+    c243_dims[0] = D2_dim;
+    c243_dims[1] = D4_dim;
+    c243_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "c243", NC_CHAR, RANK_c243, c243_dims, &c243_id); ERR
+
+    b244_dims[0] = D2_dim;
+    b244_dims[1] = D4_dim;
+    b244_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "b244", NC_BYTE, RANK_b244, b244_dims, &b244_id); ERR
+
+    s311_dims[0] = D3_dim;
+    s311_dims[1] = D1_dim;
+    s311_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "s311", NC_SHORT, RANK_s311, s311_dims, &s311_id); ERR
+
+    i312_dims[0] = D3_dim;
+    i312_dims[1] = D1_dim;
+    i312_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "i312", NC_INT, RANK_i312, i312_dims, &i312_id); ERR
+
+    f313_dims[0] = D3_dim;
+    f313_dims[1] = D1_dim;
+    f313_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "f313", NC_FLOAT, RANK_f313, f313_dims, &f313_id); ERR
+
+    d314_dims[0] = D3_dim;
+    d314_dims[1] = D1_dim;
+    d314_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "d314", NC_DOUBLE, RANK_d314, d314_dims, &d314_id); ERR
+
+    c321_dims[0] = D3_dim;
+    c321_dims[1] = D2_dim;
+    c321_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "c321", NC_CHAR, RANK_c321, c321_dims, &c321_id); ERR
+
+    b322_dims[0] = D3_dim;
+    b322_dims[1] = D2_dim;
+    b322_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "b322", NC_BYTE, RANK_b322, b322_dims, &b322_id); ERR
+
+    s323_dims[0] = D3_dim;
+    s323_dims[1] = D2_dim;
+    s323_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "s323", NC_SHORT, RANK_s323, s323_dims, &s323_id); ERR
+
+    i324_dims[0] = D3_dim;
+    i324_dims[1] = D2_dim;
+    i324_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "i324", NC_INT, RANK_i324, i324_dims, &i324_id); ERR
+
+    f331_dims[0] = D3_dim;
+    f331_dims[1] = D3_dim;
+    f331_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "f331", NC_FLOAT, RANK_f331, f331_dims, &f331_id); ERR
+
+    d332_dims[0] = D3_dim;
+    d332_dims[1] = D3_dim;
+    d332_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "d332", NC_DOUBLE, RANK_d332, d332_dims, &d332_id); ERR
+
+    c333_dims[0] = D3_dim;
+    c333_dims[1] = D3_dim;
+    c333_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "c333", NC_CHAR, RANK_c333, c333_dims, &c333_id); ERR
+
+    b334_dims[0] = D3_dim;
+    b334_dims[1] = D3_dim;
+    b334_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "b334", NC_BYTE, RANK_b334, b334_dims, &b334_id); ERR
+
+    s341_dims[0] = D3_dim;
+    s341_dims[1] = D4_dim;
+    s341_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "s341", NC_SHORT, RANK_s341, s341_dims, &s341_id); ERR
+
+    i342_dims[0] = D3_dim;
+    i342_dims[1] = D4_dim;
+    i342_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "i342", NC_INT, RANK_i342, i342_dims, &i342_id); ERR
+
+    f343_dims[0] = D3_dim;
+    f343_dims[1] = D4_dim;
+    f343_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "f343", NC_FLOAT, RANK_f343, f343_dims, &f343_id); ERR
+
+    d344_dims[0] = D3_dim;
+    d344_dims[1] = D4_dim;
+    d344_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "d344", NC_DOUBLE, RANK_d344, d344_dims, &d344_id); ERR
+
+    c411_dims[0] = D4_dim;
+    c411_dims[1] = D1_dim;
+    c411_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "c411", NC_CHAR, RANK_c411, c411_dims, &c411_id); ERR
+
+    b412_dims[0] = D4_dim;
+    b412_dims[1] = D1_dim;
+    b412_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "b412", NC_BYTE, RANK_b412, b412_dims, &b412_id); ERR
+
+    s413_dims[0] = D4_dim;
+    s413_dims[1] = D1_dim;
+    s413_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "s413", NC_SHORT, RANK_s413, s413_dims, &s413_id); ERR
+
+    i414_dims[0] = D4_dim;
+    i414_dims[1] = D1_dim;
+    i414_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "i414", NC_INT, RANK_i414, i414_dims, &i414_id); ERR
+
+    f421_dims[0] = D4_dim;
+    f421_dims[1] = D2_dim;
+    f421_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "f421", NC_FLOAT, RANK_f421, f421_dims, &f421_id); ERR
+
+    d422_dims[0] = D4_dim;
+    d422_dims[1] = D2_dim;
+    d422_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "d422", NC_DOUBLE, RANK_d422, d422_dims, &d422_id); ERR
+
+    c423_dims[0] = D4_dim;
+    c423_dims[1] = D2_dim;
+    c423_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "c423", NC_CHAR, RANK_c423, c423_dims, &c423_id); ERR
+
+    b424_dims[0] = D4_dim;
+    b424_dims[1] = D2_dim;
+    b424_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "b424", NC_BYTE, RANK_b424, b424_dims, &b424_id); ERR
+
+    s431_dims[0] = D4_dim;
+    s431_dims[1] = D3_dim;
+    s431_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "s431", NC_SHORT, RANK_s431, s431_dims, &s431_id); ERR
+
+    i432_dims[0] = D4_dim;
+    i432_dims[1] = D3_dim;
+    i432_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "i432", NC_INT, RANK_i432, i432_dims, &i432_id); ERR
+
+    f433_dims[0] = D4_dim;
+    f433_dims[1] = D3_dim;
+    f433_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "f433", NC_FLOAT, RANK_f433, f433_dims, &f433_id); ERR
+
+    d434_dims[0] = D4_dim;
+    d434_dims[1] = D3_dim;
+    d434_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "d434", NC_DOUBLE, RANK_d434, d434_dims, &d434_id); ERR
+
+    c441_dims[0] = D4_dim;
+    c441_dims[1] = D4_dim;
+    c441_dims[2] = D1_dim;
+    err=ncmpi_def_var(ncid, "c441", NC_CHAR, RANK_c441, c441_dims, &c441_id); ERR
+
+    b442_dims[0] = D4_dim;
+    b442_dims[1] = D4_dim;
+    b442_dims[2] = D2_dim;
+    err=ncmpi_def_var(ncid, "b442", NC_BYTE, RANK_b442, b442_dims, &b442_id); ERR
+
+    s443_dims[0] = D4_dim;
+    s443_dims[1] = D4_dim;
+    s443_dims[2] = D3_dim;
+    err=ncmpi_def_var(ncid, "s443", NC_SHORT, RANK_s443, s443_dims, &s443_id); ERR
+
+    i444_dims[0] = D4_dim;
+    i444_dims[1] = D4_dim;
+    i444_dims[2] = D4_dim;
+    err=ncmpi_def_var(ncid, "i444", NC_INT, RANK_i444, i444_dims, &i444_id); ERR
+
+    /* assign global attributes */
+    { /* Gc */
+    err=ncmpi_put_att_text(ncid, NC_GLOBAL, "Gc", 1, "\177"); ERR
+    }
+    { /* Gb */
+    static const signed char Gb_att[2] = {-128, 127} ;
+    err=ncmpi_put_att_schar(ncid, NC_GLOBAL, "Gb", NC_BYTE, 2, Gb_att); ERR
+    }
+    { /* Gs */
+    static const short Gs_att[3] = {-32768, 32767, 32767} ;
+    err=ncmpi_put_att_short(ncid, NC_GLOBAL, "Gs", NC_SHORT, 3, Gs_att); ERR
+    }
+    { /* Gi */
+    static const int Gi_att[4] = {INT_MIN, INT_MAX, INT_MIN, INT_MIN} ;
+    err=ncmpi_put_att_int(ncid, NC_GLOBAL, "Gi", NC_INT, 4, Gi_att); ERR
+    }
+    { /* Gf */
+    static const float Gf_att[5] = {-3.4028231e+38, 3.4028231e+38, -9.96921e+36, 9.96921e+36, 531} ;
+    err=ncmpi_put_att_float(ncid, NC_GLOBAL, "Gf", NC_FLOAT, 5, Gf_att); ERR
+    }
+    { /* Gd */
+    static const double Gd_att[6] = {-42, 42, -1, 1, 660, 650} ;
+    err=ncmpi_put_att_double(ncid, NC_GLOBAL, "Gd", NC_DOUBLE, 6, Gd_att); ERR
+    }
+
+
+    /* assign per-variable attributes */
+    { /* c */
+    err=ncmpi_put_att_text(ncid, b_id, "c", 0, ""); ERR
+    }
+    { /* b */
+    static const signed char s_b_att[1] = {-128} ;
+    err=ncmpi_put_att_schar(ncid, s_id, "b", NC_BYTE, 1, s_b_att); ERR
+    }
+    { /* s */
+    static const short s_s_att[2] = {-32768, 32767} ;
+    err=ncmpi_put_att_short(ncid, s_id, "s", NC_SHORT, 2, s_s_att); ERR
+    }
+    { /* i */
+    static const int i_i_att[3] = {INT_MIN, 2147483647, INT_MIN} ;
+    err=ncmpi_put_att_int(ncid, i_id, "i", NC_INT, 3, i_i_att); ERR
+    }
+    { /* f */
+    static const float i_f_att[4] = {-3.4028231e+38, 3.4028231e+38, -9.96921e+36, 9.96921e+36} ;
+    err=ncmpi_put_att_float(ncid, i_id, "f", NC_FLOAT, 4, i_f_att); ERR
+    }
+    { /* d */
+    static const double i_d_att[5] = {-42, 42, -1, 1, 660} ;
+    err=ncmpi_put_att_double(ncid, i_id, "d", NC_DOUBLE, 5, i_d_att); ERR
+    }
+    { /* c */
+    err=ncmpi_put_att_text(ncid, d_id, "c", 6, "blahhh"); ERR
+    }
+
+    /* leave define mode */
+    err=ncmpi_enddef (ncid); ERR
+
+    err=ncmpi_begin_indep_data (ncid); ERR
+
+    /* assign variable data */
+    {
+    MPI_Offset zero = 0;
+    static char c_data[1] = {'\002'};
+    err=ncmpi_put_var1(ncid, c_id, &zero, c_data, 0,MPI_DATATYPE_NULL);    ERR
+    }
+    {
+    MPI_Offset zero = 0;
+    static signed char b_data[1] = {-2};
+    err=ncmpi_put_var1(ncid, b_id, &zero, b_data, 0,MPI_DATATYPE_NULL);    ERR
+    }
+    {
+    MPI_Offset zero = 0;
+    static short s_data[1] = {-5};
+    err=ncmpi_put_var1(ncid, s_id, &zero, s_data, 0,MPI_DATATYPE_NULL);    ERR
+    }
+    {
+    MPI_Offset zero = 0;
+    static int i_data[1] = {-20};
+    err=ncmpi_put_var1(ncid, i_id, &zero, i_data, 0,MPI_DATATYPE_NULL);    ERR
+    }
+    {
+    MPI_Offset zero = 0;
+    static float f_data[1] = {-9};
+    err=ncmpi_put_var1(ncid, f_id, &zero, f_data, 0,MPI_DATATYPE_NULL);    ERR
+    }
+    {
+    MPI_Offset zero = 0;
+    static double d_data[1] = {-10};
+    err=ncmpi_put_var1(ncid, d_id, &zero, d_data, 0,MPI_DATATYPE_NULL);    ERR
+    }
+    {
+    char cr_data[2] = "\177\177" ;
+    MPI_Offset cr_startset[1] = {0} ;
+    MPI_Offset cr_countset[1] = {2} ;
+    err=ncmpi_put_vara(ncid, cr_id, cr_startset, cr_countset, cr_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char br_data[2] = {-128, 127} ;
+    MPI_Offset br_startset[1] = {0} ;
+    MPI_Offset br_countset[1] = {2} ;
+    err=ncmpi_put_vara(ncid, br_id, br_startset, br_countset, br_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short sr_data[2] = {-32768, 32767} ;
+    MPI_Offset sr_startset[1] = {0} ;
+    MPI_Offset sr_countset[1] = {2} ;
+    err=ncmpi_put_vara(ncid, sr_id, sr_startset, sr_countset, sr_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int ir_data[2] = {INT_MIN, 2147483647} ;
+    MPI_Offset ir_startset[1] = {0} ;
+    MPI_Offset ir_countset[1] = {2} ;
+    err=ncmpi_put_vara(ncid, ir_id, ir_startset, ir_countset, ir_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float fr_data[2] = {-3.4028231e+38, 3.4028231e+38} ;
+    MPI_Offset fr_startset[1] = {0} ;
+    MPI_Offset fr_countset[1] = {2} ;
+    err=ncmpi_put_vara(ncid, fr_id, fr_startset, fr_countset, fr_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double dr_data[2] = {-42, 42} ;
+    MPI_Offset dr_startset[1] = {0} ;
+    MPI_Offset dr_countset[1] = {2} ;
+    err=ncmpi_put_vara(ncid, dr_id, dr_startset, dr_countset, dr_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c1_data[1] = "\177" ;
+    MPI_Offset c1_startset[1] = {0} ;
+    MPI_Offset c1_countset[1] = {1} ;
+    err=ncmpi_put_vara(ncid, c1_id, c1_startset, c1_countset, c1_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b1_data[1] = {-128} ;
+    MPI_Offset b1_startset[1] = {0} ;
+    MPI_Offset b1_countset[1] = {1} ;
+    err=ncmpi_put_vara(ncid, b1_id, b1_startset, b1_countset, b1_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s1_data[1] = {-32768} ;
+    MPI_Offset s1_startset[1] = {0} ;
+    MPI_Offset s1_countset[1] = {1} ;
+    err=ncmpi_put_vara(ncid, s1_id, s1_startset, s1_countset, s1_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i1_data[1] = {INT_MIN} ;
+    MPI_Offset i1_startset[1] = {0} ;
+    MPI_Offset i1_countset[1] = {1} ;
+    err=ncmpi_put_vara(ncid, i1_id, i1_startset, i1_countset, i1_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f1_data[1] = {-3.4028231e+38} ;
+    MPI_Offset f1_startset[1] = {0} ;
+    MPI_Offset f1_countset[1] = {1} ;
+    err=ncmpi_put_vara(ncid, f1_id, f1_startset, f1_countset, f1_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d1_data[1] = {-42} ;
+    MPI_Offset d1_startset[1] = {0} ;
+    MPI_Offset d1_countset[1] = {1} ;
+    err=ncmpi_put_vara(ncid, d1_id, d1_startset, d1_countset, d1_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c2_data[2] = "\177\177" ;
+    MPI_Offset c2_startset[1] = {0} ;
+    MPI_Offset c2_countset[1] = {2} ;
+    err=ncmpi_put_vara(ncid, c2_id, c2_startset, c2_countset, c2_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b2_data[2] = {-128, 127} ;
+    MPI_Offset b2_startset[1] = {0} ;
+    MPI_Offset b2_countset[1] = {2} ;
+    err=ncmpi_put_vara(ncid, b2_id, b2_startset, b2_countset, b2_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s2_data[2] = {-32768, 32767} ;
+    MPI_Offset s2_startset[1] = {0} ;
+    MPI_Offset s2_countset[1] = {2} ;
+    err=ncmpi_put_vara(ncid, s2_id, s2_startset, s2_countset, s2_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i2_data[2] = {INT_MIN, 2147483647} ;
+    MPI_Offset i2_startset[1] = {0} ;
+    MPI_Offset i2_countset[1] = {2} ;
+    err=ncmpi_put_vara(ncid, i2_id, i2_startset, i2_countset, i2_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f2_data[2] = {-3.4028231e+38, 3.4028231e+38} ;
+    MPI_Offset f2_startset[1] = {0} ;
+    MPI_Offset f2_countset[1] = {2} ;
+    err=ncmpi_put_vara(ncid, f2_id, f2_startset, f2_countset, f2_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d2_data[2] = {-42, 42} ;
+    MPI_Offset d2_startset[1] = {0} ;
+    MPI_Offset d2_countset[1] = {2} ;
+    err=ncmpi_put_vara(ncid, d2_id, d2_startset, d2_countset, d2_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c3_data[3] = "\177\177A" ;
+    MPI_Offset c3_startset[1] = {0} ;
+    MPI_Offset c3_countset[1] = {3} ;
+    err=ncmpi_put_vara(ncid, c3_id, c3_startset, c3_countset, c3_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b3_data[3] = {-128, 127, 127} ;
+    MPI_Offset b3_startset[1] = {0} ;
+    MPI_Offset b3_countset[1] = {3} ;
+    err=ncmpi_put_vara(ncid, b3_id, b3_startset, b3_countset, b3_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s3_data[3] = {-32768, 32767, 32767} ;
+    MPI_Offset s3_startset[1] = {0} ;
+    MPI_Offset s3_countset[1] = {3} ;
+    err=ncmpi_put_vara(ncid, s3_id, s3_startset, s3_countset, s3_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i3_data[3] = {INT_MIN, 2147483647, INT_MIN} ;
+    MPI_Offset i3_startset[1] = {0} ;
+    MPI_Offset i3_countset[1] = {3} ;
+    err=ncmpi_put_vara(ncid, i3_id, i3_startset, i3_countset, i3_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f3_data[3] = {-3.4028231e+38, 3.4028231e+38, -9.96921e+36} ;
+    MPI_Offset f3_startset[1] = {0} ;
+    MPI_Offset f3_countset[1] = {3} ;
+    err=ncmpi_put_vara(ncid, f3_id, f3_startset, f3_countset, f3_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d3_data[3] = {-42, 42, -1} ;
+    MPI_Offset d3_startset[1] = {0} ;
+    MPI_Offset d3_countset[1] = {3} ;
+    err=ncmpi_put_vara(ncid, d3_id, d3_startset, d3_countset, d3_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c4_data[4] = "\177\177AZ" ;
+    MPI_Offset c4_startset[1] = {0} ;
+    MPI_Offset c4_countset[1] = {4} ;
+    err=ncmpi_put_vara(ncid, c4_id, c4_startset, c4_countset, c4_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b4_data[4] = {-128, 127, 127, -128} ;
+    MPI_Offset b4_startset[1] = {0} ;
+    MPI_Offset b4_countset[1] = {4} ;
+    err=ncmpi_put_vara(ncid, b4_id, b4_startset, b4_countset, b4_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s4_data[4] = {-32768, 32767, 32767, -32768} ;
+    MPI_Offset s4_startset[1] = {0} ;
+    MPI_Offset s4_countset[1] = {4} ;
+    err=ncmpi_put_vara(ncid, s4_id, s4_startset, s4_countset, s4_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i4_data[4] = {INT_MIN, 2147483647, INT_MIN, INT_MIN} ;
+    MPI_Offset i4_startset[1] = {0} ;
+    MPI_Offset i4_countset[1] = {4} ;
+    err=ncmpi_put_vara(ncid, i4_id, i4_startset, i4_countset, i4_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f4_data[4] = {-3.4028231e+38, 3.4028231e+38, -9.96921e+36, 9.96921e+36} ;
+    MPI_Offset f4_startset[1] = {0} ;
+    MPI_Offset f4_countset[1] = {4} ;
+    err=ncmpi_put_vara(ncid, f4_id, f4_startset, f4_countset, f4_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d4_data[4] = {-42, 42, -1, 1} ;
+    MPI_Offset d4_startset[1] = {0} ;
+    MPI_Offset d4_countset[1] = {4} ;
+    err=ncmpi_put_vara(ncid, d4_id, d4_startset, d4_countset, d4_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char cr1_data[2] = "\030\034" ;
+    MPI_Offset cr1_startset[2] = {0, 0} ;
+    MPI_Offset cr1_countset[2] = {2, 1} ;
+    err=ncmpi_put_vara(ncid, cr1_id, cr1_startset, cr1_countset, cr1_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char br2_data[4] = {-24, -26, -20, -22} ;
+    MPI_Offset br2_startset[2] = {0, 0} ;
+    MPI_Offset br2_countset[2] = {2, 2} ;
+    err=ncmpi_put_vara(ncid, br2_id, br2_startset, br2_countset, br2_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short sr3_data[6] = {-375, -380, -385, -350, -355, -360} ;
+    MPI_Offset sr3_startset[2] = {0, 0} ;
+    MPI_Offset sr3_countset[2] = {2, 3} ;
+    err=ncmpi_put_vara(ncid, sr3_id, sr3_startset, sr3_countset, sr3_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int ir4_data[8] = {-24000, -24020, -24040, -24060, -23600, -23620, -23640, -23660} ;
+    MPI_Offset ir4_startset[2] = {0, 0} ;
+    MPI_Offset ir4_countset[2] = {2, 4} ;
+    err=ncmpi_put_vara(ncid, ir4_id, ir4_startset, ir4_countset, ir4_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f11_data[1] = {-2187} ;
+    MPI_Offset f11_startset[2] = {0, 0} ;
+    MPI_Offset f11_countset[2] = {1, 1} ;
+    err=ncmpi_put_vara(ncid, f11_id, f11_startset, f11_countset, f11_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d12_data[2] = {-3000, -3010} ;
+    MPI_Offset d12_startset[2] = {0, 0} ;
+    MPI_Offset d12_countset[2] = {1, 2} ;
+    err=ncmpi_put_vara(ncid, d12_id, d12_startset, d12_countset, d12_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c13_data[3] = "\030\032\034" ;
+    MPI_Offset c13_startset[2] = {0, 0} ;
+    MPI_Offset c13_countset[2] = {1, 3} ;
+    err=ncmpi_put_vara(ncid, c13_id, c13_startset, c13_countset, c13_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b14_data[4] = {-24, -26, -28, -30} ;
+    MPI_Offset b14_startset[2] = {0, 0} ;
+    MPI_Offset b14_countset[2] = {1, 4} ;
+    err=ncmpi_put_vara(ncid, b14_id, b14_startset, b14_countset, b14_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s21_data[2] = {-375, -350} ;
+    MPI_Offset s21_startset[2] = {0, 0} ;
+    MPI_Offset s21_countset[2] = {2, 1} ;
+    err=ncmpi_put_vara(ncid, s21_id, s21_startset, s21_countset, s21_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i22_data[4] = {-24000, -24020, -23600, -23620} ;
+    MPI_Offset i22_startset[2] = {0, 0} ;
+    MPI_Offset i22_countset[2] = {2, 2} ;
+    err=ncmpi_put_vara(ncid, i22_id, i22_startset, i22_countset, i22_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f23_data[6] = {-2187, -2196, -2205, -2106, -2115, -2124} ;
+    MPI_Offset f23_startset[2] = {0, 0} ;
+    MPI_Offset f23_countset[2] = {2, 3} ;
+    err=ncmpi_put_vara(ncid, f23_id, f23_startset, f23_countset, f23_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d24_data[8] = {-3000, -3010, -3020, -3030, -2900, -2910, -2920, -2930} ;
+    MPI_Offset d24_startset[2] = {0, 0} ;
+    MPI_Offset d24_countset[2] = {2, 4} ;
+    err=ncmpi_put_vara(ncid, d24_id, d24_startset, d24_countset, d24_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c31_data[3] = "\030\034 " ;
+    MPI_Offset c31_startset[2] = {0, 0} ;
+    MPI_Offset c31_countset[2] = {3, 1} ;
+    err=ncmpi_put_vara(ncid, c31_id, c31_startset, c31_countset, c31_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b32_data[6] = {-24, -26, -20, -22, -16, -18} ;
+    MPI_Offset b32_startset[2] = {0, 0} ;
+    MPI_Offset b32_countset[2] = {3, 2} ;
+    err=ncmpi_put_vara(ncid, b32_id, b32_startset, b32_countset, b32_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s33_data[9] = {-375, -380, -385, -350, -355, -360, -325, -330, -335} ;
+    MPI_Offset s33_startset[2] = {0, 0} ;
+    MPI_Offset s33_countset[2] = {3, 3} ;
+    err=ncmpi_put_vara(ncid, s33_id, s33_startset, s33_countset, s33_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i34_data[12] = {-24000, -24020, -24040, -24060, -23600, -23620, -23640, -23660, -23200, -23220, -23240, -23260} ;
+    MPI_Offset i34_startset[2] = {0, 0} ;
+    MPI_Offset i34_countset[2] = {3, 4} ;
+    err=ncmpi_put_vara(ncid, i34_id, i34_startset, i34_countset, i34_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f41_data[4] = {-2187, -2106, -2025, -1944} ;
+    MPI_Offset f41_startset[2] = {0, 0} ;
+    MPI_Offset f41_countset[2] = {4, 1} ;
+    err=ncmpi_put_vara(ncid, f41_id, f41_startset, f41_countset, f41_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d42_data[8] = {-3000, -3010, -2900, -2910, -2800, -2810, -2700, -2710} ;
+    MPI_Offset d42_startset[2] = {0, 0} ;
+    MPI_Offset d42_countset[2] = {4, 2} ;
+    err=ncmpi_put_vara(ncid, d42_id, d42_startset, d42_countset, d42_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c43_data[12] = "\030\032\034\034\036  \"$$&(" ;
+    MPI_Offset c43_startset[2] = {0, 0} ;
+    MPI_Offset c43_countset[2] = {4, 3} ;
+    err=ncmpi_put_vara(ncid, c43_id, c43_startset, c43_countset, c43_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b44_data[16] = {-24, -26, -28, -30, -20, -22, -24, -26, -16, -18, -20, -22, -12, -14, -16, -18} ;
+    MPI_Offset b44_startset[2] = {0, 0} ;
+    MPI_Offset b44_countset[2] = {4, 4} ;
+    err=ncmpi_put_vara(ncid, b44_id, b44_startset, b44_countset, b44_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short sr11_data[2] = {2500, 2375} ;
+    MPI_Offset sr11_startset[3] = {0, 0, 0} ;
+    MPI_Offset sr11_countset[3] = {2, 1, 1} ;
+    err=ncmpi_put_vara(ncid, sr11_id, sr11_startset, sr11_countset, sr11_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int ir12_data[4] = {640000, 639980, 632000, 631980} ;
+    MPI_Offset ir12_startset[3] = {0, 0, 0} ;
+    MPI_Offset ir12_countset[3] = {2, 1, 2} ;
+    err=ncmpi_put_vara(ncid, ir12_id, ir12_startset, ir12_countset, ir12_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float fr13_data[6] = {26244, 26235, 26226, 25515, 25506, 25497} ;
+    MPI_Offset fr13_startset[3] = {0, 0, 0} ;
+    MPI_Offset fr13_countset[3] = {2, 1, 3} ;
+    err=ncmpi_put_vara(ncid, fr13_id, fr13_startset, fr13_countset, fr13_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double dr14_data[8] = {40000, 39990, 39980, 39970, 39000, 38990, 38980, 38970} ;
+    MPI_Offset dr14_startset[3] = {0, 0, 0} ;
+    MPI_Offset dr14_countset[3] = {2, 1, 4} ;
+    err=ncmpi_put_vara(ncid, dr14_id, dr14_startset, dr14_countset, dr14_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char cr21_data[4] = "@DHL" ;
+    MPI_Offset cr21_startset[3] = {0, 0, 0} ;
+    MPI_Offset cr21_countset[3] = {2, 2, 1} ;
+    err=ncmpi_put_vara(ncid, cr21_id, cr21_startset, cr21_countset, cr21_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char br22_data[8] = {64, 62, 68, 66, 56, 54, 60, 58} ;
+    MPI_Offset br22_startset[3] = {0, 0, 0} ;
+    MPI_Offset br22_countset[3] = {2, 2, 2} ;
+    err=ncmpi_put_vara(ncid, br22_id, br22_startset, br22_countset, br22_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short sr23_data[12] = {2500, 2495, 2490, 2525, 2520, 2515, 2375, 2370, 2365, 2400, 2395, 2390} ;
+    MPI_Offset sr23_startset[3] = {0, 0, 0} ;
+    MPI_Offset sr23_countset[3] = {2, 2, 3} ;
+    err=ncmpi_put_vara(ncid, sr23_id, sr23_startset, sr23_countset, sr23_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int ir24_data[16] = {640000, 639980, 639960, 639940, 640400, 640380, 640360, 640340, 632000, 631980, 631960, 631940, 632400, 632380, 632360, 632340} ;
+    MPI_Offset ir24_startset[3] = {0, 0, 0} ;
+    MPI_Offset ir24_countset[3] = {2, 2, 4} ;
+    err=ncmpi_put_vara(ncid, ir24_id, ir24_startset, ir24_countset, ir24_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float fr31_data[6] = {26244, 26325, 26406, 25515, 25596, 25677} ;
+    MPI_Offset fr31_startset[3] = {0, 0, 0} ;
+    MPI_Offset fr31_countset[3] = {2, 3, 1} ;
+    err=ncmpi_put_vara(ncid, fr31_id, fr31_startset, fr31_countset, fr31_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double dr32_data[12] = {40000, 39990, 40100, 40090, 40200, 40190, 39000, 38990, 39100, 39090, 39200, 39190} ;
+    MPI_Offset dr32_startset[3] = {0, 0, 0} ;
+    MPI_Offset dr32_countset[3] = {2, 3, 2} ;
+    err=ncmpi_put_vara(ncid, dr32_id, dr32_startset, dr32_countset, dr32_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char cr33_data[18] = "@BDDFHHJLHJLLNPPRT" ;
+    MPI_Offset cr33_startset[3] = {0, 0, 0} ;
+    MPI_Offset cr33_countset[3] = {2, 3, 3} ;
+    err=ncmpi_put_vara(ncid, cr33_id, cr33_startset, cr33_countset, cr33_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char br34_data[24] = {64, 62, 60, 58, 68, 66, 64, 62, 72, 70, 68, 66, 56, 54, 52, 50, 60, 58, 56, 54, 64, 62, 60, 58} ;
+    MPI_Offset br34_startset[3] = {0, 0, 0} ;
+    MPI_Offset br34_countset[3] = {2, 3, 4} ;
+    err=ncmpi_put_vara(ncid, br34_id, br34_startset, br34_countset, br34_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short sr41_data[8] = {2500, 2525, 2550, 2575, 2375, 2400, 2425, 2450} ;
+    MPI_Offset sr41_startset[3] = {0, 0, 0} ;
+    MPI_Offset sr41_countset[3] = {2, 4, 1} ;
+    err=ncmpi_put_vara(ncid, sr41_id, sr41_startset, sr41_countset, sr41_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int ir42_data[16] = {640000, 639980, 640400, 640380, 640800, 640780, 641200, 641180, 632000, 631980, 632400, 632380, 632800, 632780, 633200, 633180} ;
+    MPI_Offset ir42_startset[3] = {0, 0, 0} ;
+    MPI_Offset ir42_countset[3] = {2, 4, 2} ;
+    err=ncmpi_put_vara(ncid, ir42_id, ir42_startset, ir42_countset, ir42_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float fr43_data[24] = {26244, 26235, 26226, 26325, 26316, 26307, 26406, 26397, 26388, 26487, 26478, 26469, 25515, 25506, 25497, 25596, 25587, 25578, 25677, 25668, 25659, 25758, 25749, 25740} ;
+    MPI_Offset fr43_startset[3] = {0, 0, 0} ;
+    MPI_Offset fr43_countset[3] = {2, 4, 3} ;
+    err=ncmpi_put_vara(ncid, fr43_id, fr43_startset, fr43_countset, fr43_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double dr44_data[32] = {40000, 39990, 39980, 39970, 40100, 40090, 40080, 40070, 40200, 40190, 40180, 40170, 40300, 40290, 40280, 40270, 39000, 38990, 38980, 38970, 39100, 39090, 39080, 39070, 39200, 39190, 39180, 39170, 39300, 39290, 39280, 39270} ;
+    MPI_Offset dr44_startset[3] = {0, 0, 0} ;
+    MPI_Offset dr44_countset[3] = {2, 4, 4} ;
+    err=ncmpi_put_vara(ncid, dr44_id, dr44_startset, dr44_countset, dr44_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c111_data[1] = "@" ;
+    MPI_Offset c111_startset[3] = {0, 0, 0} ;
+    MPI_Offset c111_countset[3] = {1, 1, 1} ;
+    err=ncmpi_put_vara(ncid, c111_id, c111_startset, c111_countset, c111_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b112_data[2] = {64, 62} ;
+    MPI_Offset b112_startset[3] = {0, 0, 0} ;
+    MPI_Offset b112_countset[3] = {1, 1, 2} ;
+    err=ncmpi_put_vara(ncid, b112_id, b112_startset, b112_countset, b112_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s113_data[3] = {2500, 2495, 2490} ;
+    MPI_Offset s113_startset[3] = {0, 0, 0} ;
+    MPI_Offset s113_countset[3] = {1, 1, 3} ;
+    err=ncmpi_put_vara(ncid, s113_id, s113_startset, s113_countset, s113_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i114_data[4] = {640000, 639980, 639960, 639940} ;
+    MPI_Offset i114_startset[3] = {0, 0, 0} ;
+    MPI_Offset i114_countset[3] = {1, 1, 4} ;
+    err=ncmpi_put_vara(ncid, i114_id, i114_startset, i114_countset, i114_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f121_data[2] = {26244, 26325} ;
+    MPI_Offset f121_startset[3] = {0, 0, 0} ;
+    MPI_Offset f121_countset[3] = {1, 2, 1} ;
+    err=ncmpi_put_vara(ncid, f121_id, f121_startset, f121_countset, f121_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d122_data[4] = {40000, 39990, 40100, 40090} ;
+    MPI_Offset d122_startset[3] = {0, 0, 0} ;
+    MPI_Offset d122_countset[3] = {1, 2, 2} ;
+    err=ncmpi_put_vara(ncid, d122_id, d122_startset, d122_countset, d122_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c123_data[6] = "@BDDFH" ;
+    MPI_Offset c123_startset[3] = {0, 0, 0} ;
+    MPI_Offset c123_countset[3] = {1, 2, 3} ;
+    err=ncmpi_put_vara(ncid, c123_id, c123_startset, c123_countset, c123_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b124_data[8] = {64, 62, 60, 58, 68, 66, 64, 62} ;
+    MPI_Offset b124_startset[3] = {0, 0, 0} ;
+    MPI_Offset b124_countset[3] = {1, 2, 4} ;
+    err=ncmpi_put_vara(ncid, b124_id, b124_startset, b124_countset, b124_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s131_data[3] = {2500, 2525, 2550} ;
+    MPI_Offset s131_startset[3] = {0, 0, 0} ;
+    MPI_Offset s131_countset[3] = {1, 3, 1} ;
+    err=ncmpi_put_vara(ncid, s131_id, s131_startset, s131_countset, s131_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i132_data[6] = {640000, 639980, 640400, 640380, 640800, 640780} ;
+    MPI_Offset i132_startset[3] = {0, 0, 0} ;
+    MPI_Offset i132_countset[3] = {1, 3, 2} ;
+    err=ncmpi_put_vara(ncid, i132_id, i132_startset, i132_countset, i132_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f133_data[9] = {26244, 26235, 26226, 26325, 26316, 26307, 26406, 26397, 26388} ;
+    MPI_Offset f133_startset[3] = {0, 0, 0} ;
+    MPI_Offset f133_countset[3] = {1, 3, 3} ;
+    err=ncmpi_put_vara(ncid, f133_id, f133_startset, f133_countset, f133_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d134_data[12] = {40000, 39990, 39980, 39970, 40100, 40090, 40080, 40070, 40200, 40190, 40180, 40170} ;
+    MPI_Offset d134_startset[3] = {0, 0, 0} ;
+    MPI_Offset d134_countset[3] = {1, 3, 4} ;
+    err=ncmpi_put_vara(ncid, d134_id, d134_startset, d134_countset, d134_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c141_data[4] = "@DHL" ;
+    MPI_Offset c141_startset[3] = {0, 0, 0} ;
+    MPI_Offset c141_countset[3] = {1, 4, 1} ;
+    err=ncmpi_put_vara(ncid, c141_id, c141_startset, c141_countset, c141_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b142_data[8] = {64, 62, 68, 66, 72, 70, 76, 74} ;
+    MPI_Offset b142_startset[3] = {0, 0, 0} ;
+    MPI_Offset b142_countset[3] = {1, 4, 2} ;
+    err=ncmpi_put_vara(ncid, b142_id, b142_startset, b142_countset, b142_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s143_data[12] = {2500, 2495, 2490, 2525, 2520, 2515, 2550, 2545, 2540, 2575, 2570, 2565} ;
+    MPI_Offset s143_startset[3] = {0, 0, 0} ;
+    MPI_Offset s143_countset[3] = {1, 4, 3} ;
+    err=ncmpi_put_vara(ncid, s143_id, s143_startset, s143_countset, s143_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i144_data[16] = {640000, 639980, 639960, 639940, 640400, 640380, 640360, 640340, 640800, 640780, 640760, 640740, 641200, 641180, 641160, 641140} ;
+    MPI_Offset i144_startset[3] = {0, 0, 0} ;
+    MPI_Offset i144_countset[3] = {1, 4, 4} ;
+    err=ncmpi_put_vara(ncid, i144_id, i144_startset, i144_countset, i144_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f211_data[2] = {26244, 25515} ;
+    MPI_Offset f211_startset[3] = {0, 0, 0} ;
+    MPI_Offset f211_countset[3] = {2, 1, 1} ;
+    err=ncmpi_put_vara(ncid, f211_id, f211_startset, f211_countset, f211_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d212_data[4] = {40000, 39990, 39000, 38990} ;
+    MPI_Offset d212_startset[3] = {0, 0, 0} ;
+    MPI_Offset d212_countset[3] = {2, 1, 2} ;
+    err=ncmpi_put_vara(ncid, d212_id, d212_startset, d212_countset, d212_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c213_data[6] = "@BDHJL" ;
+    MPI_Offset c213_startset[3] = {0, 0, 0} ;
+    MPI_Offset c213_countset[3] = {2, 1, 3} ;
+    err=ncmpi_put_vara(ncid, c213_id, c213_startset, c213_countset, c213_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b214_data[8] = {64, 62, 60, 58, 56, 54, 52, 50} ;
+    MPI_Offset b214_startset[3] = {0, 0, 0} ;
+    MPI_Offset b214_countset[3] = {2, 1, 4} ;
+    err=ncmpi_put_vara(ncid, b214_id, b214_startset, b214_countset, b214_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s221_data[4] = {2500, 2525, 2375, 2400} ;
+    MPI_Offset s221_startset[3] = {0, 0, 0} ;
+    MPI_Offset s221_countset[3] = {2, 2, 1} ;
+    err=ncmpi_put_vara(ncid, s221_id, s221_startset, s221_countset, s221_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i222_data[8] = {640000, 639980, 640400, 640380, 632000, 631980, 632400, 632380} ;
+    MPI_Offset i222_startset[3] = {0, 0, 0} ;
+    MPI_Offset i222_countset[3] = {2, 2, 2} ;
+    err=ncmpi_put_vara(ncid, i222_id, i222_startset, i222_countset, i222_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f223_data[12] = {26244, 26235, 26226, 26325, 26316, 26307, 25515, 25506, 25497, 25596, 25587, 25578} ;
+    MPI_Offset f223_startset[3] = {0, 0, 0} ;
+    MPI_Offset f223_countset[3] = {2, 2, 3} ;
+    err=ncmpi_put_vara(ncid, f223_id, f223_startset, f223_countset, f223_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d224_data[16] = {40000, 39990, 39980, 39970, 40100, 40090, 40080, 40070, 39000, 38990, 38980, 38970, 39100, 39090, 39080, 39070} ;
+    MPI_Offset d224_startset[3] = {0, 0, 0} ;
+    MPI_Offset d224_countset[3] = {2, 2, 4} ;
+    err=ncmpi_put_vara(ncid, d224_id, d224_startset, d224_countset, d224_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c231_data[6] = "@DHHLP" ;
+    MPI_Offset c231_startset[3] = {0, 0, 0} ;
+    MPI_Offset c231_countset[3] = {2, 3, 1} ;
+    err=ncmpi_put_vara(ncid, c231_id, c231_startset, c231_countset, c231_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b232_data[12] = {64, 62, 68, 66, 72, 70, 56, 54, 60, 58, 64, 62} ;
+    MPI_Offset b232_startset[3] = {0, 0, 0} ;
+    MPI_Offset b232_countset[3] = {2, 3, 2} ;
+    err=ncmpi_put_vara(ncid, b232_id, b232_startset, b232_countset, b232_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s233_data[18] = {2500, 2495, 2490, 2525, 2520, 2515, 2550, 2545, 2540, 2375, 2370, 2365, 2400, 2395, 2390, 2425, 2420, 2415} ;
+    MPI_Offset s233_startset[3] = {0, 0, 0} ;
+    MPI_Offset s233_countset[3] = {2, 3, 3} ;
+    err=ncmpi_put_vara(ncid, s233_id, s233_startset, s233_countset, s233_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i234_data[24] = {640000, 639980, 639960, 639940, 640400, 640380, 640360, 640340, 640800, 640780, 640760, 640740, 632000, 631980, 631960, 631940, 632400, 632380, 632360, 632340, 632800, 632780, 632760, 632740} ;
+    MPI_Offset i234_startset[3] = {0, 0, 0} ;
+    MPI_Offset i234_countset[3] = {2, 3, 4} ;
+    err=ncmpi_put_vara(ncid, i234_id, i234_startset, i234_countset, i234_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f241_data[8] = {26244, 26325, 26406, 26487, 25515, 25596, 25677, 25758} ;
+    MPI_Offset f241_startset[3] = {0, 0, 0} ;
+    MPI_Offset f241_countset[3] = {2, 4, 1} ;
+    err=ncmpi_put_vara(ncid, f241_id, f241_startset, f241_countset, f241_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d242_data[16] = {40000, 39990, 40100, 40090, 40200, 40190, 40300, 40290, 39000, 38990, 39100, 39090, 39200, 39190, 39300, 39290} ;
+    MPI_Offset d242_startset[3] = {0, 0, 0} ;
+    MPI_Offset d242_countset[3] = {2, 4, 2} ;
+    err=ncmpi_put_vara(ncid, d242_id, d242_startset, d242_countset, d242_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c243_data[24] = "@BDDFHHJLLNPHJLLNPPRTTVX" ;
+    MPI_Offset c243_startset[3] = {0, 0, 0} ;
+    MPI_Offset c243_countset[3] = {2, 4, 3} ;
+    err=ncmpi_put_vara(ncid, c243_id, c243_startset, c243_countset, c243_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b244_data[32] = {64, 62, 60, 58, 68, 66, 64, 62, 72, 70, 68, 66, 76, 74, 72, 70, 56, 54, 52, 50, 60, 58, 56, 54, 64, 62, 60, 58, 68, 66, 64, 62} ;
+    MPI_Offset b244_startset[3] = {0, 0, 0} ;
+    MPI_Offset b244_countset[3] = {2, 4, 4} ;
+    err=ncmpi_put_vara(ncid, b244_id, b244_startset, b244_countset, b244_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s311_data[3] = {2500, 2375, 2250} ;
+    MPI_Offset s311_startset[3] = {0, 0, 0} ;
+    MPI_Offset s311_countset[3] = {3, 1, 1} ;
+    err=ncmpi_put_vara(ncid, s311_id, s311_startset, s311_countset, s311_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i312_data[6] = {640000, 639980, 632000, 631980, 624000, 623980} ;
+    MPI_Offset i312_startset[3] = {0, 0, 0} ;
+    MPI_Offset i312_countset[3] = {3, 1, 2} ;
+    err=ncmpi_put_vara(ncid, i312_id, i312_startset, i312_countset, i312_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f313_data[9] = {26244, 26235, 26226, 25515, 25506, 25497, 24786, 24777, 24768} ;
+    MPI_Offset f313_startset[3] = {0, 0, 0} ;
+    MPI_Offset f313_countset[3] = {3, 1, 3} ;
+    err=ncmpi_put_vara(ncid, f313_id, f313_startset, f313_countset, f313_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d314_data[12] = {40000, 39990, 39980, 39970, 39000, 38990, 38980, 38970, 38000, 37990, 37980, 37970} ;
+    MPI_Offset d314_startset[3] = {0, 0, 0} ;
+    MPI_Offset d314_countset[3] = {3, 1, 4} ;
+    err=ncmpi_put_vara(ncid, d314_id, d314_startset, d314_countset, d314_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c321_data[6] = "@DHLPT" ;
+    MPI_Offset c321_startset[3] = {0, 0, 0} ;
+    MPI_Offset c321_countset[3] = {3, 2, 1} ;
+    err=ncmpi_put_vara(ncid, c321_id, c321_startset, c321_countset, c321_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b322_data[12] = {64, 62, 68, 66, 56, 54, 60, 58, 48, 46, 52, 50} ;
+    MPI_Offset b322_startset[3] = {0, 0, 0} ;
+    MPI_Offset b322_countset[3] = {3, 2, 2} ;
+    err=ncmpi_put_vara(ncid, b322_id, b322_startset, b322_countset, b322_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s323_data[18] = {2500, 2495, 2490, 2525, 2520, 2515, 2375, 2370, 2365, 2400, 2395, 2390, 2250, 2245, 2240, 2275, 2270, 2265} ;
+    MPI_Offset s323_startset[3] = {0, 0, 0} ;
+    MPI_Offset s323_countset[3] = {3, 2, 3} ;
+    err=ncmpi_put_vara(ncid, s323_id, s323_startset, s323_countset, s323_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i324_data[24] = {640000, 639980, 639960, 639940, 640400, 640380, 640360, 640340, 632000, 631980, 631960, 631940, 632400, 632380, 632360, 632340, 624000, 623980, 623960, 623940, 624400, 624380, 624360, 624340} ;
+    MPI_Offset i324_startset[3] = {0, 0, 0} ;
+    MPI_Offset i324_countset[3] = {3, 2, 4} ;
+    err=ncmpi_put_vara(ncid, i324_id, i324_startset, i324_countset, i324_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f331_data[9] = {26244, 26325, 26406, 25515, 25596, 25677, 24786, 24867, 24948} ;
+    MPI_Offset f331_startset[3] = {0, 0, 0} ;
+    MPI_Offset f331_countset[3] = {3, 3, 1} ;
+    err=ncmpi_put_vara(ncid, f331_id, f331_startset, f331_countset, f331_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d332_data[18] = {40000, 39990, 40100, 40090, 40200, 40190, 39000, 38990, 39100, 39090, 39200, 39190, 38000, 37990, 38100, 38090, 38200, 38190} ;
+    MPI_Offset d332_startset[3] = {0, 0, 0} ;
+    MPI_Offset d332_countset[3] = {3, 3, 2} ;
+    err=ncmpi_put_vara(ncid, d332_id, d332_startset, d332_countset, d332_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c333_data[27] = "@BDDFHHJLHJLLNPPRTPRTTVXXZ\\" ;
+    MPI_Offset c333_startset[3] = {0, 0, 0} ;
+    MPI_Offset c333_countset[3] = {3, 3, 3} ;
+    err=ncmpi_put_vara(ncid, c333_id, c333_startset, c333_countset, c333_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b334_data[36] = {64, 62, 60, 58, 68, 66, 64, 62, 72, 70, 68, 66, 56, 54, 52, 50, 60, 58, 56, 54, 64, 62, 60, 58, 48, 46, 44, 42, 52, 50, 48, 46, 56, 54, 52, 50} ;
+    MPI_Offset b334_startset[3] = {0, 0, 0} ;
+    MPI_Offset b334_countset[3] = {3, 3, 4} ;
+    err=ncmpi_put_vara(ncid, b334_id, b334_startset, b334_countset, b334_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s341_data[12] = {2500, 2525, 2550, 2575, 2375, 2400, 2425, 2450, 2250, 2275, 2300, 2325} ;
+    MPI_Offset s341_startset[3] = {0, 0, 0} ;
+    MPI_Offset s341_countset[3] = {3, 4, 1} ;
+    err=ncmpi_put_vara(ncid, s341_id, s341_startset, s341_countset, s341_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i342_data[24] = {640000, 639980, 640400, 640380, 640800, 640780, 641200, 641180, 632000, 631980, 632400, 632380, 632800, 632780, 633200, 633180, 624000, 623980, 624400, 624380, 624800, 624780, 625200, 625180} ;
+    MPI_Offset i342_startset[3] = {0, 0, 0} ;
+    MPI_Offset i342_countset[3] = {3, 4, 2} ;
+    err=ncmpi_put_vara(ncid, i342_id, i342_startset, i342_countset, i342_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f343_data[36] = {26244, 26235, 26226, 26325, 26316, 26307, 26406, 26397, 26388, 26487, 26478, 26469, 25515, 25506, 25497, 25596, 25587, 25578, 25677, 25668, 25659, 25758, 25749, 25740, 24786, 24777, 24768, 24867, 24858, 24849, 24948, 24939, 24930, 25029, 25020, 25011} ;
+    MPI_Offset f343_startset[3] = {0, 0, 0} ;
+    MPI_Offset f343_countset[3] = {3, 4, 3} ;
+    err=ncmpi_put_vara(ncid, f343_id, f343_startset, f343_countset, f343_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d344_data[48] = {40000, 39990, 39980, 39970, 40100, 40090, 40080, 40070, 40200, 40190, 40180, 40170, 40300, 40290, 40280, 40270, 39000, 38990, 38980, 38970, 39100, 39090, 39080, 39070, 39200, 39190, 39180, 39170, 39300, 39290, 39280, 39270, 38000, 37990, 37980, 37970, 38100, 38090, 38080, 38070, 38200, 38190, 38180, 38170, 38300, 38290, 38280, 38270} ;
+    MPI_Offset d344_startset[3] = {0, 0, 0} ;
+    MPI_Offset d344_countset[3] = {3, 4, 4} ;
+    err=ncmpi_put_vara(ncid, d344_id, d344_startset, d344_countset, d344_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c411_data[4] = "@HPX" ;
+    MPI_Offset c411_startset[3] = {0, 0, 0} ;
+    MPI_Offset c411_countset[3] = {4, 1, 1} ;
+    err=ncmpi_put_vara(ncid, c411_id, c411_startset, c411_countset, c411_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b412_data[8] = {64, 62, 56, 54, 48, 46, 40, 38} ;
+    MPI_Offset b412_startset[3] = {0, 0, 0} ;
+    MPI_Offset b412_countset[3] = {4, 1, 2} ;
+    err=ncmpi_put_vara(ncid, b412_id, b412_startset, b412_countset, b412_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s413_data[12] = {2500, 2495, 2490, 2375, 2370, 2365, 2250, 2245, 2240, 2125, 2120, 2115} ;
+    MPI_Offset s413_startset[3] = {0, 0, 0} ;
+    MPI_Offset s413_countset[3] = {4, 1, 3} ;
+    err=ncmpi_put_vara(ncid, s413_id, s413_startset, s413_countset, s413_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i414_data[16] = {640000, 639980, 639960, 639940, 632000, 631980, 631960, 631940, 624000, 623980, 623960, 623940, 616000, 615980, 615960, 615940} ;
+    MPI_Offset i414_startset[3] = {0, 0, 0} ;
+    MPI_Offset i414_countset[3] = {4, 1, 4} ;
+    err=ncmpi_put_vara(ncid, i414_id, i414_startset, i414_countset, i414_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f421_data[8] = {26244, 26325, 25515, 25596, 24786, 24867, 24057, 24138} ;
+    MPI_Offset f421_startset[3] = {0, 0, 0} ;
+    MPI_Offset f421_countset[3] = {4, 2, 1} ;
+    err=ncmpi_put_vara(ncid, f421_id, f421_startset, f421_countset, f421_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d422_data[16] = {40000, 39990, 40100, 40090, 39000, 38990, 39100, 39090, 38000, 37990, 38100, 38090, 37000, 36990, 37100, 37090} ;
+    MPI_Offset d422_startset[3] = {0, 0, 0} ;
+    MPI_Offset d422_countset[3] = {4, 2, 2} ;
+    err=ncmpi_put_vara(ncid, d422_id, d422_startset, d422_countset, d422_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c423_data[24] = "@BDDFHHJLLNPPRTTVXXZ\\\\^`" ;
+    MPI_Offset c423_startset[3] = {0, 0, 0} ;
+    MPI_Offset c423_countset[3] = {4, 2, 3} ;
+    err=ncmpi_put_vara(ncid, c423_id, c423_startset, c423_countset, c423_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b424_data[32] = {64, 62, 60, 58, 68, 66, 64, 62, 56, 54, 52, 50, 60, 58, 56, 54, 48, 46, 44, 42, 52, 50, 48, 46, 40, 38, 36, 34, 44, 42, 40, 38} ;
+    MPI_Offset b424_startset[3] = {0, 0, 0} ;
+    MPI_Offset b424_countset[3] = {4, 2, 4} ;
+    err=ncmpi_put_vara(ncid, b424_id, b424_startset, b424_countset, b424_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s431_data[12] = {2500, 2525, 2550, 2375, 2400, 2425, 2250, 2275, 2300, 2125, 2150, 2175} ;
+    MPI_Offset s431_startset[3] = {0, 0, 0} ;
+    MPI_Offset s431_countset[3] = {4, 3, 1} ;
+    err=ncmpi_put_vara(ncid, s431_id, s431_startset, s431_countset, s431_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i432_data[24] = {640000, 639980, 640400, 640380, 640800, 640780, 632000, 631980, 632400, 632380, 632800, 632780, 624000, 623980, 624400, 624380, 624800, 624780, 616000, 615980, 616400, 616380, 616800, 616780} ;
+    MPI_Offset i432_startset[3] = {0, 0, 0} ;
+    MPI_Offset i432_countset[3] = {4, 3, 2} ;
+    err=ncmpi_put_vara(ncid, i432_id, i432_startset, i432_countset, i432_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    float f433_data[36] = {26244, 26235, 26226, 26325, 26316, 26307, 26406, 26397, 26388, 25515, 25506, 25497, 25596, 25587, 25578, 25677, 25668, 25659, 24786, 24777, 24768, 24867, 24858, 24849, 24948, 24939, 24930, 24057, 24048, 24039, 24138, 24129, 24120, 24219, 24210, 24201} ;
+    MPI_Offset f433_startset[3] = {0, 0, 0} ;
+    MPI_Offset f433_countset[3] = {4, 3, 3} ;
+    err=ncmpi_put_vara(ncid, f433_id, f433_startset, f433_countset, f433_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    double d434_data[48] = {40000, 39990, 39980, 39970, 40100, 40090, 40080, 40070, 40200, 40190, 40180, 40170, 39000, 38990, 38980, 38970, 39100, 39090, 39080, 39070, 39200, 39190, 39180, 39170, 38000, 37990, 37980, 37970, 38100, 38090, 38080, 38070, 38200, 38190, 38180, 38170, 37000, 36990, 36980, 36970, 37100, 37090, 37080, 37070, 37200, 37190, 37180, 37170} ;
+    MPI_Offset d434_startset[3] = {0, 0, 0} ;
+    MPI_Offset d434_countset[3] = {4, 3, 4} ;
+    err=ncmpi_put_vara(ncid, d434_id, d434_startset, d434_countset, d434_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    char c441_data[16] = "@DHLHLPTPTX\\X\\`d" ;
+    MPI_Offset c441_startset[3] = {0, 0, 0} ;
+    MPI_Offset c441_countset[3] = {4, 4, 1} ;
+    err=ncmpi_put_vara(ncid, c441_id, c441_startset, c441_countset, c441_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    signed char b442_data[32] = {64, 62, 68, 66, 72, 70, 76, 74, 56, 54, 60, 58, 64, 62, 68, 66, 48, 46, 52, 50, 56, 54, 60, 58, 40, 38, 44, 42, 48, 46, 52, 50} ;
+    MPI_Offset b442_startset[3] = {0, 0, 0} ;
+    MPI_Offset b442_countset[3] = {4, 4, 2} ;
+    err=ncmpi_put_vara(ncid, b442_id, b442_startset, b442_countset, b442_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    short s443_data[48] = {2500, 2495, 2490, 2525, 2520, 2515, 2550, 2545, 2540, 2575, 2570, 2565, 2375, 2370, 2365, 2400, 2395, 2390, 2425, 2420, 2415, 2450, 2445, 2440, 2250, 2245, 2240, 2275, 2270, 2265, 2300, 2295, 2290, 2325, 2320, 2315, 2125, 2120, 2115, 2150, 2145, 2140, 2175, 2170, 2165, 2200, 2195, 2190} ;
+    MPI_Offset s443_startset[3] = {0, 0, 0} ;
+    MPI_Offset s443_countset[3] = {4, 4, 3} ;
+    err=ncmpi_put_vara(ncid, s443_id, s443_startset, s443_countset, s443_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+    {
+    int i444_data[64] = {640000, 639980, 639960, 639940, 640400, 640380, 640360, 640340, 640800, 640780, 640760, 640740, 641200, 641180, 641160, 641140, 632000, 631980, 631960, 631940, 632400, 632380, 632360, 632340, 632800, 632780, 632760, 632740, 633200, 633180, 633160, 633140, 624000, 623980, 623960, 623940, 624400, 624380, 624360, 624340, 624800, 624780, 624760, 624740, 625200, 625180, 625160, 625140, 616000, 615980, 615960, 615940, 616400, 616380, 616360, 616340, 616800, 616780, 616 [...]
+    MPI_Offset i444_startset[3] = {0, 0, 0} ;
+    MPI_Offset i444_countset[3] = {4, 4, 4} ;
+    err=ncmpi_put_vara(ncid, i444_id, i444_startset, i444_countset, i444_data, 0,MPI_DATATYPE_NULL); ERR
+    }
+
+
+    err=ncmpi_close(ncid); ERR
+    return 0;
+
+}
+
+static int
+tst_atts(char *filename, int cmode)
+{
+   int err;
+
+   if (verbose) printf("\n*** Testing netCDF attributes.\n");
+   if (verbose) printf("*** testing attribute renaming for memory leak, like ncmpi_test...");
+   {
+#define A1_NAME "a"
+#define B1_NAME "b"
+#define VAR_NAME "var"
+      
+      int ncid, nvars, v, natts, varid;
+      char name_in[NC_MAX_NAME + 1];
+      char char_data = 'a';
+
+      /* Create a file with a var with two atts. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_def_var(ncid, VAR_NAME, NC_INT, 0, NULL, &varid); ERR
+      err=ncmpi_put_att(ncid, varid, A1_NAME, NC_CHAR, 1, &char_data); ERR
+      err=ncmpi_put_att(ncid, varid, B1_NAME, NC_CHAR, 1, &char_data); ERR
+      
+      /* Add a global attribute A1_NAME. */
+      err=ncmpi_put_att(ncid, NC_GLOBAL, A1_NAME, NC_CHAR, 1, &char_data); ERR
+
+      /* Change the name of the first att of each variable to
+       * A1_NAME. Then copy the global att called A1_NAME, overwriting
+       * the one we just changed. */
+      err=ncmpi_inq_nvars(ncid, &nvars); ERR
+      if (nvars != 1) ERRV
+      err=ncmpi_inq_varnatts(ncid, 0, &natts); ERR
+      if (natts != 2) ERRV
+      err=ncmpi_copy_att(ncid, NC_GLOBAL, A1_NAME, ncid, 0); ERR
+
+      /* Also test for fix of another bug, allowing invalid _FillValue
+       * attribute (not of same type as variable or with 0 values or more
+       * than 1 value) to be created. */
+      {
+	  static const int var_FillValue_atts[] = {42, -99} ;
+	  float var_FillValue_att = -99 ;
+	  /* This should return error, because attribute has too many values */
+	  if ((err=ncmpi_put_att_int(ncid, varid, "_FillValue", NC_INT, 2, var_FillValue_atts)) != NC_EINVAL) ERR
+	  /* This also should return error, because types don't match */
+	  if ((err=ncmpi_put_att_float(ncid, varid, "_FillValue", NC_FLOAT, 1, &var_FillValue_att)) != NC_EBADTYPE) ERR
+	  /* This should succeed, _FillValue is valid */
+	  err=ncmpi_put_att_int(ncid, varid, "_FillValue", NC_INT, 1, var_FillValue_atts); ERR
+      }
+
+      err=ncmpi_close(ncid); ERR
+
+      /* Reopen the file and check it. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_inq_nvars(ncid, &nvars); ERR
+      if (nvars != 1) ERRV
+      for (v = 0; v < nvars; v++)
+      {
+      	 err=ncmpi_inq_varnatts(ncid, v, &natts); ERR
+      	 if (natts)
+      	 {
+      	    err=ncmpi_inq_attname(ncid, v, 0, name_in); ERR
+      	    if (strcmp(name_in, A1_NAME)) ERRV
+      	 }
+      }
+      err=ncmpi_close(ncid); ERR
+
+   }
+   if (verbose) printf("ok\n");
+   if (verbose) printf("*** testing attribute renaming for memory leak, like ncmpi_test...");
+   {
+#define NVARS 136
+#define A_NAME "a"
+      int ncid, nvars, v, natts;
+      char name_in[NC_MAX_NAME + 1];
+      char char_data = 'a';
+
+      /* Create the same file as ncmpi_test uses (almost). */
+      if (create_file(filename, cmode)) ERRV
+
+      /* Open the file. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_redef(ncid); ERR
+
+      /* Add a global attribute A_NAME. */
+      err=ncmpi_put_att(ncid, NC_GLOBAL, A_NAME, NC_CHAR, 1, &char_data); ERR
+
+      /* Change the name of the first att of each variable to
+       * A_NAME. Then copy the global att called A_NAME, overwriting
+       * the one we just changed. */
+      err=ncmpi_inq_nvars(ncid, &nvars); ERR
+      if (nvars != NVARS) ERRV
+      for (v = 0; v < nvars; v++)
+      {
+	 err=ncmpi_inq_varnatts(ncid, v, &natts); ERR
+	 if (natts)
+	 {
+	    err=ncmpi_inq_attname(ncid, v, 0, name_in); ERR
+	    err=ncmpi_rename_att(ncid, v, name_in, A_NAME); ERR
+	    err=ncmpi_copy_att(ncid, NC_GLOBAL, A_NAME, ncid, v); ERR
+	 }
+      }
+      err=ncmpi_close(ncid); ERR
+
+      /* Reopen the file and check it. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_inq_nvars(ncid, &nvars); ERR
+      if (nvars != NVARS) ERRV
+      for (v = 0; v < nvars; v++)
+      {
+	 err=ncmpi_inq_varnatts(ncid, v, &natts); ERR
+	 if (natts)
+	 {
+	    err=ncmpi_inq_attname(ncid, v, 0, name_in); ERR
+	    if (strcmp(name_in, A_NAME)) ERRV
+	 }
+      }
+      err=ncmpi_close(ncid); ERR
+
+   }
+   if (verbose) printf("ok\n");
+   return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    char filename[256];
+    int cmode, rank, nprocs, err, nerrs=0;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    char cmd_str[256];
+    sprintf(cmd_str, "*** TESTING C   %s for emulating netCDF tst_atts ", argv[0]);
+    if (rank == 0) printf("%-66s ------ ", cmd_str);
+
+    verbose = 0;
+
+    cmode = NC_CLOBBER;
+    nerrs += tst_atts(filename, cmode);
+
+    cmode = NC_CLOBBER | NC_64BIT_OFFSET;
+    nerrs += tst_atts(filename, cmode);
+
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    nerrs += tst_atts(filename, cmode);
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/nc_test/tst_atts3.c b/test/nc_test/tst_atts3.c
new file mode 100644
index 0000000..1bf2ddc
--- /dev/null
+++ b/test/nc_test/tst_atts3.c
@@ -0,0 +1,804 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: tst_atts3.c 2219 2015-12-11 22:30:03Z wkliao $ */
+
+/* This program is based on the test program tst_atts3.c of the netCDF package */
+
+/* This is part of the netCDF package. Copyright 2005-2007 University
+   Corporation for Atmospheric Research/Unidata. See COPYRIGHT file
+   for conditions of use.
+
+   Test attributes. 
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pnetcdf.h>
+#include <signal.h>
+
+#include <testutils.h>
+
+#define ERR {if (err != NC_NOERR) {printf("Error at %s line %d: %s\n",__func__,__LINE__,ncmpi_strerror(err)); nerrs++;}}
+#define ERRV {printf("Unexpected result at %s line %d\n",__func__,__LINE__); nerrs++;}
+static int verbose;
+
+#define VAR1_NAME "Horace_Rumpole"
+#define VAR2_NAME "Claude_Erskine-Brown"
+#define VAR3_NAME "Phillida_Erskine-Brown_Q.C."
+#define DIM1_NAME "Old_Bailey_case_number"
+#define DIM1_LEN 10
+#define DIM2_NAME "occupancy_in_chambers"
+#define DIM2_LEN 15
+#define ATT_INT_NAME "Old_Bailey_Room_Numbers"
+#define ATT_DOUBLE_NAME "Equity_Court_Canteen_Charges"
+#define ATT_SHORT_NAME "Ecclesiastical_Court_Appearences"
+#define ATT_TEXT_NAME "Speech_to_Jury"
+#define ATT_TEXT_NAME2 "Speech_to_She_Who_Must_be_Obeyed"
+#define ATT_UCHAR_NAME "Number_of_current_briefs"
+#define ATT_SCHAR_NAME "Slate_totals_at_Pomeroys_Wine_Bar"
+#define ATT_USHORT_NAME "brief_no"
+#define ATT_UINT_NAME "Orders_from_SWMBO"
+#define ATT_INT64_NAME "judges_golf_score"
+#define ATT_UINT64_NAME "Number_of_drinks_in_career_to_date"
+
+/*
+#define ATT_USHORT_NAME "Chamber_Gas_Electric_and_Telephone_Bill_Share"
+*/
+#define ATT_FLOAT_NAME "Average_Nanoseconds_for_Lose_Win_or_Appeal"
+#define ATT_LEN 3
+
+char speech[] = "Once more unto the breach, dear friends, once more;\n\
+Or close the wall up with our English dead.\n\
+In peace there's nothing so becomes a man\n\
+As modest stillness and humility:\n\
+But when the blast of war blows in our ears,\n\
+Then imitate the action of the tiger;\n\
+Stiffen the sinews, summon up the blood,\n\
+Disguise fair nature with hard-favour'd rage;\n\
+Then lend the eye a terrible aspect;\n\
+Let pry through the portage of the head\n\
+Like the brass cannon; let the brow o'erwhelm it\n\
+As fearfully as doth a galled rock\n\
+O'erhang and jutty his confounded base,\n\
+Swill'd with the wild and wasteful ocean.\n\
+Now set the teeth and stretch the nostril wide,\n\
+Hold hard the breath and bend up every spirit\n\
+To his full height. On, on, you noblest English.\n\
+Whose blood is fet from fathers of war-proof!\n\
+Fathers that, like so many Alexanders,\n\
+Have in these parts from morn till even fought\n\
+And sheathed their swords for lack of argument:\n\
+Dishonour not your mothers; now attest\n\
+That those whom you call'd fathers did beget you.\n\
+Be copy now to men of grosser blood,\n\
+And teach them how to war. And you, good yeoman,\n\
+Whose limbs were made in England, show us here\n\
+The mettle of your pasture; let us swear\n\
+That you are worth your breeding; which I doubt not;\n\
+For there is none of you so mean and base,\n\
+That hath not noble lustre in your eyes.\n\
+I see you stand like greyhounds in the slips,\n\
+Straining upon the start. The game's afoot:\n\
+Follow your spirit, and upon this charge\n\
+Cry 'God for Harry, England, and Saint George!'";
+
+/* Test the ordering of atts for a cmode. */
+#define NUM_ATTS 8
+#define ATT_MAX_NAME 25
+static int
+tst_att_ordering(char *filename, int cmode)
+{
+   int ncid, err, nerrs=0;
+   char name[NUM_ATTS][ATT_MAX_NAME + 1] = {"Gc", "Gb", "Gs", "Gi", "Gf", 
+					    "Gd", "Gatt-name-dashes", "Gatt.name.dots"};
+   int len[NUM_ATTS] = {0, 2, 3, 3, 3, 3, 1, 1};
+   signed char b[2] = {-128, 127};
+   short s[3] = {-32768, 0, 32767};
+   int i[3] = {42, 0, -42};
+   float f[3] = {42.0, -42.0, 42.0};
+   double d[3] = {420.0, -420.0, 420.0};
+   int att_name_dashes = -1, att_name_dots = -2;
+   char name_in[NC_MAX_NAME];
+   int j;
+
+   /* Create a file with some global atts. */
+   err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+   err=ncmpi_put_att_text(ncid, NC_GLOBAL, name[0], len[0], NULL); ERR
+   err=ncmpi_put_att_schar(ncid, NC_GLOBAL, name[1], NC_BYTE, len[1], b); ERR
+   err=ncmpi_put_att_short(ncid, NC_GLOBAL, name[2], NC_SHORT, len[2], s); ERR
+   err=ncmpi_put_att_int(ncid, NC_GLOBAL, name[3], NC_INT, len[3], i); ERR
+   err=ncmpi_put_att_float(ncid, NC_GLOBAL, name[4], NC_FLOAT, len[4], f); ERR
+   err=ncmpi_put_att_double(ncid, NC_GLOBAL, name[5], NC_DOUBLE, len[5], d); ERR
+   err=ncmpi_put_att_int(ncid, NC_GLOBAL, name[6], NC_INT, len[6], &att_name_dashes); ERR
+   err=ncmpi_put_att_int(ncid, NC_GLOBAL, name[7], NC_INT, len[7], &att_name_dots); ERR
+   err=ncmpi_close(ncid); ERR
+      
+   /* Reopen the file and check the order. */
+   err=ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+   for (j = 0; j < NUM_ATTS; j++)
+   {
+      err=ncmpi_inq_attname(ncid, NC_GLOBAL, j, name_in); ERR
+      if (strcmp(name_in, name[j])) ERRV
+   }
+
+   /* Close up shop. */
+   err=ncmpi_close(ncid); ERR
+   return nerrs;
+}
+
+static int
+tst_atts3(char *filename, int cmode)
+{
+    char filename2[128];
+    int err, nerrs=0;
+    signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
+    unsigned char uchar_in[ATT_LEN];
+    short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
+    int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000};
+    float float_in[ATT_LEN], float_out[ATT_LEN] = {-0.5, 0.25, 0.125};
+    double double_in[ATT_LEN], double_out[ATT_LEN] = {-0.25, .5, 0.125};
+    long long longlong_in[ATT_LEN] = {-1LL, -1LL, -1LL};
+#ifdef USE_NETCDF4
+    long long_in[ATT_LEN];
+    unsigned short ushort_in[ATT_LEN], ushort_out[ATT_LEN] = {0, 128, NC_MAX_USHORT};
+    unsigned int uint_in[ATT_LEN], uint_out[ATT_LEN] = {0, 128, NC_MAX_UINT};
+    long long longlong_out[ATT_LEN] = {-3123456789LL, 128LL, 3123456789LL};
+    unsigned long long ulonglong_in[ATT_LEN] = {NC_MAX_UINT64, NC_MAX_UINT64, NC_MAX_UINT64};
+    unsigned long long ulonglong_out[ATT_LEN] = {0LL, 128LL, 3123456789LL};
+#endif
+
+    (void) signal(SIGFPE, SIG_IGN);
+
+   sprintf(filename2, "%s.2", filename);
+
+   if (verbose) printf("\n*** Testing netcdf-3 attribute functions.\n");
+   if (verbose) printf("*** testing really simple global atts...");
+#define NUM_SIMPLE_ATTS 9
+   {
+      int ncid;
+      char name[NUM_SIMPLE_ATTS][ATT_MAX_NAME + 1] = {"Gc", "Gb", "Gs", "Gi", "Gf", 
+						      "Gd", "G7", "G8", "G9"};
+      char name_in[NC_MAX_NAME];
+      int j;
+
+      /* Create a file with some global atts. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+      for (j = 0; j < NUM_SIMPLE_ATTS; j++)
+	 err=ncmpi_put_att_int(ncid, NC_GLOBAL, name[j], NC_INT, 0, NULL); ERR
+      err=ncmpi_close(ncid); ERR
+      
+      /* Reopen the file and check the order. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+      for (j = 0; j < NUM_SIMPLE_ATTS; j++)
+      {
+	 err=ncmpi_inq_attname(ncid, NC_GLOBAL, j, name_in); ERR
+	 if (strcmp(name_in, name[j])) ERRV
+      }
+
+      /* Close up shop. */
+      err=ncmpi_close(ncid); ERR
+   }
+   if (verbose) printf("ok\n");
+   if (verbose) printf("*** testing simple global atts...");
+   {
+      int ncid;
+      nc_type att_type;
+      MPI_Offset att_len;
+      int i;
+
+      char *speech_in;
+
+      /* This won't work, because classic files can't create these types. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+      err=ncmpi_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, ATT_LEN, int_out); ERR
+      /* It is also OK to read classic types converted into
+       * supported C types. though the conversion may encounter
+       * out-of-range values */
+      if ((err=ncmpi_get_att_uchar(ncid, NC_GLOBAL, ATT_INT_NAME, uchar_in)) != NC_ERANGE) ERR
+      for (i = 0; i < ATT_LEN; i++) {
+	if (i == 0 || i == 2) continue;
+	if (uchar_in[i] != (unsigned char) int_out[i]) ERRV
+      }
+
+      /* This was bug NCF-171: on 32-bit platforms, bad values returned */
+      err=ncmpi_get_att_longlong(ncid, NC_GLOBAL, ATT_INT_NAME, longlong_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+      	if (longlong_in[i] != (long long) int_out[i]) ERRV
+      err=ncmpi_close(ncid); ERR
+
+      /* Create a file with a global attribute of each type. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+      err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech); ERR
+      err=ncmpi_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, ATT_LEN, schar_out); ERR
+      err=ncmpi_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, ATT_LEN, short_out); ERR
+      err=ncmpi_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, ATT_LEN, int_out); ERR
+      err=ncmpi_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, ATT_LEN, float_out); ERR
+      err=ncmpi_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, ATT_LEN, double_out); ERR
+      err=ncmpi_close(ncid); ERR
+
+      /* Open the file and check attributes. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+      /* Check text. */
+      err=ncmpi_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, &att_type, &att_len); ERR
+      if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERRV
+      if (!(speech_in = malloc(att_len + 1))) ERRV
+      err=ncmpi_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, speech_in); ERR
+      if (strcmp(speech, speech_in)) ERRV
+      free(speech_in);
+      /* Check numeric values. */
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (schar_in[i] != schar_out[i]) ERRV
+      err=ncmpi_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (short_in[i] != short_out[i]) ERRV
+      err=ncmpi_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (int_in[i] != int_out[i]) ERRV
+      err=ncmpi_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (float_in[i] != float_out[i]) ERRV
+      err=ncmpi_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (double_in[i] != double_out[i]) ERRV
+      err=ncmpi_close(ncid); ERR
+   }
+   if (verbose) printf("ok\n");
+   if (verbose) printf("*** testing attribute data type conversions...");
+
+   {
+      int ncid;
+      int i;
+
+      /* Reopen the file and try different type conversions. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+      /* No text conversions are allowed, and people who try them should
+       * be locked up, away from decent folk! */
+      if ((err=ncmpi_get_att_short(ncid, NC_GLOBAL, ATT_TEXT_NAME, short_in)) != NC_ECHAR) ERR
+      if ((err=ncmpi_get_att_int(ncid, NC_GLOBAL, ATT_TEXT_NAME, int_in)) != NC_ECHAR) ERR
+      if ((err=ncmpi_get_att_float(ncid, NC_GLOBAL, ATT_TEXT_NAME, float_in)) != NC_ECHAR) ERR
+      if ((err=ncmpi_get_att_double(ncid, NC_GLOBAL, ATT_TEXT_NAME, double_in)) != NC_ECHAR) ERR
+
+      /* Read all atts (except text) as double. */
+      err=ncmpi_get_att_double(ncid, NC_GLOBAL, ATT_SCHAR_NAME, double_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (double_in[i] != schar_out[i]) ERRV
+      err=ncmpi_get_att_double(ncid, NC_GLOBAL, ATT_SHORT_NAME, double_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (double_in[i] != short_out[i]) ERRV
+      err=ncmpi_get_att_double(ncid, NC_GLOBAL, ATT_INT_NAME, double_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (double_in[i] != int_out[i]) ERRV
+      err=ncmpi_get_att_double(ncid, NC_GLOBAL, ATT_FLOAT_NAME, double_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (double_in[i] != float_out[i]) ERRV
+      err=ncmpi_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (double_in[i] != double_out[i]) ERRV
+
+      /* Read all atts (except text) as float. */
+      err=ncmpi_get_att_float(ncid, NC_GLOBAL, ATT_SCHAR_NAME, float_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (float_in[i] != schar_out[i]) ERRV
+      err=ncmpi_get_att_float(ncid, NC_GLOBAL, ATT_SHORT_NAME, float_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (float_in[i] != short_out[i]) ERRV
+      err=ncmpi_get_att_float(ncid, NC_GLOBAL, ATT_INT_NAME, float_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (float_in[i] != int_out[i]) ERRV
+      err=ncmpi_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (float_in[i] != float_out[i]) ERRV
+      err=ncmpi_get_att_float(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, float_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	  if (float_in[i] != (float) double_out[i]) ERRV
+
+      /* Read all atts (except text) as int. */
+      err=ncmpi_get_att_int(ncid, NC_GLOBAL, ATT_SCHAR_NAME, int_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (int_in[i] != schar_out[i]) ERRV
+      err=ncmpi_get_att_int(ncid, NC_GLOBAL, ATT_SHORT_NAME, int_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (int_in[i] != short_out[i]) ERRV
+      err=ncmpi_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (int_in[i] != int_out[i]) ERRV
+      err=ncmpi_get_att_int(ncid, NC_GLOBAL, ATT_FLOAT_NAME, int_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	  if (int_in[i] != (int) float_out[i]) ERRV
+      err=ncmpi_get_att_int(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, int_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	  if (int_in[i] != (int) double_out[i]) ERRV
+
+      /* Read all atts (except text) as short. */
+      err=ncmpi_get_att_short(ncid, NC_GLOBAL, ATT_SCHAR_NAME, short_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (short_in[i] != schar_out[i]) ERRV
+      err=ncmpi_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (short_in[i] != short_out[i]) ERRV
+      if ((err=ncmpi_get_att_short(ncid, NC_GLOBAL, ATT_INT_NAME, short_in)) != NC_ERANGE) ERR
+      for (i = 0; i < ATT_LEN; i++) {
+          if (i == 0 || i == 2) continue;
+	  if (short_in[i] != (short) int_out[i]) ERRV
+      }
+      err=ncmpi_get_att_short(ncid, NC_GLOBAL, ATT_FLOAT_NAME, short_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	  if (short_in[i] != (short) float_out[i]) ERRV
+      err=ncmpi_get_att_short(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, short_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	  if (short_in[i] != (short) double_out[i]) ERRV
+
+      /* Read all atts (except text) as schar. */
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (schar_in[i] != schar_out[i]) ERRV
+      if ((err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in)) != NC_ERANGE) ERR
+      for (i = 0; i < ATT_LEN; i++) {
+         if (i == 0 || i == 2) continue;
+	 if (schar_in[i] != (signed char) short_out[i]) ERRV
+      }
+      if ((err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in)) != NC_ERANGE) ERR
+      for (i = 0; i < ATT_LEN; i++) {
+	 if (i == 0 || i == 2) continue;
+	 if (schar_in[i] != (signed char) int_out[i]) ERRV
+      }
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (schar_in[i] != (signed char) float_out[i]) ERRV
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, schar_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (schar_in[i] != (signed char) double_out[i]) ERRV
+
+      /* Read all atts (except text) as uchar. */
+      err=ncmpi_get_att_uchar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, uchar_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (uchar_in[i] != (unsigned char) schar_out[i]) ERRV
+      if ((err=ncmpi_get_att_uchar(ncid, NC_GLOBAL, ATT_SHORT_NAME, uchar_in)) != NC_ERANGE) ERR
+/*
+      for (i = 0; i < ATT_LEN; i++)
+	 if (uchar_in[i] != (unsigned char) short_out[i]) ERRV
+*/
+      if ((err=ncmpi_get_att_uchar(ncid, NC_GLOBAL, ATT_INT_NAME, uchar_in)) != NC_ERANGE) ERR
+      for (i = 0; i < ATT_LEN; i++) {
+	 if (i == 0 || i == 2) continue;
+	 if (uchar_in[i] != (unsigned char) int_out[i]) ERRV
+      }
+      if ((err=ncmpi_get_att_uchar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, uchar_in)) != NC_ERANGE) ERR
+      for (i = 0; i < ATT_LEN; i++) {
+	 if (i == 0) continue;
+	 if (uchar_in[i] != (unsigned char) float_out[i]) ERRV
+      }
+      if ((err=ncmpi_get_att_uchar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, uchar_in)) != NC_ERANGE) ERR
+      for (i = 0; i < ATT_LEN; i++) {
+	 if (i == 0) continue;
+	 if (uchar_in[i] != (unsigned char) double_out[i]) ERRV
+      }
+
+      /* Read all atts (except text) into long long variable. */
+      err=ncmpi_get_att_longlong(ncid, NC_GLOBAL, ATT_SCHAR_NAME, longlong_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (longlong_in[i] != schar_out[i]) ERRV
+      err=ncmpi_get_att_longlong(ncid, NC_GLOBAL, ATT_SHORT_NAME, longlong_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (longlong_in[i] != short_out[i]) ERRV
+      err=ncmpi_get_att_longlong(ncid, NC_GLOBAL, ATT_INT_NAME, longlong_in); ERR
+      /* This was bug NCF-171: on 32-bit platforms, bad values returned */
+      err=ncmpi_get_att_longlong(ncid, NC_GLOBAL, ATT_INT_NAME, longlong_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+      	if (longlong_in[i] != (long long) int_out[i]) ERRV
+      err=ncmpi_get_att_longlong(ncid, NC_GLOBAL, ATT_FLOAT_NAME, longlong_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (longlong_in[i] != (long long)float_out[i]) ERRV
+      err=ncmpi_get_att_longlong(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, longlong_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (longlong_in[i] != (long long)double_out[i]) ERRV
+
+      err=ncmpi_close(ncid); ERR
+   }
+   if (verbose) printf("ok\n");
+   if (verbose) printf("*** testing zero-length attributes...");
+   {
+      int ncid;
+
+      /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/
+
+      /* Create a file with a global attribute of each type of zero length. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+      err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, 0, NULL); ERR
+      err=ncmpi_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, 0, NULL); ERR
+      err=ncmpi_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, 0, NULL); ERR
+      err=ncmpi_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, 0, NULL); ERR
+      err=ncmpi_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, 0, NULL); ERR
+      err=ncmpi_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, 0, NULL); ERR
+      err=ncmpi_close(ncid); ERR
+   }
+
+   /* Make sure we can read all these zero-length atts. */
+   {
+      int ncid;
+      signed char schar_in[ATT_LEN];
+      short short_in[ATT_LEN];
+      /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/
+      int int_in[ATT_LEN];
+      float float_in[ATT_LEN];
+      double double_in[ATT_LEN];
+      MPI_Offset len;
+      nc_type xtype;
+
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, NULL); ERR
+      err=ncmpi_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, &xtype, &len); ERR
+      if (len || xtype != NC_CHAR) ERRV
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in); ERR
+      err=ncmpi_inq_att(ncid, NC_GLOBAL, ATT_SCHAR_NAME, &xtype, &len); ERR
+      if (len || xtype != NC_BYTE) ERRV
+      err=ncmpi_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in); ERR
+      err=ncmpi_inq_att(ncid, NC_GLOBAL, ATT_SHORT_NAME, &xtype, &len); ERR
+      if (len || xtype != NC_SHORT) ERRV
+      err=ncmpi_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in); ERR
+      err=ncmpi_inq_att(ncid, NC_GLOBAL, ATT_INT_NAME, &xtype, &len); ERR
+      if (len || xtype != NC_INT) ERRV
+      err=ncmpi_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in); ERR
+      err=ncmpi_inq_att(ncid, NC_GLOBAL, ATT_FLOAT_NAME, &xtype, &len); ERR
+      if (len || xtype != NC_FLOAT) ERRV
+      err=ncmpi_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in); ERR
+      err=ncmpi_inq_att(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, &xtype, &len); ERR
+      if (len || xtype != NC_DOUBLE) ERRV
+      /* Conversions no longer result in range errors, since there's no data. */
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, schar_in); ERR
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in); ERR
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in); ERR
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in); ERR
+      err=ncmpi_close(ncid); ERR
+   }
+
+   if (verbose) printf("ok\n");
+   if (verbose) printf("*** testing zero-length attributes and redef...");
+   {
+      int ncid;
+      signed char schar_in[ATT_LEN];
+      short short_in[ATT_LEN];
+      int int_in[ATT_LEN];
+      float float_in[ATT_LEN];
+      double double_in[ATT_LEN];
+
+
+      /* Create a file with a global attribute of each type of zero length. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+      err=ncmpi_enddef(ncid); ERR
+      err=ncmpi_redef(ncid); ERR
+      err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, 0, NULL); ERR
+      err=ncmpi_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, 0, NULL); ERR
+      err=ncmpi_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, 0, NULL); ERR
+      err=ncmpi_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, 0, NULL); ERR
+      err=ncmpi_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, 0, NULL); ERR
+      err=ncmpi_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, 0, NULL); ERR
+      err=ncmpi_close(ncid); ERR
+
+      /* Make sure we can read all these zero-length atts added during a
+       * redef. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, NULL); ERR
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in); ERR
+      err=ncmpi_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in); ERR
+      err=ncmpi_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in); ERR
+      err=ncmpi_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in); ERR
+      err=ncmpi_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in); ERR
+      /* Conversions no longer result in range errors, since there's no data. */
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, schar_in); ERR
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in); ERR
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in); ERR
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in); ERR
+      err=ncmpi_close(ncid); ERR
+   }
+
+   if (verbose) printf("ok\n");
+   if (verbose) printf("*** testing attribute deletes and renames...");
+   {
+      int ncid, varid, dimids[2];
+      nc_type att_type;
+      MPI_Offset att_len;
+      char *speech_in;
+      char name_in[NC_MAX_NAME + 1];
+      int attid_in, natts_in;
+      int int_out[ATT_LEN] = {-100000, 128, 100000};
+
+      /* Create a file with a global attribute. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+      err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech); ERR
+      err=ncmpi_close(ncid); ERR
+      
+      /* Rename it. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_inq_attid(ncid, NC_GLOBAL, ATT_TEXT_NAME, &attid_in); ERR
+      if (attid_in != 0) ERRV
+      err=ncmpi_inq_attname(ncid, NC_GLOBAL, attid_in, name_in); ERR
+      if (strcmp(name_in, ATT_TEXT_NAME)) ERRV
+      err=ncmpi_redef(ncid); ERR
+      err=ncmpi_rename_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, ATT_TEXT_NAME2); ERR
+      err=ncmpi_inq_attname(ncid, NC_GLOBAL, attid_in, name_in); ERR
+      if (strcmp(name_in, ATT_TEXT_NAME2)) ERRV
+      err=ncmpi_close(ncid); ERR
+
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME2, &att_type, &att_len); ERR
+      if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERRV
+      if (!(speech_in = malloc(att_len + 1))) ERRV
+      err=ncmpi_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME2, speech_in); ERR
+      if (strcmp(speech, speech_in)) ERRV
+      free(speech_in);
+      if ((err=ncmpi_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, speech_in)) != NC_ENOTATT) ERR      
+      err=ncmpi_close(ncid); ERR
+
+      /* Now delete the att. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_redef(ncid); ERR
+      err=ncmpi_del_att(ncid, NC_GLOBAL, ATT_TEXT_NAME2); ERR
+      err=ncmpi_close(ncid); ERR
+
+      /* Now create a file with a variable, which has an att. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+      err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech); ERR
+      err=ncmpi_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0]); ERR
+      err=ncmpi_def_dim(ncid, DIM2_NAME, DIM2_LEN, &dimids[1]); ERR
+      err=ncmpi_def_var(ncid, VAR1_NAME, NC_INT, 2, dimids, &varid); ERR
+      err=ncmpi_put_att_int(ncid, varid, ATT_INT_NAME, NC_INT, 3, int_out); ERR
+      err=ncmpi_close(ncid); ERR
+      
+      /* Reopen the file and delete it. Make sure it's gone. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_redef(ncid); ERR
+      err=ncmpi_del_att(ncid, 0, ATT_INT_NAME); ERR
+      err=ncmpi_close(ncid); ERR
+
+      /* Reopen the file and readd the attribute. Enddef and redef,
+       * and delete it, then check to make sure it's gone. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_redef(ncid); ERR
+      err=ncmpi_put_att_int(ncid, varid, ATT_INT_NAME, NC_INT, 3, int_out); ERR
+      err=ncmpi_enddef(ncid); ERR
+      err=ncmpi_redef(ncid); ERR
+      err=ncmpi_del_att(ncid, 0, ATT_INT_NAME); ERR
+      err=ncmpi_inq_varnatts(ncid, 0, &natts_in); ERR
+      if (natts_in != 0) ERRV
+      err=ncmpi_close(ncid); ERR
+   }
+
+   if (verbose) printf("ok\n");
+   if (verbose) printf("*** testing attribute create order...");
+
+#define ATT0 "Maturin"
+#define ATT1 "Aubery"
+   {
+      int ncid, varid, dimids[2];
+      int attid_in;
+      const int number = 42;
+
+      /* Create a file with several global attributes. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+      err=ncmpi_put_att_int(ncid, NC_GLOBAL, ATT0, NC_INT, 1, &number); ERR
+      err=ncmpi_put_att_int(ncid, NC_GLOBAL, ATT1, NC_INT, 1, &number); ERR
+      err=ncmpi_close(ncid); ERR
+      
+      /* Open it and check the order. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_inq_attid(ncid, NC_GLOBAL, ATT0, &attid_in); ERR
+      if (attid_in != 0) ERRV
+      err=ncmpi_inq_attid(ncid, NC_GLOBAL, ATT1, &attid_in); ERR
+      if (attid_in != 1) ERRV
+      err=ncmpi_close(ncid); ERR
+
+      /* Now create a file with a variable, which has two atts. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+      err=ncmpi_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0]); ERR
+      err=ncmpi_def_dim(ncid, DIM2_NAME, DIM2_LEN, &dimids[1]); ERR
+      err=ncmpi_def_var(ncid, VAR1_NAME, NC_INT, 2, dimids, &varid); ERR
+      err=ncmpi_put_att_int(ncid, varid, ATT0, NC_INT, 1, &number); ERR
+      err=ncmpi_put_att_int(ncid, varid, ATT1, NC_INT, 1, &number); ERR
+      err=ncmpi_close(ncid); ERR
+      
+      /* Reopen the file and check the order of the attributes on the var. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_inq_attid(ncid, 0, ATT0, &attid_in); ERR
+      if (attid_in != 0) ERRV
+      err=ncmpi_inq_attid(ncid, 0, ATT1, &attid_in); ERR
+      if (attid_in != 1) ERRV
+      err=ncmpi_close(ncid); ERR
+   }
+
+   if (verbose) printf("ok\n");
+   if (verbose) printf("*** testing attribute ordering some more...");
+
+#define VAR_NAME "i"
+#define A1_NAME "i"      
+#define A2_NAME "f"      
+#define A3_NAME "d"      
+#define A1_LEN 3
+#define A2_LEN 4
+#define A3_LEN 5
+   {
+      int ncid;
+      int varid, natts, nvars;
+      double dvalue[] = {999.99, 999.99, 999.99, 999.99, 999.99};
+      char name_in[NC_MAX_NAME + 1];
+
+      /* Create a file with one var, and attach three atts to it. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+      err=ncmpi_def_var(ncid, VAR_NAME, NC_INT, 0, NULL, &varid); ERR
+      err=ncmpi_put_att_double(ncid, varid, A1_NAME, NC_INT, A1_LEN, dvalue); ERR
+      err=ncmpi_put_att_double(ncid, varid, A2_NAME, NC_INT, A2_LEN, dvalue); ERR
+      err=ncmpi_put_att_double(ncid, varid, A3_NAME, NC_INT, A3_LEN, dvalue); ERR
+      err=ncmpi_close(ncid); ERR
+      
+      /* Reopen the file and check. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_inq_nvars(ncid, &nvars); ERR
+      if (nvars != 1) ERRV
+      err=ncmpi_inq_varnatts(ncid, 0, &natts); ERR
+      if (natts != 3) ERRV
+      err=ncmpi_inq_attname(ncid, 0, 0, name_in); ERR
+      if (strcmp(name_in, A1_NAME)) ERRV
+      err=ncmpi_inq_attname(ncid, 0, 1, name_in); ERR
+      if (strcmp(name_in, A2_NAME)) ERRV
+      err=ncmpi_inq_attname(ncid, 0, 2, name_in); ERR
+      if (strcmp(name_in, A3_NAME)) ERRV
+
+      /* Close up shop. */
+      err=ncmpi_close(ncid); ERR
+   }
+
+   if (verbose) printf("ok\n");
+   if (verbose) printf("*** testing attribute ordering even more...");
+
+   /* Test the ordering of atts for each cmode. */
+   if (tst_att_ordering(filename, cmode)) ERRV
+   if (tst_att_ordering(filename, cmode)) ERRV
+
+   if (verbose) printf("ok\n");
+   if (verbose) printf("*** testing attributes and enddef/redef...");
+
+#define ATT_1 "a"
+#define ATT_2 "b"
+#define ATT_3 "c"
+   {
+      int ncid, att = 1;
+
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+      err=ncmpi_enddef(ncid); ERR
+      err=ncmpi_redef(ncid); ERR
+      err=ncmpi_put_att(ncid, NC_GLOBAL, ATT_1, NC_INT, 1, &att); ERR
+      err=ncmpi_put_att(ncid, NC_GLOBAL, ATT_2, NC_INT, 1, &att); ERR
+      err=ncmpi_put_att(ncid, NC_GLOBAL, ATT_3, NC_INT, 1, &att); ERR
+
+      err=ncmpi_close(ncid); ERR
+
+      err=ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_close(ncid); ERR
+   }
+
+   if (verbose) printf("ok\n");
+   if (verbose) printf("*** testing copy of simple global atts...");
+   {      
+      int ncid, ncid2;
+      nc_type att_type;
+      MPI_Offset att_len;
+      int i;
+
+      char *speech_in;
+      signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
+      short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
+      int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000};
+      float float_in[ATT_LEN], float_out[ATT_LEN] = {.5, 0.25, 0.125};
+      double double_in[ATT_LEN], double_out[ATT_LEN] = {0.25, .5, 0.125};
+
+      /* Create a file with a global attribute of each type. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+      err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech); ERR
+      err=ncmpi_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, ATT_LEN, schar_out); ERR
+      err=ncmpi_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, ATT_LEN, short_out); ERR
+      err=ncmpi_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, ATT_LEN, int_out); ERR
+      err=ncmpi_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, ATT_LEN, float_out); ERR
+      err=ncmpi_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, ATT_LEN, double_out); ERR
+
+      /* Create another file and copy all the attributes. */
+      err=ncmpi_create(MPI_COMM_WORLD, filename2, cmode, MPI_INFO_NULL,&ncid2); ERR
+      err=ncmpi_copy_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, ncid2, NC_GLOBAL); ERR
+      err=ncmpi_copy_att(ncid, NC_GLOBAL, ATT_SCHAR_NAME, ncid2, NC_GLOBAL); ERR
+      err=ncmpi_copy_att(ncid, NC_GLOBAL, ATT_SHORT_NAME, ncid2, NC_GLOBAL); ERR
+      err=ncmpi_copy_att(ncid, NC_GLOBAL, ATT_INT_NAME, ncid2, NC_GLOBAL); ERR
+      err=ncmpi_copy_att(ncid, NC_GLOBAL, ATT_FLOAT_NAME, ncid2, NC_GLOBAL); ERR
+      err=ncmpi_copy_att(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, ncid2, NC_GLOBAL); ERR
+
+      /* Close both files. */
+      err=ncmpi_close(ncid); ERR
+      err=ncmpi_close(ncid2); ERR
+
+      /* Open the file and check attributes. */
+      err=ncmpi_open(MPI_COMM_WORLD, filename2, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+      /* Check text. */
+      err=ncmpi_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, &att_type, &att_len); ERR
+      if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERRV
+      if (!(speech_in = malloc(att_len + 1))) ERRV
+      err=ncmpi_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, speech_in); ERR
+      if (strcmp(speech, speech_in)) ERRV
+      free(speech_in);
+      /* Check numeric values. */
+      err=ncmpi_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (schar_in[i] != schar_out[i]) ERRV
+      err=ncmpi_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (short_in[i] != short_out[i]) ERRV
+      err=ncmpi_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (int_in[i] != int_out[i]) ERRV
+      err=ncmpi_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (float_in[i] != float_out[i]) ERRV
+      err=ncmpi_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in); ERR
+      for (i = 0; i < ATT_LEN; i++)
+	 if (double_in[i] != double_out[i]) ERRV
+      err=ncmpi_close(ncid); ERR
+   }
+   if (verbose) printf("ok\n");
+   return nerrs;
+}
+
+int main(int argc, char *argv[])
+{
+    char filename[128];
+    int cmode, rank, nprocs, err, nerrs=0;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 128, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    char cmd_str[256];
+    sprintf(cmd_str, "*** TESTING C   %s for emulating netCDF tst_atts3 ", argv[0]);
+    if (rank == 0) printf("%-66s ------ ", cmd_str);
+
+    verbose = 0;
+
+    cmode = NC_CLOBBER;
+    nerrs += tst_atts3(filename, cmode);
+
+    cmode = NC_CLOBBER | NC_64BIT_OFFSET;
+    nerrs += tst_atts3(filename, cmode);
+
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    nerrs += tst_atts3(filename, cmode);
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/nc_test/tst_misc.c b/test/nc_test/tst_misc.c
new file mode 100644
index 0000000..f978ccb
--- /dev/null
+++ b/test/nc_test/tst_misc.c
@@ -0,0 +1,100 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: tst_misc.c 2133 2015-09-26 19:16:01Z wkliao $ */
+
+/* This program is based on the test program tst_misc.c of the netCDF package */
+
+/*
+  Copyright 2007, UCAR/Unidata
+  See COPYRIGHT file for copying and redistribution conditions.
+
+  This is part of netCDF.
+   
+  This program runs some extra tests.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+int
+main(int argc, char **argv) 
+{
+    char filename[128];
+    int rank, nprocs, err, nerrs=0;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    if (rank > 0) goto fn_exit;
+
+    char cmd_str[256];
+    sprintf(cmd_str, "*** TESTING C   %s for emulating netCDF t_misc ", argv[0]);
+    if (rank == 0) printf("%-66s ------ ", cmd_str);
+/*
+   printf("\n*** Testing some extra stuff.\n");
+   printf("*** Trying to open non-netCDF files of tiny length...");
+*/
+   {
+#define DATA_LEN 32    
+     int ncid,openstat;
+      char dummy_data[DATA_LEN];
+      FILE *file;
+      int i, nerrs=0;
+
+      /* Appease valgrind by initializing our data. */
+      for (i = 0; i < DATA_LEN; i++)
+	 dummy_data[i] = i;
+
+      for (i = DATA_LEN; i >= 0; i--)
+      {
+	 /* Create a small file which is not a netCDF file. */
+	 if (!(file = fopen(filename, "w+"))) nerrs++;
+	 if (fwrite(dummy_data, 1, i, file) != i) nerrs++;
+	 if (fclose(file)) nerrs++;
+	 
+	 /* Make sure that netCDF rejects this file politely. */
+	 openstat = ncmpi_open(MPI_COMM_SELF, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid);
+	 /* Some platforms (OSX, buddy) return stat = 2 (file not found)
+	    for index i == 2.  Not sure why, but this is a work around. */
+	 if(openstat != NC_ENOTNC && openstat != NC_ENOENT) {
+            printf("Expecting error code %d or %d but got %d\n",NC_ENOTNC,NC_ENOENT,openstat);
+            nerrs++;
+         }
+      }
+   }
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+fn_exit:
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/test/nc_test/tst_names.c b/test/nc_test/tst_names.c
new file mode 100644
index 0000000..4ce6b31
--- /dev/null
+++ b/test/nc_test/tst_names.c
@@ -0,0 +1,327 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: tst_names.c 2133 2015-09-26 19:16:01Z wkliao $ */
+
+/* This program is based on the test program tst_names.c of the netCDF package */
+
+/* This is part of the netCDF package.
+   Copyright 2006 University Corporation for Atmospheric Research/Unidata.
+   See COPYRIGHT file for conditions of use.
+
+   This is a very simple example which tests rejection of bad names for
+   netCDF data objects, including names with "/" character, trailing spaces, 
+   leading special characters, and invalid UTF-8 strings.
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+/* The data file we will create. */
+#define NDIMS 1
+#define DIMLEN 1
+
+int
+main(int argc, char **argv)
+{
+   char *valid[] = {
+       /* pressure in 23 languages */
+       "\xd8\xa7\xd9\x84\xd8\xb6\xd8\xba\xd8\xb7",
+       "\xd0\xbd\xd0\xb0\xd0\xbb\xd1\x8f\xd0\xb3\xd0\xb0\xd0\xbd\xd0\xb5",
+       "\xe5\x8e\x8b\xe5\x8a\x9b",
+       "\xe5\xa3\x93\xe5\x8a\x9b",
+       "pritisak",
+       "tlaku",
+       "pres",
+       "druk",
+       "pressure",
+       "paine",
+       "pression",
+       "Druck",
+       "\xcf\x80\xce\xaf\xce\xb5\xcf\x83\xce\xb7",
+       "\xe0\xa4\xa6\xe0\xa4\xac\xe0\xa4\xbe\xe0\xa4\xb5",
+       "pressione",
+       "\xe5\x9c\xa7\xe5\x8a\x9b",
+       "\xec\x95\x95\xeb\xa0\xa5",
+       "press",
+       "ci\xc5\x9bnienie",
+       "Press\xc3\xa3o",
+       "presiune",
+       "\xd0\xb4\xd0\xb0\xd0\xb2\xd0\xbb\xd0\xb5\xd0\xbd\xd0\xb8\xd0\xb5",
+       "presi\xc3\xb3n",
+       /* special characters in names, numeric characters at the start of names */
+       "has blank",
+       "has:colon",
+       "a",
+       "A",
+       "0leading_numeric_char",
+       "1",
+       "0x123"
+   };
+   char *notvalid[] = {
+       "-leading_special_char",
+       "trailing_space ",
+       "trailing_tab\t",
+       "trailing_newline\n",
+       "has_control_char_\a_in_name",
+       "has ascii_del_\x7f_in name",
+       /* Invalid UTF-8 of various sorts, thanks to Markus Kuhn */
+       "\xA0\xB0\xC0\xD0",
+       "xyz\x80", 		/* unexpected continuation bytes */
+       "\x80xyz",
+       "xyz\xBF",
+       "\xBFxyz",
+       "\xC0xyz",		/* lonely start characters */
+       "x\xC0yz",
+       "xy\xC0z",
+       "xyz\xC0",
+       "\xDFxyz",
+       "x\xDFyz",
+       "xy\xDFz",
+       "xyz\xDF",
+       "\xE0xyz",
+       "x\xE0yz",
+       "xy\xE0z",
+       "xyz\xE0",
+       "\xE0\xBFxy",
+       "x\xE0\xBFy",
+       "xy\xE0\xBF",
+       "\xEFxyz",
+       "x\xEFyz",
+       "xy\xEFz",
+       "xyz\xEF",
+       "\xEF\x80xy",
+       "x\xEF\x80y",
+       "xy\xEF\x80",
+       "\xF0xyz",
+       "x\xF0yz",
+       "xy\xF0z",
+       "xyz\xF0",
+       "\xF7xyz",
+       "x\xF7yz",
+       "xy\xF7z",
+       "xyz\xF7",
+       "\xF8xyz",
+       "x\xF8yz",
+       "xy\xF8z",
+       "xyz\xF8",
+       "\xFBxyz",
+       "x\xFByz",
+       "xy\xFBz",
+       "xyz\xFB",
+       "\xFCxyz",
+       "x\xFCyz",
+       "xy\xFCz",
+       "xyz\xFC",
+       "\xFDxyz",
+       "x\xFDyz",
+       "xy\xFDz",
+       "xyz\xFD",
+       "\xC0\xC0xy",		/* last continuation byte missing */
+       "x\xC0\xC0y",
+       "xy\xC0\xC0",
+       "\xDF\xDFxy",
+       "x\xDF\xDFy",
+       "xy\xDF\xDF",
+       "\xE0\x80xy",
+       "x\xE0\x80y",
+       "xy\xE0\x80",
+       "\xEF\x80xy",
+       "x\xEF\x80y",
+       "xy\xEF\x80",
+       "\xF0\x80\x80x",
+       "x\xF0\x80\x80",
+       "\xF7\x80\x80x",
+       "x\xF7\x80\x80",
+       "\xF8\x80\x80\x80x",
+       "x\xF8\x80\x80\x80",
+       "\xFB\x80\x80\x80x",
+       "x\xFB\x80\x80\x80",
+       "\xFC\x80\x80\x80\x80x",
+       "x\xFC\x80\x80\x80\x80",
+       "\xFD\x80\x80\x80\x80x",
+       "x\xFD\x80\x80\x80\x80",
+       "\xFExyz",		/* impossible bytes */
+       "x\xFEyz",
+       "xy\xFEz",
+       "xyz\xFE",
+       "\xFFxyz",
+       "x\xFFyz",
+       "xy\xFFz",
+       "xyz\xFF",
+       "\xC0\xAFxy",		/* overlong sequences */
+       "x\xC0\xAFy",
+       "xy\xC0\xAF",
+       "\xE0\x80\xAFx",
+       "x\xE0\x80\xAF",
+       "\xF0\x80\x80\xAFx",
+       "x\xF0\x80\x80\xAF",
+       "\xF8\x80\x80\x80\xAFx",
+       "x\xF8\x80\x80\x80\xAF",
+       "\xFC\x80\x80\x80\x80\xAFx",
+       "x\xFC\x80\x80\x80\x80\xAF",
+       "\xC1\xBFxy",
+       "x\xC1\xBFy",
+       "xy\xC1\xBF",
+       "\xE0\x9F\xBFx",
+       "x\xE0\x9F\xBF",
+       "\xF0\x8F\xBF\xBFx",
+       "x\xF0\x8F\xBF\xBF",
+       "\xF8\x87\xBF\xBF\xBFx",
+       "x\xF8\x87\xBF\xBF\xBF",
+       "\xFC\x83\xBF\xBF\xBF\xBFx",
+       "x\xFC\x83\xBF\xBF\xBF\xBF",
+       "x\xC0\x80",		/* overlong NULs */
+       "x\xE0\x80\x80",
+       "x\xF0\x80\x80\x80",
+       "x\xF8\x80\x80\x80\x80",
+       "x\xFC\x80\x80\x80\x80\x80",
+       /* single UTF-16 surrogates */
+       "x\xED\xA0\x80",
+       "x\xED\xAD\xBF",
+       "x\xED\xAE\x80",
+       "x\xED\xAF\xBF",
+       "x\xED\xB0\x80",
+       "x\xED\xBE\x80",
+       "x\xED\xBF\xBF",
+       "x\xED\xA0\x80\xED\xB0\x80", /* paired UTF-16 surrogates */
+       "x\xED\xA0\x80\xED\xBF\xBF",
+       "x\xED\xAD\xBF\xED\xB0\x80",
+       "x\xED\xAD\xBF\xED\xBF\xBF",
+       "x\xED\xAE\x80\xED\xB0\x80",
+       "x\xED\xAE\x80\xED\xBF\xBF",
+       "x\xED\xAF\xBF\xED\xB0\x80",
+       "x\xED\xAF\xBF\xED\xBF\xBF",
+       "x\xEF\xBF\xBE",		/* other illegal code positions */
+       "x\xEF\xBF\xBF"
+   };
+   int i, j;
+#define NUM_BAD (sizeof notvalid / sizeof notvalid[0])
+#define NUM_GOOD (sizeof valid / sizeof valid[0])
+   int ncid, dimid, varid, res;
+   double attvals[] = {-2.0};
+   double attvals_in[1];
+#define NATTVALS (sizeof attvals / sizeof attvals[0])
+   char *attstring = "text";
+#define MAX_ATTSTRING_LEN 100
+   char attstr_in[MAX_ATTSTRING_LEN];
+   int dimids[NUM_GOOD];
+   int varids[NUM_GOOD];
+#if 0
+   int attnums[NUM_GOOD];
+#endif
+   char *format_names[] = { "CDF-2", "CDF-5" };
+   int cmode[2] = {NC_64BIT_OFFSET, NC_64BIT_DATA};
+
+    char filename[128];
+    int rank, nprocs, err, nerrs=0, verbose=0;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+
+    char cmd_str[256];
+    sprintf(cmd_str, "*** TESTING C   %s for emulating netCDF tst_names ", argv[0]);
+    if (rank == 0) printf("%-66s ------ ", cmd_str);
+
+#define ERROR {printf("Error at line %d: %s\n",__LINE__,ncmpi_strerror(res)); nerrs++;}
+#define ERRORI {printf("Error at line %d (loop=%d): %s\n",__LINE__,i,ncmpi_strerror(res)); nerrs++;}
+
+   if (verbose) printf("\n*** testing names with file %s...\n", filename);
+   for (j = 0; j < 2; j++)
+   {
+       if (verbose) printf("*** switching to netCDF %s format...", format_names[j]);
+       if((res = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER|cmode[j], MPI_INFO_NULL, &ncid)))
+	   ERROR
+       
+       /* Define dimensions, variables, and attributes with various
+	* acceptable names */
+       for (i = 0; i < NUM_GOOD; i++) {
+	   if ((res = ncmpi_def_dim(ncid, valid[i], DIMLEN, &dimid)))
+	       ERRORI
+
+	   dimids[i] = dimid;
+	   /* Define variable with same name */
+	   if ((res = ncmpi_def_var(ncid, valid[i], NC_FLOAT, NDIMS, &dimids[i], &varid)))
+	       ERRORI
+	   varids[i] = varid;
+	   /* Define variable and global attributes with same name and value */
+	   if ((res = ncmpi_put_att_text(ncid, varid, valid[i], strlen(valid[i]), valid[i])))
+	       ERRORI
+	   if ((res = ncmpi_put_att_double(ncid, NC_GLOBAL, valid[i], NC_DOUBLE, NATTVALS, attvals)))
+	       ERRORI
+#if 0
+	   attnums[i] = i;
+#endif
+       }
+       
+       /* Try defining dimensions, variables, and attributes with various
+	* bad names and make sure these are rejected */
+       for (i = 0; i < NUM_BAD; i++) {
+	   if ((res = ncmpi_def_dim(ncid, notvalid[i], DIMLEN, &dimid)) != NC_EBADNAME)
+               ERRORI
+	   if ((res = ncmpi_def_var(ncid, notvalid[i], NC_FLOAT, NDIMS, dimids, &varid)) != NC_EBADNAME)
+               ERRORI
+	   if ((res = ncmpi_put_att_text(ncid, varid, notvalid[i], strlen(attstring), attstring)) != NC_EBADNAME)
+               ERRORI
+	   if ((res = ncmpi_put_att_double(ncid, NC_GLOBAL, notvalid[i], NC_DOUBLE, NATTVALS, attvals)) != NC_EBADNAME)
+               ERRORI
+       }
+       if ((res = ncmpi_enddef(ncid)))
+	   ERROR
+       if ((res = ncmpi_close(ncid)))
+	   ERROR
+       
+       /* Check it out, make sure all objects with good names were defined OK */
+       if ((res = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid)))
+	   ERROR
+       for (i = 0; i < NUM_GOOD; i++) {
+	   MPI_Offset attlen;
+	   if ((res = ncmpi_inq_dimid(ncid, valid[i], &dimid)) || dimid != dimids[i])
+	       ERRORI
+	   if ((res = ncmpi_inq_varid(ncid, valid[i], &varid)) || varid != varids[i])
+	       ERRORI
+	   res = ncmpi_inq_attlen(ncid, varid, valid[i], &attlen);
+	   if ((res = ncmpi_get_att_text(ncid, varid, valid[i], attstr_in))) 
+	       ERRORI
+	   attstr_in[attlen] = '\0';
+	   if (strcmp(valid[i], attstr_in) != 0) 
+	       ERRORI
+	   if ((res = ncmpi_get_att_double(ncid, NC_GLOBAL, valid[i], attvals_in)) || attvals[0] != attvals_in[0]) 
+	       ERRORI
+       }
+       if ((res = ncmpi_close(ncid)))
+	   ERROR
+   }
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/test/nc_test/tst_nofill.c b/test/nc_test/tst_nofill.c
new file mode 100644
index 0000000..1115df3
--- /dev/null
+++ b/test/nc_test/tst_nofill.c
@@ -0,0 +1,484 @@
+/*
+  Copyright 2007, UCAR/Unidata
+  See COPYRIGHT file for copying and redistribution conditions.
+
+  This is part of netCDF.
+   
+  This program tests for a bug discovered with nofill mode that failed
+  only on file systems with block size in a particular range.  It fails
+  when invoked with the blksize argument between 2091953 and 2150032,
+  inclusive, and succeeds for other blksizes.
+
+  $Id: tst_nofill.c 2219 2015-12-11 22:30:03Z wkliao $
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define ERR {if (err != NC_NOERR) {printf("Error at %s line %d: %s\n",__func__,__LINE__,ncmpi_strerror(err)); return 1;}}
+
+static void
+check_err(const int stat, const int line, const char *file) {
+    if (stat != NC_NOERR) {
+	(void) fprintf(stderr, "line %d of %s: %s\n", line, file, ncmpi_strerror(stat));
+        fflush(stderr);
+	exit(1);
+    }
+}
+
+#define LON_LEN 240
+#define LAT_LEN 121
+#define LVL_LEN 31
+#define TIME_LEN 1
+
+static int
+create_file(char *file_name, int fill_mode)
+{
+   int i;
+   int  stat;			/* return status */
+   int  ncid;			/* netCDF id */
+
+   /* dimension ids */
+   int lon_dim;
+   int lat_dim;
+   int lvl_dim;
+   int time_dim;
+
+   /* dimension lengths */
+   MPI_Offset lon_len = LON_LEN;
+   MPI_Offset lat_len = LAT_LEN;
+   MPI_Offset lvl_len = LVL_LEN;
+   MPI_Offset time_len = TIME_LEN;
+
+   /* variable ids */
+   int time_id;
+   int lat_id;
+   int lon_id;
+   int lvl_id;
+   int sfc_pres_id;
+   int temp_scrn_id;
+   int qsair_scrn_id;
+   int topog_id;
+   int mslp_id;
+   int sfc_temp_id;
+   int zonal_wnd_id;
+
+   /* rank (number of dimensions) for each variable */
+#  define RANK_time 1
+#  define RANK_lat 1
+#  define RANK_lon 1
+#  define RANK_lvl 1
+#  define RANK_sfc_pres 3
+#  define RANK_temp_scrn 3
+#  define RANK_qsair_scrn 3
+#  define RANK_topog 3
+#  define RANK_mslp 3
+#  define RANK_sfc_temp 3
+#  define RANK_zonal_wnd 4
+
+   /* variable shapes */
+   int time_dims[RANK_time];
+   int lat_dims[RANK_lat];
+   int lon_dims[RANK_lon];
+   int lvl_dims[RANK_lvl];
+   int sfc_pres_dims[RANK_sfc_pres];
+   int temp_scrn_dims[RANK_temp_scrn];
+   int qsair_scrn_dims[RANK_qsair_scrn];
+   int topog_dims[RANK_topog];
+   int mslp_dims[RANK_mslp];
+   int sfc_temp_dims[RANK_sfc_temp];
+   int zonal_wnd_dims[RANK_zonal_wnd];
+
+   MPI_Offset zonal_wnd_start[RANK_zonal_wnd];
+   MPI_Offset zonal_wnd_count[RANK_zonal_wnd];
+   float zonal_wnd[LON_LEN*LAT_LEN*TIME_LEN];
+   int ii;
+
+   int old_fill_mode;
+
+   stat = ncmpi_create(MPI_COMM_WORLD, file_name,NC_CLOBBER, MPI_INFO_NULL, &ncid);
+
+   check_err(stat,__LINE__,__FILE__);
+   stat = ncmpi_set_fill(ncid, fill_mode, &old_fill_mode);
+   check_err(stat,__LINE__,__FILE__);
+
+   /* define dimensions */
+   stat = ncmpi_def_dim(ncid, "lon", lon_len, &lon_dim);
+   check_err(stat,__LINE__,__FILE__);
+   stat = ncmpi_def_dim(ncid, "lat", lat_len, &lat_dim);
+   check_err(stat,__LINE__,__FILE__);
+   stat = ncmpi_def_dim(ncid, "lvl", lvl_len, &lvl_dim);
+   check_err(stat,__LINE__,__FILE__);
+   stat = ncmpi_def_dim(ncid, "time", time_len, &time_dim);
+   check_err(stat,__LINE__,__FILE__);
+
+   /* define variables */
+   time_dims[0] = time_dim;
+   stat = ncmpi_def_var(ncid, "time", NC_DOUBLE, RANK_time, time_dims, &time_id);
+   check_err(stat,__LINE__,__FILE__);
+
+   lat_dims[0] = lat_dim;
+   stat = ncmpi_def_var(ncid, "lat", NC_FLOAT, RANK_lat, lat_dims, &lat_id);
+   check_err(stat,__LINE__,__FILE__);
+
+   lon_dims[0] = lon_dim;
+   stat = ncmpi_def_var(ncid, "lon", NC_FLOAT, RANK_lon, lon_dims, &lon_id);
+   check_err(stat,__LINE__,__FILE__);
+
+   lvl_dims[0] = lvl_dim;
+   stat = ncmpi_def_var(ncid, "lvl", NC_FLOAT, RANK_lvl, lvl_dims, &lvl_id);
+   check_err(stat,__LINE__,__FILE__);
+
+   sfc_pres_dims[0] = time_dim;
+   sfc_pres_dims[1] = lat_dim;
+   sfc_pres_dims[2] = lon_dim;
+   stat = ncmpi_def_var(ncid, "sfc_pres", NC_FLOAT, RANK_sfc_pres, sfc_pres_dims, &sfc_pres_id);
+   check_err(stat,__LINE__,__FILE__);
+
+   temp_scrn_dims[0] = time_dim;
+   temp_scrn_dims[1] = lat_dim;
+   temp_scrn_dims[2] = lon_dim;
+   stat = ncmpi_def_var(ncid, "temp_scrn", NC_FLOAT, RANK_temp_scrn, temp_scrn_dims, &temp_scrn_id);
+   check_err(stat,__LINE__,__FILE__);
+
+   qsair_scrn_dims[0] = time_dim;
+   qsair_scrn_dims[1] = lat_dim;
+   qsair_scrn_dims[2] = lon_dim;
+   stat = ncmpi_def_var(ncid, "qsair_scrn", NC_FLOAT, RANK_qsair_scrn, qsair_scrn_dims, &qsair_scrn_id);
+   check_err(stat,__LINE__,__FILE__);
+
+   topog_dims[0] = time_dim;
+   topog_dims[1] = lat_dim;
+   topog_dims[2] = lon_dim;
+   stat = ncmpi_def_var(ncid, "topog", NC_FLOAT, RANK_topog, topog_dims, &topog_id);
+   check_err(stat,__LINE__,__FILE__);
+
+   mslp_dims[0] = time_dim;
+   mslp_dims[1] = lat_dim;
+   mslp_dims[2] = lon_dim;
+   stat = ncmpi_def_var(ncid, "mslp", NC_FLOAT, RANK_mslp, mslp_dims, &mslp_id);
+   check_err(stat,__LINE__,__FILE__);
+
+   sfc_temp_dims[0] = time_dim;
+   sfc_temp_dims[1] = lat_dim;
+   sfc_temp_dims[2] = lon_dim;
+   stat = ncmpi_def_var(ncid, "sfc_temp", NC_FLOAT, RANK_sfc_temp, sfc_temp_dims, &sfc_temp_id); 
+   check_err(stat,__LINE__,__FILE__);
+
+   zonal_wnd_dims[0] = time_dim;
+   zonal_wnd_dims[1] = lvl_dim;
+   zonal_wnd_dims[2] = lat_dim;
+   zonal_wnd_dims[3] = lon_dim;
+   stat = ncmpi_def_var(ncid, "zonal_wnd", NC_FLOAT, RANK_zonal_wnd, zonal_wnd_dims, &zonal_wnd_id);
+   check_err(stat,__LINE__,__FILE__);
+
+   /* leave define mode */
+   stat = ncmpi_enddef (ncid);
+   check_err(stat,__LINE__,__FILE__);
+
+   {				/* store time */
+       MPI_Offset time_start[RANK_time];
+       MPI_Offset time_count[RANK_time];
+       double time[TIME_LEN] = {1.};
+       time_len = 1;
+       time_start[0] = 0;
+       time_count[0] = time_len;
+       stat = ncmpi_put_vara_double_all(ncid, time_id, time_start, time_count, time);
+       check_err(stat,__LINE__,__FILE__);
+   }
+   
+   {				/* store lat */
+       float lat[] = {90, 88.5, 87, 85.5, 84, 82.5, 81, 79.5, 78, 76.5, 75, 73.5, 72, 70.5, 69, 67.5, 66, 64.5, 63, 61.5, 60, 58.5, 57, 55.5, 54, 52.5, 51, 49.5, 48, 46.5, 45, 43.5, 42, 40.5, 39, 37.5, 36, 34.5, 33, 31.5, 30, 28.5, 27, 25.5, 24, 22.5, 21, 19.5, 18, 16.5, 15, 13.5, 12, 10.5, 9, 7.5, 6, 4.5, 3, 1.5, 0, -1.5, -3, -4.5, -6, -7.5, -9, -10.5, -12, -13.5, -15, -16.5, -18, -19.5, -21, -22.5, -24, -25.5, -27, -28.5, -30, -31.5, -33, -34.5, -36, -37.5, -39, -40.5, -42, -43.5, -45, [...]
+       stat = ncmpi_put_var_float_all(ncid, lat_id, lat);
+       check_err(stat,__LINE__,__FILE__);
+   }
+   
+   {				/* store lon */
+       float lon[] = {0, 1.5, 3, 4.5, 6, 7.5, 9, 10.5, 12, 13.5, 15, 16.5, 18, 19.5, 21, 22.5, 24, 25.5, 27, 28.5, 30, 31.5, 33, 34.5, 36, 37.5, 39, 40.5, 42, 43.5, 45, 46.5, 48, 49.5, 51, 52.5, 54, 55.5, 57, 58.5, 60, 61.5, 63, 64.5, 66, 67.5, 69, 70.5, 72, 73.5, 75, 76.5, 78, 79.5, 81, 82.5, 84, 85.5, 87, 88.5, 90, 91.5, 93, 94.5, 96, 97.5, 99, 100.5, 102, 103.5, 105, 106.5, 108, 109.5, 111, 112.5, 114, 115.5, 117, 118.5, 120, 121.5, 123, 124.5, 126, 127.5, 129, 130.5, 132, 133.5, 135, [...]
+       stat = ncmpi_put_var_float_all(ncid, lon_id, lon);
+       check_err(stat,__LINE__,__FILE__);
+   }
+
+   {				/* store lvl */
+       float lvl[] = {1000, 995, 990, 985, 975, 950, 925, 900, 875, 850, 800, 750, 700, 600, 500, 450, 400, 350, 300, 275, 250, 225, 200, 175, 150, 100, 70, 50, 30, 20, 10};
+       stat = ncmpi_put_var_float_all(ncid, lvl_id, lvl);
+       check_err(stat,__LINE__,__FILE__);
+   }
+   
+   {				/* store sfc_pres */
+       MPI_Offset sfc_pres_start[RANK_sfc_pres];
+       MPI_Offset sfc_pres_count[RANK_sfc_pres];
+       float sfc_pres[LON_LEN*LAT_LEN];
+       
+       for(ii = 0; ii < LAT_LEN * LON_LEN; ii++) {
+	   sfc_pres[ii] = 6;
+       }
+       sfc_pres_start[0] = 0;
+       sfc_pres_start[1] = 0;
+       sfc_pres_start[2] = 0;
+       sfc_pres_count[0] = time_len;
+       sfc_pres_count[1] = lat_len;
+       sfc_pres_count[2] = lon_len;
+       stat = ncmpi_put_vara_float_all(ncid, sfc_pres_id, sfc_pres_start, sfc_pres_count, sfc_pres);
+       check_err(stat,__LINE__,__FILE__);
+   }
+
+   {				/* store temp_scrn */
+       MPI_Offset temp_scrn_start[RANK_temp_scrn];
+       MPI_Offset temp_scrn_count[RANK_temp_scrn];
+       float temp_scrn[LON_LEN*LAT_LEN];
+       
+       for(ii = 0; ii < LAT_LEN * LON_LEN; ii++) {
+	   temp_scrn[ii] = 11;
+       }
+       temp_scrn_start[0] = 0;
+       temp_scrn_start[1] = 0;
+       temp_scrn_start[2] = 0;
+       temp_scrn_count[0] = time_len;
+       temp_scrn_count[1] = lat_len;
+       temp_scrn_count[2] = lon_len;
+       stat = ncmpi_put_vara_float_all(ncid, temp_scrn_id, temp_scrn_start, temp_scrn_count, temp_scrn);
+       check_err(stat,__LINE__,__FILE__);
+   }
+   
+   {				/* store qsair_scrn */
+       MPI_Offset qsair_scrn_start[RANK_qsair_scrn];
+       MPI_Offset qsair_scrn_count[RANK_qsair_scrn];
+       float qsair_scrn[LON_LEN*LAT_LEN];
+       
+       for(ii = 0; ii < LAT_LEN * LON_LEN; ii++) {
+	   qsair_scrn[ii] = 22;
+       }
+       qsair_scrn_start[0] = 0;
+       qsair_scrn_start[1] = 0;
+       qsair_scrn_start[2] = 0;
+       qsair_scrn_count[0] = time_len;
+       qsair_scrn_count[1] = lat_len;
+       qsair_scrn_count[2] = lon_len;
+       stat = ncmpi_put_vara_float_all(ncid, qsair_scrn_id, qsair_scrn_start, qsair_scrn_count, qsair_scrn);
+       check_err(stat,__LINE__,__FILE__);
+   }
+   
+   {				/* store topog */
+       MPI_Offset topog_start[RANK_topog];
+       MPI_Offset topog_count[RANK_topog];
+       float topog[LON_LEN*LAT_LEN];
+       
+       for(ii = 0; ii < LAT_LEN * LON_LEN; ii++) {
+	   topog[ii] = 33;
+       }
+       topog_start[0] = 0;
+       topog_start[1] = 0;
+       topog_start[2] = 0;
+       topog_count[0] = time_len;
+       topog_count[1] = lat_len;
+       topog_count[2] = lon_len;
+       stat = ncmpi_put_vara_float_all(ncid, topog_id, topog_start, topog_count, topog);
+       check_err(stat,__LINE__,__FILE__);
+   }
+   
+   {				/* store mslp */
+       MPI_Offset mslp_start[RANK_mslp];
+       MPI_Offset mslp_count[RANK_mslp];
+       float mslp[LON_LEN*LAT_LEN];
+       
+       for(ii = 0; ii < LAT_LEN * LON_LEN; ii++) {
+	   mslp[ii] = 44;
+       }
+       mslp_start[0] = 0;
+       mslp_start[1] = 0;
+       mslp_start[2] = 0;
+       mslp_count[0] = time_len;
+       mslp_count[1] = lat_len;
+       mslp_count[2] = lon_len;
+       stat = ncmpi_put_vara_float_all(ncid, mslp_id, mslp_start, mslp_count, mslp);
+       check_err(stat,__LINE__,__FILE__);
+   }
+   
+   {				/* store sfc_temp */
+       MPI_Offset sfc_temp_start[RANK_sfc_temp];
+       MPI_Offset sfc_temp_count[RANK_sfc_temp];
+       float sfc_temp[LON_LEN*LAT_LEN];
+       
+       for(ii = 0; ii < LAT_LEN * LON_LEN; ii++) {
+	   sfc_temp[ii] = 55;
+       }
+       sfc_temp_start[0] = 0;
+       sfc_temp_start[1] = 0;
+       sfc_temp_start[2] = 0;
+       sfc_temp_count[0] = time_len;
+       sfc_temp_count[1] = lat_len;
+       sfc_temp_count[2] = lon_len;
+       stat = ncmpi_put_vara_float_all(ncid, sfc_temp_id, sfc_temp_start, sfc_temp_count, sfc_temp);
+       check_err(stat,__LINE__,__FILE__);
+   }
+   
+   {		      /* store zonal_wnd */
+       /* Bug exposed when written in reverse order. */
+       for(i = LVL_LEN - 1; i>=0; i--)
+       /* for(i = 0; i < LVL_LEN; i++) */
+       {
+	   int izw;
+	   for(izw = 0; izw < TIME_LEN * LAT_LEN * LON_LEN; izw++) {
+	       zonal_wnd[izw] = 100 + i;
+	   }
+	   zonal_wnd_start[0] = 0;
+	   zonal_wnd_start[1] = i;
+	   zonal_wnd_start[2] = 0;
+	   zonal_wnd_start[3] = 0;
+	   zonal_wnd_count[0] = time_len;
+	   zonal_wnd_count[1] = 1;
+	   zonal_wnd_count[2] = lat_len;
+	   zonal_wnd_count[3] = lon_len;
+	   stat = ncmpi_put_vara_float_all(ncid, zonal_wnd_id, zonal_wnd_start, zonal_wnd_count, zonal_wnd);
+	   check_err(stat,__LINE__,__FILE__);
+       }
+   }
+   stat = ncmpi_close(ncid);
+   check_err(stat,__LINE__,__FILE__);
+   return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+    char filename[256], fill_filename[256], nofill_filename[256];
+    int rank, nprocs, err, nerrs=0;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    char cmd_str[256];
+    sprintf(cmd_str, "*** TESTING C   %s for fill/nofill modes ", argv[0]);
+    if (rank == 0) printf("%-66s ------ ", cmd_str);
+
+    sprintf(fill_filename, "%s.fill", filename);
+    sprintf(nofill_filename, "%s.nofill", filename);
+    nerrs += create_file(nofill_filename, NC_NOFILL);
+    nerrs += create_file(fill_filename, NC_FILL);
+    {
+       int ncid1, ncid2;
+       int nvars1, nvars2;
+       int varid;
+       int badvars;
+
+       /* compare data in two files created with nofill mode and fill
+	* mode, which should be identical if all the data were written */
+       err = ncmpi_open(MPI_COMM_WORLD, nofill_filename, NC_NOWRITE, MPI_INFO_NULL, &ncid1); ERR
+       err = ncmpi_open(MPI_COMM_WORLD, fill_filename, NC_NOWRITE, MPI_INFO_NULL, &ncid2); ERR
+
+       err = ncmpi_inq_nvars(ncid1, &nvars1); ERR
+       err = ncmpi_inq_nvars(ncid2, &nvars2); ERR
+       if (nvars1 != nvars2) {
+           printf("Number of variables disagree %d != %d\n",nvars1,nvars2);
+           nerrs++;
+       }
+       badvars = 0;
+       for(varid = 0; varid < nvars1; varid++) {
+	   MPI_Offset nvals, nn;
+	   int ndims, *dimids, dim;
+	   nc_type vtype;
+	   char varname1[NC_MAX_NAME];		   
+	   char varname2[NC_MAX_NAME];
+	   /* How many values in this variable to compare? */
+	   err = ncmpi_inq_varndims(ncid1, varid, &ndims); ERR
+	   dimids = malloc((ndims + 1) * sizeof(int));
+	   if (!dimids) printf("Error in file %s line %d\n",__FILE__,__LINE__);
+	   err = ncmpi_inq_vardimid (ncid1, varid, dimids); ERR
+	   nvals = 1;
+	   for(dim = 0; dim < ndims; dim++) {
+	       MPI_Offset len;
+	       err = ncmpi_inq_dimlen(ncid1, dimids[dim], &len); ERR
+	       nvals *= len;
+	   }
+	   err = ncmpi_inq_vartype(ncid1, varid, &vtype); ERR
+	   err = ncmpi_inq_varname(ncid1, varid, varname1); ERR
+	   err = ncmpi_inq_varname(ncid1, varid, varname2); ERR
+	   
+	   if (vtype != NC_CHAR) {  /* numeric data, just read in as doubles */
+	       double *data1, *data2;
+	       /* Allocate space to hold values in both files */
+	       data1 = malloc((nvals + 1) * sizeof(double));
+	       if (!data1) printf("Error in file %s line %d\n",__FILE__,__LINE__);
+	       data2 = malloc((nvals + 1) * sizeof(double));
+	       if (!data2) printf("Error in file %s line %d\n",__FILE__,__LINE__);
+	       /* Read in values */
+	       err = ncmpi_get_var_double_all(ncid1, varid, data1); ERR
+	       err = ncmpi_get_var_double_all(ncid2, varid, data2); ERR
+	       /* Compare values */
+	       for(nn = 0; nn < nvals; nn++) {
+		   if (data1[nn] != data2[nn]) {
+		       badvars++;
+		       fprintf(stderr, 
+			       "\tFrom nofill file, %s[%lu] = %.15g\tFrom fill file, %s[%lu] = %.15g\n", 
+			       varname1, (unsigned long)nn, data1[nn], varname2, (unsigned long)nn, data2[nn]);
+		       break;
+		   };
+	       }
+	       free(data1);
+	       free(data2);
+	   } else {		/* character data */
+	       char *data1, *data2;
+	       /* Allocate space to hold values in both files */
+	       data1 = malloc((nvals + 1) * sizeof(char));
+	       if (!data1) printf("Error in file %s line %d\n",__FILE__,__LINE__);
+	       data2 = malloc((nvals + 1) * sizeof(char));
+	       if (!data2) printf("Error in file %s line %d\n",__FILE__,__LINE__);
+	       /* Read in values */
+	       err = ncmpi_get_var_text_all(ncid1, varid, data1); ERR
+	       err = ncmpi_get_var_text_all(ncid2, varid, data2); ERR
+	       /* Compare values */
+	       for(nn = 0; nn < nvals; nn++) {
+		   if (data1[nn] != data2[nn]) {
+		       badvars++;
+		       fprintf(stderr, 
+			       "\tFrom nofill file, %s[%lu] = %d\tFrom fill file, %s[%lu] = %d\n", 
+			       varname1, (unsigned long)nn, data1[nn], varname2, (unsigned long)nn, data2[nn]);
+		       break;
+		   };
+	       }
+	       free(data1);
+	       free(data2);
+	   }
+	   free(dimids);
+       }
+       if(badvars > 0) printf("Error in file %s line %d\n",__FILE__,__LINE__);
+       err = ncmpi_close(ncid1); ERR
+       err = ncmpi_close(ncid2); ERR
+   }
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/test/nc_test/tst_norm.c b/test/nc_test/tst_norm.c
new file mode 100644
index 0000000..57a5261
--- /dev/null
+++ b/test/nc_test/tst_norm.c
@@ -0,0 +1,218 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: tst_norm.c 2219 2015-12-11 22:30:03Z wkliao $ */
+
+/* This program is based on the test program tst_norm.c of the netCDF package */
+
+/* This is part of the netCDF package.
+   Copyright 2006 University Corporation for Atmospheric Research/Unidata.
+   See COPYRIGHT file for conditions of use.
+
+   This is a very simple example which tests NFC normalization of 
+   Unicode names encoded with UTF-8.
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+/* The data file we will create. */
+#define UNITS "units"
+#define NDIMS 1
+#define NX 18
+
+#define ERR {if (err != NC_NOERR) {printf("Error at %s line %d: %s\n",__func__,__LINE__,ncmpi_strerror(err)); return 1;}}
+
+static
+int tst_norm(char *filename, int cmode)
+{
+   int ncid, dimid, varid;
+   int dimids[NDIMS];
+
+   /* unnormalized UTF-8 encoding for Unicode 8-character "Hello" in Greek: */
+   unsigned char uname_utf8[] = {
+       0x41,              	/* LATIN CAPITAL LETTER A */
+       0xCC, 0x80,		/* COMBINING GRAVE ACCENT */
+       0x41,              	/* LATIN CAPITAL LETTER A */
+       0xCC, 0x81,		/* COMBINING ACUTE ACCENT */
+       0x41,              	/* LATIN CAPITAL LETTER A */
+       0xCC, 0x82,		/* COMBINING CIRCUMFLEX ACCENT */
+       0x41,              	/* LATIN CAPITAL LETTER A */
+       0xCC, 0x83,		/* COMBINING TILDE */
+       0x41,              	/* LATIN CAPITAL LETTER A */
+       0xCC, 0x88,		/* COMBINING DIAERESIS */
+       0x41,              	/* LATIN CAPITAL LETTER A */
+       0xCC, 0x8A,		/* COMBINING RING ABOVE */
+       0x43,			/* LATIN CAPITAL LETTER C */
+       0xCC, 0xA7,		/* COMBINING CEDILLA */
+       0x45,			/* LATIN CAPITAL LETTER E */
+       0xCC, 0x80,		/* COMBINING GRAVE ACCENT */
+       0x45,			/* LATIN CAPITAL LETTER E */
+       0xCC, 0x81,		/* COMBINING ACUTE ACCENT */
+       0x45,			/* LATIN CAPITAL LETTER E */
+       0xCC, 0x82,		/* COMBINING CIRCUMFLEX ACCENT */
+       0x45,			/* LATIN CAPITAL LETTER E */
+       0xCC, 0x88,		/* COMBINING DIAERESIS */
+       0x49,			/* LATIN CAPITAL LETTER I */
+       0xCC, 0x80,		/* COMBINING GRAVE ACCENT */
+       0x49,			/* LATIN CAPITAL LETTER I */
+       0xCC, 0x81,		/* COMBINING ACUTE ACCENT */
+       0x49,			/* LATIN CAPITAL LETTER I */
+       0xCC, 0x82,		/* COMBINING CIRCUMFLEX ACCENT */
+       0x49,			/* LATIN CAPITAL LETTER I */
+       0xCC, 0x88,		/* COMBINING DIAERESIS */
+       0x4E,			/* LATIN CAPITAL LETTER N */
+       0xCC, 0x83,		/* COMBINING TILDE */
+       0x00
+   };
+
+   /* NFC normalized UTF-8 encoding for same Unicode string: */
+   unsigned char nname_utf8[] = {
+       0xC3, 0x80,	        /* LATIN CAPITAL LETTER A WITH GRAVE */
+       0xC3, 0x81,	        /* LATIN CAPITAL LETTER A WITH ACUTE */
+       0xC3, 0x82,	        /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
+       0xC3, 0x83,	        /* LATIN CAPITAL LETTER A WITH TILDE */
+       0xC3, 0x84,		/* LATIN CAPITAL LETTER A WITH DIAERESIS */
+       0xC3, 0x85,		/* LATIN CAPITAL LETTER A WITH RING ABOVE */
+       0xC3, 0x87,		/* LATIN CAPITAL LETTER C WITH CEDILLA */
+       0xC3, 0x88,		/* LATIN CAPITAL LETTER E WITH GRAVE */
+       0xC3, 0x89,		/* LATIN CAPITAL LETTER E WITH ACUTE */
+       0xC3, 0x8A,		/* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
+       0xC3, 0x8B,		/* LATIN CAPITAL LETTER E WITH DIAERESIS */
+       0xC3, 0x8C,		/* LATIN CAPITAL LETTER I WITH GRAVE */
+       0xC3, 0x8D,		/* LATIN CAPITAL LETTER I WITH ACUTE */
+       0xC3, 0x8E,		/* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
+       0xC3, 0x8F,		/* LATIN CAPITAL LETTER I WITH DIAERESIS */
+       0xC3, 0x91,	        /* LATIN CAPITAL LETTER N WITH TILDE */
+       0x00
+   };
+
+/* Unnormalized name used for dimension, variable, and attribute value */
+#define UNAME ((char *) uname_utf8)
+#define UNAMELEN (sizeof uname_utf8)
+/* Normalized name */
+#define NNAME ((char *) nname_utf8)
+#define NNAMELEN (sizeof nname_utf8)
+
+   char name_in[UNAMELEN + 1], strings_in[UNAMELEN + 1];
+   nc_type att_type;
+   MPI_Offset att_len;
+   int err, dimid_in, varid_in, attnum_in;
+   int attvals[] = {42};
+#define ATTNUM ((sizeof attvals)/(sizeof attvals[0]))
+
+   err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR
+
+   /* Define dimension with unnormalized Unicode UTF-8 encoded name */
+   err = ncmpi_def_dim(ncid, UNAME, NX, &dimid); ERR
+   dimids[0] = dimid;
+
+   /* Define variable with same name */
+   err = ncmpi_def_var(ncid, UNAME, NC_CHAR, NDIMS, dimids, &varid); ERR
+
+   /* Create string attribute with same value */
+   err = ncmpi_put_att_text(ncid, varid, UNITS, UNAMELEN, UNAME); ERR
+
+   /* Create int attribute with same name */
+   err = ncmpi_put_att_int(ncid, varid, UNAME, NC_INT, ATTNUM, attvals); ERR
+
+   /* Try to create dimension and variable with NFC-normalized
+    * version of same name.  These should fail, as unnormalized name
+    * should have been normalized in library, so these are attempts to
+    * create duplicate netCDF objects. */
+   if ((err = ncmpi_def_dim(ncid, NNAME, NX, &dimid)) != NC_ENAMEINUSE) {
+       printf("Error at line %d: expecting error code %d but got %d\n",__LINE__,NC_ENAMEINUSE,err);
+       return 1;
+   }
+
+   if ((err=ncmpi_def_var(ncid, NNAME, NC_CHAR, NDIMS, dimids, &varid)) != NC_ENAMEINUSE) {
+       printf("Error at line %d: expecting error code %d but got %d\n",__LINE__,NC_ENAMEINUSE,err);
+       return 1;
+   }
+   err = ncmpi_enddef(ncid); ERR
+
+   /* Write string data, UTF-8 encoded, to the file */
+   err = ncmpi_put_var_text_all(ncid, varid, UNAME); ERR
+   err = ncmpi_close(ncid); ERR
+
+   /* Check it out. */
+   err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+   err = ncmpi_inq_varid(ncid, UNAME, &varid); ERR
+   err = ncmpi_inq_varname(ncid, varid, name_in); ERR
+   err = strncmp(NNAME, name_in, NNAMELEN); ERR
+   err = ncmpi_inq_varid(ncid, NNAME, &varid_in); ERR
+   if ((err = ncmpi_inq_dimid(ncid, UNAME, &dimid_in)) || dimid != dimid_in)
+       {printf("Error at line %d\n",__LINE__);return 1;}
+   if ((err = ncmpi_inq_dimid(ncid, NNAME, &dimid_in)) || dimid != dimid_in)
+       {printf("Error at line %d\n",__LINE__);return 1;}
+   err = ncmpi_inq_att(ncid, varid, UNITS, &att_type, &att_len); ERR
+   if ( att_type != NC_CHAR || att_len != UNAMELEN)
+       {printf("Error at line %d\n",__LINE__);return 1;}
+   err = ncmpi_get_att_text(ncid, varid, UNITS, strings_in); ERR
+   strings_in[UNAMELEN] = '\0';
+   err = strncmp(UNAME, strings_in, UNAMELEN); ERR
+   if ((err = ncmpi_inq_attid(ncid, varid, UNAME, &attnum_in)) || ATTNUM != attnum_in)
+       {printf("Error at line %d\n",__LINE__);return 1;}
+   if ((err = ncmpi_inq_attid(ncid, varid, NNAME, &attnum_in)) || ATTNUM != attnum_in)
+       {printf("Error at line %d\n",__LINE__);return 1;}
+   err = ncmpi_close(ncid); ERR
+
+   return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+    char filename[256];
+    int rank, nprocs, cmode, err, nerrs=0, verbose=0;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    char cmd_str[256];
+    sprintf(cmd_str, "*** TESTING C   %s for emulating netCDF tst_norm ", argv[0]);
+    if (rank == 0) printf("%-66s ------ ", cmd_str);
+
+    if (verbose) printf("\n*** testing UTF-8 normalization...");
+
+    /* test CDF-2 format */
+    cmode = NC_CLOBBER | NC_64BIT_OFFSET;
+    nerrs += tst_norm(filename, cmode);
+
+    /* test CDF-5 format */
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    nerrs += tst_norm(filename, cmode);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/test/nc_test/tst_small.c b/test/nc_test/tst_small.c
new file mode 100644
index 0000000..10fd706
--- /dev/null
+++ b/test/nc_test/tst_small.c
@@ -0,0 +1,481 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: tst_small.c 2205 2015-11-28 20:41:50Z wkliao $ */
+
+/* This program is based on the test program tst_small.c of the netCDF package */
+
+/* This is part of the netCDF package. Copyright 2005 University
+   Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
+   conditions of use. See www.unidata.ucar.edu for more info.
+
+   Test small files.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+/* Test everything for classic, 64-bit offseti, and 64-bit data files. */
+#define NUM_FORMATS 3
+
+#define ATT_NAME "Atom"
+#define MAX_LEN 7   
+
+#define ERR {if (err != NC_NOERR) {printf("Error at %s line %d: %s\n",__func__,__LINE__,ncmpi_strerror(err)); return 1;}}
+
+static int
+test_small_atts(const char *testfile, int cmode)
+{
+   int ncid, err;
+   char att[MAX_LEN + 1], att_in[MAX_LEN + 1], source[MAX_LEN + 1] = "0123456";
+   int ndims, nvars, natts, unlimdimid;
+   MPI_Offset len_in;
+   int t, f;
+   
+   /* Run this with and without fill mode. */
+   for (f = 0; f < 2; f++)
+   {
+      /* Create small files with an attribute that grows by one each
+       * time. */
+      for (t = 1; t < MAX_LEN; t++)
+      {
+	 /* Create null-terminated text string of correct length. */
+	 strncpy(att, source, t);
+	 
+	 /* Create a file with one attribute. */
+         err = ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
+	 err = ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_NAME, t + 1, att); ERR
+	 if (f) { err=ncmpi_set_fill(ncid, NC_NOFILL, NULL); ERR}
+	 err=ncmpi_close(ncid); ERR;
+	 
+	 /* Reopen the file and check it. */
+         err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+	 err=ncmpi_inq(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR
+	 if (ndims != 0 && nvars != 0 && natts != 1 && unlimdimid != -1) {printf("Error at line %d\n",__LINE__);return 1;}
+	 err=ncmpi_inq_attlen(ncid, NC_GLOBAL, ATT_NAME, &len_in); ERR
+	 if (len_in != t + 1) {printf("Error at line %d\n",__LINE__);return 1;}
+	 err=ncmpi_get_att_text(ncid, NC_GLOBAL, ATT_NAME, att_in); ERR
+	 if (strncmp(att_in, att, t)) {printf("Error at line %d\n",__LINE__);return 1;}
+	 err=ncmpi_close(ncid); ERR
+      }
+   }
+   return 0;
+}
+
+#define DIM1_NAME "Time"
+#define DIM2_NAME "DataStrLen"
+#define VAR_NAME "Times"
+#define STR_LEN 19
+#define NUM_VALS 2
+#define NDIMS 2
+#define TITLE " OUTPUT FROM WRF V2.0.3.1 MODEL"
+#define ATT_NAME2 "TITLE"
+
+/* Test a small file with an unlimited dimension. NOTE: Normally I
+ * write a NULL terminator for my attributes and text strings, but
+ * this reproduces a bug that a fortran user sent us. So string data
+ * are written to the file without null terminators. - Ed */
+static int
+test_small_unlim(const char *testfile, int cmode)
+{
+   int i, err, ncid, dimids[NDIMS], varid;
+   char data[NUM_VALS][STR_LEN + 1], data_in[NUM_VALS][STR_LEN];
+   int ndims, nvars, natts, unlimdimid;
+   MPI_Offset start[NDIMS], count[NDIMS];
+
+   /* Create null-terminated text strings of correct length. */
+   /*for (i = 0; i < NUM_VALS; i++)
+     strcpy(data[i], source);*/
+   strcpy(data[0], "2005-04-11_12:00:00");
+   strcpy(data[1], "2005-04-11_13:00:00");
+   
+   /* Create a file with two dimensions, one unlimited, and one
+    * var, and a global att. */
+   err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
+   err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, dimids); ERR
+   err=ncmpi_def_dim(ncid, DIM2_NAME, STR_LEN, &dimids[1]); ERR
+   err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 2, dimids, &varid); ERR
+   err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_NAME2, strlen(TITLE), TITLE); ERR
+   err=ncmpi_enddef(ncid); ERR
+
+   /* Write some records of var data. */
+   count[0] = 1;
+   count[1] = STR_LEN;
+   start[1] = 0;
+   for (start[0] = 0; start[0] < NUM_VALS; start[0]++) {
+      err=ncmpi_put_vara_text_all(ncid, varid, start, count, data[start[0]]); ERR
+   }
+
+   /* We're done! */
+   err=ncmpi_close(ncid); ERR
+   
+   /* Reopen the file and check it. */
+   err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+   err=ncmpi_inq(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR
+   if (ndims != 2 && nvars != 1 && natts != 0 && unlimdimid != 0) {printf("Error at line %d\n",__LINE__);return 1;}
+   err=ncmpi_get_var_text_all(ncid, varid, (char *)data_in); ERR
+   for (i = 0; i < NUM_VALS; i++)
+      /* if (strncmp(data[i], data_in[i], STR_LEN)) {printf("Error at line %d\n",__LINE__);return 1;} */
+      if (strncmp(data[i], data_in[i], STR_LEN)) {
+printf("i=%d data=%s data_in=%s\n",i,data[i],data_in[i]);
+      }
+   err=ncmpi_close(ncid); ERR
+   return 0;
+}
+
+/* Test a small file with a fixed dimension. */
+static int
+test_small_fixed(const char *testfile, int cmode)
+{
+   int i, err, ncid, dimids[NDIMS], varid;
+   char data[NUM_VALS][STR_LEN + 1], data_in[NUM_VALS][STR_LEN];
+   int ndims, nvars, natts, unlimdimid;
+   MPI_Offset start[NDIMS], count[NDIMS];
+
+   /* Create null-terminated text strings of correct length. */
+   /*for (i = 0; i < NUM_VALS; i++)
+     strcpy(data[i], source);*/
+   strcpy(data[0], "2005-04-11_12:00:00");
+   strcpy(data[1], "2005-04-11_13:00:00");
+   
+   /* Create a file with two dimensions, one unlimited, and one
+    * var, and a global att. */
+   err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
+   err=ncmpi_def_dim(ncid, DIM1_NAME, NUM_VALS, dimids); ERR
+   err=ncmpi_def_dim(ncid, DIM2_NAME, STR_LEN, &dimids[1]); ERR
+   err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, NDIMS, dimids, &varid); ERR
+   err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_NAME2, strlen(TITLE), TITLE); ERR
+   err=ncmpi_enddef(ncid); ERR
+
+   /* Write some records of var data. */
+   count[0] = 1;
+   count[1] = STR_LEN;
+   start[1] = 0;
+   for (start[0] = 0; start[0] < NUM_VALS; start[0]++) {
+      err=ncmpi_put_vara_text_all(ncid, varid, start, count, data[start[0]]); ERR
+   }
+
+   /* We're done! */
+   err=ncmpi_close(ncid); ERR
+   
+   /* Reopen the file and check it. */
+   err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+   err=ncmpi_inq(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR
+   if (ndims != 2 && nvars != 1 && natts != 0 && unlimdimid != -1) {printf("Error at line %d\n",__LINE__);return 1;}
+   err=ncmpi_get_var_text_all(ncid, varid, (char *)data_in); ERR
+   for (i = 0; i < NUM_VALS; i++)
+      if (strncmp(data[i], data_in[i], STR_LEN)) {printf("Error at line %d\n",__LINE__);return 1;}
+   err=ncmpi_close(ncid); ERR
+   return 0;
+}
+
+/* Test a small file with one var. */
+static int
+test_small_one(const char *testfile, int cmode)
+{
+   int err, ncid, dimid, varid;
+   char data = 'h', data_in;
+   int ndims, nvars, natts, unlimdimid;
+   MPI_Offset start[NDIMS], count[NDIMS];
+
+   /* Create a file with one ulimited dimensions, and one var. */
+   err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
+   err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR
+   err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid); ERR
+   err=ncmpi_enddef(ncid); ERR
+
+   /* Write one record of var data, a single character. */
+   count[0] = 1;
+   start[0] = 0;
+   err=ncmpi_put_vara_text_all(ncid, varid, start, count, &data); ERR
+
+   /* We're done! */
+   err=ncmpi_close(ncid); ERR
+   
+   /* Reopen the file and check it. */
+   err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+   err=ncmpi_inq(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR
+   if (ndims != 1 && nvars != 1 && natts != 0 && unlimdimid != 0) {printf("Error at line %d\n",__LINE__);return 1;}
+   err=ncmpi_get_var_text_all(ncid, varid, &data_in); ERR
+   if (data_in != data) {printf("Error at line %d\n",__LINE__);return 1;}
+   err=ncmpi_close(ncid); ERR
+   return 0;
+}
+
+#define ONE_DIM 1
+#define MAX_RECS 10
+
+/* Test a small file with one record var, which grows. */
+static int
+test_one_growing(const char *testfile, int cmode)
+{
+   int err, ncid, dimid, varid;
+   char data[MAX_RECS], data_in;
+   MPI_Offset start[ONE_DIM], count[ONE_DIM], index[ONE_DIM], len_in;
+   int r, f;
+
+   /* Create some phoney data. */
+   for (data[0] = 'a', r = 1; r < MAX_RECS; r++)
+      data[r] = data[r - 1] + 1;
+
+   /* Run this with and without fill mode. */
+   for (f = 0; f < 2; f++)
+   {
+      /* Create a file with one ulimited dimensions, and one var. */
+      err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR
+      err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid); ERR
+      err=ncmpi_close(ncid); ERR
+
+      /* Normally one would not close and reopen the file for each
+       * record, but I am giving the library a little work-out here... */
+      for (r = 0; r < MAX_RECS; r++)
+      {
+	 /* Write one record of var data, a single character. */
+         err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+	 /* if (f) { err=ncmpi_set_fill(ncid, NC_NOFILL, NULL); ERR} */
+	 count[0] = 1;
+	 start[0] = r;
+	 err=ncmpi_put_vara_text_all(ncid, varid, start, count, &data[r]); ERR
+	 err=ncmpi_close(ncid); ERR
+      
+	 /* Reopen the file and check it. */
+         err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+	 err=ncmpi_inq_dimlen(ncid, 0, &len_in); ERR
+	 if (len_in != r + 1) {printf("Error at line %d\n",__LINE__);return 1;}
+	 index[0] = r;
+	 err=ncmpi_begin_indep_data(ncid); ERR
+	 err=ncmpi_get_var1_text(ncid, 0, index, &data_in); ERR
+	 if (data_in != data[r]) {printf("Error at line %d\n",__LINE__);return 1;}
+	 err=ncmpi_close(ncid); ERR
+      } /* Next record. */
+   }
+   return 0;
+}
+
+#define ONE_DIM 1
+#define MAX_RECS 10
+
+/* Test a small file with one record var, which grows, and has
+ * attributes. */
+static int
+test_one_growing_with_att(const char *testfile, int cmode)
+{
+   int err, ncid, dimid, varid;
+   char data[MAX_RECS], data_in;
+   char att_name[NC_MAX_NAME + 1];
+   MPI_Offset start[ONE_DIM], count[ONE_DIM], index[ONE_DIM], len_in;
+   int r;
+
+   /* Create a file with one ulimited dimensions, and one var. */
+   err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
+   err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR
+   err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid); ERR
+   err=ncmpi_close(ncid); ERR
+
+   /* Create some phoney data. */
+   for (data[0] = 'a', r = 1; r < MAX_RECS; r++)
+      data[r] = data[r - 1] + 1;
+
+   /* Normally one would not close and reopen the file for each
+    * record, nor add an attribute each time I add a record, but I am
+    * giving the library a little work-out here... */
+   for (r = 0; r < MAX_RECS; r++)
+   {
+      /* Write one record of var data, a single character. */
+      err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+      count[0] = 1;
+      start[0] = r;
+      err=ncmpi_put_vara_text_all(ncid, varid, start, count, &data[r]); ERR
+      sprintf(att_name, "a_%d", data[r]);
+      err=ncmpi_redef(ncid); ERR
+      err=ncmpi_put_att_text(ncid, varid, att_name, 1, &data[r]); ERR
+      err=ncmpi_close(ncid); ERR
+      
+      /* Reopen the file and check it. */
+      err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_inq_dimlen(ncid, 0, &len_in); ERR
+      if (len_in != r + 1) {printf("Error at line %d\n",__LINE__);return 1;}
+      index[0] = r;
+      err=ncmpi_begin_indep_data(ncid); ERR
+      err=ncmpi_get_var1_text(ncid, 0, index, &data_in); ERR
+      if (data_in != data[r]) {printf("Error at line %d\n",__LINE__);return 1;}
+      err=ncmpi_get_att_text(ncid, varid, att_name, &data_in); ERR
+      if (data_in != data[r]) {printf("Error at line %d\n",__LINE__);return 1;}
+      err=ncmpi_close(ncid); ERR
+   } /* Next record. */
+   return 0;
+}
+
+#define VAR_NAME2 "var2"
+#define NUM_VARS 2
+
+/* Test a small file with two record vars, which grow, and has
+ * attributes added. */
+static int
+test_two_growing_with_att(const char *testfile, int cmode)
+{
+   int err, ncid, dimid, varid[NUM_VARS];
+   char data[MAX_RECS], data_in;
+   char att_name[NC_MAX_NAME + 1];
+   MPI_Offset start[ONE_DIM], count[ONE_DIM], index[ONE_DIM], len_in;
+   int v, r;
+
+   /* Create a file with one ulimited dimensions, and one var. */
+   err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
+   err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR
+   err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid[0]); ERR
+   err=ncmpi_def_var(ncid, VAR_NAME2, NC_CHAR, 1, &dimid, &varid[1]); ERR
+   err=ncmpi_close(ncid); ERR
+
+   /* Create some phoney data. */
+   for (data[0] = 'a', r = 1; r < MAX_RECS; r++)
+      data[r] = data[r - 1] + 1;
+
+   /* Normally one would not close and reopen the file for each
+    * record, nor add an attribute each time I add a record, but I am
+    * giving the library a little work-out here... */
+   for (r = 0; r < MAX_RECS; r++)
+   {
+      /* Write one record of var data, a single character. */
+      err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_WRITE, MPI_INFO_NULL, &ncid); ERR
+      count[0] = 1;
+      start[0] = r;
+      sprintf(att_name, "a_%d", data[r]);
+      for (v = 0; v < NUM_VARS; v++)
+      {
+	 err=ncmpi_put_vara_text_all(ncid, varid[v], start, count, &data[r]); ERR
+	 err=ncmpi_redef(ncid); ERR
+	 err=ncmpi_put_att_text(ncid, varid[v], att_name, 1, &data[r]); ERR
+	 err=ncmpi_enddef(ncid); ERR
+      }
+      err=ncmpi_close(ncid); ERR
+      
+      /* Reopen the file and check it. */
+      err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+      err=ncmpi_inq_dimlen(ncid, 0, &len_in); ERR
+      if (len_in != r + 1) {printf("Error at line %d\n",__LINE__);return 1;}
+      index[0] = r;
+      err=ncmpi_begin_indep_data(ncid); ERR
+      for (v = 0; v < NUM_VARS; v++)
+      {
+	 err=ncmpi_get_var1_text(ncid, varid[v], index, &data_in); ERR
+	 if (data_in != data[r]) {printf("Error at line %d\n",__LINE__);return 1;}
+      }
+      err=ncmpi_close(ncid); ERR
+   } /* Next record. */
+   return 0;
+}
+
+/* Test a small file with one var and one att. */
+static int
+test_one_with_att(const char *testfile, int cmode)
+{
+   int err, ncid, dimid, varid;
+   char data = 'h', data_in;
+   int ndims, nvars, natts, unlimdimid;
+   MPI_Offset start[NDIMS], count[NDIMS];
+
+   /* Create a file with one ulimited dimensions, and one var. */
+   err=ncmpi_create(MPI_COMM_WORLD, testfile,cmode, MPI_INFO_NULL, &ncid); ERR
+   err=ncmpi_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid); ERR
+   err=ncmpi_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid); ERR
+   err=ncmpi_put_att_text(ncid, NC_GLOBAL, ATT_NAME, 1, &data); ERR
+   err=ncmpi_enddef(ncid); ERR
+
+   /* Write one record of var data, a single character. */
+   count[0] = 1;
+   start[0] = 0;
+   err=ncmpi_put_vara_text_all(ncid, varid, start, count, &data); ERR
+
+   /* We're done! */
+   err=ncmpi_close(ncid); ERR
+   
+   /* Reopen the file and check it. */
+   err=ncmpi_open(MPI_COMM_WORLD, testfile, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+   err=ncmpi_inq(ncid, &ndims, &nvars, &natts, &unlimdimid); ERR
+   if (ndims != 1 && nvars != 1 && natts != 0 && unlimdimid != 0) {printf("Error at line %d\n",__LINE__);return 1;}
+   err=ncmpi_get_var_text_all(ncid, varid, &data_in); ERR
+   if (data_in != data) {printf("Error at line %d\n",__LINE__);return 1;}
+   err=ncmpi_get_att_text(ncid, NC_GLOBAL, ATT_NAME, &data_in); ERR
+   if (data_in != data) {printf("Error at line %d\n",__LINE__);return 1;}
+   err=ncmpi_close(ncid); ERR
+   return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    char filename[256];
+    int i, rank, nprocs, err, nerrs=0, verbose=0;
+    int cmode[NUM_FORMATS]={0, NC_64BIT_OFFSET, NC_64BIT_DATA};
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    char cmd_str[256];
+    sprintf(cmd_str, "*** TESTING C   %s for emulating netCDF tst_small ", argv[0]);
+    if (rank == 0) printf("%-66s ------ ", cmd_str);
+
+    for (i=0; i<NUM_FORMATS; i++) {
+      if (verbose) printf("*** testing simple small file with a global attribute...");
+      nerrs += test_small_atts(filename, cmode[i]|NC_CLOBBER);
+      
+      if (verbose) printf("*** testing simple small file with fixed dimensions...");
+      nerrs += test_small_fixed(filename, cmode[i]|NC_CLOBBER);
+
+      if (verbose) printf("*** testing simple small file with an unlimited dimension...");
+      nerrs += test_small_unlim(filename, cmode[i]|NC_CLOBBER);
+      
+      if (verbose) printf("*** testing small file with one variable...");
+      nerrs += test_small_one(filename, cmode[i]|NC_CLOBBER);
+      
+      if (verbose) printf("*** testing small file with one variable and one att...");
+      nerrs += test_one_with_att(filename, cmode[i]|NC_CLOBBER);
+      
+      if (verbose) printf("*** testing small file with one record variable, which grows...");
+      nerrs += test_one_growing(filename, cmode[i]|NC_CLOBBER);
+
+      if (verbose) printf("*** testing small file with one growing record "
+	     "variable, with attributes added...");
+      nerrs += test_one_growing_with_att(filename, cmode[i]|NC_CLOBBER);
+
+      if (verbose) printf("*** testing small file with two growing record "
+	     "variables, with attributes added...");
+      nerrs += test_two_growing_with_att(filename, cmode[i]|NC_CLOBBER);
+   }
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/nc_test/util.c b/test/nc_test/util.c
new file mode 100644
index 0000000..620436f
--- /dev/null
+++ b/test/nc_test/util.c
@@ -0,0 +1,1055 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: util.c 2293 2016-01-06 03:43:04Z wkliao $
+ */
+
+#include <math.h> /* floor() */
+#include "tests.h"
+
+/* Prototypes */
+
+void
+print_nok(int nok)
+{
+    if (verbose || nfails > 0)
+        print("\n");
+    print("%4d good comparisons. ", nok);
+}
+
+
+/* Is value within external type range? */
+int
+inRange(const double value, const nc_type datatype)
+{
+    switch (datatype) {
+        case NC_CHAR:   return value >= X_CHAR_MIN   && value <= X_CHAR_MAX;
+        case NC_BYTE:   return value >= X_BYTE_MIN   && value <= X_BYTE_MAX;
+        case NC_SHORT:  return value >= X_SHORT_MIN  && value <= X_SHORT_MAX;
+        case NC_INT:    return value >= X_INT_MIN    && value <= X_INT_MAX;
+        case NC_FLOAT:  return value >= X_FLOAT_MIN  && value <= X_FLOAT_MAX;
+        case NC_DOUBLE: return value >= X_DOUBLE_MIN && value <= X_DOUBLE_MAX;
+        case NC_UBYTE:  return value >= 0            && value <= X_UCHAR_MAX;
+        case NC_USHORT: return value >= 0            && value <= X_USHORT_MAX;
+        case NC_UINT:   return value >= 0            && value <= X_UINT_MAX;
+        case NC_INT64:  return value >= X_INT64_MIN  && value <= X_INT64_MAX;
+        case NC_UINT64: return value >= 0            && value <= X_UINT64_MAX;
+        default:
+            assert(0);
+	    return(0);
+    }
+}
+
+static int
+inRange_uchar(const double value, const nc_type datatype)
+{
+    /* check value of type datatype if within uchar range */
+
+    if (datatype == NC_BYTE) {
+        /* netCDF specification make a special case for type conversion between
+         * uchar and scahr: do not check for range error. See
+         * http://www.unidata.ucar.edu/software/netcdf/docs_rc/data_type.html#type_conversion
+         */
+        return(value >= 0 && value <= 255);
+        /* this is to ensure value is within the range of uchar */
+    }
+    /* else */
+    return inRange(value, datatype);
+}
+
+static int
+inRange_float(const double value, const nc_type datatype)
+{
+    double min, max;
+
+    switch (datatype) {
+        case NC_CHAR:   min = X_CHAR_MIN;   max = X_CHAR_MAX;  break;
+        case NC_BYTE:   min = X_BYTE_MIN;   max = X_BYTE_MAX;  break;
+        case NC_SHORT:  min = X_SHORT_MIN;  max = X_SHORT_MAX; break;
+        case NC_INT:    min = X_INT_MIN;    max = X_INT_MAX;   break;
+        case NC_FLOAT:
+            if (FLT_MAX < X_FLOAT_MAX) {
+                min = (-FLT_MAX);
+                max = FLT_MAX;
+            } else {
+                min = X_FLOAT_MIN;
+                max = X_FLOAT_MAX;
+            }
+            break;
+        case NC_DOUBLE:
+            if (FLT_MAX < X_DOUBLE_MAX) {
+                min = (-FLT_MAX);
+                max = FLT_MAX;
+            } else {
+                min = X_DOUBLE_MIN;
+                max = X_DOUBLE_MAX;
+            }
+            break;
+        case NC_UBYTE:  min = 0;            max = X_UCHAR_MAX;  break;
+        case NC_USHORT: min = 0;            max = X_USHORT_MAX; break;
+        case NC_UINT:   min = 0;            max = X_UINT_MAX;   break;
+        case NC_INT64:  min = X_INT64_MIN;  max = X_INT64_MAX;  break;
+        case NC_UINT64: min = 0;            max = X_UINT64_MAX; break;
+        default:
+            min = 0.0;
+            max = 0.0;
+            assert(0);
+    }
+    if (!( value >= min && value <= max)) {
+#if 0    /* DEBUG */
+        if (datatype == NC_FLOAT) {
+            fprintf(stderr, "\n");
+            fprintf(stderr, "min   % .17e\n", min);
+            fprintf(stderr, "value % .17e\n", value);
+            fprintf(stderr, "max   % .17e\n", max);
+        }
+#endif
+        return 0;
+    }
+#if FLT_MANT_DIG != DBL_MANT_DIG
+    /* else */
+    {
+        const float fvalue = value;
+        return fvalue >= min && fvalue <= max;
+    }
+#else
+    return 1;
+#endif
+}
+
+/* wrapper for inRange to handle special NC_BYTE/uchar adjustment */
+/* this function checks whether "value" to be casted to type "itype" is
+ * within the range of external "datatype".
+ */
+int
+inRange3(const double    value, 
+         const nc_type   datatype,
+         const nct_itype itype)
+{
+    /* netCDF specification make a special case for type conversion between
+     * uchar and scahr: do not check for range error. See
+     * http://www.unidata.ucar.edu/software/netcdf/docs_rc/data_type.html#type_conversion
+     * The _uchar and _schar functions were introduced in netCDF-3 to eliminate
+     * an ambiguity, and support both signed and unsigned byte data. In
+     * netCDF-2, whether the external NC_BYTE type represented signed or
+     * unsigned values was left up to the user. In netcdf-3, we treat NC_BYTE
+     * as signed for the purposes of conversion to short, int, long, float, or
+     * double. (Of course, no conversion takes place when the internal type is
+     * signed char.) In the _uchar functions, we treat NC_BYTE as if it were
+     * unsigned. Thus, no NC_ERANGE error can occur converting between NC_BYTE
+     * and unsigned char.
+     */
+    switch (itype) {
+        case NCT_UCHAR:
+            return inRange_uchar(value, datatype);
+        case NCT_FLOAT:
+            return inRange_float(value, datatype);
+        default:
+            break;
+    }
+    return inRange(value, datatype);
+}
+
+
+/* 
+ *  Does x == y, where one is internal and other external (netCDF)?  
+ *  Use tolerant comparison based on IEEE FLT_EPSILON or DBL_EPSILON.
+ */
+int
+equal(double x, 
+      double y, 
+      nc_type      extType,     /* external data type */
+      nct_itype    itype)
+{
+    const double flt_epsilon = 1.19209290E-07;
+    const double dbl_epsilon = 2.2204460492503131E-16;
+    double epsilon;
+
+    epsilon = extType == NC_FLOAT ||
+              itype == NCT_FLOAT ? flt_epsilon : dbl_epsilon;
+
+    if (extType == NC_CHAR && itype == NCT_TEXT) {
+        /* because in-memory data type char can be signed or unsigned,
+         * type cast the value from external NC_CHAR before the comparison
+         */
+        char x2 = (char) x;
+        char y2 = (char) y;
+        x = x2;
+        y = y2;
+    }
+    return ABS(x-y) <= epsilon * MAX( ABS(x), ABS(y));
+}
+
+/* this function is for the APIs without itype, i.e. extType == itype */
+int
+equal2(
+    double x,
+    double y,
+    nc_type extType)    /* external data type */
+{
+    const double flt_epsilon = 1.19209290E-07;
+    const double dbl_epsilon = 2.2204460492503131E-16;
+    double epsilon;
+
+    epsilon = extType == NC_FLOAT ? flt_epsilon : dbl_epsilon;
+
+    if (extType == NC_CHAR) {
+        /* because in-memory data type char can be signed or unsigned,
+         * type cast the value from external NC_CHAR before the comparison
+         */
+        char x2 = (char) x;
+        char y2 = (char) y;
+        x = x2;
+        y = y2;
+    }
+
+    return ABS(x-y) <= epsilon * MAX( ABS(x), ABS(y));
+}
+
+/* Test whether two int vectors are equal. If so return 1, else 0  */
+int
+int_vec_eq(const int *v1, const int *v2, const int n)
+{
+    int i;
+    for (i= 0; i < n && v1[i] == v2[i]; i++)
+    ;
+    return i == n;
+}
+
+
+/*
+ *  Generate random integer from 0 to n-1
+ *  Like throwing an n-sided dice marked 0, 1, 2, ..., n-1
+ */
+int roll( int n )
+{
+    int  r;
+
+    do
+    /*
+     * Compute a pseudo-random value between 0.0 and 1.0, multiply
+     * it by n-1, and then find the nearest integer.
+     *
+     * We don't use RAND_MAX here because not all compilation
+     * environments define it (e.g. gcc(1) under SunOS 4.1.4).
+     */
+    r = ((rand() % 32768) / 32767.0) * (n - 1) + 0.5;
+    while (r >= n);
+
+    return r;
+}
+
+
+/*
+ *      Convert number to mixed base
+ *
+ *      E.g. to convert 41 inches to yards, feet and inches:
+ *      MPI_Offset base[] = {1, 3, 12};
+ *      MPI_Offset result[3];
+ *      status = toMixedBase(41, 3, base, result);
+ *
+ *      Author: Harvey Davies, Unidata/UCAR, Boulder, Colorado
+ *
+ *      wkliao: this is like finding the N-dimensional array index
+ *              given a linearized length. For example, given a 2x3x4 array,
+ *              if number==37, then the result=(2,2,5)
+ *              because 37 = 2x(3x4) + 2x(4) + 5
+ */
+int
+toMixedBase(size_t           number,   /* to be converted to mixed base */
+            size_t           length,
+            const MPI_Offset base[],   /* in:  [length], base[0] ignored */
+            MPI_Offset       result[]) /* out: [length] */
+{
+    size_t i;
+
+    if (length > 0) {
+        for (i = length - 1; i > 0; i--) {
+            if (base[i] == 0) return 1;
+            result[i] = number % base[i];
+            number = number / base[i];
+        }
+        result[0] = number;
+    }
+    return 0;
+}
+
+/*
+ *      Convert number from mixed base
+ *
+ *      E.g. to convert 1 yard, 0 feet, 5 inches to inches:
+ *      MPI_Offset number[] = {1, 0, 5};
+ *      MPI_Offset base[] = {1, 3, 12};
+ *      inches = fromMixedBase(3, number, base);
+ *
+ *      Author: Harvey Davies, Unidata/UCAR, Boulder, Colorado
+ */
+size_t
+fromMixedBase(size_t     length,
+              MPI_Offset number[],  /* [length] */
+              MPI_Offset base[])    /* [length], base[0] ignored */
+{
+    size_t i;
+    size_t result = 0;
+
+    for (i = 1; i < length; i++) {
+        result += number[i-1];
+        result *= base[i];
+    }
+    if (length > 0)
+        result += number[i-1];
+    return result;
+}
+
+
+/* Convert any nc_type to double */
+int nc2dbl ( const nc_type datatype, const void *p, double *result)
+{
+    if ( ! p ) return 2;
+    if ( ! result ) return 3;
+    switch (datatype) {
+        case NC_CHAR:   *result = *((signed char *)    p); break;
+        case NC_BYTE:   *result = *((signed char *)    p); break;
+        case NC_UBYTE:  *result = *((unsigned char *)  p); break;
+        case NC_SHORT:  *result = *((short *)          p); break;
+        case NC_USHORT: *result = *((unsigned short *) p); break;
+        case NC_INT:
+#if INT_MAX >= X_INT_MAX
+            *result = *((int *) p); break;
+#else
+            *result = *((long *) p); break;
+#endif
+        case NC_UINT:
+#if UINT_MAX >= X_UINT_MAX
+            *result = *((unsigned int *) p); break;
+#else
+            *result = *((unsigned long *) p); break;
+#endif
+        case NC_FLOAT:  *result = *((float *)              p); break;
+        case NC_DOUBLE: *result = *((double *)             p); break;
+        case NC_INT64:  *result = *((long long *)          p); break;
+        case NC_UINT64: *result = *((unsigned long long *) p); break;
+        default: return 1;
+    }
+    return 0;
+}
+
+
+/* Convert double to any nc_type */
+int dbl2nc ( const double d, const nc_type datatype, void *p)
+{
+    double r;   /* rounded value */
+
+    if (p == NULL) return 1;
+    switch (datatype) {
+        case NC_CHAR:
+            r = floor(0.5+d);
+            /* d is obtained from hash() which may be set to X_CHAR_MIN (0)
+             * or X_CHAR_MAX (255). When in-memory data type char is signed
+             * (i.e. ranged from -128 to 127), we should still allow a type
+             * cast a unsigned value > 127 to a signed char without reporting
+             * it as a range error.
+             */
+            if ( r < X_CHAR_MIN || r > X_CHAR_MAX ) return 2;
+#if defined(__CHAR_UNSIGNED__) && __CHAR_UNSIGNED__ != 0
+            *((signed char*) p) = r;
+#else
+            *((char   *) p) = r;
+#endif
+            break;
+        case NC_BYTE:
+            r = floor(0.5+d);
+            if ( r < schar_min  ||  r > schar_max )  return 2;
+            *((signed char *) p) = r;
+            break;
+        case NC_UBYTE:
+            r = floor(0.5+d);
+            if ( r < 0.0  ||  r > uchar_max )  return 2;
+            *((unsigned char *) p) = r;
+            break;
+        case NC_SHORT:
+            r = floor(0.5+d);
+            if ( r < short_min  ||  r > short_max )  return 2;
+            *((short *) p) = r;
+            break;
+        case NC_USHORT:
+            r = floor(0.5+d);
+            if ( r < 0.0  ||  r > ushort_max )  return 2;
+            *((unsigned short *) p) = r;
+            break;
+        case NC_INT:
+            r = floor(0.5+d);
+            if ( r < long_min  ||  r > long_max )  return 2;
+#if INT_MAX >= X_INT_MAX
+            *((int   *) p) = r;
+#else
+            *((long   *) p) = r;
+#endif
+            break;
+        case NC_UINT:
+            r = floor(0.5+d);
+            if ( r < 0.0  ||  r > uint_max )  return 2;
+#if UINT_MAX >= X_UINT_MAX
+            *((unsigned int  *) p) = r;
+#else
+            *((unsigned long *) p) = r;
+#endif
+            break;
+        case NC_FLOAT:
+            if ( fabs(d) > float_max )  return 2;
+            *((float  *) p) = d;
+            break;
+        case NC_DOUBLE:
+            *((double *) p) = d;
+            break;
+        case NC_INT64:
+            r = floor(0.5+d);
+            if ( r < int64_min  ||  r > int64_max )  return 2;
+            *((long long *) p) = r;
+            break;
+        case NC_UINT64:
+            r = floor(0.5+d);
+            if ( r < 0.0  ||  r > uint64_max )  return 2;
+            *((unsigned long long *) p) = r;
+            break;
+        default:
+            return 1;
+    }
+    return 0;
+}
+
+
+#define FUZZ (1.19209290E-07)
+
+/* Generate data values as function of type, rank (-1 for attribute), index */
+double
+hash( const nc_type type, const int rank, const MPI_Offset *index ) 
+{
+    double base;
+    double result = 0.0;
+    int  d;       /* index of dimension */
+
+    /* If vector then elements 0 & 1 are min & max. Elements 2 & 3 are */
+    /* just < min & > max (except for NC_CHAR & NC_DOUBLE) */
+    if (abs(rank) == 1 && index[0] <= 3) {
+        switch (index[0]) {
+            case 0:
+                switch (type) {  /* test if can get/put MIN value */
+                    case NC_CHAR:   return X_CHAR_MIN;
+                    case NC_BYTE:   return X_BYTE_MIN;
+                    case NC_SHORT:  return X_SHORT_MIN;
+                    case NC_INT:    return X_INT_MIN;
+                    case NC_FLOAT:  return X_FLOAT_MIN;
+                    case NC_DOUBLE: return X_DOUBLE_MIN;
+                    case NC_UBYTE:  return 0;
+                    case NC_USHORT: return 0;
+                    case NC_UINT:   return 0;
+                    case NC_INT64:  return X_INT_MIN - 128.0; /* slight smaller
+                                                                 than INT_MIN */
+                    case NC_UINT64: return 0;
+                    default:  assert(0);
+                }
+            case 1:
+                switch (type) {  /* test if can get/put MAX value */
+                    case NC_CHAR:   return X_CHAR_MAX;
+                    case NC_BYTE:   return X_BYTE_MAX;
+                    case NC_SHORT:  return X_SHORT_MAX;
+                    case NC_INT:    return X_INT_MAX;
+                    case NC_FLOAT:  return X_FLOAT_MAX;
+                    case NC_DOUBLE: return X_DOUBLE_MAX;
+                    case NC_UBYTE:  return X_UCHAR_MAX;
+                    case NC_USHORT: return X_USHORT_MAX;
+                    case NC_UINT:   return X_UINT_MAX;
+                    case NC_INT64:  return X_INT_MAX + 128.0;
+                                    /* slightly bigger than INT_MAX */
+                    case NC_UINT64: return X_UINT_MAX + 128.0;
+                                    /* slightly bigger than UINT_MAX */
+                    default:  assert(0);
+                }
+            case 2:
+                switch (type) {  /* test if can detect out-of-boundary value */
+                    case NC_CHAR:   return 'A';
+                    case NC_BYTE:   return X_BYTE_MIN-1.0;
+                    case NC_SHORT:  return X_SHORT_MIN-1.0;
+                    case NC_INT:    return X_INT_MIN-1.0;
+                    case NC_FLOAT:  return X_FLOAT_MIN * (1.0 + FUZZ);
+                    case NC_DOUBLE: return -1.0;  /* skip test */
+                    case NC_UBYTE:  return -1.0;
+                    case NC_USHORT: return -1.0;
+                    case NC_UINT:   return -1.0;
+                    case NC_INT64:  return -1.0;  /* skip test */
+                    case NC_UINT64: return -1.0;
+                    default:  assert(0);
+                }
+            case 3:
+                switch (type) {  /* test if can detect out-of-boundary value */
+                    case NC_CHAR:   return 'Z';
+                    case NC_BYTE:   return X_BYTE_MAX  +1.0;
+                    case NC_SHORT:  return X_SHORT_MAX +1.0;
+                    case NC_INT:    return X_INT_MAX   +1.0;
+                    case NC_FLOAT:  return X_FLOAT_MAX * (1.0 + FUZZ);
+                    case NC_DOUBLE: return 1.0;    /* skip test */
+                    case NC_UBYTE:  return X_UCHAR_MAX +1.0;
+                    case NC_USHORT: return X_USHORT_MAX+1.0;
+                    case NC_UINT:   return X_UINT_MAX  +1.0;
+                    case NC_INT64:  return 1.0;    /* skip test */
+                    case NC_UINT64: return 1.0;    /* skip test */
+                    default:  assert(0);
+                }
+        }
+    } else { /* for array with more than 4 elements, pick some random numbers */
+        /* wkliao: what is "base" ? */
+        switch (type) {
+            case NC_CHAR:   base =  2;  break;
+            case NC_BYTE:   base = -2;  break;
+            case NC_SHORT:  base = -5;  break;
+            case NC_INT:    base = -20; break;
+            case NC_FLOAT:  base = -9;  break;
+            case NC_DOUBLE: base = -10; break;
+
+            /* not sure what right values are */
+            case NC_UBYTE:   base =   2;  break;
+            case NC_USHORT:  base =   5;  break;
+            case NC_UINT:    base =  20;  break;
+            case NC_INT64:   base = -20;  break;
+            case NC_UINT64:  base =  20;  break;
+            default:
+                base = 0;
+                assert(0);
+        }
+        if (rank < 0)  /* attribute */
+            result = base * 7;
+        else
+            result = base * (rank + 1);
+
+        for (d=0; d<abs(rank); d++)
+            result = base * (result + index[d]);
+    }
+    return result;
+}
+
+/* wrapper for hash to handle special NC_BYTE/uchar adjustment */
+double
+hash4(const nc_type     type, 
+      const int         rank, 
+      const MPI_Offset *index, 
+      const nct_itype   itype)
+{
+    double result;
+
+    result = hash(type, rank, index);
+    if (itype == NCT_UCHAR && type == NC_BYTE && result >= -128 && result < 0)
+        result += 256;
+    return result;
+}
+
+static nc_type
+char2type(char letter) {
+    switch (letter) {
+        case 'c': return NC_CHAR;
+        case 'b': return NC_BYTE;
+        case 's': return NC_SHORT;
+        case 'i': return NC_INT;
+        case 'f': return NC_FLOAT;
+        case 'd': return NC_DOUBLE;
+        case 'y': return NC_UBYTE;
+        case 't': return NC_USHORT;
+        case 'u': return NC_UINT;
+        case 'x': return NC_INT64;
+        case 'z': return NC_UINT64;
+        default:  assert(0);
+    }
+    return NC_CHAR;  /* Just to keep compiler happy */
+}
+
+
+static void
+init_dims(const char *digit)
+{
+    int dimid;    /* index of dimension */
+
+    for (dimid = 0; dimid < NDIMS; dimid++) {
+        dim_len[dimid] = dimid == 0 ? NRECS : dimid;
+        /* lengths = 1, 2, 3, ...
+         * names = Dr, D1, D1, D2, ...
+         */
+        dim_name[dimid][0] = 'D';
+        dim_name[dimid][1] = digit[dimid];
+        dim_name[dimid][2] = '\0';
+    }
+}
+
+static void
+init_gatts(const char *type_letter)
+{
+    int attid;
+    for (attid = 0; attid < numGatts; attid++) {
+        gatt_name[attid][0] = 'G';
+        gatt_name[attid][1] = type_letter[attid];
+        gatt_name[attid][2] = '\0';
+        gatt_len[attid]     = 1 + attid;
+        gatt_type[attid]    = char2type (type_letter[attid]);
+    }
+}
+
+static MPI_Offset
+product(size_t nn, const MPI_Offset *sp)
+{
+    MPI_Offset result = 1;
+    while (nn-- > 0)
+        result *= *sp++;
+    return result;  /* == sp[0] * sp[1] * ... * sp[nn-1] */
+}
+
+/* 
+   define global variables:
+   dim_name, dim_len, 
+   var_name, var_type, var_rank, var_shape, var_natts, var_dimid, var_nels
+   att_name, gatt_name, att_type, gatt_type, att_len, gatt_len
+ */
+void
+init_gvars (void)
+{
+    const MPI_Offset max_dim_len[MAX_RANK] = {MAX_DIM_LEN +1,
+                                              MAX_DIM_LEN,
+                                              MAX_DIM_LEN };
+    const char type_letter[] = "cbsifdytuxz";
+    /* c:char, b:byte, s:short, i:int, f:float, d:double, y:ubyte, t:ushort,
+     * u:uint, x:int64, z:uint64
+     */
+    const char digit[] = "r123456789";
+
+    size_t rank;
+    int vn;           /* var number */
+    int xtype;        /* index of type */
+    int an;           /* attribute number */
+
+    assert(sizeof(max_dim_len)/sizeof(max_dim_len[0]) >= MAX_RANK);
+
+    init_dims(digit);
+
+    for (vn=0; vn<numVars; vn++)
+        memset(var_name[vn], 0, 2+MAX_RANK);
+
+    vn    = 0;
+    xtype = 0;
+    an    = 0;
+    for (rank=0; rank<=MAX_RANK; rank++) { /* dimension ranks */
+        /* number variables of a type and rank
+         * == max_dim_len[0] * max_dim_len[1] * ... * max_dim_len[rank-1] */
+        const size_t nvars = product(rank, max_dim_len);
+
+        int jj;
+        for (jj=0; jj<nvars; jj++) {
+            /* number types of this shape */
+            const int ntypes = rank < 2 ? numTypes : 1;
+
+            int ac, tc;
+            for (tc=0; tc<ntypes; tc++, vn++, xtype = (xtype + 1) % numTypes) {
+                MPI_Offset tmp[MAX_RANK];
+
+                var_name[vn][0] = type_letter[xtype];
+                var_type[vn]    = char2type(type_letter[xtype]);
+                var_rank[vn]    = rank;
+                var_natts[vn]   = rank == 0 ? vn % (MAX_NATTS + 1) : 0;
+
+                /* ac block */
+                for (ac=0; ac<var_natts[vn]; ac++, an++) {
+                     att_name[vn][ac][0] = type_letter[an % numTypes];
+                     att_name[vn][ac][1] = '\0';
+                     att_len[vn][ac]     = an;
+                     att_type[vn][ac]    = char2type(type_letter[an % numTypes]);
+                }
+#ifndef NDEBUG
+                assert(toMixedBase(jj, rank, max_dim_len, tmp) == 0);
+#else
+                toMixedBase(jj, rank, max_dim_len, tmp);
+#endif
+                /* dn block */
+                int dn; /* dimension number */
+                for (dn=0; dn<rank; dn++)
+                     var_dimid[vn][dn] = (int)tmp[dn];
+
+                for (dn=0, var_nels[vn]=1; dn<rank; dn++) {
+                     var_dimid[vn][dn]   += dn > 0;
+                     assert (var_dimid[vn][dn] <= 9);
+                     var_name[vn][dn + 1] = digit[var_dimid[vn][dn]];
+                     var_shape[vn][dn]    = var_dimid[vn][dn] ?
+                                            var_dimid[vn][dn] : NRECS;
+                     var_nels[vn]        *= var_shape[vn][dn];
+                }
+            }
+        }
+    }
+    init_gatts(type_letter);
+}
+
+
+/* define dims defined by global variables */
+void                                                        
+def_dims(int ncid)
+{
+    int  i, err, dimid;
+
+    for (i=0; i<NDIMS; i++) {
+        err = ncmpi_def_dim(ncid, dim_name[i],
+                            i==0 ? NC_UNLIMITED : dim_len[i], &dimid);
+        IF (err != NC_NOERR) error("ncmpi_def_dim: %s", ncmpi_strerror(err));
+    }
+}
+
+
+/* define vars defined by global variables */
+void                                                        
+def_vars(int ncid)
+{
+    int i, err, var_id;
+
+    for (i = 0; i < numVars; i++) {
+        err = ncmpi_def_var(ncid, var_name[i], var_type[i], var_rank[i],
+                            var_dimid[i], &var_id);
+        IF (err != NC_NOERR) error("ncmpi_def_var: %s", ncmpi_strerror(err));
+    }
+}
+
+
+/* put attributes defined by global variables */
+void                                                        
+put_atts(int ncid)
+{
+    int  i, j, allInRange, err;
+    MPI_Offset  k;
+    char catt[MAX_NELS];
+    double att[MAX_NELS];
+
+    for (i=-1; i<numVars; i++) {  /* -1: global attribute */
+        for (j=0; j<NATTS(i); j++) {
+            if (ATT_TYPE(i,j) == NC_CHAR) {
+                for (k=0; k<ATT_LEN(i,j); k++) {
+                    catt[k] = hash(ATT_TYPE(i,j), -1, &k);
+                }
+                err = ncmpi_put_att_text(ncid, i, ATT_NAME(i,j),
+                                         ATT_LEN(i,j), catt);
+                IF (err != NC_NOERR) 
+                    error("ncmpi_put_att_text: %s", ncmpi_strerror(err));
+            } else {
+                for (allInRange=1, k=0; k<ATT_LEN(i,j); k++) {
+                    att[k] = hash(ATT_TYPE(i,j), -1, &k);
+                    allInRange = allInRange && inRange(att[k], ATT_TYPE(i,j));
+                }
+                err = ncmpi_put_att_double(ncid, i, ATT_NAME(i,j),
+                                           ATT_TYPE(i,j), ATT_LEN(i,j), att);
+                if (allInRange) {
+                    IF (err != NC_NOERR)
+                        error("ncmpi_put_att_double: %s", ncmpi_strerror(err));
+                } else {
+                    /* when ATT_LEN(i,j) >= 3, some values returned for 3rd,
+                     * 4th, ... will be specially made to cause NC_ERANG
+                     */
+                    IF (err != NC_ERANGE)
+                        error("type-conversion range error: status = %d", err);
+                }
+            }
+        }
+    }
+}
+
+/* put variables defined by global variables */
+void                                                        
+put_vars(int ncid)
+{
+    MPI_Offset start[MAX_RANK];
+    MPI_Offset index[MAX_RANK];
+    int  i, j, err, allInRange;
+    double value[MAX_NELS];
+    char text[MAX_NELS];
+
+    for (j = 0; j < MAX_RANK; j++) start[j] = 0;
+    for (i = 0; i < numVars; i++) {
+        for (allInRange = 1, j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR) error("toMixedBase");
+            if (var_name[i][0] == 'c') { /* var_type[i] is NC_CHAR */
+                text[j] = hash(var_type[i], var_rank[i], index);
+            } else {
+                value[j]  = hash(var_type[i], var_rank[i], index);
+                allInRange = allInRange && inRange(value[j], var_type[i]);
+            }
+        }
+        if (var_name[i][0] == 'c') {
+            err = ncmpi_put_vara_text_all(ncid, i, start, var_shape[i], text);
+            IF (err != NC_NOERR)
+                error("ncmpi_put_vara_text_all: %s", ncmpi_strerror(err));
+        } else {
+            err = ncmpi_put_vara_double_all(ncid, i, start, var_shape[i],value);
+            if (allInRange) {
+                IF (err != NC_NOERR)
+                    error("ncmpi_put_vara_double_all: %s", ncmpi_strerror(err));
+            } else {
+                IF (err != NC_ERANGE)
+                    error("type-conversion range error: status = %d", err);
+            }
+        }
+    }
+}
+
+
+/* Create & write all of specified file using global variables */
+void
+write_file(char *filename) 
+{
+    int  err, ncid;
+
+    err = ncmpi_create(comm, filename, NC_CLOBBER|extra_flags, info,
+                       &ncid);
+    IF (err != NC_NOERR) error("ncmpi_create: %s", ncmpi_strerror(err));
+
+    def_dims(ncid);
+    def_vars(ncid);
+    put_atts(ncid);
+
+    err = ncmpi_enddef(ncid);
+    IF (err != NC_NOERR) error("ncmpi_enddef: %s", ncmpi_strerror(err));
+
+    put_vars(ncid);
+
+    err = ncmpi_close (ncid);
+    IF (err != NC_NOERR) error("ncmpi_close: %s", ncmpi_strerror(err));
+}
+
+
+/*
+ * check dimensions of specified file have expected name & length
+ */
+void
+check_dims(int  ncid)
+{
+    char name[NC_MAX_NAME];
+    MPI_Offset length;
+    int  i, err;
+
+    for (i = 0; i < NDIMS; i++) {
+        err = ncmpi_inq_dim(ncid, i, name, &length);
+        IF (err != NC_NOERR)
+            error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
+        IF (strcmp(name, dim_name[i]) != 0)
+            error("Unexpected name of dimension %d", i);
+        IF (length != dim_len[i])
+            error("Unexpected length %d of dimension %d", length, i);
+    }
+}
+
+
+/*
+ * check variables of specified file have expected name, type, shape & values
+ */
+void
+check_vars(int  ncid)
+{
+    MPI_Offset index[MAX_RANK];
+    char text, name[NC_MAX_NAME];
+    int  i, j, err;
+    int  nok = 0;      /* count of valid comparisons */
+    int  isChar, ndims, dimids[MAX_RANK];
+    double value, expect;
+    nc_type datatype;
+    MPI_Offset length;
+
+    for (i = 0; i < numVars; i++) {
+        isChar = var_type[i] == NC_CHAR;
+        err = ncmpi_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
+        IF (err != NC_NOERR) 
+            error("ncmpi_inq_var: %s", ncmpi_strerror(err));
+        IF (strcmp(name, var_name[i]) != 0) 
+            error("Unexpected var_name");
+        IF (datatype != var_type[i]) 
+            error("Unexpected type");
+        IF (ndims != var_rank[i]) 
+            error("Unexpected rank");
+        for (j = 0; j < ndims; j++) {
+            err = ncmpi_inq_dim(ncid, dimids[j], name, &length);
+            IF (err != NC_NOERR) 
+                error("ncmpi_inq_dim: %s", ncmpi_strerror(err));
+            IF (length != var_shape[i][j]) 
+                error("Unexpected shape");
+        }
+        for (j = 0; j < var_nels[i]; j++) {
+            err = toMixedBase(j, var_rank[i], var_shape[i], index);
+            IF (err != NC_NOERR) 
+                error("error in toMixedBase 2");
+            expect = hash( var_type[i], var_rank[i], index );
+            if (isChar) {
+                ncmpi_begin_indep_data(ncid);
+                err = ncmpi_get_var1_text(ncid, i, index, &text);
+                IF (err != NC_NOERR)
+                    error("ncmpi_get_var1_text: %s", ncmpi_strerror(err));
+                IF (text != (char)expect) {
+                    error("Var %s (varid=%d) value read 0x%02x not that expected 0x%02x ",
+                          var_name[i], i, text, (char)expect);
+                    print_n_size_t(var_rank[i], index);
+                } else {
+                    nok++;
+                }
+                ncmpi_end_indep_data(ncid);
+            } else {
+                ncmpi_begin_indep_data(ncid);
+                err = ncmpi_get_var1_double(ncid, i, index, &value); 
+                if (inRange(expect,var_type[i])) {
+                    IF (err != NC_NOERR) {
+                        error("ncmpi_get_var1_double: %s", ncmpi_strerror(err));
+                    } else {
+                        IF (!equal(value,expect,var_type[i], NCT_DOUBLE)) {
+                            error("Var %s (varid=%d) value read % 12.5e not that expected % 12.7e ",
+                                  var_name[i], i, value, expect);
+                            print_n_size_t(var_rank[i], index);
+                        } else {
+                            nok++;
+                        }
+                    }
+                }
+                ncmpi_end_indep_data(ncid);
+            }
+        }
+    }
+    /* print_nok(nok); */
+}
+
+
+/*
+ * check attributes of specified file have expected name, type, length & values
+ */
+void
+check_atts(int  ncid) 
+{
+    char name[NC_MAX_NAME], text[MAX_NELS];
+    int  i, j, err;        /* status */
+    nc_type datatype;
+    MPI_Offset k, length;
+    double expect, value[MAX_NELS];
+    int nok = 0;      /* count of valid comparisons */
+
+    for (i = -1; i < numVars; i++) {
+        for (j = 0; j < NATTS(i); j++) {
+            err = ncmpi_inq_attname(ncid, i, j, name);
+            IF (err != NC_NOERR) 
+                error("ncmpi_inq_attname: %s", ncmpi_strerror(err));
+            IF (strcmp(name, ATT_NAME(i,j)) != 0)
+                error("ncmpi_inq_attname: unexpected name");
+            err = ncmpi_inq_att(ncid, i, name, &datatype, &length);
+            IF (err != NC_NOERR) 
+                error("ncmpi_inq_att: %s", ncmpi_strerror(err));
+            IF (datatype != ATT_TYPE(i,j))
+                error("ncmpi_inq_att: unexpected type");
+            IF (length != ATT_LEN(i,j))
+                error("ncmpi_inq_att: unexpected length");
+            if (datatype == NC_CHAR) {
+                err = ncmpi_get_att_text(ncid, i, name, text);
+                IF (err != NC_NOERR)
+                    error("ncmpi_get_att_text: %s", ncmpi_strerror(err));
+                for (k = 0; k < ATT_LEN(i,j); k++) {
+                    expect = hash(datatype, -1, &k);
+                    if (text[k] != (char)expect) {
+                        error("ncmpi_get_att_text: unexpected value");
+                    } else {
+                        nok++;
+                    }
+                }
+            } else {
+                err = ncmpi_get_att_double(ncid, i, name, value);
+                for (k = 0; k < ATT_LEN(i,j); k++) {
+                    expect = hash(datatype, -1, &k);
+                    if (inRange(expect,ATT_TYPE(i,j))) {
+                        IF (err != NC_NOERR)
+                            error("ncmpi_get_att_double: %s", ncmpi_strerror(err));
+                        IF (!equal(value[k], expect, ATT_TYPE(i,j), NCT_DOUBLE)) {
+                            error("Att value read not that expected");
+                        } else {
+                            nok++;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    /* print_nok(nok); */
+}
+
+
+/* Check file (dims, vars, atts) corresponds to global variables */
+void
+check_file(char *filename) 
+{
+    int ncid, err;
+
+    err = ncmpi_open(comm, filename, NC_NOWRITE, info, &ncid);
+    IF (err != NC_NOERR) {
+        error("ncmpi_open: %s", ncmpi_strerror(err));
+    } else {
+        check_dims(ncid);
+        check_vars(ncid);
+        check_atts(ncid);
+        err = ncmpi_close (ncid);
+        IF (err != NC_NOERR) 
+            error("ncmpi_close: %s", ncmpi_strerror(err));
+    }
+}
+
+/* TODO: Maybe this function belongs in the netcdf library. */
+const char *
+s_nc_type(nc_type type)
+{
+    switch((int)type){
+        case NC_CHAR:   return "NC_CHAR";
+        case NC_BYTE:   return "NC_BYTE";
+        case NC_UBYTE:  return "NC_UBYTE";
+        case NC_SHORT:  return "NC_SHORT";
+        case NC_USHORT: return "NC_USHORT";
+        case NC_INT:    return "NC_INT";
+        case NC_UINT:   return "NC_UINT";
+        case NC_FLOAT:  return "NC_FLOAT";
+        case NC_DOUBLE: return "NC_DOUBLE";
+        case NC_INT64:  return "NC_INT64";
+        case NC_UINT64: return "NC_UINT64";
+    }
+    return "";
+}
+
+int
+nctypelen(nc_type type)
+{
+    switch(type){
+        case NC_BYTE :
+        case NC_CHAR :   return((int)sizeof(char));
+        case NC_SHORT :  return((int)sizeof(short));
+        case NC_INT :    return((int)sizeof(int));
+        case NC_FLOAT :  return((int)sizeof(float));
+        case NC_DOUBLE : return((int)sizeof(double));
+        case NC_UBYTE :  return(1);
+        case NC_USHORT : return((int)sizeof(unsigned short));
+        case NC_UINT :   return((int)sizeof(unsigned int));
+        case NC_INT64 :  return((int)sizeof(long long));
+        case NC_UINT64 : return((int)sizeof(unsigned long long));
+        default:         return -1;
+    }
+}
+
+MPI_Datatype
+nc_mpi_type(nc_type type)
+{
+    switch(type){
+        case NC_BYTE :   return MPI_SIGNED_CHAR;
+        case NC_CHAR :   return MPI_CHAR;
+        case NC_SHORT :  return MPI_SHORT;
+        case NC_INT :    return MPI_INT;
+        case NC_FLOAT :  return MPI_FLOAT;
+        case NC_DOUBLE : return MPI_DOUBLE;
+        case NC_UBYTE :  return MPI_UNSIGNED_CHAR;
+        case NC_USHORT : return MPI_UNSIGNED_SHORT;
+        case NC_UINT :   return MPI_UNSIGNED;
+        case NC_INT64 :  return MPI_LONG_LONG_INT;
+        case NC_UINT64 : return MPI_UNSIGNED_LONG_LONG;
+        default:         return MPI_DATATYPE_NULL;
+    }
+}
+
diff --git a/test/nf90_test/Makefile.in b/test/nf90_test/Makefile.in
new file mode 100644
index 0000000..b534681
--- /dev/null
+++ b/test/nf90_test/Makefile.in
@@ -0,0 +1,92 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I../../src/lib -I../../src/libf
+INCLUDES += -I$(srcdir) -I$(srcdir)/../../src/libf
+INCLUDES += @FC_MODINC at ../../src/libf90
+LDFLAGS  := $(LDFLAGS) -L../common
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
+
+M4SRCS      = test_get.m4 \
+              test_put.m4  \
+              test_iget.m4 \
+              test_iput.m4
+
+M4SRCS_F90  = $(M4SRCS:.m4=.F90)
+
+F90_SRCS    = nf90_error.F90 \
+              nf90_test.F90 \
+              test_read.F90 \
+              test_write.F90 \
+              util.F90
+
+C_SRCS      = fortlib.c
+
+HEADERS     = tests.inc
+
+C_OBJS   = $(C_SRCS:.c=.o)
+F90_OBJS = $(F90_SRCS:.F90=.o) $(M4SRCS_F90:.F90=.o)
+OBJS     = $(C_OBJS) $(F90_OBJS)
+
+PROGS    = nf90_test
+
+GARBAGE  = $(PROGS) $(M4SRCS_F90) \
+           scratch.nc test.nc
+
+PACKING_LIST = $(C_SRCS) $(F90_SRCS) $(M4SRCS) $(HEADERS) depend Makefile.in README
+
+all: $(PROGS)
+
+$(C_OBJS): $(srcdir)/../common/testutils.h
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+nf90_test: $(OBJS) $(LIBRARY)
+	$(LINK.F90) $(OBJS) $(LDFLAGS) $(LIBS)
+
+tags: $(F90_SRCS) $(C_SRCS) FORCE
+	ctags -t $(F90_SRCS) $(C_SRCS) ../fortran/*.c ../libsrc/*.c
+
+# This simple testing target ensures that the test files are present
+testing check: all
+	$(RM) -f $(TEST_OUTDIR)/scratch.nc $(TEST_OUTDIR)/test.nc
+	$(TEST_SEQRUN) ./nf90_test -c    -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf90_test       -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf90_test -c -2 -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf90_test -2    -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf90_test -c -5 -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf90_test -5    -d $(TEST_OUTDIR)
+
+verbose_testing: all
+	$(RM) -f $(TEST_OUTDIR)/scratch.nc $(TEST_OUTDIR)/test.nc
+	$(TEST_SEQRUN) ./nf90_test -v -c    -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf90_test -v       -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf90_test -v -c -2 -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf90_test -v -2    -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf90_test -v -c -5 -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf90_test -v -5    -d $(TEST_OUTDIR)
+
+#test.nc: 
+#	(cd ../nc_test && $(MAKE) $(MFLAGS) nc_test && ./nc_test -c)
+#	cp ../nc_test/test.nc .
+
+ptest ptests ptest2 ptest4 ptest6 ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+include $(srcdir)/depend
+
+$(LIBRARY): ;
+
diff --git a/test/nf90_test/README b/test/nf90_test/README
new file mode 100644
index 0000000..11cf35d
--- /dev/null
+++ b/test/nf90_test/README
@@ -0,0 +1,3 @@
+This test is ported from ../nf_test to test the functionality
+of the PnetCDF API Fortran 90 interface particularly on a single processor. 
+
diff --git a/test/nf90_test/depend b/test/nf90_test/depend
new file mode 100644
index 0000000..ace6d17
--- /dev/null
+++ b/test/nf90_test/depend
@@ -0,0 +1,28 @@
+fortlib.o: fortlib.c
+nf90_error.o: ../../src/libf/pnetcdf.inc
+nf90_error.o: nf90_error.F90
+nf90_error.o: tests.inc
+nf90_test.o: ../../src/libf/pnetcdf.inc
+nf90_test.o: nf90_test.F90
+nf90_test.o: tests.inc
+test_get.o: ../../src/libf/pnetcdf.inc
+test_get.o: test_get.F90
+test_get.o: tests.inc
+test_put.o: ../../src/libf/pnetcdf.inc
+test_put.o: test_put.F90
+test_put.o: tests.inc
+test_iget.o: ../../src/libf/pnetcdf.inc
+test_iget.o: test_iget.F90
+test_iget.o: tests.inc
+test_iput.o: ../../src/libf/pnetcdf.inc
+test_iput.o: test_iput.F90
+test_iput.o: tests.inc
+test_read.o: ../../src/libf/pnetcdf.inc
+test_read.o: test_read.F90
+test_read.o: tests.inc
+test_write.o: ../../src/libf/pnetcdf.inc
+test_write.o: test_write.F90
+test_write.o: tests.inc
+util.o: ../../src/libf/pnetcdf.inc
+util.o: tests.inc
+util.o: util.F90
diff --git a/test/nf90_test/fortlib.c b/test/nf90_test/fortlib.c
new file mode 100644
index 0000000..6d2303d
--- /dev/null
+++ b/test/nf90_test/fortlib.c
@@ -0,0 +1,289 @@
+/*
+ * $Id: fortlib.c 1468 2013-10-26 16:53:18Z wkliao $
+ *
+ * This file contains support functions for FORTRAN code.  For example,
+ * under HP-UX A.09.05, the U77 library doesn't contain the exit()
+ * routine -- so we create one here.
+ *
+ * This file is heavily modified from nf_test/fortlib.c in the serial netcdf
+ * source.
+ */
+
+
+#include <stdlib.h>
+#include <limits.h>
+#include <float.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <mpinetcdf_impl.h>
+#include <mpifnetcdf.h>
+
+extern FORTRAN_API void FORT_CALL ud_exit_(int *v1);
+extern FORTRAN_API void FORT_CALL ud_abort_(int *v1);
+extern FORTRAN_API double FORT_CALL ud_rand_(int *seed);
+extern FORTRAN_API int FORT_CALL ud_shift_(int * value, int *amount);
+extern FORTRAN_API void FORT_CALL nc_ignorefpe_(int *doit);
+extern FORTRAN_API double FORT_CALL min_schar_(void);
+extern FORTRAN_API double FORT_CALL min_short_(void);
+extern FORTRAN_API double FORT_CALL min_int_(void);
+extern FORTRAN_API double FORT_CALL min_int64_(void);
+extern FORTRAN_API double FORT_CALL max_schar_(void);
+extern FORTRAN_API double FORT_CALL max_short_(void);
+extern FORTRAN_API double FORT_CALL max_int_(void);
+extern FORTRAN_API double FORT_CALL max_int64_(void);
+extern FORTRAN_API double FORT_CALL max_float_(void);
+extern FORTRAN_API double FORT_CALL max_double_(void);
+
+
+#ifdef F77_NAME_UPPER
+#define ud_exit_ UD_EXIT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define ud_exit_  ud_exit__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define ud_exit_  ud_exit
+/* Else leave name alone */
+#endif
+
+FORTRAN_API void FORT_CALL ud_exit_(int *v1) {
+	if (*v1 == 0) {
+		MPI_Finalize();
+		exit(0);
+	}
+	MPI_Abort(MPI_COMM_WORLD, *v1);
+	return;
+}
+
+#ifdef F77_NAME_UPPER
+#define ud_abort_ UD_ABORT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define ud_abort_  ud_abort__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define ud_abort_  ud_abort
+/* Else leave name alone */
+#endif
+
+FORTRAN_API void FORT_CALL ud_abort_(int *v1) {
+	MPI_Abort(MPI_COMM_WORLD, *v1);
+	return;
+}
+
+#ifdef F77_NAME_UPPER
+#define ud_rand_ UD_RAND
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define ud_rand_  ud_rand__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define ud_rand_  ud_rand
+/* Else leave name alone */
+#endif
+
+/*
+* Return a pseudo-random value between 0.0 and 1.0.
+*
+* We don't use RAND_MAX here because not all compilation
+* environments define it (e.g. gcc(1) under SunOS 4.1.3).
+*/
+FORTRAN_API double FORT_CALL ud_rand_(int *seed) {
+	if (*seed != 0)
+		srand(*seed);
+	return (rand() % 32768 )/ 32767.0;
+}
+
+#ifdef F77_NAME_UPPER
+#define ud_shift_ UD_SHIFT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define ud_shift_  ud_shift__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define ud_shift_  ud_shift
+/* Else leave name alone */
+#endif
+
+FORTRAN_API int FORT_CALL ud_shift_(int * value, int *amount) {
+	if(*amount < 0)
+		*value >>= -*amount;
+	else if (*amount > 0)
+		*value <<= *amount;
+	return *value;
+}
+
+#ifdef F77_NAME_UPPER
+#define nc_ignorefpe_ NC_IGNOREFPE
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define nc_ignorefpe_  nc_ignorefpe__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define nc_ignorefpe_  nc_ignorefpe
+/* Else leave name alone */
+#endif
+#include <signal.h>
+FORTRAN_API void FORT_CALL nc_ignorefpe_(int *doit)
+{
+	if(doit)
+		(void) signal(SIGFPE, SIG_IGN);
+}
+
+#ifdef F77_NAME_UPPER
+#define min_schar_ MIN_SCHAR
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define min_schar_  min_schar__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define min_schar_  min_schar
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL min_schar_(void) {
+	return SCHAR_MIN;
+}
+
+#ifdef F77_NAME_UPPER
+#define min_short_ MIN_SHORT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define min_short_  min_short__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define min_short_  min_short
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL min_short_(void) {
+	return SHRT_MIN;
+}
+
+#ifdef F77_NAME_UPPER
+#define min_int_ MIN_INT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define min_int_  min_int__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define min_int_  min_int
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL min_int_(void) {
+	return INT_MIN;
+}
+
+#ifdef F77_NAME_UPPER
+#define min_int64_ MIN_INT64
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define min_int64_  min_int64__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define min_int64_  min_int64
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL min_int64_(void) {
+	return INT64_MIN;
+}
+
+#ifdef F77_NAME_UPPER
+#define max_schar_ MAX_SCHAR
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define max_schar_  max_schar__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define max_schar_  max_schar
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL max_schar_(void) {
+	return SCHAR_MAX;
+}
+
+#ifdef F77_NAME_UPPER
+#define max_short_ MAX_SHORT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define max_short_  max_short__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define max_short_  max_short
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL max_short_(void) {
+	return SHRT_MAX;
+}
+
+#ifdef F77_NAME_UPPER
+#define max_int_ MAX_INT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define max_int_  max_int__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define max_int_  max_int
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL max_int_(void) {
+	return INT_MAX;
+}
+
+#ifdef F77_NAME_UPPER
+#define max_int64_ MAX_INT64
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define max_int64_  max_int64__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define max_int64_  max_int64
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL max_int64_(void) {
+	return INT64_MAX;
+}
+
+#ifdef F77_NAME_UPPER
+#define max_float_ MAX_FLOAT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define max_float_  max_float__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define max_float_  max_float
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL max_float_(void) {
+	return FLT_MAX;
+}
+
+#ifdef F77_NAME_UPPER
+#define max_double_ MAX_DOUBLE
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define max_double_  max_double__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define max_double_  max_double
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL max_double_(void) {
+	return DBL_MAX;
+}
+
+#if 0 /* this is implemented in library src now */
+
+#ifdef F77_NAME_UPPER
+#define nfmpi_issyserr_ NFMPI_ISSYSERR
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define nfmpi_issyserr_  nfmpi_issyserr__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define nfmpi_issyserr_  nfmpi_issyserr
+/* Else leave name alone */
+#endif
+
+FORTRAN_API int FORT_CALL nfmpi_issyserr_(int * A1) {
+	if (*A1 > 0)
+		return 1;
+	else 
+		return 0;
+}
+
+
+#ifdef F77_NAME_UPPER
+#define nfmpi_delete_ NFMPI_DELETE
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define nfmpi_delete_  nfmpi_delete__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define nfmpi_delete_  nfmpi_delete
+/* Else leave name alone */
+#endif
+FORTRAN_API void FORT_CALL nfmpi_delete_(char * name, int *err, int d1) {
+    char *p1;
+
+    {char *p = name + d1 - 1;
+     int  li;
+        while (*p == ' ' && p > name) p--;
+        p++;
+        p1 = (char *)malloc( p-name + 1 );
+        for (li=0; li<(p-name); li++) { p1[li] = name[li]; }
+        p1[li] = 0; 
+    }
+
+	if ( unlink(p1) != 0 )
+		*err = errno;
+	else
+		*err = 0;
+	free(p1);
+}
+
+#endif
diff --git a/test/nf90_test/nf90_error.F90 b/test/nf90_test/nf90_error.F90
new file mode 100644
index 0000000..9daaba2
--- /dev/null
+++ b/test/nf90_test/nf90_error.F90
@@ -0,0 +1,80 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: nf90_error.F90 1468 2013-10-26 16:53:18Z wkliao $
+!
+
+!
+! Use for logging error messages
+!
+        subroutine error(msg)
+        use pnetcdf
+        implicit        none
+        character*(*)   msg
+#include "tests.inc"
+
+        nfails = nfails + 1
+        if (nfails .le. max_nmpt) print *, msg
+        end
+
+
+!
+! Use for logging error conditions
+!
+        subroutine errori(msg, i)
+        use pnetcdf
+        implicit        none
+        character*(*)   msg
+        integer         i
+#include "tests.inc"
+
+        nfails = nfails + 1
+        if (nfails .le. max_nmpt) print *, msg, i
+        end
+
+
+!
+! Use for logging error conditions
+!
+        subroutine errord(msg, d)
+        use pnetcdf
+        implicit        none
+        character*(*)   msg
+        doubleprecision d
+#include "tests.inc"
+
+        nfails = nfails + 1
+        if (nfails .le. max_nmpt) print *, msg, d
+        end
+
+
+!
+! Use for logging error conditions
+!
+        subroutine errorc(msg, string)
+        use pnetcdf
+        implicit        none
+        character*(*)   msg
+        character*(*)   string
+#include "tests.inc"
+
+        nfails = nfails + 1
+        if (nfails .le. max_nmpt) print *, msg, &
+            trim(string)
+        end
+
+
+!
+! Use for logging error conditions
+!
+        subroutine errore(msg, err)
+        use pnetcdf
+        implicit        none
+        character*(*)   msg
+        integer         err
+#include "tests.inc"
+
+        nfails = nfails + 1
+        call errorc(msg, nf90mpi_strerror(err))
+        end
diff --git a/test/nf90_test/nf90_test.F90 b/test/nf90_test/nf90_test.F90
new file mode 100644
index 0000000..e905bb7
--- /dev/null
+++ b/test/nf90_test/nf90_test.F90
@@ -0,0 +1,849 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: nf90_test.F90 2131 2015-09-25 22:33:12Z wkliao $
+!
+
+!
+! Test driver for netCDF-3 interface.  This program performs tests against
+! the netCDF-3 specification for all user-level functions in an
+! implementation of the netCDF library.
+!
+! Unless invoked with "-r" (readonly) option, must be invoked from a
+! directory in which the invoker has write permission.
+!
+! Files:
+! The read-only tests read files:
+!     test.nc (see below)
+!     test_get.F (used merely as an example of a non-netCDF file)
+! 
+! The write tests 
+!     read test.nc (see below) 
+!     write scratch.nc (deleted after each test)
+! 
+! The file test.nc is created by running nc_test with the -c (create) option.
+!
+
+        subroutine usage()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+
+        call error('usage: nf90_test [-hrv] [-n <MAX_NMPT>]')
+        call error('       nf90_test [-c]')
+        call error('   [-h] Print help' )
+        call error('   [-c] Create file test.nc (Do not do tests)' )
+        call error('   [-1] test CDF-1 format' )
+        call error('   [-2] test CDF-2 format' )
+        call error('   [-5] test CDF-5 format' )
+        call error('   [-r] Just do read-only tests' )
+        call error( &
+        '   [-d directory] directory for storing input/output files' )
+        call error('   [-v] Verbose mode' )
+        call error( &
+        '   [-n <max>] max. number of messages per test (Default: 20)')
+        end
+
+        subroutine report_test
+        implicit        none
+        character*128   msg
+#include "tests.inc"
+
+        write(msg,"(A,I1)") '*** TESTING F90 '//trim(PROGNAME)// &
+                            ' for CDF-', cdf_format
+        if (nfailsTotal .ne. 0) then
+          write(*,*) trim(PROGNAME)//' expects to see 0 failure ... '//&
+                     'Total number of failures: ', nfailsTotal
+        endif
+        call pass_fail(nfailsTotal, msg)
+        end
+
+        subroutine test(name, func)
+        use pnetcdf
+        implicit        none
+        character*(*)   name
+        character(len=25) name_str
+        integer           name_len
+        external        func
+#include "tests.inc"
+
+        name_len = LEN_TRIM(name)
+        name_str(1:name_len) = name(:)
+        name_str(name_len+1:25) = ' '
+        if (verbose) write(*, 1, advance="no") name_str
+1       format('*** Testing ', a, ' ... ')
+
+        nfails = 0
+        call func()
+        nfailsTotal = nfailsTotal + nfails
+        if ( nfails .ne. 0) then
+            print *, ' '
+            print *, '  ### ', nfails, ' FAILURES TESTING ', name,  &
+                     '! Stop ... ###'
+            call report_test
+            stop
+        end if
+        end
+
+
+#if _CRAYIEEE
+! which machines need this?
+        subroutine getarg(iarg, carg)
+        use pnetcdf
+        implicit        none
+        integer iarg
+        character*(*)   carg
+        integer ilen
+        integer ierror
+        call PXFGETARG(iarg, carg, ilen, ierror)
+        end
+#endif
+
+        program nf_test
+        use pnetcdf
+#if defined(VISUAL_CPLUSPLUS)
+!       DIGITAL Visual Fortran needs DFLIB for getarg
+        USE DFLIB
+!       DIGITAL Visual Fortran needs DFPORT for iargc
+        USE DFPORT
+        implicit        none
+#elif defined(NAGf90Fortran)
+        USE F90_UNIX_ENV, only : iargc, getarg
+        implicit none
+#else
+        implicit        none
+        integer         iargc
+#endif
+#if defined(__crayx1)
+        integer         ipxfargc 
+#endif
+#include "tests.inc"
+
+        integer         argc
+        character*80    arg
+        integer         iarg
+        integer         iopt
+        character*1     opt
+        integer         lastopt
+        logical         skiparg
+        integer         err                       
+
+        external        test_nf90mpi_strerror
+        external        test_nf90mpi_open
+        external        test_nf90mpi_close
+        external        test_nf90mpi_inq
+        external        test_nf90mpi_inq_dimid
+        external        test_nf90mpi_inq_dim
+        external        test_nf90mpi_inq_dimlen
+        external        test_nf90mpi_inq_dimname
+        external        test_nf90mpi_inq_varid
+        external        test_nf90mpi_inq_var
+        external        test_nf90mpi_inq_natts
+        external        test_nf90mpi_inq_ndims
+        external        test_nf90mpi_inq_nvars
+        external        test_nf90mpi_inq_unlimdim
+        external        test_nf90mpi_inq_vardimid
+        external        test_nf90mpi_inq_varname
+        external        test_nf90mpi_inq_varnatts
+        external        test_nf90mpi_inq_varndims
+        external        test_nf90mpi_inq_vartype
+        external        test_nf90mpi_get_var1_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_get_var1_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_get_var1_int2
+#endif
+        external        test_nf90mpi_get_var1_int
+        external        test_nf90mpi_get_var1_real
+        external        test_nf90mpi_get_var1_double
+        external        test_nf90mpi_get_var1_int8
+        external        test_nf90mpi_get_var_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_get_var_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_get_var_int2
+#endif
+        external        test_nf90mpi_get_var_int
+        external        test_nf90mpi_get_var_real
+        external        test_nf90mpi_get_var_double
+        external        test_nf90mpi_get_var_int8
+        external        test_nf90mpi_get_vara_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_get_vara_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_get_vara_int2
+#endif
+        external        test_nf90mpi_get_vara_int
+        external        test_nf90mpi_get_vara_real
+        external        test_nf90mpi_get_vara_double
+        external        test_nf90mpi_get_vara_int8
+        external        test_nf90mpi_get_vars_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_get_vars_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_get_vars_int2
+#endif
+        external        test_nf90mpi_get_vars_int
+        external        test_nf90mpi_get_vars_real
+        external        test_nf90mpi_get_vars_double
+        external        test_nf90mpi_get_vars_int8
+
+        external        test_nf90mpi_get_varm_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_get_varm_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_get_varm_int2
+#endif
+        external        test_nf90mpi_get_varm_int
+        external        test_nf90mpi_get_varm_real
+        external        test_nf90mpi_get_varm_double
+        external        test_nf90mpi_get_varm_int8
+
+        external        test_nf90mpi_iget_var1_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_iget_var1_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_iget_var1_int2
+#endif
+        external        test_nf90mpi_iget_var1_int
+        external        test_nf90mpi_iget_var1_real
+        external        test_nf90mpi_iget_var1_double
+        external        test_nf90mpi_iget_var1_int8
+        external        test_nf90mpi_iget_var_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_iget_var_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_iget_var_int2
+#endif
+        external        test_nf90mpi_iget_var_int
+        external        test_nf90mpi_iget_var_real
+        external        test_nf90mpi_iget_var_double
+        external        test_nf90mpi_iget_var_int8
+        external        test_nf90mpi_iget_vara_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_iget_vara_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_iget_vara_int2
+#endif
+        external        test_nf90mpi_iget_vara_int
+        external        test_nf90mpi_iget_vara_real
+        external        test_nf90mpi_iget_vara_double
+        external        test_nf90mpi_iget_vara_int8
+        external        test_nf90mpi_iget_vars_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_iget_vars_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_iget_vars_int2
+#endif
+        external        test_nf90mpi_iget_vars_int
+        external        test_nf90mpi_iget_vars_real
+        external        test_nf90mpi_iget_vars_double
+        external        test_nf90mpi_iget_vars_int8
+
+        external        test_nf90mpi_iget_varm_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_iget_varm_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_iget_varm_int2
+#endif
+        external        test_nf90mpi_iget_varm_int
+        external        test_nf90mpi_iget_varm_real
+        external        test_nf90mpi_iget_varm_double
+        external        test_nf90mpi_iget_varm_int8
+
+        external        test_nf90mpi_get_att_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_get_att_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_get_att_int2
+#endif
+        external        test_nf90mpi_get_att_int
+        external        test_nf90mpi_get_att_real
+        external        test_nf90mpi_get_att_double
+        external        test_nf90mpi_get_att_int8
+        external        test_nf90mpi_inq_att
+        external        test_nf90mpi_inq_attname
+        external        test_nf90mpi_inq_attid
+        external        test_nf90mpi_inq_attlen
+        external        test_nf90mpi_inq_atttype
+        external        test_nf90mpi_create
+        external        test_nf90mpi_redef
+        external        test_nf90mpi_enddef
+        external        test_nf90mpi_sync
+        external        test_nf90mpi_abort
+        external        test_nf90mpi_def_dim
+        external        test_nf90mpi_rename_dim
+        external        test_nf90mpi_def_var
+        external        test_nf90mpi_put_var1_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_put_var1_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_put_var1_int2
+#endif
+        external        test_nf90mpi_put_var1_int
+        external        test_nf90mpi_put_var1_real
+        external        test_nf90mpi_put_var1_double
+        external        test_nf90mpi_put_var1_int8
+        external        test_nf90mpi_put_var_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_put_var_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_put_var_int2
+#endif
+        external        test_nf90mpi_put_var_int
+        external        test_nf90mpi_put_var_real
+        external        test_nf90mpi_put_var_double
+        external        test_nf90mpi_put_var_int8
+        external        test_nf90mpi_put_vara_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_put_vara_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_put_vara_int2
+#endif
+        external        test_nf90mpi_put_vara_int
+        external        test_nf90mpi_put_vara_real
+        external        test_nf90mpi_put_vara_double
+        external        test_nf90mpi_put_vara_int8
+        external        test_nf90mpi_put_vars_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_put_vars_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_put_vars_int2
+#endif
+        external        test_nf90mpi_put_vars_int
+        external        test_nf90mpi_put_vars_real
+        external        test_nf90mpi_put_vars_double
+        external        test_nf90mpi_put_vars_int8
+
+        external        test_nf90mpi_put_varm_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_put_varm_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_put_varm_int2
+#endif
+        external        test_nf90mpi_put_varm_int
+        external        test_nf90mpi_put_varm_real
+        external        test_nf90mpi_put_varm_double
+        external        test_nf90mpi_put_varm_int8
+
+        external        test_nf90mpi_iput_var1_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_iput_var1_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_iput_var1_int2
+#endif
+        external        test_nf90mpi_iput_var1_int
+        external        test_nf90mpi_iput_var1_real
+        external        test_nf90mpi_iput_var1_double
+        external        test_nf90mpi_iput_var1_int8
+        external        test_nf90mpi_iput_var_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_iput_var_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_iput_var_int2
+#endif
+        external        test_nf90mpi_iput_var_int
+        external        test_nf90mpi_iput_var_real
+        external        test_nf90mpi_iput_var_double
+        external        test_nf90mpi_iput_var_int8
+        external        test_nf90mpi_iput_vara_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_iput_vara_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_iput_vara_int2
+#endif
+        external        test_nf90mpi_iput_vara_int
+        external        test_nf90mpi_iput_vara_real
+        external        test_nf90mpi_iput_vara_double
+        external        test_nf90mpi_iput_vara_int8
+        external        test_nf90mpi_iput_vars_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_iput_vars_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_iput_vars_int2
+#endif
+        external        test_nf90mpi_iput_vars_int
+        external        test_nf90mpi_iput_vars_real
+        external        test_nf90mpi_iput_vars_double
+        external        test_nf90mpi_iput_vars_int8
+
+        external        test_nf90mpi_iput_varm_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_iput_varm_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_iput_varm_int2
+#endif
+        external        test_nf90mpi_iput_varm_int
+        external        test_nf90mpi_iput_varm_real
+        external        test_nf90mpi_iput_varm_double
+        external        test_nf90mpi_iput_varm_int8
+
+        external        test_nf90mpi_rename_var
+        external        test_nf90mpi_put_att_text
+#if defined(NF_INT1_T)
+        external        test_nf90mpi_put_att_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nf90mpi_put_att_int2
+#endif
+        external        test_nf90mpi_put_att_int
+        external        test_nf90mpi_put_att_real
+        external        test_nf90mpi_put_att_double
+        external        test_nf90mpi_put_att_int8
+        external        test_nf90mpi_copy_att
+        external        test_nf90mpi_rename_att
+        external        test_nf90mpi_del_att
+        external        test_nf90mpi_set_fill
+#if 0
+        external        test_nf90mpi_set_default_format
+#endif
+        external        nc_ignorefpe
+
+        call MPI_INIT(err)                        
+        comm = MPI_COMM_WORLD                   
+
+        call nc_ignorefpe(1)
+
+        testfile = 'test.nc'
+        scratch = 'scratch.nc'
+
+        nfailsTotal = 0
+        call getarg(0, progname)
+        create_file = .false.   !/* file test.nc will normally already exist */
+        readonly = .false.      !/* assume may write in test dir as default */
+        verbose = .false.
+        max_nmpt = 20
+        skiparg = .false.
+        cdf_format = 1
+        extra_flags = 0
+
+#if defined(__crayx1)
+        argc = ipxfargc()
+#else
+        argc = iargc()
+#endif
+        call getarg(0, PROGNAME)
+
+        do 1, iarg = 1, argc
+            if (skiparg) then
+                skiparg = .false.
+            else
+                call getarg(iarg, arg)
+                if (arg(1:1) .eq. '-') then
+                    lastopt = index(arg, ' ') - 1
+                    do 2, iopt = 2, lastopt
+                        opt = arg(iopt:iopt)
+                        if (opt .eq. 'c') then
+                            create_file = .true.
+                        else if (opt .eq. 'r') then
+                            readonly = .true.
+                        else if (opt .eq. 'v') then
+                            verbose = .true.
+                        else if (opt .eq. 'n') then
+                            call getarg(iarg+1, arg)
+                            ! NOTE: The UNICOS 8 fort77(1) compiler does
+                            ! not support list-directed I/O from an internal
+                            ! file -- so we use a format specification.
+                            read (arg, '(i6)') max_nmpt
+                            skiparg = .true.
+                            go to 1
+                        else if (opt .eq. '1') then
+                            cdf_format = 1
+                        else if (opt .eq. '2') then
+                            cdf_format = 2
+                            extra_flags = NF90_64BIT_OFFSET
+                        else if (opt .eq. '5') then
+                            cdf_format = 5
+                            extra_flags = NF90_64BIT_DATA
+                        else if (opt .eq. 'd') then
+                            call getarg(iarg+1, arg)
+                            testfile = trim(arg) // "/test.nc"
+                            scratch = trim(arg) // "/scratch.nc"
+                            skiparg = .true.
+                            go to 1
+                        else
+                            call usage
+                            call ud_exit(1)
+                        end if
+    2           continue
+                else
+                    call usage
+                    call ud_exit(1)
+                end if
+            end if
+1       continue
+
+        call MPI_Info_create(info, err)
+        ! call MPI_Info_set(info, "romio_pvfs2_posix_write", "enable",err)
+
+        numGatts = 6
+        numVars  = 136
+        numTypes = 6
+        if (cdf_format .EQ. 5) then
+            numGatts = NGATTS
+            numVars  = NVARS
+            numTypes = NTYPES
+        endif
+
+!       /* Initialize global variables defining test file */
+        call init_gvars
+
+        if ( create_file ) then
+            call write_file(testfile)
+            call MPI_Info_free(info, err)
+            if (nfailsTotal .eq. 0) &
+                 call ud_exit(0)
+            call ud_exit(1)
+        end if
+
+!       /* delete any existing scratch netCDF file */
+        if ( .not. readonly ) &
+            err = nf90mpi_delete(scratch, info)
+
+!       /* Test read-only functions, using pregenerated test-file */
+        call test('nf90mpi_strerror', test_nf90mpi_strerror)
+        call test('nf90mpi_open', test_nf90mpi_open)
+        call test('nf90mpi_close', test_nf90mpi_close)
+        call test('nf90mpi_inq', test_nf90mpi_inq)
+        call test('nf90mpi_inq_dimid', test_nf90mpi_inq_dimid)
+        call test('nf90mpi_inq_dim', test_nf90mpi_inq_dim)
+        call test('nf90mpi_inq_dimlen', test_nf90mpi_inq_dimlen)
+        call test('nf90mpi_inq_dimname', test_nf90mpi_inq_dimname)
+        call test('nf90mpi_inq_varid', test_nf90mpi_inq_varid)
+        call test('nf90mpi_inq_var', test_nf90mpi_inq_var)
+        call test('nf90mpi_inq_natts', test_nf90mpi_inq_natts)
+        call test('nf90mpi_inq_ndims', test_nf90mpi_inq_ndims)
+        call test('nf90mpi_inq_nvars', test_nf90mpi_inq_nvars)
+        call test('nf90mpi_inq_unlimdim', test_nf90mpi_inq_unlimdim)
+        call test('nf90mpi_inq_vardimid', test_nf90mpi_inq_vardimid)
+        call test('nf90mpi_inq_varname', test_nf90mpi_inq_varname)
+        call test('nf90mpi_inq_varnatts', test_nf90mpi_inq_varnatts)
+        call test('nf90mpi_inq_varndims', test_nf90mpi_inq_varndims)
+        call test('nf90mpi_inq_vartype', test_nf90mpi_inq_vartype)
+
+        call test('nf90mpi_get_var1_text', test_nf90mpi_get_var1_text)
+#if defined(NF_INT1_T)
+        call test('nf90mpi_get_var1_int1', test_nf90mpi_get_var1_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nf90mpi_get_var1_int2', test_nf90mpi_get_var1_int2)
+#endif
+        call test('nf90mpi_get_var1_int', test_nf90mpi_get_var1_int)
+        call test('nf90mpi_get_var1_real', test_nf90mpi_get_var1_real)
+        call test('nf90mpi_get_var1_double', test_nf90mpi_get_var1_double)
+        call test('nf90mpi_get_var1_int8', test_nf90mpi_get_var1_int8)
+
+        call test('nf90mpi_get_var_text', test_nf90mpi_get_var_text)
+#if defined(NF_INT1_T)
+        call test('nf90mpi_get_var_int1', test_nf90mpi_get_var_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nf90mpi_get_var_int2', test_nf90mpi_get_var_int2)
+#endif
+        call test('nf90mpi_get_var_int', test_nf90mpi_get_var_int)
+        call test('nf90mpi_get_var_real', test_nf90mpi_get_var_real)
+        call test('nf90mpi_get_var_double', test_nf90mpi_get_var_double)
+        call test('nf90mpi_get_var_int8', test_nf90mpi_get_var_int8)
+
+        call test('nf90mpi_get_vara_text', test_nf90mpi_get_vara_text)
+#if defined(NF_INT1_T)
+        call test('nf90mpi_get_vara_int1', test_nf90mpi_get_vara_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nf90mpi_get_vara_int2', test_nf90mpi_get_vara_int2)
+#endif
+        call test('nf90mpi_get_vara_int', test_nf90mpi_get_vara_int)
+        call test('nf90mpi_get_vara_real', test_nf90mpi_get_vara_real)
+        call test('nf90mpi_get_vara_double', test_nf90mpi_get_vara_double)
+        call test('nf90mpi_get_vara_int8', test_nf90mpi_get_vara_int8)
+
+        call test('nf90mpi_get_vars_text', test_nf90mpi_get_vars_text)
+#if defined(NF_INT1_T)
+        call test('nf90mpi_get_vars_int1', test_nf90mpi_get_vars_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nf90mpi_get_vars_int2', test_nf90mpi_get_vars_int2)
+#endif
+        call test('nf90mpi_get_vars_int', test_nf90mpi_get_vars_int)
+        call test('nf90mpi_get_vars_real', test_nf90mpi_get_vars_real)
+        call test('nf90mpi_get_vars_double', test_nf90mpi_get_vars_double)
+        call test('nf90mpi_get_vars_int8', test_nf90mpi_get_vars_int8)
+
+        call test('nf90mpi_get_varm_text', test_nf90mpi_get_varm_text)
+#if defined(NF_INT1_T)
+        call test('nf90mpi_get_varm_int1', test_nf90mpi_get_varm_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nf90mpi_get_varm_int2', test_nf90mpi_get_varm_int2)
+#endif
+        call test('nf90mpi_get_varm_int', test_nf90mpi_get_varm_int)
+        call test('nf90mpi_get_varm_real', test_nf90mpi_get_varm_real)
+        call test('nf90mpi_get_varm_double', test_nf90mpi_get_varm_double)
+        call test('nf90mpi_get_varm_int8', test_nf90mpi_get_varm_int8)
+
+        call test('nf90mpi_iget_var1_text', test_nf90mpi_iget_var1_text)
+#if defined(NF_INT1_T)
+        call test('nf90mpi_iget_var1_int1', test_nf90mpi_iget_var1_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nf90mpi_iget_var1_int2', test_nf90mpi_iget_var1_int2)
+#endif
+        call test('nf90mpi_iget_var1_int', test_nf90mpi_iget_var1_int)
+        call test('nf90mpi_iget_var1_real', test_nf90mpi_iget_var1_real)
+        call test('nf90mpi_iget_var1_double', test_nf90mpi_iget_var1_double)
+        call test('nf90mpi_iget_var1_int8', test_nf90mpi_iget_var1_int8)
+
+        call test('nf90mpi_iget_var_text', test_nf90mpi_iget_var_text)
+#if defined(NF_INT1_T)
+        call test('nf90mpi_iget_var_int1', test_nf90mpi_iget_var_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nf90mpi_iget_var_int2', test_nf90mpi_iget_var_int2)
+#endif
+        call test('nf90mpi_iget_var_int', test_nf90mpi_iget_var_int)
+        call test('nf90mpi_iget_var_real', test_nf90mpi_iget_var_real)
+        call test('nf90mpi_iget_var_double', test_nf90mpi_iget_var_double)
+        call test('nf90mpi_iget_var_int8', test_nf90mpi_iget_var_int8)
+
+        call test('nf90mpi_iget_vara_text', test_nf90mpi_iget_vara_text)
+#if defined(NF_INT1_T)
+        call test('nf90mpi_iget_vara_int1', test_nf90mpi_iget_vara_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nf90mpi_iget_vara_int2', test_nf90mpi_iget_vara_int2)
+#endif
+        call test('nf90mpi_iget_vara_int', test_nf90mpi_iget_vara_int)
+        call test('nf90mpi_iget_vara_real', test_nf90mpi_iget_vara_real)
+        call test('nf90mpi_iget_vara_double', test_nf90mpi_iget_vara_double)
+        call test('nf90mpi_iget_vara_int8', test_nf90mpi_iget_vara_int8)
+
+        call test('nf90mpi_iget_vars_text', test_nf90mpi_iget_vars_text)
+#if defined(NF_INT1_T)
+        call test('nf90mpi_iget_vars_int1', test_nf90mpi_iget_vars_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nf90mpi_iget_vars_int2', test_nf90mpi_iget_vars_int2)
+#endif
+        call test('nf90mpi_iget_vars_int', test_nf90mpi_iget_vars_int)
+        call test('nf90mpi_iget_vars_real', test_nf90mpi_iget_vars_real)
+        call test('nf90mpi_iget_vars_double', test_nf90mpi_iget_vars_double)
+        call test('nf90mpi_iget_vars_int8', test_nf90mpi_iget_vars_int8)
+
+        call test('nf90mpi_iget_varm_text', test_nf90mpi_iget_varm_text)
+#if defined(NF_INT1_T)
+        call test('nf90mpi_iget_varm_int1', test_nf90mpi_iget_varm_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nf90mpi_iget_varm_int2', test_nf90mpi_iget_varm_int2)
+#endif
+        call test('nf90mpi_iget_varm_int', test_nf90mpi_iget_varm_int)
+        call test('nf90mpi_iget_varm_real', test_nf90mpi_iget_varm_real)
+        call test('nf90mpi_iget_varm_double', test_nf90mpi_iget_varm_double)
+        call test('nf90mpi_iget_varm_int8', test_nf90mpi_iget_varm_int8)
+
+        call test('nf90mpi_get_att_text', test_nf90mpi_get_att_text)
+#if defined(NF_INT1_T)
+        call test('nf90mpi_get_att_int1', test_nf90mpi_get_att_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nf90mpi_get_att_int2', test_nf90mpi_get_att_int2)
+#endif
+        call test('nf90mpi_get_att_int', test_nf90mpi_get_att_int)
+        call test('nf90mpi_get_att_real', test_nf90mpi_get_att_real)
+        call test('nf90mpi_get_att_double', test_nf90mpi_get_att_double)
+        call test('nf90mpi_get_att_int8', test_nf90mpi_get_att_int8)
+        call test('nf90mpi_inq_att', test_nf90mpi_inq_att)
+        call test('nf90mpi_inq_attname', test_nf90mpi_inq_attname)
+        call test('nf90mpi_inq_attid', test_nf90mpi_inq_attid)
+        call test('nf90mpi_inq_attlen', test_nf90mpi_inq_attlen)
+        call test('nf90mpi_inq_atttype', test_nf90mpi_inq_atttype)
+
+!           /* Test write functions */
+        if (.not. readonly) then
+            call test('nf90mpi_create', test_nf90mpi_create)
+            call test('nf90mpi_redef', test_nf90mpi_redef)
+            call test('nf90mpi_enddef', test_nf90mpi_enddef)
+            call test('nf90mpi_sync', test_nf90mpi_sync)
+            call test('nf90mpi_abort', test_nf90mpi_abort)
+            call test('nf90mpi_def_dim', test_nf90mpi_def_dim)
+            call test('nf90mpi_rename_dim', test_nf90mpi_rename_dim)
+            call test('nf90mpi_def_var', test_nf90mpi_def_var)
+            call test('nf90mpi_put_var1_text', test_nf90mpi_put_var1_text)
+#if defined(NF_INT1_T)
+            call test('nf90mpi_put_var1_int1', test_nf90mpi_put_var1_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nf90mpi_put_var1_int2', test_nf90mpi_put_var1_int2)
+#endif
+            call test('nf90mpi_put_var1_int', test_nf90mpi_put_var1_int)
+            call test('nf90mpi_put_var1_real', test_nf90mpi_put_var1_real)
+            call test('nf90mpi_put_var1_double',  &
+                       test_nf90mpi_put_var1_double)
+            call test('nf90mpi_put_var1_int8', test_nf90mpi_put_var1_int8)
+            call test('nf90mpi_put_var_text', test_nf90mpi_put_var_text)
+#if defined(NF_INT1_T)
+            call test('nf90mpi_put_var_int1', test_nf90mpi_put_var_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nf90mpi_put_var_int2', test_nf90mpi_put_var_int2)
+#endif
+            call test('nf90mpi_put_var_int', test_nf90mpi_put_var_int)
+            call test('nf90mpi_put_var_real', test_nf90mpi_put_var_real)
+            call test('nf90mpi_put_var_double', &
+                       test_nf90mpi_put_var_double)
+            call test('nf90mpi_put_var_int8', test_nf90mpi_put_var_int8)
+            call test('nf90mpi_put_vara_text', test_nf90mpi_put_vara_text)
+#if defined(NF_INT1_T)
+            call test('nf90mpi_put_vara_int1', test_nf90mpi_put_vara_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nf90mpi_put_vara_int2', test_nf90mpi_put_vara_int2)
+#endif
+            call test('nf90mpi_put_vara_int', test_nf90mpi_put_vara_int)
+            call test('nf90mpi_put_vara_real', test_nf90mpi_put_vara_real)
+            call test('nf90mpi_put_vara_double', &
+                       test_nf90mpi_put_vara_double)
+            call test('nf90mpi_put_vara_int8', test_nf90mpi_put_vara_int8)
+            call test('nf90mpi_put_vars_text', test_nf90mpi_put_vars_text)
+#if defined(NF_INT1_T)
+            call test('nf90mpi_put_vars_int1', test_nf90mpi_put_vars_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nf90mpi_put_vars_int2', test_nf90mpi_put_vars_int2)
+#endif
+            call test('nf90mpi_put_vars_int', test_nf90mpi_put_vars_int)
+            call test('nf90mpi_put_vars_real', test_nf90mpi_put_vars_real)
+            call test('nf90mpi_put_vars_double', &
+                       test_nf90mpi_put_vars_double)
+            call test('nf90mpi_put_vars_int8', test_nf90mpi_put_vars_int8)
+
+            call test('nf90mpi_put_varm_text', test_nf90mpi_put_varm_text)
+#if defined(NF_INT1_T)
+            call test('nf90mpi_put_varm_int1', test_nf90mpi_put_varm_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nf90mpi_put_varm_int2', test_nf90mpi_put_varm_int2)
+#endif
+            call test('nf90mpi_put_varm_int', test_nf90mpi_put_varm_int)
+            call test('nf90mpi_put_varm_real', test_nf90mpi_put_varm_real)
+            call test('nf90mpi_put_varm_double', &
+                       test_nf90mpi_put_varm_double)
+            call test('nf90mpi_put_varm_int8', test_nf90mpi_put_varm_int8)
+
+            call test('nf90mpi_iput_var1_text', test_nf90mpi_iput_var1_text)
+#if defined(NF_INT1_T)
+            call test('nf90mpi_iput_var1_int1', test_nf90mpi_iput_var1_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nf90mpi_iput_var1_int2', test_nf90mpi_iput_var1_int2)
+#endif
+            call test('nf90mpi_iput_var1_int', test_nf90mpi_iput_var1_int)
+            call test('nf90mpi_iput_var1_real', test_nf90mpi_iput_var1_real)
+            call test('nf90mpi_iput_var1_double',  &
+                       test_nf90mpi_iput_var1_double)
+            call test('nf90mpi_iput_var1_int8', test_nf90mpi_iput_var1_int8)
+
+            call test('nf90mpi_iput_var_text', test_nf90mpi_iput_var_text)
+#if defined(NF_INT1_T)
+            call test('nf90mpi_iput_var_int1', test_nf90mpi_iput_var_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nf90mpi_iput_var_int2', test_nf90mpi_iput_var_int2)
+#endif
+            call test('nf90mpi_iput_var_int', test_nf90mpi_iput_var_int)
+            call test('nf90mpi_iput_var_real', test_nf90mpi_iput_var_real)
+            call test('nf90mpi_iput_var_double', &
+                       test_nf90mpi_iput_var_double)
+            call test('nf90mpi_iput_var_int8', test_nf90mpi_iput_var_int8)
+
+            call test('nf90mpi_iput_vara_text', test_nf90mpi_iput_vara_text)
+#if defined(NF_INT1_T)
+            call test('nf90mpi_iput_vara_int1', test_nf90mpi_iput_vara_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nf90mpi_iput_vara_int2', test_nf90mpi_iput_vara_int2)
+#endif
+            call test('nf90mpi_iput_vara_int', test_nf90mpi_iput_vara_int)
+            call test('nf90mpi_iput_vara_real', test_nf90mpi_iput_vara_real)
+            call test('nf90mpi_iput_vara_double', &
+                       test_nf90mpi_iput_vara_double)
+            call test('nf90mpi_iput_vara_int8', test_nf90mpi_iput_vara_int8)
+
+            call test('nf90mpi_iput_vars_text', test_nf90mpi_iput_vars_text)
+#if defined(NF_INT1_T)
+            call test('nf90mpi_iput_vars_int1', test_nf90mpi_iput_vars_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nf90mpi_iput_vars_int2', test_nf90mpi_iput_vars_int2)
+#endif
+            call test('nf90mpi_iput_vars_int', test_nf90mpi_iput_vars_int)
+            call test('nf90mpi_iput_vars_real', test_nf90mpi_iput_vars_real)
+            call test('nf90mpi_iput_vars_double', &
+                       test_nf90mpi_iput_vars_double)
+            call test('nf90mpi_iput_vars_int8', test_nf90mpi_iput_vars_int8)
+
+            call test('nf90mpi_iput_varm_text', test_nf90mpi_iput_varm_text)
+#if defined(NF_INT1_T)
+            call test('nf90mpi_iput_varm_int1', test_nf90mpi_iput_varm_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nf90mpi_iput_varm_int2', test_nf90mpi_iput_varm_int2)
+#endif
+            call test('nf90mpi_iput_varm_int', test_nf90mpi_iput_varm_int)
+            call test('nf90mpi_iput_varm_real', test_nf90mpi_iput_varm_real)
+            call test('nf90mpi_iput_varm_double', &
+                       test_nf90mpi_iput_varm_double)
+            call test('nf90mpi_iput_varm_int8', test_nf90mpi_iput_varm_int8)
+
+            call test('nf90mpi_rename_var', test_nf90mpi_rename_var)
+            call test('nf90mpi_put_att_text', test_nf90mpi_put_att_text)
+#if defined(NF_INT1_T)
+            call test('nf90mpi_put_att_int1', test_nf90mpi_put_att_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nf90mpi_put_att_int2', test_nf90mpi_put_att_int2)
+#endif
+            call test('nf90mpi_put_att_int', test_nf90mpi_put_att_int)
+            call test('nf90mpi_put_att_real', test_nf90mpi_put_att_real)
+            call test('nf90mpi_put_att_double', &
+                       test_nf90mpi_put_att_double)
+            call test('nf90mpi_put_att_int8', test_nf90mpi_put_att_int8)
+            call test('nf90mpi_copy_att', test_nf90mpi_copy_att)
+            call test('nf90mpi_rename_att', test_nf90mpi_rename_att)
+            call test('nf90mpi_del_att', test_nf90mpi_del_att)
+            call test('nf90mpi_set_fill', test_nf90mpi_set_fill)
+#if 0
+            call test('nf90mpi_set_default_format', &
+                      test_nf90mpi_set_default_format);
+#endif
+        end if
+
+        call MPI_Info_free(info, err)
+
+        call report_test
+
+        ! if (nfailsTotal .eq. 0) call ud_exit(0)
+        call ud_exit(0)
+        end
diff --git a/test/nf90_test/test_get.m4 b/test/nf90_test/test_get.m4
new file mode 100644
index 0000000..402cf80
--- /dev/null
+++ b/test/nf90_test/test_get.m4
@@ -0,0 +1,1163 @@
+dnl
+dnl  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+dnl  See COPYRIGHT notice in top-level directory.
+dnl
+dnl $Id: test_get.m4 1699 2014-07-05 00:32:53Z wkliao $
+dnl
+
+divert(-1)
+
+dnl This is m4 source.
+dnl Process using m4 to produce FORTRAN language file.
+
+changequote([,])
+
+undefine([index])dnl
+
+dnl Macros
+
+dnl Upcase(str)
+dnl
+define([Upcase],[dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)])
+
+dnl NFT_ITYPE(type)
+dnl
+define([NFT_ITYPE], [NFT_[]Upcase($1)])
+
+dnl ARITH_VAR1(itype, value)
+dnl
+define([ARITH_VAR1], [ifelse($1, text, ichar($2(1:1)), $2(1))])
+
+dnl ARITH3(itype, value)
+dnl
+define([ARITH3], [ifelse($1, text, ichar($2($3:$3)), $2($3,1))])
+
+dnl VALUE3(itype, value)
+dnl
+define([VALUE3], [ifelse($1, text, $2(1:nels), $2(1:nels,1))])
+
+dnl ATTARITH3(itype, value)
+dnl
+define([ATTARITH3], [ifelse($1, text, ichar($2($3:$3)), $2($3))])
+
+dnl  DATATYPE(funf_suffix)
+dnl
+define([DATATYPE], [dnl
+dnl ifelse($1, text, character(len=MAX_NELS) $2,
+ifelse($1, text, character(len=$3) $2,
+ifelse($1, int1, NF_INT1_T $2($3,1),
+ifelse($1, int2, NF_INT2_T $2($3,1),
+ifelse($1, int, integer $2($3,1),
+ifelse($1, int8, NF_INT8_T $2($3,1),
+ifelse($1, real, real $2($3,1),
+ifelse($1, double, doubleprecision $2($3,1))[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  DATATYPE_VAR1(funf_suffix)
+dnl
+define([DATATYPE_VAR1], [dnl
+ifelse($1, text, character(len=1) $2,
+ifelse($1, int1, NF_INT1_T $2(1),
+ifelse($1, int2, NF_INT2_T $2(1),
+ifelse($1, int, integer $2(1),
+ifelse($1, int8, NF_INT8_T $2(1),
+ifelse($1, real, real $2(1),
+ifelse($1, double, doubleprecision $2(1))[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  ATTDATATYPE(funf_suffix)
+dnl
+define([ATTDATATYPE], [dnl
+dnl ifelse($1, text, character(len=MAX_NELS) $2,
+ifelse($1, text, character(len=$3) $2,
+ifelse($1, int1, NF_INT1_T $2($3),
+ifelse($1, int2, NF_INT2_T $2($3),
+ifelse($1, int, integer $2($3),
+ifelse($1, int8, NF_INT8_T $2($3),
+ifelse($1, real, real $2($3),
+ifelse($1, double, doubleprecision $2($3))[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl TEST_NFMPI_GET_VAR1(TYPE)
+dnl
+define([TEST_NFMPI_GET_VAR1],[dnl
+        subroutine test_nf90mpi_get_var1_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes
+        double precision hash4
+        logical inRange3, in_internal_range, equal
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        integer nok      
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        doubleprecision expect
+        logical canConvert     
+        DATATYPE_VAR1($1, value)
+        doubleprecision val
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_begin_indep_data(ncid)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            do 2, j = 1, var_rank(i)
+                index(j) = 1
+2           continue
+            err = nf90mpi_get_var(BAD_ID, i, value(1:1), index)
+            if (err .ne. NF90_EBADID) &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_get_var(ncid, BAD_VARID, value(1:1), index)
+            if (err .ne. NF90_ENOTVAR) &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                index(j) = var_shape(j,i) + 1
+                err = nf90mpi_get_var(ncid, i, value(1:1), index)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad index: ', err)
+                endif
+                index(j) = 1
+3           continue
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                    index)
+                if (err .ne. NF90_NOERR) &
+                    call error('error in index2indexes 1')
+                expect = hash4( var_type(i), var_rank(i), index,  &
+                                NFT_ITYPE($1) )
+                err = nf90mpi_get_var(ncid, i, value(1:1), index)
+                if (canConvert) then
+                    if (inRange3(expect,var_type(i),  &
+                                 NFT_ITYPE($1))) then
+                        if (in_internal_range(NFT_ITYPE($1), &
+                                              expect)) then
+                            if (err .ne. NF90_NOERR) then
+                                call errore('nf90mpi_get_var: ', err)
+                            else
+                                val = ARITH_VAR1($1, value)
+                                if (.not. equal(val, expect,  &
+                                                var_type(i),  &
+                                                NFT_ITYPE($1))) then
+                                    call errord('unexpected: ', val)
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+                        else
+                            if (err .ne. NF90_ERANGE) &
+                                call errore('Range error: ', err)
+                        end if
+                    else
+                        if (err .ne. NF90_NOERR .and. err .ne. NF90_ERANGE) &
+                            call errore('OK or Range error: ', err)
+                    end if
+                else
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                end if
+4           continue
+1       continue
+        err = nf90mpi_end_indep_data(ncid)
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ',  err)
+        call print_nok(nok)
+        end
+])
+
+dnl TEST_NFMPI_GET_VAR(TYPE)
+dnl
+define([TEST_NFMPI_GET_VAR],[dnl
+        subroutine test_nf90mpi_get_var_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes
+        double precision hash4
+        logical inrange3, in_internal_range, equal
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer nok      
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        doubleprecision expect(MAX_NELS)
+        logical canConvert     
+        DATATYPE($1, value, MAX_NELS)
+        doubleprecision val
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            err = nf90mpi_get_var_all(BAD_ID, i, value)
+            if (err .ne. NF90_EBADID) &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_get_var_all(ncid, BAD_VARID, value)
+            if (err .ne. NF90_ENOTVAR) &
+                call errore('bad var id: ', err)
+            nels = 1
+            do 3, j = 1, var_rank(i)
+                nels = nels * var_shape(j,i)
+3           continue
+            allInExtRange = .true.
+            allInIntRange = .true.
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                    index)
+                if (err .ne. NF90_NOERR) &
+                    call error('error in index2indexes 1')
+                expect(j) = hash4( var_type(i), var_rank(i), index,  &
+                                NFT_ITYPE($1) )
+                if (inRange3(expect(j),var_type(i), NFT_ITYPE($1))) then
+                    allInIntRange = allInIntRange .and. &
+                        in_internal_range(NFT_ITYPE($1), expect(j))
+                else
+                    allInExtRange = .false.
+                end if
+4           continue
+            err = nf90mpi_get_var_all(ncid, i, VALUE3($1, value), count=var_shape(:,i))
+            if (canConvert) then
+                if (allInExtRange) then
+                    if (allInIntRange) then
+                        if (err .ne. NF90_NOERR)  &
+                            call errore('nf90mpi_get_var_all: ', err)
+                    else
+                        if (err .ne. NF90_ERANGE) &
+                            call errore('Range error: ', err)
+                    endif
+                else
+                    if (err .ne. NF90_NOERR  .and. err .ne. NF90_ERANGE) &
+                        call errore('Range error: ', err)
+                endif
+                do 5, j = 1, var_nels(i)
+                    if (inRange3(expect(j),var_type(i), &
+                                 NFT_ITYPE($1)) .and. &
+                        in_internal_range(NFT_ITYPE($1), &
+                                                expect(j))) then
+                        val = ARITH3($1, value, j)
+                        if (.not. equal(val, expect(j),  &
+                                        var_type(i),  &
+                                        NFT_ITYPE($1))) then
+                            call errord('unexpected: ', val)
+                        else
+                            nok = nok + 1
+                        end if
+                    endif
+5               continue
+            else
+                if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+            end if
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ',  err)
+        call print_nok(nok)
+        end
+])
+
+
+dnl TEST_NFMPI_GET_VARA(TYPE)
+dnl
+define([TEST_NFMPI_GET_VARA],[dnl
+        subroutine test_nf90mpi_get_vara_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash4
+        logical inrange3, in_internal_range, equal
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer nslabs
+        integer nok      
+        integer(kind=MPI_OFFSET_KIND) start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) edge(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) mid(MAX_RANK)
+        logical canConvert     
+        DATATYPE($1, value, MAX_NELS)
+        doubleprecision expect(MAX_NELS)
+        doubleprecision val
+        integer ud_shift
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv.  &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert'
+            if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+2           continue
+            err = nf90mpi_get_var_all(BAD_ID, i, value, start, &
+                        edge)
+            if (err .ne. NF90_EBADID) &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_get_var_all(ncid, BAD_VARID, value, start,  &
+                                 edge)
+            if (err .ne. NF90_ENOTVAR) &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_get_var_all(ncid, i, value, start, &
+                                     edge)
+                if (canConvert .and. err .ne. NF90_EINVALCOORDS) &
+                    call errore('bad index: ', err)
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nf90mpi_get_var_all(ncid, i, value, start, &
+                                     edge)
+                if (canConvert .and. err .ne. NF90_EEDGE) &
+                    call errore('bad edge: ', err)
+                edge(j) = 1
+3           continue
+
+!           /* Check non-scalars for correct error returned even when */
+!           /* there is nothing to get (edge(j).eq.0) */
+            if (var_rank(i) .gt. 0) then
+                do 10, j = 1, var_rank(i)
+                    edge(j) = 0
+10              continue
+                err = nf90mpi_get_var_all(BAD_ID, i, value, start, &
+                        edge)
+                if (err .ne. NF90_EBADID)  &
+                    call errore('bad ncid: ', err)
+                err = nf90mpi_get_var_all(ncid, BAD_VARID, value, &
+                        start, edge)
+                if (err .ne. NF90_ENOTVAR)  &
+                    call errore('bad var id: ', err)
+                do 11, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .gt. 1) then     !/* skip record dim */
+                        start(j) = var_shape(j,i) + 1
+                        err = nf90mpi_get_var_all(ncid, i, value, &
+                                start, edge)
+                        if (canConvert .and. err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                        start(j) = 1
+                    endif
+11              continue
+                err = nf90mpi_get_var_all(ncid, i, value, start, &
+                                edge)
+                if (canConvert) then
+                    if (err .ne. NF90_NOERR)  &
+                        call error(nf90mpi_strerror(err))
+                else
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                endif
+                do 12, j = 1, var_rank(i)
+                    edge(j) = 1
+12              continue
+            endif
+
+!           Choose a random point dividing each dim into 2 parts
+!           get 2^rank (nslabs) slabs so defined
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+!           bits of k determine whether to get lower or upper part of dim 
+            do 5, k = 1, nslabs
+                nels = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift((k-1), -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    nels = nels * edge(j)
+6               continue
+                allInIntRange = .true.
+                allInExtRange = .true.
+                do 7, j = 1, INT(nels)
+                    err = index2indexes(j, var_rank(i), edge, index)
+                    if (err .ne. NF90_NOERR) &
+                        call error('error in index2indexes 1')
+                    do 8, d = 1, var_rank(i)
+                        index(d) = index(d) + start(d) - 1
+8                   continue
+                    expect(j) = hash4(var_type(i), var_rank(i), index,  &
+                                      NFT_ITYPE($1))
+                    if (inRange3(expect(j),var_type(i),  &
+                                 NFT_ITYPE($1))) then
+                        allInIntRange =  &
+                            allInIntRange .and. &
+                            in_internal_range(NFT_ITYPE($1), expect(j))
+                    else
+                        allInExtRange = .false.
+                    end if
+7               continue
+                err = nf90mpi_get_var_all(ncid, i, value, start, &
+                                edge)
+                if (canConvert) then
+                    if (allInExtRange) then
+                        if (allInIntRange) then
+                            if (err .ne. NF90_NOERR) &
+                                call errore('nf90mpi_get_var:', &
+                                             err)
+                        else
+                            if (err .ne. NF90_ERANGE) &
+                                call errore('Range error: ', err)
+                        end if
+                    else
+                        if (err .ne. NF90_NOERR .and. err .ne. NF90_ERANGE) &
+                            call errore('OK or Range error: ', err)
+                    end if
+                    do 9, j = 1, INT(nels)
+                        if (inRange3(expect(j),var_type(i), &
+                                     NFT_ITYPE($1)) .and. &
+                            in_internal_range(NFT_ITYPE($1), expect(j))) &
+                                then
+                            val = ARITH3($1, value, j)
+                            if (.not.equal(val,expect(j), &
+                                           var_type(i),NFT_ITYPE($1)))  &
+                                    then
+                                call error( &
+                                    'value read not that expected')
+                                if (verbose) then
+                                    call error(' ')
+                                    call errori('varid: ', i)
+                                    call errorc('var_name: ', &
+                                        var_name(i))
+                                    call errori('element number: %d ',  &
+                                                j)
+                                    call errord('expect: ', expect(j))
+                                    call errord('got: ', val)
+                                end if
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+9                   continue
+                else
+                    if (nels .gt. 0  .and. err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                end if
+5           continue
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errorc('nf90mpi_close: ', nf90mpi_strerror(err))
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_GET_VARS(TYPE)
+dnl
+define([TEST_NFMPI_GET_VARS],dnl
+[dnl
+        subroutine test_nf90mpi_get_vars_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash4
+        logical inrange3, in_internal_range, equal
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer nslabs
+        integer(kind=MPI_OFFSET_KIND) nstarts         
+        integer nok             
+        integer(kind=MPI_OFFSET_KIND) start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) edge(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index2(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) mid(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) count(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) sstride(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) stride(MAX_RANK)
+        logical canConvert     
+        DATATYPE($1, value, MAX_NELS)
+        doubleprecision expect(MAX_NELS)
+        doubleprecision val
+        integer ud_shift
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv.  &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert'
+            if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+2           continue
+            err = nf90mpi_get_var_all(BAD_ID, i, value, start, &
+                        edge, stride)
+            if (err .ne. NF90_EBADID) &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_get_var_all(ncid, BAD_VARID, value, &
+                        start, edge, stride) 
+            if (err .ne. NF90_ENOTVAR) &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_get_var_all(ncid, i, value, start, &
+                                     edge, stride) 
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad index: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nf90mpi_get_var_all(ncid, i, value, start, &
+                                     edge, stride) 
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EEDGE) &
+                        call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nf90mpi_get_var_all(ncid, i, value, start, &
+                                     edge, stride)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_ESTRIDE) &
+                        call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
+3           continue
+!           Choose a random point dividing each dim into 2 parts
+!           get 2^rank (nslabs) slabs so defined
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+!           bits of k determine whether to get lower or upper part of dim
+!           choose random stride from 1 to edge
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, j-1), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        sstride(j) = 1 + roll(edge(j))
+                    else
+                        sstride(j) = 1
+                    end if
+                    nstarts = nstarts * stride(j)
+6               continue
+                do 7, m = 1, INT(nstarts)
+                    err = index2indexes(m, var_rank(i), sstride,  &
+                                        index)
+                    if (err .ne. NF90_NOERR) &
+                        call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) /  &
+                                        stride(j)
+                        nels = nels * count(j)
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+!                   Random choice of forward or backward 
+!    /* TODO
+!                   if ( roll(2) ) then
+!                       for (j = 0 j < var_rank(i) j++) {
+!                           index(j) += (count(j) - 1) * stride(j)
+!                           stride(j) = -stride(j)
+!                       }
+!                   end if
+!    */
+                    allInIntRange = .true.
+                    allInExtRange = .true.
+                    do 9, j = 1, INT(nels)
+                        err = index2indexes(j, var_rank(i), count,  &
+                                            index2)
+                        if (err .ne. NF90_NOERR) &
+                            call error('error in index2indexes() 1')
+                        do 10, d = 1, var_rank(i)
+                            index2(d) = index(d) + (index2(d)-1) *  &
+                                        stride(d)
+10                      continue
+                        expect(j) = hash4(var_type(i), var_rank(i),  &
+                                          index2, NFT_ITYPE($1))
+                        if (inRange3(expect(j),var_type(i), &
+                                     NFT_ITYPE($1))) then
+                            allInIntRange =  &
+                                allInIntRange .and. &
+                                in_internal_range(NFT_ITYPE($1),  &
+                                                  expect(j))
+                        else
+                            allInExtRange = .false.
+                        end if
+9                   continue
+                    err = nf90mpi_get_var_all(ncid, i, value, index, &
+                                         count, stride)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (allInIntRange) then
+                                if (err .ne. NF90_NOERR) &
+                                    call error(nf90mpi_strerror(err))
+                            else
+                                if (err .ne. NF90_ERANGE) &
+                                    call errore('Range error: ', err)
+                            end if
+                        else
+                            if (err .ne. NF90_NOERR .and. &
+                                err .ne. NF90_ERANGE) &
+                                call errore('OK or Range error: ', err)
+                        end if
+                        do 11, j = 1, INT(nels)
+                            if (inRange3(expect(j),var_type(i), &
+                                NFT_ITYPE($1)) .and. &
+                                in_internal_range(NFT_ITYPE($1),  &
+                                                  expect(j))) then
+                                val = ARITH3($1, value, j)
+                                if (.not.equal(val, expect(j), &
+                                    var_type(i), NFT_ITYPE($1))) then
+                                    call error( &
+                                        'value read not that expected')
+                                    if (verbose) then
+                                        call error(' ')
+                                        call errori('varid: ', i)
+                                        call errorc('var_name: ',  &
+                                                    var_name(i))
+                                        call errori('element number: ', &
+                                                    j)
+                                        call errord('expect: ',  &
+                                                    expect(j))
+                                        call errord('got: ', val)
+                                    end if
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+11                      continue
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_GET_VARM(TYPE)
+dnl
+define([TEST_NFMPI_GET_VARM],dnl
+[dnl
+        subroutine test_nf90mpi_get_varm_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash4
+        logical inrange3, in_internal_range, equal
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer nslabs
+        integer(kind=MPI_OFFSET_KIND) nstarts         
+        integer nok             
+        integer(kind=MPI_OFFSET_KIND) start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) edge(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index2(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) mid(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) count(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) sstride(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) stride(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) imap(MAX_RANK)
+        logical canConvert     
+        DATATYPE($1, value, MAX_NELS)
+        doubleprecision expect(MAX_NELS)
+        doubleprecision val
+        integer ud_shift
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv.  &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assertion'
+            if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assertion'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+                imap(j) = 1
+2           continue
+            err = nf90mpi_get_var_all(BAD_ID, i, value, start, edge, &
+                                 stride, imap) 
+            if (err .ne. NF90_EBADID) &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_get_var_all(ncid, BAD_VARID, value, start, &
+                                 edge, stride, imap)
+            if (err .ne. NF90_ENOTVAR) &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_get_var_all(ncid, i, value, start, &
+                                     edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad index: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nf90mpi_get_var_all(ncid, i, value, start, &
+                                     edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EEDGE) &
+                        call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nf90mpi_get_var_all(ncid, i, value, start, &
+                                     edge, stride, imap)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_ESTRIDE) &
+                        call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
+3           continue
+!           Choose a random point dividing each dim into 2 parts 
+!           get 2^rank (nslabs) slabs so defined 
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+!           /* bits of k determine whether to get lower or upper part 
+!            * of dim
+!            * choose random stride from 1 to edge */
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift((k-1), -(j-1)), 2) .ne. 0) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        stride(j) = 1+roll(edge(j))
+                    else
+                        stride(j) = 1
+                    end if
+                    sstride(j) = stride(j)
+                    nstarts = nstarts * stride(j)
+6               continue
+                do 7, m = 1, INT(nstarts)
+                    err = index2indexes(m, var_rank(i), sstride, index)
+                    if (err .ne. NF90_NOERR) &
+                        call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) /  &
+                                        stride(j)
+                        nels = nels * count(j)
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+!                   Random choice of forward or backward 
+!    /* TODO
+!                   if ( roll(2) ) then
+!                       for (j = 0 j < var_rank(i) j++) {
+!                           index(j) += (count(j) - 1) * stride(j)
+!                           stride(j) = -stride(j)
+!                       }
+!                   end if
+!     */
+                    if (var_rank(i) .gt. 0) then
+                        imap(1) = 1
+                        do 9, j = 2, var_rank(i)
+                            imap(j) = imap(j-1) * count(j-1)
+9                       continue
+                    end if
+                    allInIntRange = .true.
+                    allInExtRange = .true.
+                    do 10, j = 1, INT(nels)
+                        err = index2indexes(j, var_rank(i), count,  &
+                                            index2)
+                        if (err .ne. NF90_NOERR) &
+                            call error('error in index2indexes 1')
+                        do 11, d = 1, var_rank(i)
+                            index2(d) = index(d) + (index2(d)-1) *  &
+                                        stride(d)
+11                      continue
+                        expect(j) = hash4(var_type(i), var_rank(i),  &
+                                          index2, NFT_ITYPE($1))
+                        if (inRange3(expect(j),var_type(i), &
+                                     NFT_ITYPE($1))) then
+                            allInIntRange =  &
+                                allInIntRange .and. &
+                                in_internal_range(NFT_ITYPE($1), &
+                                                  expect(j))
+                        else
+                            allInExtRange = .false.
+                        end if
+10                  continue
+                    err = nf90mpi_get_var_all(ncid,i,value,index,count, &
+                                         stride,imap)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (allInIntRange) then
+                                if (err .ne. NF90_NOERR) &
+                                    call error(nf90mpi_strerror(err))
+                            else
+                                if (err .ne. NF90_ERANGE) &
+                                    call errore('Range error: ', err)
+                            end if
+                        else
+                            if (err .ne. NF90_NOERR .and. &
+                                err .ne. NF90_ERANGE) &
+                                call errore('OK or Range error: ', err)
+                        end if
+                        do 12, j = 1, INT(nels)
+                            if (inRange3(expect(j),var_type(i), &
+                                         NFT_ITYPE($1)) .and. &
+                                in_internal_range(NFT_ITYPE($1), &
+                                                  expect(j))) then
+                                val = ARITH3($1, value, j)
+                                if (.not.equal(val, expect(j), &
+                                               var_type(i),  &
+                                               NFT_ITYPE($1))) then
+                                    call error( &
+                                        'value read not that expected')
+                                    if (verbose) then
+                                        call error(' ')
+                                        call errori('varid: ', i)
+                                        call errorc('var_name: ',  &
+                                                var_name(i))
+                                        call errori('element number: ', &
+                                                    j)
+                                        call errord('expect: ',  &
+                                                    expect(j))
+                                        call errord('got: ', val)
+                                    end if
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+12                      continue
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ',  err)
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_GET_ATT(TYPE)
+dnl
+define([TEST_NFMPI_GET_ATT],dnl
+[dnl
+        subroutine test_nf90mpi_get_att_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer ATT_TYPE, NATTS, ATT_LEN
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer i
+        integer j
+        integer k
+        integer err
+        integer(kind=MPI_OFFSET_KIND) ndx(1)
+        logical allInExtRange
+        logical allInIntRange
+        logical canConvert     
+        ATTDATATYPE($1, value, MAX_NELS)
+        doubleprecision expect(MAX_NELS)
+        integer nok             
+        doubleprecision val
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_open: ', err)
+
+        do 1, i = 0, numVars
+            do 2, j = 1, NATTS(i)
+                canConvert = (ATT_TYPE(j,i) .eq. NF90_CHAR) .eqv. &
+                             (NFT_ITYPE($1) .eq. NFT_TEXT)
+                err = nf90mpi_get_att(BAD_ID, i, ATT_NAME(j,i), value)
+                if (err .ne. NF90_EBADID)  &
+                    call errore('bad ncid: ', err)
+                err = nf90mpi_get_att(ncid, BAD_VARID, ATT_NAME(j,i), value)
+                if (err .ne. NF90_ENOTVAR)  &
+                    call errore('bad var id: ', err)
+                err = nf90mpi_get_att(ncid, i, 'noSuch', value)
+                if (err .ne. NF90_ENOTATT)  &
+                    call errore('Bad attribute name: ', err)
+                allInIntRange = .true.
+                allInExtRange = .true.
+                do 3, k = 1, ATT_LEN(j,i)
+                    ndx(1) = k
+                    expect(k) = hash4(ATT_TYPE(j,i), -1, ndx,  &
+                                      NFT_ITYPE($1))
+                    if (inRange3(expect(k),ATT_TYPE(j,i), &
+                                 NFT_ITYPE($1))) then
+                        allInIntRange =  &
+                            allInIntRange .and. &
+                            in_internal_range(NFT_ITYPE($1), expect(k))
+                    else
+                        allInExtRange = .false.
+                    end if
+3               continue
+                err = nf90mpi_get_att(ncid, i, ATT_NAME(j,i), value)
+                if (canConvert .or. ATT_LEN(j,i) .eq. 0) then
+                    if (allInExtRange) then
+                        if (allInIntRange) then
+                            if (err .ne. NF90_NOERR) &
+                                 call errore('nf90mpi_get_att ', &
+                                 err)
+                        else
+                            if (err .ne. NF90_ERANGE) &
+                                call errore('Range error: ', err)
+                        end if
+                    else
+                        if (err .ne. NF90_NOERR .and. err .ne. NF90_ERANGE) &
+                            call errore('OK or Range error: ', &
+                                        err)
+                    end if
+                    do 4, k = 1, ATT_LEN(j,i)
+                        if (inRange3(expect(k),ATT_TYPE(j,i), &
+                                     NFT_ITYPE($1)) .and. &
+                            in_internal_range(NFT_ITYPE($1), &
+                                              expect(k))) then
+                            val = ATTARITH3($1, value, k)
+                            if (.not.equal(val, expect(k), &
+                                           ATT_TYPE(j,i),  &
+                                           NFT_ITYPE($1)))then
+                                call error( &
+                                    'value read not that expected')
+                                if (verbose) then
+                                    call error(' ')
+                                    call errori('varid: ', i)
+                                    call errorc('att_name: ',  &
+                                        ATT_NAME(j,i))
+                                    call errori('element number: ', k)
+                                    call errord('expect: ', expect(k))
+                                    call errord('got: ', val)
+                                end if
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+4                   continue
+                else
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                end if
+2           continue
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+])dnl
+
+divert(0)dnl
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source */
+
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+
+TEST_NFMPI_GET_VAR1(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_GET_VAR1(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_GET_VAR1(int2)
+#endif
+TEST_NFMPI_GET_VAR1(int)
+TEST_NFMPI_GET_VAR1(int8)
+TEST_NFMPI_GET_VAR1(real)
+TEST_NFMPI_GET_VAR1(double)
+
+TEST_NFMPI_GET_VAR(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_GET_VAR(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_GET_VAR(int2)
+#endif
+TEST_NFMPI_GET_VAR(int)
+TEST_NFMPI_GET_VAR(int8)
+TEST_NFMPI_GET_VAR(real)
+TEST_NFMPI_GET_VAR(double)
+
+TEST_NFMPI_GET_VARA(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_GET_VARA(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_GET_VARA(int2)
+#endif
+TEST_NFMPI_GET_VARA(int)
+TEST_NFMPI_GET_VARA(int8)
+TEST_NFMPI_GET_VARA(real)
+TEST_NFMPI_GET_VARA(double)
+
+TEST_NFMPI_GET_VARS(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_GET_VARS(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_GET_VARS(int2)
+#endif
+TEST_NFMPI_GET_VARS(int)
+TEST_NFMPI_GET_VARS(int8)
+TEST_NFMPI_GET_VARS(real)
+TEST_NFMPI_GET_VARS(double)
+
+TEST_NFMPI_GET_VARM(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_GET_VARM(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_GET_VARM(int2)
+#endif
+TEST_NFMPI_GET_VARM(int)
+TEST_NFMPI_GET_VARM(int8)
+TEST_NFMPI_GET_VARM(real)
+TEST_NFMPI_GET_VARM(double)
+
+TEST_NFMPI_GET_ATT(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_GET_ATT(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_GET_ATT(int2)
+#endif
+TEST_NFMPI_GET_ATT(int)
+TEST_NFMPI_GET_ATT(int8)
+TEST_NFMPI_GET_ATT(real)
+TEST_NFMPI_GET_ATT(double)
diff --git a/test/nf90_test/test_iget.m4 b/test/nf90_test/test_iget.m4
new file mode 100644
index 0000000..1bed4ef
--- /dev/null
+++ b/test/nf90_test/test_iget.m4
@@ -0,0 +1,1018 @@
+dnl
+dnl  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+dnl  See COPYRIGHT notice in top-level directory.
+dnl
+dnl $Id: test_iget.m4 2081 2015-08-20 01:00:47Z wkliao $
+dnl
+
+divert(-1)
+
+dnl This is m4 source.
+dnl Process using m4 to produce FORTRAN language file.
+
+changequote([,])
+
+undefine([index])dnl
+
+dnl Macros
+
+dnl Upcase(str)
+dnl
+define([Upcase],[dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)])
+
+dnl NFT_ITYPE(type)
+dnl
+define([NFT_ITYPE], [NFT_[]Upcase($1)])
+
+dnl ARITH_VAR1(itype, value)
+dnl
+define([ARITH_VAR1], [ifelse($1, text, ichar($2), $2)])
+
+dnl ARITH3(itype, value)
+dnl
+define([ARITH3], [ifelse($1, text, ichar($2($3:$3)), $2($3))])
+
+dnl  DATATYPE(funf_suffix)
+dnl
+define([DATATYPE], [dnl
+ifelse($1, text, character(len=MAX_NELS) $2,
+ifelse($1, int1, NF_INT1_T $2$3,
+ifelse($1, int2, NF_INT2_T $2$3,
+ifelse($1, int, integer $2$3,
+ifelse($1, int8, NF_INT8_T $2$3,
+ifelse($1, real, real $2$3,
+ifelse($1, double, doubleprecision $2$3)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  DATATYPE_VAR1(funf_suffix)
+dnl
+define([DATATYPE_VAR1], [dnl
+ifelse($1, text, character $2,
+ifelse($1, int1, NF_INT1_T $2,
+ifelse($1, int2, NF_INT2_T $2,
+ifelse($1, int, integer $2,
+ifelse($1, int8, NF_INT8_T $2,
+ifelse($1, real, real $2,
+ifelse($1, double, doubleprecision $2)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl TEST_NFMPI_IGET_VAR1(TYPE)
+dnl
+define([TEST_NFMPI_IGET_VAR1],[dnl
+        subroutine test_nf90mpi_iget_var1_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        integer nok      
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        doubleprecision expect
+        logical canConvert     
+        DATATYPE_VAR1($1, value)
+        doubleprecision val
+        integer err_w, reqid(1), st(1)
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, & 
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            do 2, j = 1, var_rank(i)
+                index(j) = 1
+2           continue
+            err = nf90mpi_iget_var(BAD_ID,i,value, reqid(1),index)
+            if (err .ne. NF90_EBADID) &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iget_var(ncid,BAD_VARID, value, reqid(1), index)
+            if (err .ne. NF90_ENOTVAR) &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                index(j) = var_shape(j,i) + 1
+                err = nf90mpi_iget_var(ncid,i,value, reqid(1),index)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad index: ', err)
+                endif
+                index(j) = 1
+3           continue
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                    index)
+                if (err .ne. NF90_NOERR) &
+                    call error('error in index2indexes 1')
+                expect = hash4( var_type(i), var_rank(i), index,  &
+                                NFT_ITYPE($1) )
+                err = nf90mpi_iget_var(ncid,i,value, reqid(1),index)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (canConvert) then
+                    if (inRange3(expect,var_type(i),  &
+                                 NFT_ITYPE($1))) then
+                        if (in_internal_range(NFT_ITYPE($1), &
+                                              expect)) then
+                            if (st(1) .ne. 0) then
+                                call errore('nf90mpi_iget_var: ',st(1))
+                            else
+                                val = ARITH_VAR1($1, value)
+                                if (.not. equal(val, expect,  &
+                                                var_type(i),  &
+                                                NFT_ITYPE($1))) then
+                                    call errord('unexpected: ', val)
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+                        else
+                            if (st(1) .ne. NF90_ERANGE) &
+                                call errore('Range error: ', st(1))
+                        end if
+                    else
+                        if (st(1) .ne. 0  .and. st(1) .ne. NF90_ERANGE) &
+                            call errore('OK or Range error: ', st(1))
+                    end if
+                else
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                end if
+4           continue
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ',  err)
+        call print_nok(nok)
+        end
+])
+
+dnl TEST_NFMPI_IGET_VAR(TYPE)
+dnl
+define([TEST_NFMPI_IGET_VAR],[dnl
+        subroutine test_nf90mpi_iget_var_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer nok      
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        doubleprecision expect(MAX_NELS)
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer err_w, reqid(1), st(1)      
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            err = nf90mpi_iget_var(BAD_ID, i, value,reqid(1))
+            if (err .ne. NF90_EBADID) &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iget_var(ncid, BAD_VARID, value,reqid(1))
+            if (err .ne. NF90_ENOTVAR) &
+                call errore('bad var id: ', err)
+            nels = 1
+            do 3, j = 1, var_rank(i)
+                nels = nels * var_shape(j,i)
+3           continue
+            allInExtRange = .true.
+            allInIntRange = .true.
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                    index)
+                if (err .ne. NF90_NOERR) &
+                    call error('error in index2indexes 1')
+                expect(j) = hash4( var_type(i), var_rank(i), index,  &
+                                NFT_ITYPE($1) )
+                if (inRange3(expect(j),var_type(i), NFT_ITYPE($1))) then
+                    allInIntRange = allInIntRange .and. &
+                        in_internal_range(NFT_ITYPE($1), expect(j))
+                else
+                    allInExtRange = .false.
+                end if
+4           continue
+            err = nf90mpi_iget_var(ncid, i, value,reqid(1), count=var_shape(:,i))
+            if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+            if (canConvert) then
+                if (allInExtRange) then
+                    if (allInIntRange) then
+                        if (st(1) .ne. 0)  &
+                            call errore('nf90mpi_iget_var: ', st(1))
+                    else
+                        if (st(1) .ne. NF90_ERANGE) &
+                            call errore('Range error: ', st(1))
+                    endif
+                else
+                    if (st(1) .ne. 0  .and. st(1) .ne. NF90_ERANGE) &
+                        call errore('Range error: ', st(1))
+                endif
+                do 5, j = 1, var_nels(i)
+                    if (inRange3(expect(j),var_type(i), &
+                                 NFT_ITYPE($1)) .and. &
+                        in_internal_range(NFT_ITYPE($1), &
+                                                expect(j))) then
+                        val = ARITH3($1, value, j)
+                        if (.not. equal(val, expect(j),  &
+                                        var_type(i),  &
+                                        NFT_ITYPE($1))) then
+                            call errord('unexpected: ', val)
+                        else
+                            nok = nok + 1
+                        end if
+                    endif
+5               continue
+            else
+                if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+            end if
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ',  err)
+        call print_nok(nok)
+        end
+])
+
+
+dnl TEST_NFMPI_IGET_VARA(TYPE)
+dnl
+define([TEST_NFMPI_IGET_VARA],[dnl
+        subroutine test_nf90mpi_iget_vara_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer roll, index2indexes
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer nslabs
+        integer nok      
+        integer(kind=MPI_OFFSET_KIND) start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) edge(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) mid(MAX_RANK)
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision expect(MAX_NELS)
+        doubleprecision val
+        integer ud_shift
+        integer err_w, reqid(1), st(1)      
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv.  &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert'
+            if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+2           continue
+            err = nf90mpi_iget_var(BAD_ID, i, value,reqid(1), start, edge)
+            if (err .ne. NF90_EBADID) &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iget_var(ncid, BAD_VARID, value,reqid(1), start, edge)
+            if (err .ne. NF90_ENOTVAR) &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (canConvert .and. err .ne. NF90_EINVALCOORDS) &
+                    call errore('bad index: ', err)
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (canConvert .and. err .ne. NF90_EEDGE) &
+                    call errore('bad edge: ', err)
+                edge(j) = 1
+3           continue
+
+!           /* Check non-scalars for correct error returned even when */
+!           /* there is nothing to get (edge(j).eq.0) */
+            if (var_rank(i) .gt. 0) then
+                do 10, j = 1, var_rank(i)
+                    edge(j) = 0
+10              continue
+                err = nf90mpi_iget_var(BAD_ID, i, value,reqid(1), start, edge)
+                if (err .ne. NF90_EBADID)  &
+                    call errore('bad ncid: ', err)
+                err = nf90mpi_iget_var(ncid, BAD_VARID, value,reqid(1), start, edge)
+                if (err .ne. NF90_ENOTVAR)  &
+                    call errore('bad var id: ', err)
+                do 11, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .gt. 1) then     !/* skip record dim */
+                        start(j) = var_shape(j,i) + 1
+                        err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge)
+                        if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                            err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                        if (canConvert .and. err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                        start(j) = 1
+                    endif
+11              continue
+                err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (canConvert) then
+                    if (err .ne. NF90_NOERR) &
+                        call error(nf90mpi_strerror(err))
+                else
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                endif
+                do 12, j = 1, var_rank(i)
+                    edge(j) = 1
+12              continue
+            endif
+
+!           Choose a random point dividing each dim into 2 parts
+!           get 2^rank (nslabs) slabs so defined
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+!           bits of k determine whether to get lower or upper part of dim 
+            do 5, k = 1, nslabs
+                nels = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift((k-1), -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    nels = nels * edge(j)
+6               continue
+                allInIntRange = .true.
+                allInExtRange = .true.
+                do 7, j = 1, INT(nels)
+                    err = index2indexes(j, var_rank(i), edge, index)
+                    if (err .ne. NF90_NOERR) &
+                        call error('error in index2indexes 1')
+                    do 8, d = 1, var_rank(i)
+                        index(d) = index(d) + start(d) - 1
+8                   continue
+                    expect(j) = hash4(var_type(i), var_rank(i), index,  &
+                                      NFT_ITYPE($1))
+                    if (inRange3(expect(j),var_type(i),  &
+                                 NFT_ITYPE($1))) then
+                        allInIntRange =  &
+                            allInIntRange .and. &
+                            in_internal_range(NFT_ITYPE($1), expect(j))
+                    else
+                        allInExtRange = .false.
+                    end if
+7               continue
+                err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (canConvert) then
+                    if (allInExtRange) then
+                        if (allInIntRange) then
+                            if (st(1) .ne. 0) &
+                                call errore( &
+                                    'nf90mpi_iget_var:',st(1))
+                        else
+                            if (st(1) .ne. NF90_ERANGE) &
+                                call errore('Range error: ', st(1))
+                        end if
+                    else
+                        if (st(1) .ne. 0 .and. st(1) .ne. NF90_ERANGE) &
+                            call errore('OK or Range error: ', st(1))
+                    end if
+                    do 9, j = 1, INT(nels)
+                        if (inRange3(expect(j),var_type(i), &
+                                     NFT_ITYPE($1)) .and. &
+                            in_internal_range(NFT_ITYPE($1), expect(j))) &
+                                then
+                            val = ARITH3($1, value, j)
+                            if (.not.equal(val,expect(j), &
+                                           var_type(i),NFT_ITYPE($1)))  &
+                                    then
+                                call error( &
+                                    'value read not that expected')
+                                if (verbose) then
+                                    call error(' ')
+                                    call errori('varid: ', i)
+                                    call errorc('var_name: ', &
+                                        var_name(i))
+                                    call errori('element number: %d ',  &
+                                                j)
+                                    call errord('expect: ', expect(j))
+                                    call errord('got: ', val)
+                                end if
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+9                   continue
+                else
+                    if (nels .gt. 0  .and. err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                end if
+5           continue
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errorc('nf90mpi_close: ', nf90mpi_strerror(err))
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_IGET_VARS(TYPE)
+dnl
+define([TEST_NFMPI_IGET_VARS],dnl
+[dnl
+        subroutine test_nf90mpi_iget_vars_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer roll, index2indexes
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer nslabs
+        integer(kind=MPI_OFFSET_KIND) nstarts         
+        integer nok             
+        integer(kind=MPI_OFFSET_KIND) start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) edge(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index2(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) mid(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) count(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) sstride(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) stride(MAX_RANK)
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision expect(MAX_NELS)
+        doubleprecision val
+        integer ud_shift
+        integer err_w, reqid(1), st(1)      
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv.  &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert'
+            if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+2           continue
+            err = nf90mpi_iget_var(BAD_ID, i, value,reqid(1), start, edge, stride)
+            if (err .ne. NF90_EBADID) &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iget_var(ncid, BAD_VARID, value,reqid(1), start, edge, stride)
+            if (err .ne. NF90_ENOTVAR) &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad index: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EEDGE) &
+                        call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_ESTRIDE) &
+                        call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
+3           continue
+!               Choose a random point dividing each dim into 2 parts
+!               get 2^rank (nslabs) slabs so defined
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+!           bits of k determine whether to get lower or upper part of dim
+!           choose random stride from 1 to edge
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, j-1), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        sstride(j) = 1 + roll(edge(j))
+                    else
+                        sstride(j) = 1
+                    end if
+                    nstarts = nstarts * stride(j)
+6               continue
+                do 7, m = 1, INT(nstarts)
+                    err = index2indexes(m, var_rank(i), sstride,  &
+                                        index)
+                    if (err .ne. NF90_NOERR) &
+                        call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) /  &
+                                        stride(j)
+                        nels = nels * count(j)
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+!                   Random choice of forward or backward 
+!    /* TODO
+!                   if ( roll(2) ) then
+!                       for (j = 0 j < var_rank(i) j++) {
+!                           index(j) += (count(j) - 1) * stride(j)
+!                           stride(j) = -stride(j)
+!                       }
+!                   end if
+!    */
+                    allInIntRange = .true.
+                    allInExtRange = .true.
+                    do 9, j = 1, INT(nels)
+                        err = index2indexes(j, var_rank(i), count,  &
+                                            index2)
+                        if (err .ne. NF90_NOERR) &
+                            call error('error in index2indexes() 1')
+                        do 10, d = 1, var_rank(i)
+                            index2(d) = index(d) + (index2(d)-1) *  &
+                                        stride(d)
+10                      continue
+                        expect(j) = hash4(var_type(i), var_rank(i),  &
+                                          index2, NFT_ITYPE($1))
+                        if (inRange3(expect(j),var_type(i), &
+                                     NFT_ITYPE($1))) then
+                            allInIntRange =  &
+                                allInIntRange .and. &
+                                in_internal_range(NFT_ITYPE($1),  &
+                                                  expect(j))
+                        else
+                            allInExtRange = .false.
+                        end if
+9                   continue
+                    err = nf90mpi_iget_var(ncid, i,value,reqid(1), index, count,stride)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (allInIntRange) then
+                                if (st(1) .ne. 0) &
+                                    call error(nf90mpi_strerror(st(1)))
+                            else
+                                if (st(1) .ne. NF90_ERANGE) &
+                                    call errore('Range error: ', st(1))
+                            end if
+                        else
+                            if (st(1) .ne. 0 .and. st(1) .ne. NF90_ERANGE) &
+                                call errore('OK or Range error: ',st(1))
+                        end if
+                        do 11, j = 1, INT(nels)
+                            if (inRange3(expect(j),var_type(i), &
+                                NFT_ITYPE($1)) .and. &
+                                in_internal_range(NFT_ITYPE($1),  &
+                                                  expect(j))) then
+                                val = ARITH3($1, value, j)
+                                if (.not.equal(val, expect(j), &
+                                    var_type(i), NFT_ITYPE($1))) then
+                                    call error( &
+                                        'value read not that expected')
+                                    if (verbose) then
+                                        call error(' ')
+                                        call errori('varid: ', i)
+                                        call errorc('var_name: ',  &
+                                                    var_name(i))
+                                        call errori('element number: ', &
+                                                    j)
+                                        call errord('expect: ',  &
+                                                    expect(j))
+                                        call errord('got: ', val)
+                                    end if
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+11                      continue
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_IGET_VARM(TYPE)
+dnl
+define([TEST_NFMPI_IGET_VARM],dnl
+[dnl
+        subroutine test_nf90mpi_iget_varm_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer roll, index2indexes
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer nslabs
+        integer(kind=MPI_OFFSET_KIND) nstarts         
+        integer nok             
+        integer(kind=MPI_OFFSET_KIND) start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) edge(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index2(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) mid(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) count(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) sstride(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) stride(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) imap(MAX_RANK)
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision expect(MAX_NELS)
+        doubleprecision val
+        integer ud_shift
+        integer err_w, reqid(1), st(1)      
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv.  &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assertion'
+            if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assertion'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+                imap(j) = 1
+2           continue
+            err = nf90mpi_iget_var(BAD_ID, i, value,reqid(1), start, edge, stride, imap)
+            if (err .ne. NF90_EBADID) &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iget_var(ncid, BAD_VARID, value,reqid(1), start, edge, stride, imap)
+            if (err .ne. NF90_ENOTVAR) &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 1
+                err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride, imap)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EINVALCOORDS) &
+                        call errore('bad index: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nf90mpi_iget_var(ncid, i, value,reqid(1), start, edge, stride, imap)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_EEDGE) &
+                        call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nf90mpi_iget_var(ncid, i, value, reqid(1), start, edge, stride, imap)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('conversion: ', err)
+                else
+                    if (err .ne. NF90_ESTRIDE) &
+                        call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
+3           continue
+!           Choose a random point dividing each dim into 2 parts 
+!           get 2^rank (nslabs) slabs so defined 
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+!           /* bits of k determine whether to get lower or upper part 
+!            * of dim
+!            * choose random stride from 1 to edge */
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift((k-1), -(j-1)), 2) .ne. 0) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        stride(j) = 1+roll(edge(j))
+                    else
+                        stride(j) = 1
+                    end if
+                    sstride(j) = stride(j)
+                    nstarts = nstarts * stride(j)
+6               continue
+                do 7, m = 1, INT(nstarts)
+                    err = index2indexes(m, var_rank(i), sstride, index)
+                    if (err .ne. NF90_NOERR) &
+                        call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) /  &
+                                        stride(j)
+                        nels = nels * count(j)
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+!                   Random choice of forward or backward 
+!    /* TODO
+!                   if ( roll(2) ) then
+!                       for (j = 0 j < var_rank(i) j++) {
+!                           index(j) += (count(j) - 1) * stride(j)
+!                           stride(j) = -stride(j)
+!                       }
+!                   end if
+!     */
+                    if (var_rank(i) .gt. 0) then
+                        imap(1) = 1
+                        do 9, j = 2, var_rank(i)
+                            imap(j) = imap(j-1) * count(j-1)
+9                       continue
+                    end if
+                    allInIntRange = .true.
+                    allInExtRange = .true.
+                    do 10, j = 1, INT(nels)
+                        err = index2indexes(j, var_rank(i), count,  &
+                                            index2)
+                        if (err .ne. NF90_NOERR) &
+                            call error('error in index2indexes 1')
+                        do 11, d = 1, var_rank(i)
+                            index2(d) = index(d) + (index2(d)-1) *  &
+                                        stride(d)
+11                      continue
+                        expect(j) = hash4(var_type(i), var_rank(i),  &
+                                          index2, NFT_ITYPE($1))
+                        if (inRange3(expect(j),var_type(i), &
+                                     NFT_ITYPE($1))) then
+                            allInIntRange =  &
+                                allInIntRange .and. &
+                                in_internal_range(NFT_ITYPE($1), &
+                                                  expect(j))
+                        else
+                            allInExtRange = .false.
+                        end if
+10                  continue
+                    err = nf90mpi_iget_var(ncid,i, value, reqid(1), index, count, stride, imap)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (allInIntRange) then
+                                if (st(1) .ne. 0) &
+                                    call error(nf90mpi_strerror(st(1)))
+                            else
+                                if (st(1) .ne. NF90_ERANGE) &
+                                    call errore('Range error: ', st(1))
+                            end if
+                        else
+                            if (st(1) .ne. 0 .and. st(1) .ne. NF90_ERANGE) &
+                                call errore('OK or Range error: ',st(1))
+                        end if
+                        do 12, j = 1, INT(nels)
+                            if (inRange3(expect(j),var_type(i), &
+                                         NFT_ITYPE($1)) .and. &
+                                in_internal_range(NFT_ITYPE($1), &
+                                                  expect(j))) then
+                                val = ARITH3($1, value, j)
+                                if (.not.equal(val, expect(j), &
+                                               var_type(i),  &
+                                               NFT_ITYPE($1))) then
+                                    call error( &
+                                        'value read not that expected')
+                                    if (verbose) then
+                                        call error(' ')
+                                        call errori('varid: ', i)
+                                        call errorc('var_name: ',  &
+                                                var_name(i))
+                                        call errori('element number: ', &
+                                                    j)
+                                        call errord('expect: ',  &
+                                                    expect(j))
+                                        call errord('got: ', val)
+                                    end if
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+12                      continue
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ',  err)
+        call print_nok(nok)
+        end
+])dnl
+
+divert(0)dnl
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source */
+
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+
+TEST_NFMPI_IGET_VAR1(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IGET_VAR1(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IGET_VAR1(int2)
+#endif
+TEST_NFMPI_IGET_VAR1(int)
+TEST_NFMPI_IGET_VAR1(int8)
+TEST_NFMPI_IGET_VAR1(real)
+TEST_NFMPI_IGET_VAR1(double)
+
+TEST_NFMPI_IGET_VAR(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IGET_VAR(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IGET_VAR(int2)
+#endif
+TEST_NFMPI_IGET_VAR(int)
+TEST_NFMPI_IGET_VAR(int8)
+TEST_NFMPI_IGET_VAR(real)
+TEST_NFMPI_IGET_VAR(double)
+
+TEST_NFMPI_IGET_VARA(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IGET_VARA(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IGET_VARA(int2)
+#endif
+TEST_NFMPI_IGET_VARA(int)
+TEST_NFMPI_IGET_VARA(int8)
+TEST_NFMPI_IGET_VARA(real)
+TEST_NFMPI_IGET_VARA(double)
+
+TEST_NFMPI_IGET_VARS(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IGET_VARS(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IGET_VARS(int2)
+#endif
+TEST_NFMPI_IGET_VARS(int)
+TEST_NFMPI_IGET_VARS(int8)
+TEST_NFMPI_IGET_VARS(real)
+TEST_NFMPI_IGET_VARS(double)
+
+TEST_NFMPI_IGET_VARM(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IGET_VARM(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IGET_VARM(int2)
+#endif
+TEST_NFMPI_IGET_VARM(int)
+TEST_NFMPI_IGET_VARM(int8)
+TEST_NFMPI_IGET_VARM(real)
+TEST_NFMPI_IGET_VARM(double)
+
diff --git a/test/nf90_test/test_iput.m4 b/test/nf90_test/test_iput.m4
new file mode 100644
index 0000000..fc7fa36
--- /dev/null
+++ b/test/nf90_test/test_iput.m4
@@ -0,0 +1,1087 @@
+dnl
+dnl  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+dnl  See COPYRIGHT notice in top-level directory.
+dnl
+dnl $Id: test_iput.m4 2156 2015-10-12 01:15:25Z wkliao $
+dnl
+
+divert(-1)
+
+dnl This is m4 source.
+dnl Process using m4 to produce FORTRAN language file.
+
+changequote([,]) dnl
+
+undefine([index])dnl
+
+dnl Macros
+
+dnl Upcase(str)
+dnl
+define([Upcase],[dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)])
+
+dnl NFT_ITYPE(type)
+dnl
+define([NFT_ITYPE], [NFT_[]Upcase($1)])
+
+dnl ARITH3(itype, value)
+dnl
+define([ARITH3], [ifelse($1, text, ichar($2($3:$3)), $2($3))])
+
+dnl VALUE3(itype, value)
+dnl
+define([VALUE3], [ifelse($1, text, $2(1:nels), $2(1:nels))])
+
+dnl VAR_ELEM(itype, value)
+dnl
+define([VAR_ELEM], [ifelse($1, text, $2($3:$3), $2($3))])
+
+dnl ARITH_VAR1(itype, value)
+dnl
+define([ARITH_VAR1], [ifelse($1, text, ichar($2(1:1)), $2(1))])
+
+dnl  DATATYPE(funf_suffix)
+dnl
+define([DATATYPE], [dnl
+ifelse($1, text, character(len=$3) $2,
+ifelse($1, int1, NF_INT1_T $2($3),
+ifelse($1, int2, NF_INT2_T $2($3),
+ifelse($1, int, integer $2($3),
+ifelse($1, int8, NF_INT8_T $2($3),
+ifelse($1, real, real $2($3),
+ifelse($1, double, doubleprecision $2($3))[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  DATATYPE_VAR1(funf_suffix)
+dnl
+define([DATATYPE_VAR1], [dnl
+ifelse($1, text, character(len=1) $2,
+ifelse($1, int1, NF_INT1_T $2(1),
+ifelse($1, int2, NF_INT2_T $2(1),
+ifelse($1, int, integer $2(1),
+ifelse($1, int8, NF_INT8_T $2(1),
+ifelse($1, real, real $2(1),
+ifelse($1, double, double precision $2(1))[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  MAKE_ARITH_VAR1(funf_suffix, var)
+dnl
+define([MAKE_ARITH_VAR1], [dnl
+ifelse($1, text, ichar($2), $2)[]dnl
+])
+
+dnl  MAKE_ARITH3(funf_suffix, var)
+dnl
+define([MAKE_ARITH3], [dnl
+ifelse($1, text, ichar($2($3:$3)), $2($3))[]dnl
+])
+
+dnl  MAKE_DOUBLE(funf_suffix, var)
+dnl
+define([MAKE_DOUBLE], [dnl
+ifelse($1, text, dble(ichar($2)), dble($2))[]dnl
+])
+
+dnl  MAKE_TYPE(funf_suffix, var)
+dnl
+define([MAKE_TYPE], [dnl
+ifelse($1, text, char(int($2)),
+       ifelse($1, int, INT($2),
+       ifelse($1, int1, INT($2,KIND=INT1_KIND),
+       ifelse($1, int2, INT($2,KIND=INT2_KIND),
+       ifelse($1, int8, INT($2,KIND=INT8_KIND),
+       ifelse($1, real, REAL($2),
+       $2))))))[]dnl
+])
+
+dnl  MAKE_TYPE2(funf_suffix, var_dest, var_src)
+dnl
+define([MAKE_TYPE2], [dnl
+ifelse($1, text, $2 = char(int($3)),
+       ifelse($1, int, $2 = INT($3),
+       ifelse($1, int1, $2 = INT($3,KIND=INT1_KIND),
+       ifelse($1, int2, $2 = INT($3,KIND=INT2_KIND),
+       ifelse($1, int8,
+                if ($3 .EQ. X_INT8_MAX) then
+                    $2 = X_INT8_MAX
+                else
+                    $2 = INT($3,KIND=INT8_KIND)
+                endif,
+       ifelse($1, real, $2 = REAL($3),
+       $2 = $3))))))[]dnl
+])
+
+dnl TEST_NFMPI_IPUT_VAR1(TYPE)
+dnl
+define([TEST_NFMPI_IPUT_VAR1],dnl
+[dnl
+        subroutine test_nf90mpi_iput_var1_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer i
+        integer j
+        integer err, flags
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        DATATYPE_VAR1($1, value)
+        double precision val
+        integer err_w, reqid(1), st(1)
+
+        value = MAKE_TYPE($1, 5)!/* any value would do - only for error cases */
+
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            do 2, j = 1, var_rank(i)
+                index(j) = 1
+2           continue
+            err = nf90mpi_iput_var(BAD_ID, i, value(1:1), reqid(1), index)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iput_var(ncid, BAD_VARID, value(1:1),reqid(1), index)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .gt. 1) then         !/* skip record dim */
+                    index(j) = var_shape(j,i) + 1
+                    err = nf90mpi_iput_var(ncid, i, value(1:1),reqid(1), index)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad index: ', err)
+                    endif
+                    index(j) = 0
+                end if
+3           continue
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                    index)
+                if (err .ne. NF90_NOERR)  &
+                    call error('error in index2indexes 1')
+                val = hash_$1(var_type(i),var_rank(i), &
+                                  index, NFT_ITYPE($1))
+                MAKE_TYPE2($1, value, val)
+                err = nf90mpi_iput_var(ncid, i, value(1:1), reqid(1), index)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                if (canConvert) then
+                    val = ARITH_VAR1($1, value)
+                    if (inRange3(val, var_type(i), NFT_ITYPE($1))) then
+                        if (st(1) .ne. 0) &
+                            call error(nf90mpi_strerror(st(1)))
+                    else
+                        if (err .ne. NF90_ERANGE) &
+                            call errore('Range error: ', err)
+                    end if
+                else
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                end if
+4           continue
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed: ',  &
+                        scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_IPUT_VAR(TYPE)
+dnl
+define([TEST_NFMPI_IPUT_VAR],dnl
+[dnl
+        subroutine test_nf90mpi_iput_var_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer vid
+        integer i
+        integer j
+        integer err, flags
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* All values within external range?*/
+        DATATYPE($1, value, MAX_NELS)
+        doubleprecision val
+        integer err_w, reqid(1), st(1)
+
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            err = nf90mpi_iput_var(BAD_ID, i, value, reqid(1))
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iput_var(ncid, BAD_VARID, value, reqid(1))
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            nels = 1
+            do 3, j = 1, var_rank(i)
+                nels = nels * var_shape(j,i)
+3           continue
+            allInExtRange = .true.
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                    index)
+                if (err .ne. NF90_NOERR)  &
+                    call error('error in index2indexes 1')
+                val = hash_$1(var_type(i), var_rank(i), &
+                              index, NFT_ITYPE($1))
+                MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                val = ARITH3($1, value, j)
+                allInExtRange = allInExtRange .and. &
+                    inRange3(val, var_type(i), NFT_ITYPE($1))
+4           continue
+            err = nf90mpi_iput_var(ncid, i, value, reqid(1), count=var_shape(:,i))
+            if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                err_w = nf90mpi_wait_all(ncid, 1, reqid, st)
+                ! NF90_ERANGE is not a fatal error
+
+            if (canConvert) then
+                if (allInExtRange) then
+                    if (err .ne. NF90_NOERR) &
+                        call error(nf90mpi_strerror(err))
+                else
+                    if (err .ne. NF90_ERANGE .and. &
+                            var_dimid(var_rank(i),i) .ne. RECDIM) &
+                        call errore('Range error: ', err)
+                endif
+            else
+                if (err .ne. NF90_ECHAR) &
+                    call errore('wrong type: ', err)
+            endif
+1       continue
+
+!       The preceeding has written nothing for record variables, now try
+!       again with more than 0 records.
+
+!       Write record number NRECS to force writing of preceding records.
+!       Assumes variable cr is char vector with UNLIMITED dimension.
+
+        err = nf90mpi_inq_varid(ncid, "cr", vid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_inq_varid: ', err)
+        index(1) = NRECS
+        err = nf90mpi_iput_var(ncid, vid, 'x',reqid(1), index)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_iput_var: ', err)
+        else
+            err_w = nf90mpi_wait_all(ncid, 1, reqid, st)
+        endif
+
+        do 5 i = 1, numVars
+!           Only test record variables here
+            if (var_rank(i) .ge. 1 .and. &
+                var_dimid(var_rank(i),i) .eq. RECDIM) then
+                canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+                if (var_rank(i) .gt. MAX_RANK) &
+                    stop 'var_rank(i) .gt. MAX_RANK'
+                if (var_nels(i) .gt. MAX_NELS) &
+                    stop 'var_nels(i) .gt. MAX_NELS'
+
+                nels = 1
+                do 6 j = 1, var_rank(i)
+                    nels = nels * var_shape(j,i)
+6               continue
+                allInExtRange = .true.
+                do 7, j = 1, INT(nels)
+                    err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                    index)
+                    if (err .ne. NF90_NOERR)  &
+                        call error('error in index2indexes()')
+                    val = hash_$1(var_type(i), var_rank(i), &
+                                  index, NFT_ITYPE($1))
+                    MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                    val = ARITH3($1, value, j)
+                    allInExtRange = allInExtRange .and. &
+                        inRange3(val, var_type(i), NFT_ITYPE($1))
+7               continue
+                err = nf90mpi_iput_var(ncid, i, value, reqid(1), count=var_shape(:,i))
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid, 1, reqid, st)
+                    ! NF90_ERANGE is not a fatal error
+                if (canConvert) then
+                    if (allInExtRange) then
+                        if (err .ne. NF90_NOERR) &
+                            call error(nf90mpi_strerror(err))
+                    else
+                        if (err .ne. NF90_ERANGE) &
+                            call errore('range error: ', err)
+                    endif
+                else
+                    if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                endif
+            endif
+5       continue
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed: ',  &
+                        scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_IPUT_VARA(TYPE)
+dnl
+define([TEST_NFMPI_IPUT_VARA],dnl
+[dnl
+        subroutine test_nf90mpi_iput_vara_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer roll, index2indexes
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer i
+        integer j
+        integer k
+        integer d
+        integer err, flags
+        integer nslabs
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer(kind=MPI_OFFSET_KIND) start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) edge(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) mid(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* all values within external range? */
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer ud_shift
+        integer err_w, reqid(1), st(1)
+
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) &
+                stop 'assert(var_rank(i) .le. MAX_RANK)'
+            if (.not.(var_nels(i) .le. MAX_NELS)) &
+                stop 'assert(var_nels(i) .le. MAX_NELS)'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+2           continue
+            err = nf90mpi_iput_var(BAD_ID, i, value,reqid(1), start, edge)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iput_var(ncid, BAD_VARID, &
+                        value,reqid(1), start, edge)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                        ! NF90_ERANGE is not a fatal error
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                    edge(j) = var_shape(j,i) + 1
+                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                        ! NF90_ERANGE is not a fatal error
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EEDGE) &
+                            call errore('bad edge: ', err)
+                    endif
+                    edge(j) = 1
+                end if
+3           continue
+
+!           /* Check correct error returned even when nothing to put */
+            do 20, j = 1, var_rank(i)
+                  edge(j) = 0
+20          continue
+            err = nf90mpi_iput_var(BAD_ID, i, value,reqid(1), start, edge)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iput_var(ncid, BAD_VARID, value,reqid(1), start, edge)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 21, j = 1, var_rank(i)
+                if (var_dimid(j,i) .gt. 1) then     ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid, 1, reqid, st)
+                        ! NF90_ERANGE is not a fatal error
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                endif
+21          continue
+            err = nf90mpi_iput_var(ncid, i, value, reqid(1), start, edge)
+            if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+            if (canConvert) then
+                if (st(1) .ne. 0)  &
+                    call error(nf90mpi_strerror(st(1)))
+            else
+                if (err .ne. NF90_ECHAR) &
+                    call errore('wrong type: ', err)
+            endif
+            do 22, j = 1, var_rank(i)
+                  edge(j) = 1
+22          continue
+
+
+            !/* Choose a random point dividing each dim into 2 parts */
+            !/* Put 2^rank (nslabs) slabs so defined */
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+                !/* bits of k determine whether to put lower or upper part of dim */
+            do 5, k = 1, nslabs
+                nels = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    nels = nels * edge(j)
+6               continue
+                allInExtRange = .true.
+                do 7, j = 1, INT(nels)
+                    err = index2indexes(j, var_rank(i), edge, index)
+                    if (err .ne. NF90_NOERR)  &
+                        call error('error in index2indexes 1')
+                    do 8, d = 1, var_rank(i)
+                        index(d) = index(d) + start(d) - 1
+8                   continue
+                    val = hash_$1(var_type(i), var_rank(i), &
+                                  index, NFT_ITYPE($1))
+                    MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                    val = ARITH3($1, value, j)
+                    allInExtRange = allInExtRange .and. &
+                        inRange3(val, var_type(i), NFT_ITYPE($1))
+7               continue
+                err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge)
+                if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                    err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                    ! NF90_ERANGE is not a fatal error
+                if (canConvert) then
+                    if (allInExtRange) then
+                        if (st(1) .ne. 0)  &
+                            call error(nf90mpi_strerror(st(1)))
+                    else
+                        if (err .ne. NF90_ERANGE) &
+                            call errore('range error: ', err)
+                    end if
+                else
+                    if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                end if
+5           continue
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed: ',  &
+                scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_IPUT_VARS(TYPE)
+dnl
+define([TEST_NFMPI_IPUT_VARS],dnl
+[dnl
+        subroutine test_nf90mpi_iput_vars_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer roll, index2indexes
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err, flags
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer nslabs
+        integer(kind=MPI_OFFSET_KIND) nstarts        !/* number of different starts */
+        integer(kind=MPI_OFFSET_KIND) start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) edge(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index2(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) mid(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) count(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) sstride(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) stride(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* all values within external range? */
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer ud_shift
+        integer err_w, reqid(1), st(1)
+
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) &
+                stop 'assert(var_rank(i) .le. MAX_RANK)'
+            if (.not.(var_nels(i) .le. MAX_NELS)) &
+                stop 'assert(var_nels(i) .le. MAX_NELS)'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+2           continue
+            err = nf90mpi_iput_var(BAD_ID, i, value,reqid(1), start, edge, stride)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iput_var(ncid, BAD_VARID, value,reqid(1), start, edge, stride)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .ne. RECDIM) then    ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                                call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                    edge(j) = var_shape(j,i) + 1
+                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EEDGE) &
+                            call errore('bad edge: ', err)
+                    endif
+                    edge(j) = 1
+                    stride(j) = 0
+                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), start, edge, stride)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_ESTRIDE) &
+                            call errore('bad stride: ', err)
+                    endif
+                    stride(j) = 1
+                end if
+3           continue
+            !/* Choose a random point dividing each dim into 2 parts */
+            !/* Put 2^rank (nslabs) slabs so defined */
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+            !/* bits of k determine whether to put lower or upper part of dim */
+            !/* choose random stride from 1 to edge */
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        stride(j) = 1+roll(edge(j))
+                    else
+                        stride(j) = 1
+                    end if
+                    sstride(j) = stride(j)
+                    nstarts = nstarts * stride(j)
+6               continue
+                do 7, m = 1, INT(nstarts)
+                    err = index2indexes(m, var_rank(i), sstride, index)
+                    if (err .ne. NF90_NOERR) &
+                        call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) / stride(j)
+                        nels = nels * count(j)
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+                    !/* Random choice of forward or backward */
+! TODO
+!                   if ( roll(2) ) {
+!                       for (j = 1 j .lt. var_rank(i) j++) {
+!                           index(j) += (count(j) - 1) * stride(j)
+!                           stride(j) = -stride(j)
+!                       }
+!                   }
+!
+                    allInExtRange = .true.
+                    do 9, j = 1, INT(nels)
+                        err = index2indexes(j, var_rank(i), count,  &
+                                            index2)
+                        if (err .ne. NF90_NOERR) &
+                            call error('error in index2indexes')
+                        do 10, d = 1, var_rank(i)
+                            index2(d) = index(d) +  &
+                                        (index2(d)-1) * stride(d)
+10                      continue
+                        val = hash_$1(var_type(i), var_rank(i), &
+                                      index2, NFT_ITYPE($1))
+                        MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                        val = ARITH3($1, value, j)
+                        allInExtRange = allInExtRange .and. &
+                            inRange3(val, var_type(i),  &
+                                     NFT_ITYPE($1))
+9                   continue
+                    err = nf90mpi_iput_var(ncid, i, value,reqid(1), index, count, stride)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (st(1) .ne. 0)  &
+                                call error(nf90mpi_strerror(st(1)))
+                        else
+                            if (err .ne. NF90_ERANGE) &
+                                call errore('range error: ', err)
+                        end if
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed:',  &
+                scratch)
+        end
+])dnl
+
+
+dnl  since parallel-netcdf doesn't have varm type, we haven't completed the
+dnl  parallel-netcdf-ification of these routines
+dnl TEST_NFMPI_IPUT_VARM(TYPE)
+dnl
+define([TEST_NFMPI_IPUT_VARM],dnl
+[dnl
+        subroutine test_nf90mpi_iput_varm_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer roll, index2indexes
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err, flags
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer nslabs
+        integer(kind=MPI_OFFSET_KIND) nstarts        !/* number of different starts */
+        integer(kind=MPI_OFFSET_KIND) start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) edge(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index2(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) mid(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) count(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) sstride(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) stride(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) imap(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* all values within external range? */
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer ud_shift
+        integer err_w, reqid(1), st(1)
+
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) &
+                stop 'assert(var_rank(i) .le. MAX_RANK)'
+            if (.not.(var_nels(i) .le. MAX_NELS)) &
+                stop 'assert(var_nels(i) .le. MAX_NELS)'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+                imap(j) = 1
+2           continue
+            err = nf90mpi_iput_var(BAD_ID, i, value,reqid(1), start, edge, stride, imap)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_iput_var(ncid, BAD_VARID, &
+                                 value,reqid(1), start, edge, stride, imap)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_iput_var(ncid, i, &
+                                         value,reqid(1), start, edge, stride, imap)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                    edge(j) = var_shape(j,i) + 1
+                    err = nf90mpi_iput_var(ncid, i, &
+                                         value,reqid(1), start, edge, stride, imap)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EEDGE) &
+                            call errore('bad edge: ', err)
+                    endif
+                    edge(j) = 1
+                    stride(j) = 0
+                    err = nf90mpi_iput_var(ncid, i, &
+                                         value,reqid(1), start, edge, stride, imap)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_ESTRIDE) &
+                            call errore('bad stride: ', err)
+                    endif
+                    stride(j) = 1
+                end if
+3           continue
+            !/* Choose a random point dividing each dim into 2 parts */
+            !/* Put 2^rank (nslabs) slabs so defined */
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+            !/* bits of k determine whether to put lower or upper part of dim */
+            !/* choose random stride from 1 to edge */
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        stride(j) = 1+roll(edge(j))
+                    else
+                        stride(j) = 1
+                    end if
+                    sstride(j) = stride(j)
+                    nstarts = nstarts * stride(j)
+6               continue
+                do 7, m = 1, INT(nstarts)
+                    err = index2indexes(m, var_rank(i), sstride, index)
+                    if (err .ne. NF90_NOERR) &
+                        call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) / stride(j)
+                        nels = nels * count(j)
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+                    !/* Random choice of forward or backward */
+! TODO
+!                   if ( roll(2) ) then
+!                       do 9, j = 1, var_rank(i)
+!                           index(j) = index(j) +  &
+!                               (count(j) - 1) * stride(j)
+!                           stride(j) = -stride(j)
+!9                      continue
+!                   end if
+!
+                    if (var_rank(i) .gt. 0) then
+                        imap(1) = 1
+                        do 10, j = 2, var_rank(i)
+                            imap(j) = imap(j-1) * count(j-1)
+10                      continue
+                    end if
+                    allInExtRange = .true.
+                    do 11 j = 1, INT(nels)
+                        err = index2indexes(j, var_rank(i), count,  &
+                                            index2)
+                        if (err .ne. NF90_NOERR) &
+                            call error('error in index2indexes')
+                        do 12, d = 1, var_rank(i)
+                            index2(d) = index(d) +  &
+                                (index2(d)-1) * stride(d)
+12                      continue
+                        val = hash_$1(var_type(i),var_rank(i), &
+                                      index2, NFT_ITYPE($1))
+                        MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                        val = ARITH3($1, value, j)
+                        allInExtRange = allInExtRange .and. &
+                            inRange3(val, var_type(i),  &
+                                     NFT_ITYPE($1))
+11                  continue
+                    err = nf90mpi_iput_var(ncid,i,&
+                                         value,reqid(1), index, count, stride, imap)
+                    if (err .eq. NF90_NOERR .or. err .eq. NF90_ERANGE) &
+                        err_w = nf90mpi_wait_all(ncid,1,reqid,st)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (st(1) .ne. 0) &
+                                call error(nf90mpi_strerror(st(1)))
+                        else
+                            if (err .ne. NF90_ERANGE) &
+                                call errore('range error: ', err)
+                        end if
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed:',  &
+                scratch)
+        end
+])dnl
+
+
+divert(0)dnl
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source */
+
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+
+TEST_NFMPI_IPUT_VAR1(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IPUT_VAR1(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IPUT_VAR1(int2)
+#endif
+TEST_NFMPI_IPUT_VAR1(int)
+TEST_NFMPI_IPUT_VAR1(int8)
+TEST_NFMPI_IPUT_VAR1(real)
+TEST_NFMPI_IPUT_VAR1(double)
+
+TEST_NFMPI_IPUT_VAR(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IPUT_VAR(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IPUT_VAR(int2)
+#endif
+TEST_NFMPI_IPUT_VAR(int)
+TEST_NFMPI_IPUT_VAR(int8)
+TEST_NFMPI_IPUT_VAR(real)
+TEST_NFMPI_IPUT_VAR(double)
+
+TEST_NFMPI_IPUT_VARA(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IPUT_VARA(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IPUT_VARA(int2)
+#endif
+TEST_NFMPI_IPUT_VARA(int)
+TEST_NFMPI_IPUT_VARA(int8)
+TEST_NFMPI_IPUT_VARA(real)
+TEST_NFMPI_IPUT_VARA(double)
+
+TEST_NFMPI_IPUT_VARS(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IPUT_VARS(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IPUT_VARS(int2)
+#endif
+TEST_NFMPI_IPUT_VARS(int)
+TEST_NFMPI_IPUT_VARS(int8)
+TEST_NFMPI_IPUT_VARS(real)
+TEST_NFMPI_IPUT_VARS(double)
+
+TEST_NFMPI_IPUT_VARM(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IPUT_VARM(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IPUT_VARM(int2)
+#endif
+TEST_NFMPI_IPUT_VARM(int)
+TEST_NFMPI_IPUT_VARM(int8)
+TEST_NFMPI_IPUT_VARM(real)
+TEST_NFMPI_IPUT_VARM(double)
diff --git a/test/nf90_test/test_put.m4 b/test/nf90_test/test_put.m4
new file mode 100644
index 0000000..a1c9733
--- /dev/null
+++ b/test/nf90_test/test_put.m4
@@ -0,0 +1,1518 @@
+dnl
+dnl  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+dnl  See COPYRIGHT notice in top-level directory.
+dnl
+dnl $Id: test_put.m4 2156 2015-10-12 01:15:25Z wkliao $
+dnl
+
+divert(-1)
+
+dnl This is m4 source.
+dnl Process using m4 to produce FORTRAN language file.
+
+changequote([,]) dnl
+
+undefine([index])dnl
+
+dnl Macros
+
+dnl Upcase(str)
+dnl
+define([Upcase],[dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)])
+
+dnl NFT_ITYPE(type)
+dnl
+define([NFT_ITYPE], [NFT_[]Upcase($1)])
+
+dnl ARITH3(itype, value)
+dnl
+define([ARITH3], [ifelse($1, text, ichar($2($3:$3)), $2($3))])
+
+dnl VALUE3(itype, value)
+dnl
+define([VALUE3], [ifelse($1, text, $2(1:nels), $2(1:nels))])
+
+dnl VAR_ELEM(itype, value)
+dnl
+define([VAR_ELEM], [ifelse($1, text, $2($3:$3), $2($3))])
+
+dnl ARITH_VAR1(itype, value)
+dnl
+define([ARITH_VAR1], [ifelse($1, text, ichar($2(1:1)), $2(1))])
+
+dnl  DATATYPE(funf_suffix)
+dnl
+define([DATATYPE], [dnl
+ifelse($1, text, character(len=$3) $2,
+ifelse($1, int1, NF_INT1_T $2($3),
+ifelse($1, int2, NF_INT2_T $2($3),
+ifelse($1, int, integer $2($3),
+ifelse($1, int8, NF_INT8_T $2($3),
+ifelse($1, real, real $2($3),
+ifelse($1, double, doubleprecision $2($3))[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  DATATYPE_VAR1(funf_suffix)
+dnl
+define([DATATYPE_VAR1], [dnl
+ifelse($1, text, character(len=1) $2,
+ifelse($1, int1, NF_INT1_T $2(1),
+ifelse($1, int2, NF_INT2_T $2(1),
+ifelse($1, int, integer $2(1),
+ifelse($1, int8, NF_INT8_T $2(1),
+ifelse($1, real, real $2(1),
+ifelse($1, double, doubleprecision $2(1))[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  ATTDATATYPE(funf_suffix)
+dnl
+define([ATTDATATYPE], [dnl
+dnl ifelse($1, text, character(len=MAX_NELS) $2,
+ifelse($1, text, character(len=$3) $2,
+ifelse($1, int1, NF_INT1_T $2($3),
+ifelse($1, int2, NF_INT2_T $2($3),
+ifelse($1, int, integer $2($3),
+ifelse($1, int8, NF_INT8_T $2($3),
+ifelse($1, real, real $2($3),
+ifelse($1, double, doubleprecision $2($3))[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  MAKE_ARITH_VAR1(funf_suffix, var)
+dnl
+define([MAKE_ARITH_VAR1], [dnl
+ifelse($1, text, ichar($2(1:1)), $2(1))[]dnl
+])
+
+dnl  MAKE_ARITH3(funf_suffix, var)
+dnl
+define([MAKE_ARITH3], [dnl
+ifelse($1, text, ichar($2($3:$3)), $2($3))[]dnl
+])
+
+dnl  MAKE_DOUBLE(funf_suffix, var)
+dnl
+define([MAKE_DOUBLE], [dnl
+ifelse($1, text, dble(ichar($2)), dble($2))[]dnl
+])
+
+dnl  MAKE_TYPE(funf_suffix, var)
+dnl
+define([MAKE_TYPE], [dnl
+ifelse($1, text, char(int($2)),
+       ifelse($1, int, INT($2),
+       ifelse($1, int1, INT($2,KIND=INT1_KIND),
+       ifelse($1, int2, INT($2,KIND=INT2_KIND),
+       ifelse($1, int8, INT($2,KIND=INT8_KIND),
+       ifelse($1, real, REAL($2),
+       $2))))))[]dnl
+])
+
+dnl  MAKE_TYPE2(funf_suffix, var_dest, var_src)
+dnl
+define([MAKE_TYPE2], [dnl
+ifelse($1, text, $2 = char(int($3)),
+       ifelse($1, int, $2 = INT($3),
+       ifelse($1, int1, $2 = INT($3,KIND=INT1_KIND),
+       ifelse($1, int2, $2 = INT($3,KIND=INT2_KIND),
+       ifelse($1, int8,
+                if ($3 .EQ. X_INT8_MAX) then
+                    $2 = X_INT8_MAX
+                else
+                    $2 = INT($3,KIND=INT8_KIND)
+                endif,
+       ifelse($1, real, $2 = REAL($3),
+       $2 = $3))))))[]dnl
+])
+
+
+dnl HASH(TYPE)
+dnl
+define([HASH],
+[dnl
+!
+! ensure hash value within range for internal TYPE
+!
+        doubleprecision function hash_$1(type, rank, index, itype)
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer type
+        integer rank
+        integer(kind=MPI_OFFSET_KIND) index(1)
+        integer itype
+        doubleprecision minimum
+        doubleprecision maximum
+        doubleprecision internal_min, internal_max, hash4
+
+        minimum = internal_min(itype)
+        maximum = internal_max(itype)
+
+        hash_$1 = max(minimum, min(maximum, hash4( type, rank, &
+            index, itype)))
+        end
+])dnl
+
+
+dnl CHECK_VARS(TYPE)
+dnl
+define([CHECK_VARS],dnl
+[dnl
+!
+! check all vars in file which are (text/numeric) compatible with TYPE
+!
+        subroutine check_vars_$1(filename)
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        character*(*)   filename
+        integer  ncid          ! netCDF id
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        integer  err
+        integer  d
+        integer  i
+        integer  j
+        DATATYPE_VAR1($1, value)
+        integer datatype
+        integer ndims
+        integer dimids(MAX_RANK)
+        integer ngatts
+        doubleprecision expect
+        character*(NF90_MAX_NAME) name
+        integer(kind=MPI_OFFSET_KIND) length
+        logical canConvert      ! Both text or both numeric
+        integer nok             ! count of valid comparisons
+        doubleprecision val
+        integer  intindex
+
+        nok = 0
+
+        err = nf90mpi_open(comm, filename, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_begin_indep_data(ncid)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (canConvert)  then
+                err = nf90mpi_inquire_variable(ncid, i, name, datatype, ndims, &
+                                    dimids, ngatts)
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_inquire_variable: ', err)
+                if (name .ne. var_name(i)) &
+                    call error('Unexpected var_name')
+                if (datatype .ne. var_type(i)) &
+                    call error('Unexpected type')
+                if (ndims .ne. var_rank(i)) &
+                    call error('Unexpected rank')
+                do 2, j = 1, ndims
+                    err = nf90mpi_inquire_dimension(ncid, dimids(j), name,  &
+                         length)
+                    if (err .ne. NF90_NOERR) &
+                        call errore('nf90mpi_inquire_dimension: ', err)
+                    if (length .ne. var_shape(j,i)) &
+                        call error('Unexpected shape')
+2               continue
+                do 3, j = 1, var_nels(i)
+                    err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                        index)
+                    if (err .ne. NF90_NOERR) &
+                        call error('error in index2indexes()')
+                    expect = hash4( var_type(i), var_rank(i), index,  &
+                                   NFT_ITYPE($1))
+                    err = nf90mpi_get_var(ncid, i, value, index)
+                    if (inRange3(expect,datatype,NFT_ITYPE($1)))  then
+                        if (in_internal_range(NFT_ITYPE($1), expect)) then
+                            if (err .ne. NF90_NOERR)  then
+                                call errore &
+                               ('nf90mpi_get_var: ', err)
+                            else
+                                val = MAKE_ARITH_VAR1($1,value)
+                                if (.not.equal( &
+                                    val, &
+                                    expect,var_type(i), &
+                                    NFT_ITYPE($1)))  then
+                                    call error( &
+                                'Var value read not that expected')
+                                    if (verbose)  then
+                                        call error(' ')
+                                        call errori('varid: %d', i)
+                                        call errorc('var_name: ',  &
+                                                var_name(i))
+                                        call error('index:')
+                                        do 4, d = 1, var_rank(i)
+                                            intindex = INT(index(d))
+                                            call errori(' ', intindex)
+4                                       continue
+                                        call errord('expect: ', expect)
+                                        call errord('got: ',  val)
+                                    end if
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+                        end if
+                    end if
+3               continue
+            end if
+1       continue
+        err = nf90mpi_end_indep_data(ncid)
+        err = nf90mpi_close (ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl CHECK_ATTS(TYPE)         numeric only
+dnl
+define([CHECK_ATTS],dnl
+[dnl
+! 
+!  check all attributes in file which are (text/numeric) compatible with TYPE
+!  ignore any attributes containing values outside range of TYPE
+!
+        subroutine check_atts_$1(ncid)
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer ATT_TYPE, NATTS, ATT_LEN
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer  err
+        integer  i
+        integer  j
+        integer  k
+        integer(kind=MPI_OFFSET_KIND) ndx(1)
+        ATTDATATYPE($1, value, MAX_NELS)
+        integer datatype
+        doubleprecision expect(MAX_NELS)
+        integer(kind=MPI_OFFSET_KIND) length
+        integer nInExtRange     !/* number values within external range */
+        integer nInIntRange     !/* number values within internal range */
+        logical canConvert      !/* Both text or both numeric */
+        integer nok             !/* count of valid comparisons */
+        doubleprecision val
+
+        nok = 0
+
+        do 1, i = 0, numVars
+            do 2, j = 1, NATTS(i)
+                canConvert = (ATT_TYPE(j,i) .eq. NF90_CHAR) .eqv. &
+                             (NFT_ITYPE($1) .eq. NFT_TEXT)
+                if (canConvert) then
+                    err = nf90mpi_inquire_attribute(ncid, i, ATT_NAME(j,i),  &
+                                     datatype, length)
+                    if (err .ne. NF90_NOERR) &
+                        call errore('nf90mpi_inquire_attribute: ', err)
+                    if (datatype .ne. ATT_TYPE(j,i)) &
+                        call error('nf90mpi_inquire_attribute: unexpected type')
+                    if (length .ne. ATT_LEN(j,i)) &
+                        call error('nf90mpi_inquire_attribute: unexpected length')
+                    if (.not.(length .le. MAX_NELS)) &
+                        stop 'assert(length .le. MAX_NELS)'
+                    nInIntRange = 0
+                    nInExtRange = 0
+                    do 4, k = 1, INT(length)
+                        ndx(1) = k
+                        expect(k) = hash4( datatype, -1, ndx,  &
+                                          NFT_ITYPE($1))
+                        if (inRange3(expect(k), datatype,  &
+                                     NFT_ITYPE($1))) then
+                            nInExtRange = nInExtRange + 1
+                            if (in_internal_range(NFT_ITYPE($1), &
+                                                  expect(k))) &
+                                nInIntRange = nInIntRange + 1
+                        end if
+4                   continue
+                    err = nf90mpi_get_att(ncid, i, ATT_NAME(j,i), value)
+                    if (nInExtRange .eq. length .and.  &
+                        nInIntRange .eq. length) then
+                        if (err .ne. NF90_NOERR) &
+                            call error(nf90mpi_strerror(err))
+                    else
+                        if (err .ne. NF90_NOERR .and. err .ne. NF90_ERANGE) &
+                            call errore('OK or Range error: ', err)
+                    end if
+                    do 3, k = 1, INT(length)
+                        if (inRange3(expect(k),datatype,NFT_ITYPE($1)) &
+                                .and.  &
+                                in_internal_range(NFT_ITYPE($1),  &
+                                                  expect(k))) then
+                            val = MAKE_ARITH3($1,value,k)
+                            if (.not.equal( &
+                                val, &
+                                expect(k),datatype, &
+                                NFT_ITYPE($1))) then
+                                call error( &
+                                    'att. value read not that expected')
+                                if (verbose) then
+                                    call error(' ')
+                                    call errori('varid: ', i)
+                                    call errorc('att_name: ',  &
+                                        ATT_NAME(j,i))
+                                    call errori('element number: ', k)
+                                    call errord('expect: ', expect(k))
+                                    call errord('got: ',  val)
+                                end if
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+3                   continue
+                end if                                               
+2           continue
+1       continue
+
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_PUT_VAR1(TYPE)
+dnl
+define([TEST_NFMPI_PUT_VAR1],dnl
+[dnl
+        subroutine test_nf90mpi_put_var1_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer i
+        integer j
+        integer err, flags
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        DATATYPE_VAR1($1, value)
+        doubleprecision val
+
+        value = MAKE_TYPE($1, 5)!/* any value would do - only for error cases */
+
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        err = nf90mpi_begin_indep_data(ncid)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            do 2, j = 1, var_rank(i)
+                index(j) = 1
+2           continue
+            err = nf90mpi_put_var(BAD_ID, i, value(1:1), index)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_put_var(ncid, BAD_VARID, value(1:1), index)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .gt. 1) then         !/* skip record dim */
+                    index(j) = var_shape(j,i) + 1
+                    err = nf90mpi_put_var(ncid, i, value(1:1), index)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad index: ', err)
+                    endif
+                    index(j) = 0
+                end if
+3           continue
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), index)
+                if (err .ne. NF90_NOERR)  &
+                    call error('error in index2indexes 1')
+                val = hash_$1(var_type(i),var_rank(i), &
+                              index, NFT_ITYPE($1))
+                MAKE_TYPE2($1, value, val)
+                err = nf90mpi_put_var(ncid, i, value(1:1), index)
+                if (canConvert) then
+                    val = ARITH_VAR1($1, value)
+                    if (inRange3(val, var_type(i), NFT_ITYPE($1))) then
+                        if (err .ne. NF90_NOERR) &
+                            call errore('nf90mpi_put_var: ', err)
+                    else
+                        if (err .ne. NF90_ERANGE) &
+                            call errore('Range error: ', err)
+                    end if
+                else
+                    if (err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                end if
+4           continue
+1       continue
+        err = nf90mpi_end_indep_data(ncid)
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed: ',  &
+                        scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_PUT_VAR(TYPE)
+dnl
+define([TEST_NFMPI_PUT_VAR],dnl
+[dnl
+        subroutine test_nf90mpi_put_var_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer vid
+        integer i
+        integer j
+        integer err, flags
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* All values within external range?*/
+        DATATYPE($1, value, MAX_NELS)
+        doubleprecision val
+
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        err = nf90mpi_begin_indep_data(ncid)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            err = nf90mpi_put_var(BAD_ID, i, value)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_put_var(ncid, BAD_VARID, value)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            nels = 1
+            do 3, j = 1, var_rank(i)
+                nels = nels * var_shape(j,i)
+3           continue
+            allInExtRange = .true.
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                    index)
+                if (err .ne. NF90_NOERR)  &
+                    call error('error in index2indexes 1')
+                val = hash_$1(var_type(i), var_rank(i), &
+                              index, NFT_ITYPE($1))
+                MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                val = ARITH3($1, value, j)
+                allInExtRange = allInExtRange .and. &
+                    inRange3(val, var_type(i), NFT_ITYPE($1))
+4           continue
+            err = nf90mpi_put_var(ncid, i, VALUE3($1, value), count=var_shape(:,i))
+            if (canConvert) then
+                if (allInExtRange) then
+                    if (err .ne. NF90_NOERR) &
+                        call errore('nf90mpi_put_var: ', err)
+                else
+                    if (err .ne. NF90_ERANGE .and. &
+                            var_dimid(var_rank(i),i) .ne. RECDIM) &
+                        call errore('Range error: ', err)
+                endif
+            else
+                if (err .ne. NF90_ECHAR) &
+                    call errore('wrong type: ', err)
+            endif
+1       continue
+        err = nf90mpi_end_indep_data(ncid)
+
+!       The preceeding has written nothing for record variables, now try
+!       again with more than 0 records.
+
+!       Write record number NRECS to force writing of preceding records.
+!       Assumes variable cr is char vector with UNLIMITED dimension.
+
+        err = nf90mpi_inq_varid(ncid, "cr", vid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_inq_varid: ', err)
+        index(1) = NRECS
+        err = nf90mpi_begin_indep_data(ncid)
+        err = nf90mpi_put_var(ncid, vid, 'x', index)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_put_var: ', err)
+
+        do 5 i = 1, numVars
+!           Only test record variables here
+            if (var_rank(i) .ge. 1 .and. &
+                var_dimid(var_rank(i),i) .eq. RECDIM) then
+                canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+                if (var_rank(i) .gt. MAX_RANK) &
+                    stop 'var_rank(i) .gt. MAX_RANK'
+                if (var_nels(i) .gt. MAX_NELS) &
+                    stop 'var_nels(i) .gt. MAX_NELS'
+
+                nels = 1
+                do 6 j = 1, var_rank(i)
+                    nels = nels * var_shape(j,i)
+6               continue
+                allInExtRange = .true.
+                do 7, j = 1, INT(nels)
+                    err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                    index)
+                    if (err .ne. NF90_NOERR)  &
+                        call error('error in index2indexes()')
+                    val = hash_$1(var_type(i), var_rank(i), &
+                                  index, NFT_ITYPE($1))
+                    MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                    val = ARITH3($1, value, j)
+                    allInExtRange = allInExtRange .and. &
+                        inRange3(val, var_type(i), NFT_ITYPE($1))
+7               continue
+                err = nf90mpi_put_var(ncid, i, value, count=var_shape(:,i))
+                if (canConvert) then
+                    if (allInExtRange) then
+                        if (err .ne. NF90_NOERR) &
+                            call errore('nf90mpi_put_var: ', err)
+                    else
+                        if (err .ne. NF90_ERANGE) &
+                            call errore('range error: ', err)
+                    endif
+                else
+                    if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                endif
+            endif
+5       continue
+        err = nf90mpi_end_indep_data(ncid);
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed: ',  &
+                        scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_PUT_VARA(TYPE)
+dnl
+define([TEST_NFMPI_PUT_VARA],dnl
+[dnl
+        subroutine test_nf90mpi_put_vara_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer i
+        integer j
+        integer k
+        integer d
+        integer err, flags
+        integer nslabs
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer(kind=MPI_OFFSET_KIND) start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) edge(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) mid(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* all values within external range? */
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer ud_shift
+
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) &
+                stop 'assert(var_rank(i) .le. MAX_RANK)'
+            if (.not.(var_nels(i) .le. MAX_NELS)) &
+                stop 'assert(var_nels(i) .le. MAX_NELS)'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+2           continue
+            err = nf90mpi_put_var_all(BAD_ID, i, value, start, edge)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_put_var_all(ncid, BAD_VARID, value, start, edge)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_put_var_all(ncid, i, value, start, edge)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                    edge(j) = var_shape(j,i) + 1
+                    err = nf90mpi_put_var_all(ncid, i, value, start, edge)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EEDGE) &
+                            call errore('bad edge: ', err)
+                    endif
+                    edge(j) = 1
+                end if
+3           continue
+
+!           /* Check correct error returned even when nothing to put */
+            do 20, j = 1, var_rank(i)
+                edge(j) = 0
+20          continue
+            err = nf90mpi_put_var_all(BAD_ID, i, value, start, edge)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_put_var_all(ncid, BAD_VARID, value, start, edge)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 21, j = 1, var_rank(i)
+                if (var_dimid(j,i) .gt. 1) then     ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_put_var_all(ncid, i, value, start, edge)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                endif
+21          continue
+
+! wkliao: this test below of put_vara is redundant and incorrectly uses the
+!         value[] set from the previously iteration. There is no such test
+!         in put_vars and put_varm.
+!
+!           err = nf90mpi_put_var_all(ncid, i, value, start, edge)
+!           if (canConvert) then
+!               if (err .ne. NF90_NOERR)  &
+!                   call error(nf90mpi_strerror(err))
+!           else
+!               if (err .ne. NF90_ECHAR) &
+!                   call errore('wrong type: ', err)
+!           endif
+
+            do 22, j = 1, var_rank(i)
+                edge(j) = 1
+22          continue
+
+
+            !/* Choose a random point dividing each dim into 2 parts */
+            !/* Put 2^rank (nslabs) slabs so defined */
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+            !/* bits of k determine whether to put lower or upper part of dim */
+            do 5, k = 1, nslabs
+                nels = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    nels = nels * edge(j)
+6               continue
+                allInExtRange = .true.
+                do 7, j = 1, INT(nels)
+                    err = index2indexes(j, var_rank(i), edge, index)
+                    if (err .ne. NF90_NOERR)  &
+                        call error('error in index2indexes 1')
+                    do 8, d = 1, var_rank(i)
+                        index(d) = index(d) + start(d) - 1
+8                   continue
+                    val = hash_$1(var_type(i), var_rank(i), &
+                                  index, NFT_ITYPE($1))
+                    MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                    val = ARITH3($1, value, j)
+                    allInExtRange = allInExtRange .and. &
+                        inRange3(val, var_type(i), NFT_ITYPE($1))
+7               continue
+                err = nf90mpi_put_var_all(ncid, i, value, start, edge)
+                if (canConvert) then
+                    if (allInExtRange) then
+                        if (err .ne. NF90_NOERR)  &
+                            call error(nf90mpi_strerror(err))
+                    else
+                        if (err .ne. NF90_ERANGE) &
+                            call errore('range error: ', err)
+                    end if
+                else
+                    if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
+                        call errore('wrong type: ', err)
+                end if
+5           continue
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed: ',  &
+                scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_PUT_VARS(TYPE)
+dnl
+define([TEST_NFMPI_PUT_VARS],dnl
+[dnl
+        subroutine test_nf90mpi_put_vars_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        double precision hash_$1
+        logical inRange3
+        integer roll, index2indexes
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err, flags
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer nslabs
+        integer(kind=MPI_OFFSET_KIND) nstarts        !/* number of different starts */
+        integer(kind=MPI_OFFSET_KIND) start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) edge(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index2(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) mid(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) count(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) sstride(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) stride(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* all values within external range? */
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer ud_shift
+
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) &
+                stop 'assert(var_rank(i) .le. MAX_RANK)'
+            if (.not.(var_nels(i) .le. MAX_NELS)) &
+                stop 'assert(var_nels(i) .le. MAX_NELS)'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+2           continue
+            err = nf90mpi_put_var_all(BAD_ID, i, value, start, edge, stride)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_put_var_all(ncid, BAD_VARID, value, start, edge, stride)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .ne. RECDIM) then    ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_put_var_all(ncid, i, value, start, &
+                                         edge, stride)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                                call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                    edge(j) = var_shape(j,i) + 1
+                    err = nf90mpi_put_var_all(ncid, i, value, start, &
+                                         edge, stride)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EEDGE) &
+                            call errore('bad edge: ', err)
+                    endif
+                    edge(j) = 1
+                    stride(j) = 0
+                    err = nf90mpi_put_var_all(ncid, i, value, start, &
+                                         edge, stride)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_ESTRIDE) &
+                            call errore('bad stride: ', err)
+                    endif
+                    stride(j) = 1
+                end if
+3           continue
+            !/* Choose a random point dividing each dim into 2 parts */
+            !/* Put 2^rank (nslabs) slabs so defined */
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+            !/* bits of k determine whether to put lower or upper part of dim */
+            !/* choose random stride from 1 to edge */
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        stride(j) = 1+roll(edge(j))
+                    else
+                        stride(j) = 1
+                    end if
+                    sstride(j) = stride(j)
+                    nstarts = nstarts * stride(j)
+6               continue
+                do 7, m = 1, INT(nstarts)
+                    err = index2indexes(m, var_rank(i), sstride, index)
+                    if (err .ne. NF90_NOERR) &
+                        call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) / stride(j)
+                        nels = nels * count(j)
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+                    !/* Random choice of forward or backward */
+! TODO
+!                   if ( roll(2) ) {
+!                       for (j = 1 j .lt. var_rank(i) j++) {
+!                           index(j) += (count(j) - 1) * stride(j)
+!                           stride(j) = -stride(j)
+!                       }
+!                   }
+!
+                    allInExtRange = .true.
+                    do 9, j = 1, INT(nels)
+                        err = index2indexes(j, var_rank(i), count,  &
+                                            index2)
+                        if (err .ne. NF90_NOERR) &
+                            call error('error in index2indexes')
+                        do 10, d = 1, var_rank(i)
+                            index2(d) = index(d) +  &
+                                        (index2(d)-1) * stride(d)
+10                      continue
+                        val = hash_$1(var_type(i), var_rank(i), &
+                                      index2, NFT_ITYPE($1))
+                        MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                        val = ARITH3($1, value, j)
+                        allInExtRange = allInExtRange .and. &
+                            inRange3(val, var_type(i),  &
+                                     NFT_ITYPE($1))
+9                   continue
+                    err = nf90mpi_put_var_all(ncid, i, value, index, &
+                                         count, stride)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (err .ne. NF90_NOERR)  &
+                                call error(nf90mpi_strerror(err))
+                        else
+                            if (err .ne. NF90_ERANGE) &
+                                call errore('range error: ', err)
+                        end if
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed:',  &
+                scratch)
+        end
+])dnl
+
+
+dnl  since parallel-netcdf doesn't have varm type, we haven't completed the
+dnl  parallel-netcdf-ification of these routines
+dnl TEST_NFMPI_PUT_VARM(TYPE)
+dnl
+define([TEST_NFMPI_PUT_VARM],dnl
+[dnl
+        subroutine test_nf90mpi_put_varm_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err, flags
+        integer(kind=MPI_OFFSET_KIND) nels
+        integer nslabs
+        integer(kind=MPI_OFFSET_KIND) nstarts        !/* number of different starts */
+        integer(kind=MPI_OFFSET_KIND) start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) edge(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) index2(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) mid(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) count(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) sstride(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) stride(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) imap(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* all values within external range? */
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer ud_shift
+
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF90_CHAR) .eqv. &
+                         (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) &
+                stop 'assert(var_rank(i) .le. MAX_RANK)'
+            if (.not.(var_nels(i) .le. MAX_NELS)) &
+                stop 'assert(var_nels(i) .le. MAX_NELS)'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+                imap(j) = 1
+2           continue
+            err = nf90mpi_put_var_all(BAD_ID, i, value, start, &
+                                 edge, stride, imap)
+            if (err .ne. NF90_EBADID)  &
+                call errore('bad ncid: ', err)
+            err = nf90mpi_put_var_all(ncid, BAD_VARID, value, start, &
+                                 edge, stride, imap)
+            if (err .ne. NF90_ENOTVAR)  &
+                call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
+                    start(j) = var_shape(j,i) + 1
+                    err = nf90mpi_put_var_all(ncid, i, value, start, &
+                                         edge, stride, imap)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EINVALCOORDS) &
+                            call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                    edge(j) = var_shape(j,i) + 1
+                    err = nf90mpi_put_var_all(ncid, i, value, start, &
+                                         edge, stride, imap)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_EEDGE) &
+                            call errore('bad edge: ', err)
+                    endif
+                    edge(j) = 1
+                    stride(j) = 0
+                    err = nf90mpi_put_var_all(ncid, i, value, start, &
+                                         edge, stride, imap)
+                    if (.not. canConvert) then
+                        if (err .ne. NF90_ECHAR) &
+                            call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF90_ESTRIDE) &
+                            call errore('bad stride: ', err)
+                    endif
+                    stride(j) = 1
+                end if
+3           continue
+            !/* Choose a random point dividing each dim into 2 parts */
+            !/* Put 2^rank (nslabs) slabs so defined */
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+            !/* bits of k determine whether to put lower or upper part of dim */
+            !/* choose random stride from 1 to edge */
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        stride(j) = 1+roll(edge(j))
+                    else
+                        stride(j) = 1
+                    end if
+                    sstride(j) = stride(j)
+                    nstarts = nstarts * stride(j)
+6               continue
+                do 7, m = 1, INT(nstarts)
+                    err = index2indexes(m, var_rank(i), sstride, index)
+                    if (err .ne. NF90_NOERR) &
+                        call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) / stride(j)
+                        nels = nels * count(j)
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+                    !/* Random choice of forward or backward */
+! TODO
+!                   if ( roll(2) ) then
+!                       do 9, j = 1, var_rank(i)
+!                           index(j) = index(j) +  &
+!                               (count(j) - 1) * stride(j)
+!                           stride(j) = -stride(j)
+!9                      continue
+!                   end if
+!
+                    if (var_rank(i) .gt. 0) then
+                        imap(1) = 1
+                        do 10, j = 2, var_rank(i)
+                            imap(j) = imap(j-1) * count(j-1)
+10                      continue
+                    end if
+                    allInExtRange = .true.
+                    do 11 j = 1, INT(nels)
+                        err = index2indexes(j, var_rank(i), count,  &
+                                            index2)
+                        if (err .ne. NF90_NOERR) &
+                            call error('error in index2indexes')
+                        do 12, d = 1, var_rank(i)
+                            index2(d) = index(d) +  &
+                                (index2(d)-1) * stride(d)
+12                      continue
+                        val = hash_$1(var_type(i),var_rank(i), &
+                                      index2, NFT_ITYPE($1))
+                        MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                        val = ARITH3($1, value, j)
+                        allInExtRange = allInExtRange .and. &
+                            inRange3(val, var_type(i),  &
+                                     NFT_ITYPE($1))
+11                  continue
+                    err = nf90mpi_put_var_all(ncid,i,value,index,count, &
+                                         stride,imap)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (err .ne. NF90_NOERR) &
+                                call error(nf90mpi_strerror(err))
+                        else
+                            if (err .ne. NF90_ERANGE) &
+                                call errore('range error: ', err)
+                        end if
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF90_ECHAR) &
+                            call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed:',  &
+                scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_PUT_ATT(TYPE)         numeric only
+dnl
+define([TEST_NFMPI_PUT_ATT],dnl
+[dnl
+        subroutine test_nf90mpi_put_att_$1()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer ATT_TYPE, NATTS, ATT_LEN
+        integer(kind=MPI_OFFSET_KIND) ATT_LEN_LL
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer i
+        integer j
+        integer k
+        integer(kind=MPI_OFFSET_KIND) ndx(1)
+        integer err, flags
+        ATTDATATYPE($1, value, MAX_NELS)
+        logical allInExtRange  !/* all values within external range? */
+        doubleprecision val
+
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+
+        do 1, i = 0, numVars
+            do 2, j = 1, NATTS(i)
+                if (.not.(ATT_TYPE(j,i) .eq. NF90_CHAR)) then
+                    ATT_LEN_LL = ATT_LEN(j,i)
+                    if (.not.((ATT_LEN_LL .le. MAX_NELS))) &
+                        stop 'assert(ATT_LEN_LL .le. MAX_NELS)'
+                    err = nf90mpi_put_att(BAD_ID, i, ATT_NAME(j,i), value)
+                    if (err .ne. NF90_EBADID) &
+                        call errore('bad ncid: ', err)
+                    err = nf90mpi_put_att(ncid, BAD_VARID, ATT_NAME(j,i), value)
+                    if (err .ne. NF90_ENOTVAR) &
+                        call errore('bad var id: ', err)
+                    allInExtRange = .true.
+                    do 3, k = 1, INT(ATT_LEN_LL)
+                        ndx(1) = k
+                        val = hash_$1(ATT_TYPE(j,i), &
+                                      -1, ndx, NFT_ITYPE($1))
+                        MAKE_TYPE2($1, VAR_ELEM($1, value, k), val)
+                        val = ARITH3($1, value, k)
+                        allInExtRange = allInExtRange .and. &
+                            inRange3(val, ATT_TYPE(j,i),  &
+                                     NFT_ITYPE($1))
+3                   continue
+                    ! err = nf90mpi_put_att(ncid, i, ATT_NAME(j,i), value(1:ATT_LEN_LL))
+                    ! cannot use F90 API, as type casting is performed,
+                    ! as ATT_TYPE(j,i) may not be the same as value's type
+                    err = nfmpi_put_att_$1(ncid, i, ATT_NAME(j,i), &
+                                           ATT_TYPE(j,i), ATT_LEN_LL, value)
+                    if (allInExtRange) then
+                        if (err .ne. NF90_NOERR) &
+                            call errore('nf90mpi_put_att: ', err)
+                    else
+                        if (err .ne. NF90_ERANGE) &
+                            call errore('range error: ', err)
+                    end if
+                end if
+2           continue
+1       continue
+
+        call check_atts_$1(ncid)
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed:',  &
+                scratch)
+        end
+])dnl
+
+divert(0)dnl
+dnl If you see this line, you can ignore the next one.
+! Do not edit this file. It is produced from the corresponding .m4 source */
+
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_put.m4 2156 2015-10-12 01:15:25Z wkliao $
+!
+
+HASH(text)
+#ifdef NF_INT1_T
+HASH(int1)
+#endif
+#ifdef NF_INT2_T
+HASH(int2)
+#endif
+HASH(int)
+HASH(int8)
+HASH(real)
+HASH(double)
+
+CHECK_VARS(text)
+#ifdef NF_INT1_T
+CHECK_VARS(int1)
+#endif
+#ifdef NF_INT2_T
+CHECK_VARS(int2)
+#endif
+CHECK_VARS(int)
+CHECK_VARS(int8)
+CHECK_VARS(real)
+CHECK_VARS(double)
+
+CHECK_ATTS(text)
+#ifdef NF_INT1_T
+CHECK_ATTS(int1)
+#endif
+#ifdef NF_INT2_T
+CHECK_ATTS(int2)
+#endif
+CHECK_ATTS(int)
+CHECK_ATTS(int8)
+CHECK_ATTS(real)
+CHECK_ATTS(double)
+
+TEST_NFMPI_PUT_VAR1(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_PUT_VAR1(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_PUT_VAR1(int2)
+#endif
+TEST_NFMPI_PUT_VAR1(int)
+TEST_NFMPI_PUT_VAR1(int8)
+TEST_NFMPI_PUT_VAR1(real)
+TEST_NFMPI_PUT_VAR1(double)
+
+TEST_NFMPI_PUT_VAR(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_PUT_VAR(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_PUT_VAR(int2)
+#endif
+TEST_NFMPI_PUT_VAR(int)
+TEST_NFMPI_PUT_VAR(int8)
+TEST_NFMPI_PUT_VAR(real)
+TEST_NFMPI_PUT_VAR(double)
+
+TEST_NFMPI_PUT_VARA(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_PUT_VARA(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_PUT_VARA(int2)
+#endif
+TEST_NFMPI_PUT_VARA(int)
+TEST_NFMPI_PUT_VARA(int8)
+TEST_NFMPI_PUT_VARA(real)
+TEST_NFMPI_PUT_VARA(double)
+
+TEST_NFMPI_PUT_VARS(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_PUT_VARS(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_PUT_VARS(int2)
+#endif
+TEST_NFMPI_PUT_VARS(int)
+TEST_NFMPI_PUT_VARS(int8)
+TEST_NFMPI_PUT_VARS(real)
+TEST_NFMPI_PUT_VARS(double)
+
+TEST_NFMPI_PUT_VARM(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_PUT_VARM(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_PUT_VARM(int2)
+#endif
+TEST_NFMPI_PUT_VARM(int)
+TEST_NFMPI_PUT_VARM(int8)
+TEST_NFMPI_PUT_VARM(real)
+TEST_NFMPI_PUT_VARM(double)
+
+        subroutine test_nf90mpi_put_att_text()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer ATT_TYPE, NATTS, ATT_LEN
+        double precision hash
+
+        integer ncid
+        integer i
+        integer j
+        integer(kind=MPI_OFFSET_KIND) k
+        integer err, flags
+        character(len=MAX_NELS) value
+
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+
+        do 1, i = 0, numVars
+            do 2, j = 1, NATTS(i)
+                if (ATT_TYPE(j,i) .eq. NF90_CHAR) then
+                    if (.not.(ATT_LEN(j,i) .le. MAX_NELS)) &
+                        stop 'assert(ATT_LEN(j,i) .le. MAX_NELS)'
+                    err = nf90mpi_put_att(BAD_ID, i, ATT_NAME(j,i), value)
+                    if (err .ne. NF90_EBADID) &
+                        call errore('bad ncid: ', err)
+                    err = nf90mpi_put_att(ncid, BAD_VARID,  &
+                                          ATT_NAME(j,i), value)
+                    if (err .ne. NF90_ENOTVAR) &
+                        call errore('bad var id: ', err)
+                    do 3, k = 1, ATT_LEN(j,i)
+                        value(k:k) = char(int(hash(ATT_TYPE(j,i), &
+                                                   -1, k)))
+3                   continue
+                    err = nf90mpi_put_att(ncid, i, ATT_NAME(j,i), value(1:ATT_LEN(j,i)))
+                    if (err .ne. NF90_NOERR) &
+                        call error(nf90mpi_strerror(err))
+                end if
+2           continue
+1       continue
+
+        call check_atts_text(ncid)
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed:',  &
+                scratch)
+        end
+
+#ifdef NF_INT1_T
+TEST_NFMPI_PUT_ATT(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_PUT_ATT(int2)
+#endif
+TEST_NFMPI_PUT_ATT(int)
+TEST_NFMPI_PUT_ATT(int8)
+TEST_NFMPI_PUT_ATT(real)
+TEST_NFMPI_PUT_ATT(double)
diff --git a/test/nf90_test/test_read.F90 b/test/nf90_test/test_read.F90
new file mode 100644
index 0000000..aa6193f
--- /dev/null
+++ b/test/nf90_test/test_read.F90
@@ -0,0 +1,1454 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_read.F90 2296 2016-01-06 21:19:36Z wkliao $
+!
+
+! Test nf90mpi_strerror.
+!    Try on a bad error status.
+!    Test for each defined error status.
+!
+        subroutine test_nf90mpi_strerror()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer         number_of_messages
+        parameter       (number_of_messages = 27)
+
+        integer         i, msg_len
+        integer         status(number_of_messages)
+        character*80    message, unknown_err_msg
+        character*80    msg(number_of_messages)
+        integer         nok
+
+        data    status(1)  / NF90_NOERR/
+        data    status(2)  / NF90_EBADID /
+        data    status(3)  / NF90_EEXIST /
+        data    status(4)  / NF90_EINVAL /
+        data    status(5)  / NF90_EPERM /
+        data    status(6)  / NF90_ENOTINDEFINE /
+        data    status(7)  / NF90_EINDEFINE /
+        data    status(8)  / NF90_EINVALCOORDS /
+        data    status(9)  / NF90_EMAXDIMS /
+        data    status(10) / NF90_ENAMEINUSE /
+        data    status(11) / NF90_ENOTATT /
+        data    status(12) / NF90_EMAXATTS /
+        data    status(13) / NF90_EBADTYPE /
+        data    status(14) / NF90_EBADDIM /
+        data    status(15) / NF90_EUNLIMPOS /
+        data    status(16) / NF90_EMAXVARS /
+        data    status(17) / NF90_ENOTVAR /
+        data    status(18) / NF90_EGLOBAL /
+        data    status(19) / NF90_ENOTNC /
+        data    status(20) / NF90_ESTS /
+        data    status(21) / NF90_EMAXNAME /
+        data    status(22) / NF90_EUNLIMIT /
+        data    status(23) / NF90_ENORECVARS /
+        data    status(24) / NF90_ECHAR /
+        data    status(25) / NF90_EEDGE /
+        data    status(26) / NF90_ESTRIDE /
+        data    status(27) / NF90_EBADNAME /
+
+        data msg(1)  / 'No error' /
+        data msg(2)  / 'NetCDF: Not a valid ID' /
+        data msg(3)  / 'NetCDF: File exists && NC_NOCLOBBER' /
+        data msg(4)  / 'NetCDF: Invalid argument' /
+        data msg(5)  / 'NetCDF: Write to read only' /
+        data msg(6)  / 'NetCDF: Operation not allowed in data mode' /
+        data msg(7)  / 'NetCDF: Operation not allowed in define mode' /
+        data msg(8)  / 'NetCDF: Index exceeds dimension bound' /
+        data msg(9)  / 'NetCDF: NC_MAX_DIMS exceeded' /
+        data msg(10) / 'NetCDF: String match to name in use' /
+        data msg(11) / 'NetCDF: Attribute not found' /
+        data msg(12) / 'NetCDF: NC_MAX_ATTRS exceeded' /
+        data msg(13) &
+        / 'NetCDF: Not a valid data type or _FillValue type mismatch' /
+        data msg(14) / 'NetCDF: Invalid dimension ID or name' /
+        data msg(15) / 'NetCDF: NC_UNLIMITED in the wrong index' /
+        data msg(16) / 'NetCDF: NC_MAX_VARS exceeded' /
+        data msg(17) / 'NetCDF: Variable not found' /
+        data msg(18) / 'NetCDF: Action prohibited on NC_GLOBAL varid' /
+        data msg(19) / 'NetCDF: Unknown file format' /
+        data msg(20) / 'NetCDF: In Fortran, string too short' /
+        data msg(21) / 'NetCDF: NC_MAX_NAME exceeded' /
+        data msg(22) / 'NetCDF: NC_UNLIMITED size already in use' /
+        data msg(23) &
+        / 'NetCDF: nc_rec op when there are no record vars' /
+        data msg(24) &
+        /'NetCDF: Attempt to convert between text & numbers'/
+        data msg(25) / 'NetCDF: Start+count exceeds dimension bound' /
+        data msg(26) / 'NetCDF: Illegal stride' /
+        data msg(27) / 'NetCDF: Name contains illegal characters' /
+
+        nok = 0
+
+!       /* Try on a bad error status */
+        message = nf90mpi_strerror(-666)!/* should fail */
+!       pnetcdf differs from serial netcdf in that we report the error
+!       code along with the message.
+
+        unknown_err_msg = "Unknown Error"
+        msg_len = LEN(TRIM(unknown_err_msg))
+        if (message(1:msg_len) .ne. unknown_err_msg(1:msg_len)) then
+            call errorc('nf90mpi_strerror on bad error status returned: ', &
+                message)
+        else
+            nok = nok + 1
+        endif
+
+!       /* Try on each legitimate error status */
+        do 1, i=1, number_of_messages
+            message = nf90mpi_strerror(status(i))
+            if (trim(message) .ne. trim(msg(i))) then
+                call error('nf90mpi_strerror() should return "'  &
+                           // trim(msg(i)) // '"' // ' but got '// &
+                           '"' // trim(message) // '"')
+            else
+                nok = nok + 1
+            endif
+1       continue
+        call print_nok(nok)
+        end
+
+
+! Test nf90mpi_open.
+! If in read-only section of tests,
+!    Try to open a non-existent netCDF file, check error return.
+!    Open a file that is not a netCDF file, check error return.
+!    Open a netCDF file with a bad mode argument, check error return.
+!    Open a netCDF file with NFMPI_NOWRITE mode, try to write, check error.
+!    Try to open a netcdf twice, check whether returned netcdf ids different.
+! If in writable section of tests,
+!    Open a netCDF file with NFMPI_WRITE mode, write something, close it.
+! On exit, any open netCDF files are closed.
+        subroutine test_nf90mpi_open()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer err
+        integer ncid
+        integer ncid2
+        integer         nok, flags
+
+        nok = 0
+
+!       /* Try to open a nonexistent file */
+        err = nf90mpi_open(comm, 'tooth-fairy.nc', NF90_NOWRITE, &
+                         info, ncid)!/* should fail */
+
+!       On some systems, opening an nonexisting file will actually create the
+!       file. In this case, we print the error messages on screen and move on
+!       to the next test, instead of aborting the entire test.
+
+        if (err .eq. NF90_NOERR) then
+            print*, &
+        'opening a nonexistent file expects to fail, but got NF90_NOERR'
+        elseif (err .ne. NF90_ENOENT) then
+            print*, &
+        'opening a nonexistent file expects NF90_ENOENT, but got ',err
+        else
+!           print*, "Expected error message complaining: "// &
+!                   "File tooth-fairy.nc does not exist"
+            nok = nok + 1
+        endif
+
+!       Open a file that is not a netCDF file. This call should fail
+        err = nf90mpi_open(comm, 'test_get.F90', NF90_NOWRITE, &
+                           info, ncid)
+        if (err .ne. NF90_ENOTNC .and. err .ne. NF90_EOFILE) then
+            call errore('nf90mpi_open of non-netCDF file: ', err)
+        else
+            nok = nok + 1
+        endif
+
+!       Open a netCDF file in read-only mode, check that write fails
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, ncid)
+        if (err .NE. NF90_NOERR) then
+            call errore('nf90mpi_open: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_redef(ncid)    !/* should fail */
+        if (err .ne. NF90_EPERM) &
+            call error('nf90mpi_redef of read-only file should fail')
+!       Opened OK, see if can open again and get a different netCDF ID
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid2)
+        if (err .NE. NF90_NOERR) then
+            call errore('nf90mpi_open: ', err)
+        else
+            err = nf90mpi_close(ncid2)
+            nok = nok + 1
+        end if
+        if (ncid2 .eq. ncid) &
+            call error('netCDF IDs for first and second '// &
+                       'nf90mpi_open calls should differ')
+
+        if (.not. readonly) then        !/* tests using netCDF scratch file */
+            flags = IOR(NF90_NOCLOBBER, extra_flags)
+            err = nf90mpi_create(comm, scratch, flags, &
+                               info, ncid2)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_create: ', err)
+            else 
+                err = nf90mpi_close(ncid2)
+            end if
+            err = nf90mpi_open(comm, scratch, NF90_WRITE, info, &
+                             ncid2)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_open: ', err)
+            else 
+                err = nf90mpi_close(ncid2)
+                nok = nok + 1
+            end if
+            err = nf90mpi_delete(scratch, info)
+            if (err .NE. NF90_NOERR)  &
+                call errorc('delete of scratch file failed: ', scratch)
+        end if
+
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+! 
+! Test nf90mpi_close.
+!    Try to close a netCDF file twice, check whether second close fails.
+!    Try on bad handle, check error return.
+!    Try in define mode and data mode.
+!
+        subroutine test_nf90mpi_close()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer err
+        integer nok, flags
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+
+!       /* Close a netCDF file twice, second time should fail */
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) then
+            call errore('nf90mpi_close failed: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_EBADID) then
+            call error('nf90mpi_close of closed file should have failed')
+        else
+            nok = nok + 1
+        endif
+
+!       /* Try with a bad netCDF ID */
+        err = nf90mpi_close(BAD_ID)!/* should fail */
+        if (err .ne. NF90_EBADID) then
+            call errore( &
+               'nf90mpi_close with bad netCDF ID returned wrong error: ',  &
+               err)
+        else
+            nok = nok + 1
+        endif
+
+!       /* Close in data mode */
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) then
+            call errore('nf90mpi_close in data mode failed: ', err)
+        else
+            nok = nok + 1
+        endif
+
+        if (.not. readonly) then        !/* tests using netCDF scratch file */
+            flags = IOR(NF90_NOCLOBBER, extra_flags)
+            err = nf90mpi_create(comm, scratch, flags, &
+                               info, ncid)
+            if (err .NE. NF90_NOERR)  &
+                call errore('nf90mpi_create: ', err)
+            err = nf90mpi_close(ncid)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_close in define mode: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_delete(scratch, info)
+            if (err .NE. NF90_NOERR) then
+                call errorc('delete of scratch file failed: ',  &
+                    scratch)
+            else
+                nok = nok + 1
+            endif
+        end if
+        call print_nok(nok)
+        end
+
+
+! Test nf90mpi_inq.
+!    Try on bad handle, check error return.
+!    Try in data mode, check returned values.
+!    Try asking for subsets of info.
+! If in writable section of tests,
+!    Try in define mode, after adding an unlimited dimension, variable.
+! On exit, any open netCDF files are closed.
+        subroutine test_nf90mpi_inq()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer ncid2                   !/* for scratch netCDF dataset */
+        integer ndims                   !/* number of dimensions */
+        integer nvars                   !/* number of variables */
+        integer ngatts                  !/* number of global attributes */
+        integer recdim                  !/* id of unlimited dimension */
+        integer err
+        integer ndims0
+        integer nvars0
+        integer ngatts0
+        integer recdim0
+        integer did
+        integer vid
+        integer(kind=MPI_OFFSET_KIND) length
+        integer VDIMS(1)
+        integer nok, flags
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        
+!       /* Try on bad handle */
+        err = nf90mpi_inquire(BAD_ID, ndims, nvars, ngatts, recdim)
+        if (err .ne. NF90_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+        
+        err = nf90mpi_inquire(ncid, ndims, nvars, ngatts, recdim)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_inquire: ', err)
+        else if (ndims .ne. NDIMS) then
+            call errori &
+            ('nf90mpi_inquire: wrong number of dimensions returned: ', ndims)
+        else if (nvars .ne. numVars) then
+            call errori &
+            ('nf90mpi_inquire: wrong number of variables returned: ', nvars)
+        else if (ngatts .ne. numGatts) then
+            call errori( &
+                'nf90mpi_inquire: wrong number of global atts returned: ', &
+                ngatts)
+        else if (recdim .ne. RECDIM) then
+            call errori &
+            ('nf90mpi_inquire: wrong record dimension ID returned: ', recdim)
+        else
+            nok = nok + 1
+        end if
+
+        if (.not. readonly) then  ! tests using netCDF scratch file
+            flags = IOR(NF90_NOCLOBBER, extra_flags)
+            err = nf90mpi_create(comm, scratch, flags, &
+                               info, ncid2)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_create: ', err)
+            else                ! add dim, var, gatt, check inq
+                err = nf90mpi_enddef(ncid2) ! enter data mode
+                err = nf90mpi_inquire(ncid2, ndims0, nvars0,  &
+                    ngatts0, recdim0)
+                if (err .NE. NF90_NOERR) then
+                    call errore('nf90mpi_inquire: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_redef(ncid2) !/* enter define mode */
+!               /* Check that inquire still works in define mode */
+                err = nf90mpi_inquire(ncid2, ndims, nvars, ngatts, recdim)
+                if (err .NE. NF90_NOERR) then
+                    call errore('nf90mpi_inquire in define mode: ', err)
+                else if (ndims .ne. ndims0) then
+                    call errori &
+                    ('nf90mpi_inquire in define mode: ndims wrong, ', ndims)
+                else if (nvars .ne. nvars0) then
+                    call errori &
+                    ('nf90mpi_inquire in define mode: nvars wrong, ', nvars)
+                else if (ngatts .ne. ngatts0) then
+                    call errori( &
+                    'nf90mpi_inquire in define mode: ngatts wrong, ', ngatts)
+                    print *, ' expected ', ngatts0
+                else if (recdim .ne. recdim0) then
+                    call errori &
+                    ('nf90mpi_inquire in define mode: recdim wrong, ', recdim)
+                else
+                    nok = nok + 1
+                end if
+
+!               /* Add dim, var, global att */
+                length = 1
+                err = nf90mpi_def_dim(ncid2, 'inqd', length, did)
+                if (err .NE. NF90_NOERR) &
+                    call errore('nf90mpi_def_dim: ', err)
+                VDIMS = 0
+                err = nf90mpi_def_var(ncid2, 'inqv', NF90_FLOAT, varid=vid)
+                if (err .NE. NF90_NOERR) &
+                    call errore('nf90mpi_def_var: ', err)
+
+                length = len('stuff')
+                err = nf90mpi_put_att(ncid2, NF90_GLOBAL, 'inqa',  &
+                                      'stuff')
+                if (err .NE. NF90_NOERR) &
+                    call errore('nf90mpi_put_att: ', err)
+
+!               Make sure nf90mpi_inquire sees the additions while in define mode
+                err = nf90mpi_inquire(ncid2, ndims, nvars, ngatts, recdim)
+                if (err .NE. NF90_NOERR) then
+                    call errore('nf90mpi_inquire in define mode: ', err)
+                else if (ndims .ne. ndims0 + 1) then
+                    call errori &
+                    ('nf90mpi_inquire in define mode: ndims wrong, ', ndims)
+                else if (nvars .ne. nvars0 + 1) then
+                    call errori &
+                    ('nf90mpi_inquire in define mode: nvars wrong, ', nvars)
+                else if (ngatts .ne. ngatts0 + 1) then
+                    call errori &
+                    ('nf90mpi_inquire in define mode: ngatts wrong, ', ngatts)
+                    print *, ' expected (added attr)', ngatts0 + 1
+                else
+                    nok = nok + 1
+                end if
+                err = nf90mpi_enddef(ncid2)
+                if (err .NE. NF90_NOERR) &
+                    call errore('nf90mpi_enddef: ', err)
+
+!               Make sure nf90mpi_inquire stills sees additions in data mode
+                err = nf90mpi_inquire(ncid2, ndims, nvars, ngatts, recdim)
+                if (err .NE. NF90_NOERR) then
+                    call errore('nf90mpi_inquire failed in data mode: ',err)
+                else if (ndims .ne. ndims0 + 1) then
+                    call errori &
+                    ('nf90mpi_inquire in define mode: ndims wrong, ', ndims)
+                else if (nvars .ne. nvars0 + 1) then
+                    call errori &
+                    ('nf90mpi_inquire in define mode: nvars wrong, ', nvars)
+                else if (ngatts .ne. ngatts0 + 1) then
+                    call errori &
+                    ('nf90mpi_inquire in define mode: ngatts wrong, ', ngatts)
+                else
+                    nok = nok + 1
+                end if
+                err = nf90mpi_close(ncid2)
+                err = nf90mpi_delete(scratch, info)
+                if (err .NE. NF90_NOERR) &
+                    call errorc('delete of scratch file failed: ',  &
+                        scratch)
+            end if
+        end if
+
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_natts()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer ngatts                  ! number of global attributes
+        integer err
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_inquire(BAD_ID, nAttributes=ngatts)
+        if (err .ne. NF90_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_inquire(ncid, nAttributes=ngatts)
+        if (err .NE. NF90_NOERR) then
+            call errore('nf90mpi_inquire: ', err)
+        else if (ngatts .ne. numGatts) then
+            call errori &
+            ('nf90mpi_inquire: wrong number of global atts returned, ', &
+              ngatts)
+        else
+            nok = nok + 1
+        end if
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_ndims()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer ndims
+        integer err
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_inquire(BAD_ID, ndims)
+        if (err .ne. NF90_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                           ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_inquire(ncid, ndims)
+        if (err .NE. NF90_NOERR) then
+            call errore('nf90mpi_inquire: ', err)
+        else if (ndims .ne. NDIMS) then
+            call errori &
+            ('nf90mpi_inquire: wrong number returned, ', ndims)
+        else
+            nok = nok + 1
+        end if
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_nvars()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer nvars
+        integer err
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_inquire(BAD_ID, nVariables=nvars)
+        if (err .ne. NF90_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_inquire(ncid, nVariables=nvars)
+        if (err .NE. NF90_NOERR) then
+            call errore('nf90mpi_inquire: ', err)
+        else if (nvars .ne. numVars) then
+            call errori &
+            ('nf90mpi_inquire: wrong number returned, ', nvars)
+        else
+            nok = nok + 1
+        end if
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_unlimdim()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer unlimdim
+        integer err
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_inquire(BAD_ID, unlimitedDimId=unlimdim)
+        if (err .ne. NF90_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                           ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_inquire(ncid, unlimitedDimId=unlimdim)
+        if (err .NE. NF90_NOERR) then
+            call errore('nf90mpi_inquire: ', err)
+        else if (unlimdim .ne. RECDIM) then
+            call errori &
+            ('nf90mpi_inquire: wrong number returned, ', unlimdim)
+            print *, 'expected ', RECDIM
+        else
+            nok = nok + 1
+        end if
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_dimid()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer dimid
+        integer i
+        integer err
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_inq_dimid(ncid, 'noSuch', dimid)
+        if (err .ne. NF90_EBADDIM) then
+            call errore('bad dim name: ', err)
+        else
+            nok = nok + 1
+        endif
+        do 1, i = 1, NDIMS
+            err = nf90mpi_inq_dimid(BAD_ID, dim_name(i), dimid)
+            if (err .ne. NF90_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inq_dimid(ncid, dim_name(i), dimid)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_inq_dimid: ', err)
+            else if (dimid .ne. i) then
+                call errori('expected ', i)
+                call errori('got ', dimid)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_dim()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer i
+        integer err
+        character*(NF90_MAX_NAME) name
+        integer(kind=MPI_OFFSET_KIND) length
+        integer intlen
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, NDIMS
+            err = nf90mpi_inquire_dimension(BAD_ID, i, name, length)
+            if (err .ne. NF90_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inquire_dimension(ncid, BAD_DIMID, name, length)
+            if (err .ne. NF90_EBADDIM) then
+                call errore('bad dimid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inquire_dimension(ncid, i, name, length)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_inquire_dimension: ', err)
+            else if (dim_name(i) .ne. name)  then
+                call errorc('name unexpected: ', name)
+                print *, ' expected ', dim_name(i),' for the ',i,'entry'
+            else if (dim_len(i) .ne. length) then
+                intlen = INT(length)
+                call errori('size unexpected: ', intlen)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_dimlen()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer i
+        integer err
+        integer(kind=MPI_OFFSET_KIND) length
+        integer intlen
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, NDIMS
+            err = nf90mpi_inquire_dimension(BAD_ID, i, len=length)
+            if (err .ne. NF90_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inquire_dimension(ncid, BAD_DIMID, len=length)
+            if (err .ne. NF90_EBADDIM) &
+                call errore('bad dimid: ', err)
+            err = nf90mpi_inquire_dimension(ncid, i, len=length)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_inquire_dimension: ', err)
+            else if (dim_len(i) .ne. length) then
+                intlen = INT(length)
+                call errori('size unexpected: ', intlen)
+                print *, 'expected ', dim_len(i),' for the ',i,'entry'
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_dimname()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer i
+        integer err
+        character*(NF90_MAX_NAME)  name
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, NDIMS
+            err = nf90mpi_inquire_dimension(BAD_ID, i, name)
+            if (err .ne. NF90_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nf90mpi_inquire_dimension(ncid, BAD_DIMID, name)
+            if (err .ne. NF90_EBADDIM) then
+                call errore('bad dimid: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nf90mpi_inquire_dimension(ncid, i, name)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_inquire_dimension: ', err)
+            else if (dim_name(i) .ne. name)  then
+                call errorc('name unexpected: ', name)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_varid()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer vid
+        integer i
+        integer err
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+
+        err = nf90mpi_inq_varid(ncid, 'noSuch', vid)
+        if (err .ne. NF90_ENOTVAR) &
+            call errore('bad ncid: ', err)
+
+        do 1, i = 1, numVars
+            err = nf90mpi_inq_varid(BAD_ID, var_name(i), vid)
+            if (err .ne. NF90_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nf90mpi_inq_varid(ncid, var_name(i), vid)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_inq_varid: ', err)
+            else if (vid .ne. i) then
+                call errori('varid unexpected: ', vid)
+            else
+                nok = nok + 1
+            endif
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_var()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        LOGICAL INT_VEC_EQ
+
+        integer ncid
+        integer i
+        integer err
+        character*(NF90_MAX_NAME) name
+        integer datatype
+        integer ndims
+        integer dimids(MAX_RANK)
+        integer na
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            err = nf90mpi_inquire_variable(BAD_ID, i, name, datatype, ndims,  &
+                  dimids, na)
+            if (err .ne. NF90_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inquire_variable(ncid,BAD_VARID,name,datatype,ndims, &
+                             dimids,na)
+            if (err .ne. NF90_ENOTVAR) then
+                call errore('bad var id: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inquire_variable(ncid, i, name, datatype, ndims, dimids,  &
+                             na)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_inquire_variable: ', err)
+            else if (var_name(i) .ne. name)  then
+                call errorc('name unexpected: ', name)
+            else if (var_type(i) .ne. datatype) then
+                call errori('type unexpected: ', datatype)
+            else if (var_rank(i) .ne. ndims) then
+                call errori('ndims expected: ', ndims)
+            else if (.not.int_vec_eq(var_dimid(1,i),dimids,ndims)) then
+                call error('unexpected dimid')
+            else if (var_natts(i) .ne. na) then
+                call errori('natts unexpected: ', na)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_vardimid()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        LOGICAL INT_VEC_EQ
+
+        integer ncid
+        integer i
+        integer err
+        integer dimids(MAX_RANK)
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            err = nf90mpi_inquire_variable(BAD_ID, i, dimids=dimids)
+            if (err .ne. NF90_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inquire_variable(ncid, BAD_VARID, dimids=dimids)
+            if (err .ne. NF90_ENOTVAR) then
+                call errore('bad var id: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inquire_variable(ncid, i, dimids=dimids)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_inquire_variable: ', err)
+            else if (.not.int_vec_eq(var_dimid(1,i), dimids,  &
+                     var_rank(i))) then
+                call error('unexpected dimid')
+                print *, ' for variable ', i
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_varname()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer i
+        integer err
+        character*(NF90_MAX_NAME) name
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            err = nf90mpi_inquire_variable(BAD_ID, i, name)
+            if (err .ne. NF90_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inquire_variable(ncid, BAD_VARID, name)
+            if (err .ne. NF90_ENOTVAR) then
+                call errore('bad var id: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inquire_variable(ncid, i, name)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_inquire_variable: ', err)
+            else if (var_name(i) .ne. name)  then
+                call errorc('name unexpected: ', name)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_varnatts()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer VARID, NATTS
+
+        integer ncid
+        integer i
+        integer err
+        integer na
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 0, numVars    ! start with global attributes
+            err = nf90mpi_inquire_variable(BAD_ID, i, nAtts=na)
+            if (err .ne. NF90_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nf90mpi_inquire_variable(ncid, BAD_VARID, nAtts=na)
+            if (err .ne. NF90_ENOTVAR) then
+                call errore('bad var id: ', err)
+            else
+                nok = nok + 1
+            end if
+            if (i .eq. 0) then
+                err = nf90mpi_inquire(ncid, nAttributes=na)
+            else
+                err = nf90mpi_inquire_variable(ncid, VARID(i), nAtts=na)
+            endif
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_inquire_variable: ', err)
+            else if (NATTS(i) .ne. na) then ! works for global attributes
+                call errori('natts unexpected: ', na)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_varndims()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer i
+        integer err
+        integer ndims
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            err = nf90mpi_inquire_variable(BAD_ID, i, ndims=ndims)
+            if (err .ne. NF90_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nf90mpi_inquire_variable(ncid, BAD_VARID, ndims=ndims)
+            if (err .ne. NF90_ENOTVAR) then
+                call errore('bad var id: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nf90mpi_inquire_variable(ncid, i, ndims=ndims)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_inquire_variable: ', err)
+            else if (var_rank(i) .ne. ndims) then
+                call errori('ndims unexpected: ', ndims)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_vartype()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ncid
+        integer i
+        integer err
+        integer datatype
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 1, i = 1, numVars
+            err = nf90mpi_inquire_variable(BAD_ID, i, xtype=datatype)
+            if (err .ne. NF90_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inquire_variable(ncid, BAD_VARID, xtype=datatype)
+            if (err .ne. NF90_ENOTVAR) then
+                call errore('bad var id: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inquire_variable(ncid, i, xtype=datatype)
+            if (err .NE. NF90_NOERR) then
+                call errore('nf90mpi_inquire_variable: ', err)
+            else if (var_type(i) .ne. datatype) then
+                call errori('type unexpected: ', datatype)
+                nok = nok + 1
+            end if
+1       continue
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_att()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer ATT_TYPE, ATT_LEN, NATTS
+
+        integer ncid, i, j, err, type, nok
+        integer(kind=MPI_OFFSET_KIND) alen
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR)  &
+            call errore('nf90mpi_open: ', err)
+
+        do 1, i = 0, numVars
+            ! NF90_GLOBAL is defined to be 0
+            do 2, j = 1, NATTS(i)
+                err = nf90mpi_inquire_attribute(BAD_ID, i, ATT_NAME(j,i), type, alen)
+                if (err .ne. NF90_EBADID) then
+                    call errore('bad ncid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_inquire_attribute &
+                           (ncid, BAD_VARID, ATT_NAME(j,i), type, alen)
+                if (err .ne. NF90_ENOTVAR) then
+                    call errore('bad var id: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_inquire_attribute(ncid, i, 'noSuch', type, alen)
+                if (err .ne. NF90_ENOTATT) then
+                    call errore('Bad attribute name: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_inquire_attribute(ncid, i, ATT_NAME(j,i), type, alen)
+                if (err .NE. NF90_NOERR) then
+                    call error(nf90mpi_strerror(err))
+                else
+                    if (type .ne. ATT_TYPE(j,i)) then
+                        print*,'ATT_NAME=',trim(ATT_NAME(j,i))
+                        print*,'i=',i,' j=',j,' type=',type,' ATT_TYPE=',ATT_TYPE(j,i)
+                    endif
+                    if (type .ne. ATT_TYPE(j,i)) &
+                        call error('type not that expected')
+                    if (alen .ne. ATT_LEN(j,i))  &
+                        call error('length not that expected')
+                    nok = nok + 1
+                end if
+2           continue
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_attlen()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer ATT_LEN, NATTS
+        character*2 ATT_NAME
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        integer(kind=MPI_OFFSET_KIND) len
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+
+        do 1, i = 0, numVars
+            err = nf90mpi_inquire_attribute(ncid, i, 'noSuch', len=len)
+            if (err .ne. NF90_ENOTATT) then
+                call errore('Bad attribute name: ', err)
+            else
+                nok = nok + 1
+            endif
+            do 2, j = 1, NATTS(i)
+                err = nf90mpi_inquire_attribute(BAD_ID, i,  &
+                   ATT_NAME(j,i), len=len)
+                if (err .ne. NF90_EBADID) then
+                    call errore('bad ncid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_inquire_attribute &
+                      (ncid, BAD_VARID, ATT_NAME(j,i), len=len)
+                if (err .ne. NF90_ENOTVAR) then
+                    call errore('bad varid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_inquire_attribute(ncid, i, ATT_NAME(j,i), len=len)
+                if (err .NE. NF90_NOERR) then
+                    call error(nf90mpi_strerror(err))
+                else
+                    if (len .ne. ATT_LEN(j,i)) &
+                        call error('len not that expected')
+                    nok = nok + 1
+                end if
+2           continue
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_atttype()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer ATT_TYPE, NATTS
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        integer datatype
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+
+        do 1, i = 0, numVars
+            err = nf90mpi_inquire_attribute(ncid, i, 'noSuch', datatype)
+            if (err .ne. NF90_ENOTATT) then
+                call errore('Bad attribute name: ', err)
+            else
+                nok = nok + 1
+            endif
+            do 2, j = 1, NATTS(i)
+                err = nf90mpi_inquire_attribute &
+                      (BAD_ID, i, ATT_NAME(j,i), datatype)
+                if (err .ne. NF90_EBADID) then
+                    call errore('bad ncid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_inquire_attribute(ncid, BAD_VARID, ATT_NAME(j,i),  &
+                                     datatype)
+                if (err .ne. NF90_ENOTVAR) then
+                    call errore('bad varid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_inquire_attribute &
+                      (ncid, i, ATT_NAME(j,i), datatype)
+                if (err .NE. NF90_NOERR) then
+                    call error(nf90mpi_strerror(err))
+                else
+                    if (datatype .ne. ATT_TYPE(j,i)) &
+                        call error('type not that expected')
+                    nok = nok + 1
+                end if
+2           continue
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_attname()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer NATTS
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        character*(NF90_MAX_NAME) name
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+
+        do 1, i = 0, numVars
+            err = nf90mpi_inq_attname(ncid, i, BAD_ATTNUM, name)
+            if (err .ne. NF90_ENOTATT) then
+                call errore('Bad attribute number: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inq_attname(ncid, i, NATTS(i)+1, name)
+            if (err .ne. NF90_ENOTATT) then
+                call errore('Bad attribute number: ', err)
+            else
+                nok = nok + 1
+            endif
+            do 2, j = 1, NATTS(i)
+                err = nf90mpi_inq_attname(BAD_ID, i, j, name)
+                if (err .ne. NF90_EBADID) then
+                    call errore('bad ncid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_inq_attname(ncid, BAD_VARID, j, name)
+                if (err .ne. NF90_ENOTVAR) then
+                    call errore('bad var id: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_inq_attname(ncid, i, j, name)
+                if (err .NE. NF90_NOERR) then
+                    call error(nf90mpi_strerror(err))
+                else
+                    if (ATT_NAME(j,i) .ne. name) &
+                        call error('name not that expected')
+                    nok = nok + 1
+                end if
+2           continue
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nf90mpi_inq_attid()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer NATTS
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        integer attnum
+        integer nok
+
+        nok = 0
+
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info,  &
+                         ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+
+        do 1, i = 0, numVars
+            err = nf90mpi_inquire_attribute(ncid, i, 'noSuch', attnum=attnum)
+            if (err .ne. NF90_ENOTATT) then
+                call errore('Bad attribute name: ', err)
+            else
+                nok = nok + 1
+            endif
+            do 2, j = 1, NATTS(i)
+                err = nf90mpi_inquire_attribute(BAD_ID, i,  &
+                      ATT_NAME(j,i), attnum=attnum)
+                if (err .ne. NF90_EBADID) then
+                    call errore('bad ncid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_inquire_attribute(ncid, BAD_VARID, ATT_NAME(j,i),  &
+                                   attnum=attnum)
+                if (err .ne. NF90_ENOTVAR) then
+                    call errore('bad varid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_inquire_attribute(ncid, i,  &
+                     ATT_NAME(j,i), attnum=attnum)
+                if (err .NE. NF90_NOERR) then
+                    call error(nf90mpi_strerror(err))
+                else
+                    if (attnum .ne. j) &
+                        call error('attnum not that expected')
+                    nok = nok + 1
+                end if
+2           continue
+1       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .NE. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        call print_nok(nok)
+        end
diff --git a/test/nf90_test/test_write.F90 b/test/nf90_test/test_write.F90
new file mode 100644
index 0000000..d879c46
--- /dev/null
+++ b/test/nf90_test/test_write.F90
@@ -0,0 +1,1755 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_write.F90 2011 2015-02-14 19:48:35Z wkliao $
+!
+
+! Test nf90mpi_create
+!    For mode in NF90_NOCLOBBER, NF90_CLOBBER do:
+!       create netcdf file 'scratch.nc' with no data, close it
+!       test that it can be opened, do nf90mpi_inq to check nvars = 0, etc.
+!    Try again in NF90_NOCLOBBER mode, check error return
+! On exit, delete this file
+        subroutine test_nf90mpi_create()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+
+        integer clobber         !/* 0 for NF90_NOCLOBBER, 1 for NF90_CLOBBER */
+        integer err
+        integer ncid
+        integer ndims           !/* number of dimensions */
+        integer nvars           !/* number of variables */
+        integer ngatts          !/* number of global attributes */
+        integer recdim          !/* id of unlimited dimension */
+        integer flags
+        integer nok
+
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        nok = 0
+        do 1, clobber = 0, 1
+            err = nf90mpi_create(comm, scratch, flags,  info, &
+                               ncid)
+            if (err .ne. NF90_NOERR) then
+                call errore('nf90mpi_create: ', err)
+            end if
+            nok = nok + 1
+            err = nf90mpi_close(ncid)
+            if (err .ne. NF90_NOERR) then
+                call errore('nf90mpi_close: ', err)
+            end if
+            err = nf90mpi_open(comm, scratch, NF90_NOWRITE, info,  &
+                             ncid)
+            if (err .ne. NF90_NOERR) then
+                call errore('nf90mpi_open: ', err)
+            end if
+            err = nf90mpi_inquire(ncid, ndims, nvars, ngatts, recdim)
+            if (err .ne. NF90_NOERR) then
+                call errore('nf90mpi_inquire: ', err)
+            else if (ndims .ne. 0) then
+                call errori( &
+                    'nf90mpi_inquire: wrong number of dimensions returned, ', &
+                    ndims)
+            else if (nvars .ne. 0) then
+                call errori( &
+                    'nf90mpi_inquire: wrong number of variables returned, ', &
+                    nvars)
+            else if (ngatts .ne. 0) then
+                call errori( &
+                    'nf90mpi_inquire: wrong number of global atts returned, ', &
+                    ngatts)
+            else if (recdim .ge. 1) then
+                call errori( &
+                    'nf90mpi_inquire: wrong record dimension ID returned, ', &
+                    recdim)
+            end if
+            err = nf90mpi_close(ncid)
+            if (err .ne. NF90_NOERR) then
+                call errore('nf90mpi_close: ', err)
+            end if
+
+            flags = IOR(NF90_CLOBBER, extra_flags)
+1       continue
+
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags,  info, &
+                           ncid)
+        if (err .ne. NF90_EEXIST) then
+            call errore('attempt to overwrite file: ', err)
+        end if
+        nok = nok + 1
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) then
+            call errori('delete of scratch file failed: ', err)
+        end if
+        call print_nok(nok)
+        end
+
+
+! Test nf90mpi_redef 
+! (In fact also tests nf90mpi_enddef - called from test_nf90mpi_enddef)
+!    BAD_ID
+!    attempt redef (error) & enddef on read-only file
+!    create file, define dims & vars. 
+!    attempt put var (error)
+!    attempt redef (error) & enddef.
+!    put vars
+!    attempt def new dims (error)
+!    redef
+!    def new dims, vars.
+!    put atts
+!    enddef
+!    put vars
+!    close
+!    check file: vars & atts
+        subroutine test_nf90mpi_redef()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer         title_len
+        parameter       (title_len = 9)
+
+        integer                 ncid            !/* netcdf id */
+        integer                 dimid           !/* dimension id */
+        integer                 vid             !/* variable id */
+        integer                 err, flags
+        character*(title_len)   title
+        doubleprecision         var
+        character*(NF90_MAX_NAME) name
+        integer(kind=MPI_OFFSET_KIND)                 start(1)
+        integer(kind=MPI_OFFSET_KIND)                 length
+        integer                 intlen
+        integer                 dimids(1)
+        integer                 nok
+
+        nok = 0
+
+        title = 'Not funny'
+
+        ! BAD_ID tests
+        err = nf90mpi_redef(BAD_ID)
+        if (err .ne. NF90_EBADID) then
+            call errore('bad ncid: ', err)
+        endif
+        nok = nok + 1
+        err = nf90mpi_enddef(BAD_ID)
+        if (err .ne. NF90_EBADID) then
+            call errore('bad ncid: ', err)
+        endif
+        nok = nok + 1
+
+        ! read-only tests
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_redef(ncid)
+        if (err .ne. NF90_EPERM) then
+            call errore('nf90mpi_redef in NF90_NOWRITE mode: ', err)
+        endif
+        nok = nok + 1
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_ENOTINDEFINE) then
+            call errore('nf90mpi_redef in NF90_NOWRITE mode: ', err)
+        endif
+        nok = nok + 1
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_close: ', err)
+
+!           /* tests using scratch file */
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+        err = nf90mpi_inq_varid(ncid, 'd', vid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_inq_varid: ', err)
+        var = 1.0
+!       should not enter indep mode in define mode
+        err = nf90mpi_begin_indep_data(ncid)       
+        if (err .ne. NF90_EINDEFINE) &
+          call errore('nf90mpi_begin_indep_data... in define mode: ', err)
+        start = 0
+        err = nf90mpi_put_var(ncid, vid, var, start)
+        if (err .ne. NF90_EINDEFINE) &
+            call errore('nf90mpi_put_var... in define mode: ', err)
+        err = nf90mpi_end_indep_data(ncid)
+        if (err .ne. NF90_ENOTINDEP) &
+          call errore('nf90mpi_end_indep_data... not in indep mode: ', err)
+        err = nf90mpi_redef(ncid)
+        if (err .ne. NF90_EINDEFINE) then
+            call errore('nf90mpi_redef in define mode: ', err)
+        endif
+        nok = nok + 1
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        call put_vars(ncid)
+        length = 8
+        err = nf90mpi_def_dim(ncid, 'abc', length, dimid)
+        if (err .ne. NF90_ENOTINDEFINE) &
+            call errore('nf90mpi_def_dim in define mode: ', err)
+        err = nf90mpi_redef(ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_redef: ', err)
+        endif
+        nok = nok + 1
+        length = 8
+        err = nf90mpi_def_dim(ncid, 'abc', length, dimid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_def_dim: ', err)
+        dimids(1) = 0
+        err = nf90mpi_def_var(ncid, 'abc', NF90_INT, varid=vid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_def_var: ', err)
+        length = len(title)
+        err = nf90mpi_put_att(ncid, NF90_GLOBAL, 'title', &
+                              title)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_put_att: ', err)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        var = 1.0
+        err = nf90mpi_end_indep_data(ncid)
+        if (err .ne. NF90_ENOTINDEP) &
+          call errore('nf90mpi_end_indep_data: in collective mode: ',err)
+        err = nf90mpi_begin_indep_data(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_begin_indep_data: ', err)
+        err = nf90mpi_put_var(ncid, vid, var, start)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_put_var: ', err)
+        err = nf90mpi_end_indep_data(ncid)       
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_end_indep_data: ', err)
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_close: ', err)
+
+!           /* check scratch file written as expected */
+        call check_file(scratch)
+        err = nf90mpi_open(comm, scratch, NF90_NOWRITE, &
+              info, ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_inquire_dimension(ncid, dimid, name, length)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_inquire_dimension: ', err)
+        if (name .ne. "abc") &
+            call errori('Unexpected dim name in netCDF ', ncid)
+        if (length .ne. 8) then
+            intlen = INT(length)
+            call errori('Unexpected dim length: ', intlen)
+        end if
+        err = nf90mpi_begin_indep_data(ncid)
+        err = nf90mpi_get_var(ncid, vid, var, start)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_get_var: ', err)
+        if (var .ne. 1.0) &
+            call errori( &
+                'nf90mpi_get_var: unexpected value in netCDF ' &
+                , ncid)
+        err = nf90mpi_end_indep_data(ncid)
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errori('delete failed for netCDF: ', err)
+        call print_nok(nok)
+        end
+
+! Test nf90mpi_enddef 
+! Simply calls test_nf90mpi_redef which tests both nf90mpi_redef & nf90mpi_enddef
+
+        subroutine test_nf90mpi_enddef()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+
+        call test_nf90mpi_redef
+        end
+
+
+! Test nf90mpi_sync
+!    try with bad handle, check error
+!    try in define mode, check error
+!    try writing with one handle, reading with another on same netCDF
+        subroutine test_nf90mpi_sync()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+
+        integer ncidw         !/* netcdf id for writing */
+        integer ncidr         !/* netcdf id for reading */
+        integer err, flags
+        integer nok
+
+        nok = 0
+!           /* BAD_ID test */
+        err = nf90mpi_sync(BAD_ID)
+        if (err .ne. NF90_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+
+!           /* create scratch file & try nf90mpi_sync in define mode */
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncidw)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        err = nf90mpi_sync(ncidw)
+        if (err .ne. NF90_EINDEFINE) then
+            call errore('nf90mpi_sync called in define mode: ', err)
+        else
+            nok = nok + 1
+        endif
+
+!           /* write using same handle */
+        call def_dims(ncidw)
+        call def_vars(ncidw)
+        call put_atts(ncidw)
+        err = nf90mpi_enddef(ncidw)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        call put_vars(ncidw)
+        err = nf90mpi_sync(ncidw)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_sync of ncidw failed: ', err)
+        else
+            nok = nok + 1
+        endif
+
+!           /* open another handle, nf90mpi_sync, read (check) */
+        err = nf90mpi_open(comm, scratch, NF90_NOWRITE, info, &
+                         ncidr)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_sync(ncidr)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_sync of ncidr failed: ', err)
+        else
+            nok = nok + 1
+        endif
+        call check_dims(ncidr)
+        call check_atts(ncidr)
+        call check_vars(ncidr)
+
+!           /* close both handles */
+        err = nf90mpi_close(ncidr)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        err = nf90mpi_close(ncidw)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errori('delete of scratch file failed: ', err)
+        call print_nok(nok)
+        end
+
+
+! Test nf90mpi_abort
+!    try with bad handle, check error
+!    try in define mode before anything written, check that file was deleted
+!    try after nf90mpi_enddef, nf90mpi_redef, define new dims, vars, atts
+!    try after writing variable
+        subroutine test_nf90mpi_abort()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+
+        integer ncid          !/* netcdf id */
+        integer err, flags
+        integer ndims
+        integer nvars
+        integer ngatts
+        integer recdim
+        integer nok
+
+        nok = 0
+
+!           /* BAD_ID test */
+        err = nf90mpi_abort(BAD_ID)
+        if (err .ne. NF90_EBADID) then
+            call errore('bad ncid: status = ', err)
+        else
+            nok = nok + 1
+        endif
+
+!           /* create scratch file & try nf90mpi_abort in define mode */
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+        err = nf90mpi_abort(ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_abort of ncid failed: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_close(ncid)    !/* should already be closed */
+        if (err .ne. NF90_EBADID) &
+            call errore('bad ncid: ', err)
+        err = nf90mpi_delete(scratch, info)    !/* should already be deleted */
+        if (err .eq. NF90_NOERR) &
+            call errori('scratch file should not exist: ', err)
+
+!            create scratch file
+!            do nf90mpi_enddef & nf90mpi_redef
+!            define new dims, vars, atts
+!            try nf90mpi_abort: should restore previous state (no dims, vars, atts)
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        err = nf90mpi_redef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_redef: ', err)
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+        err = nf90mpi_abort(ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_abort of ncid failed: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_close(ncid)    !/* should already be closed */
+        if (err .ne. NF90_EBADID) &
+            call errore('bad ncid: ', err)
+        err = nf90mpi_open(comm, scratch, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_inquire(ncid, ndims, nvars, ngatts, recdim)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_inquire: ', err)
+        if (ndims .ne. 0) &
+            call errori('ndims should be ', 0)
+        if (nvars .ne. 0) &
+            call errori('nvars should be ', 0)
+        if (ngatts .ne. 0) &
+            call errori('ngatts should be ', 0)
+        err = nf90mpi_close (ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+
+!           /* try nf90mpi_abort in data mode - should just close */
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        call put_vars(ncid)
+        err = nf90mpi_abort(ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_abort of ncid failed: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_close(ncid)       !/* should already be closed */
+        if (err .ne. NF90_EBADID) &
+            call errore('bad ncid: ', err)
+        call check_file(scratch)
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errori('delete of scratch file failed: ', err)
+        call print_nok(nok)
+        end
+
+
+! Test nf90mpi_def_dim
+!    try with bad netCDF handle, check error
+!    try in data mode, check error
+!    check that returned id is one more than previous id
+!    try adding same dimension twice, check error
+!    try with illegal sizes, check error
+!    make sure unlimited size works, shows up in nf90mpi_inq_unlimdim
+!    try to define a second unlimited dimension, check error
+        subroutine test_nf90mpi_def_dim()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+
+        integer ncid
+        integer err             !/* status */
+        integer i
+        integer dimid         !/* dimension id */
+        integer(kind=MPI_OFFSET_KIND) length
+        integer nok, flags
+
+        nok = 0
+
+!           /* BAD_ID test */
+        length = 8
+        err = nf90mpi_def_dim(BAD_ID, 'abc', length, dimid)
+        if (err .ne. NF90_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+
+!           /* data mode test */
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        length = 8
+        err = nf90mpi_def_dim(ncid, 'abc', length, dimid)
+        if (err .ne. NF90_ENOTINDEFINE) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+
+!           /* define-mode tests: unlimited dim */
+        err = nf90mpi_redef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_redef: ', err)
+        err = nf90mpi_def_dim(ncid, dim_name(1), NF90MPI_UNLIMITED, dimid)
+        if (err .ne. NF90_NOERR)  then
+            call errore('nf90mpi_def_dim: ', err)
+        else
+            nok = nok + 1
+        endif
+        if (dimid .ne. 1)  &
+            call errori('Unexpected dimid: ', dimid)
+        err = nf90mpi_inquire(ncid, unlimitedDimId=dimid)
+        if (err .ne. NF90_NOERR)  &
+            call errore('nf90mpi_inquire: ', err)
+        if (dimid .ne. RECDIM)  &
+            call error('Unexpected recdim: ')
+        err = nf90mpi_inquire_dimension(ncid, dimid, len=length)
+        if (length .ne. 0)  &
+            call errori('Unexpected length: ', 0)
+        err = nf90mpi_def_dim(ncid, 'abc', NF90MPI_UNLIMITED, dimid)
+        if (err .ne. NF90_EUNLIMIT) then
+            call errore('2nd unlimited dimension: ', err)
+        else
+            nok = nok + 1
+        endif
+
+!           /* define-mode tests: remaining dims */
+        do 1, i = 2, NDIMS
+            err = nf90mpi_def_dim(ncid, dim_name(i-1), dim_len(i),  &
+                             dimid)
+            if (err .ne. NF90_ENAMEINUSE) then
+                call errore('duplicate name: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_def_dim(ncid, BAD_NAME, dim_len(i), dimid)
+            if (err .ne. NF90_EBADNAME) then
+                call errore('bad name: ', err)
+            else
+                nok = nok + 1
+            endif
+            length = NF90MPI_UNLIMITED - 1
+            err = nf90mpi_def_dim(ncid, dim_name(i), length, &
+                             dimid)
+            if (err .ne. NF90_EDIMSIZE) then
+                call errore('bad size: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_def_dim(ncid, dim_name(i), dim_len(i), dimid)
+            if (err .ne. NF90_NOERR)  then
+                call errore('nf90mpi_def_dim: ', err)
+            else
+                nok = nok + 1
+            endif
+            if (dimid .ne. i)  &
+                call errori('Unexpected dimid: ', 0)
+1       continue
+
+!           /* Following just to expand unlimited dim */
+        call def_vars(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        call put_vars(ncid)
+
+!           /* Check all dims */
+        call check_dims(ncid)
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errori('delete of scratch file failed: ', err)
+        call print_nok(nok)
+        end
+
+
+! Test nf90mpi_rename_dim
+!    try with bad netCDF handle, check error
+!    check that proper rename worked with nf90mpi_inquire_dimension
+!    try renaming to existing dimension name, check error
+!    try with bad dimension handle, check error
+        subroutine test_nf90mpi_rename_dim()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+
+        integer ncid
+        integer err             !/* status */
+        character*(NF90_MAX_NAME) name
+        integer nok, flags
+
+        nok = 0
+
+!           /* BAD_ID test */
+        err = nf90mpi_rename_dim(BAD_ID, 1, 'abc')
+        if (err .ne. NF90_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+
+!           /* main tests */
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        err = nf90mpi_rename_dim(ncid, BAD_DIMID, 'abc')
+        if (err .ne. NF90_EBADDIM) then
+            call errore('bad dimid: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_rename_dim(ncid, 3, 'abc')
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_rename_dim: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_inquire_dimension(ncid, 3, name)
+        if (name .ne. 'abc') &
+            call errorc('Unexpected name: ', name)
+        err = nf90mpi_rename_dim(ncid, 1, 'abc')
+        if (err .ne. NF90_ENAMEINUSE) then
+            call errore('duplicate name: ', err)
+        else
+            nok = nok + 1
+        endif
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errori('delete of scratch file failed: ', err)
+        call print_nok(nok)
+        end
+
+
+! Test nf90mpi_def_var
+!    try with bad netCDF handle, check error
+!    try with bad name, check error
+!    scalar tests:
+!      check that proper define worked with nf90mpi_inq_var
+!      try redefining an existing variable, check error
+!      try with bad datatype, check error
+!      try with bad number of dimensions, check error
+!      try in data mode, check error
+!    check that returned id is one more than previous id
+!    try with bad dimension ids, check error
+        subroutine test_nf90mpi_def_var()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+
+        integer ncid
+        integer vid
+        integer err             !/* status */
+        integer i
+        integer ndims
+        integer na
+        character*(NF90_MAX_NAME) name
+        integer dimids(MAX_RANK)
+        integer datatype
+        integer nok, flags
+
+        nok = 0
+
+!           /* BAD_ID test */
+        err = nf90mpi_def_var(BAD_ID, 'abc', NF90_SHORT, varid=vid)
+        if (err .ne. NF90_EBADID) then
+            call errore('bad ncid: status = ', err)
+        else
+            nok = nok + 1
+        endif
+
+!       scalar tests
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        err = nf90mpi_def_var(ncid, 'abc', NF90_SHORT, varid=vid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_def_var: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_inquire_variable(ncid, vid, name, datatype, ndims, dimids,  &
+                         na)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_inquire_variable: ', err)
+        if (name .ne. 'abc') &
+            call errorc('Unexpected name: ', name)
+        if (datatype .ne. NF90_SHORT) &
+            call error('Unexpected datatype')
+        if (ndims .ne. 0) &
+            call error('Unexpected rank')
+        err = nf90mpi_def_var(ncid, BAD_NAME, NF90_SHORT, varid=vid)
+        if (err .ne. NF90_EBADNAME) then
+            call errore('bad name: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_def_var(ncid, 'abc', NF90_SHORT, varid=vid)
+        if (err .ne. NF90_ENAMEINUSE) then
+            call errore('duplicate name: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_def_var(ncid, 'ABC', BAD_TYPE, varid=vid)
+        if (err .ne. NF90_EBADTYPE) then
+            call errore('bad type: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        err = nf90mpi_def_var(ncid, 'ABC', NF90_SHORT, varid=vid)
+        if (err .ne. NF90_ENOTINDEFINE) then
+            call errore('nf90mpi_def_var called in data mode: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed: ', scratch)
+
+!           /* general tests using global vars */
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        do 1, i = 1, numVars
+            err = nf90mpi_def_var(ncid, var_name(i), var_type(i),  &
+                             var_dimid(1:var_rank(i),i), vid)
+            if (err .ne. NF90_NOERR)  then
+                call errore('nf90mpi_def_var: ', err)
+            else
+                nok = nok + 1
+            endif
+            if (vid .ne. i) &
+                call error('Unexpected varid')
+1       continue
+
+!           /* try bad dim ids */
+        dimids(1) = BAD_DIMID
+        err = nf90mpi_def_var(ncid, 'abc', NF90_SHORT, dimids(1:1), vid)
+        if (err .ne. NF90_EBADDIM) then
+            call errore('bad dim ids: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed: ', scratch)
+        call print_nok(nok)
+        end
+
+
+! Test nf90mpi_rename_var
+!    try with bad netCDF handle, check error
+!    try with bad variable handle, check error
+!    try renaming to existing variable name, check error
+!    check that proper rename worked with nf90mpi_inq_varid
+!    try in data mode, check error
+        subroutine test_nf90mpi_rename_var()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+
+        integer ncid
+        integer vid
+        integer err
+        integer i
+        character*(NF90_MAX_NAME) name
+        integer nok, flags
+
+        nok = 0
+
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        err = nf90mpi_rename_var(ncid, BAD_VARID, 'newName')
+        if (err .ne. NF90_ENOTVAR) then
+            call errore('bad var id: ', err)
+        else
+            nok = nok + 1
+        endif
+        call def_dims(ncid)
+        call def_vars(ncid)
+
+!           /* Prefix "new_" to each name */
+        do 1, i = 1, numVars
+            err = nf90mpi_rename_var(BAD_ID, i, 'newName')
+            if (err .ne. NF90_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_rename_var(ncid, i, var_name(numVars))
+            if (err .ne. NF90_ENAMEINUSE) then
+                call errore('duplicate name: ', err)
+            else
+                nok = nok + 1
+            endif
+            name = 'new_' // var_name(i)
+            err = nf90mpi_rename_var(ncid, i, name)
+            if (err .ne. NF90_NOERR) then
+                call errore('nf90mpi_rename_var: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inq_varid(ncid, name, vid)
+            if (err .ne. NF90_NOERR) &
+                call errore('nf90mpi_inq_varid: ', err)
+            if (vid .ne. i) &
+                call error('Unexpected varid')
+1       continue
+
+!           /* Change to data mode */
+!           /* Try making names even longer. Then restore original names */
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        do 2, i = 1, numVars
+            name = 'even_longer_' // var_name(i)
+            err = nf90mpi_rename_var(ncid, i, name)
+            if (err .ne. NF90_ENOTINDEFINE) then
+                call errore('longer name in data mode: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_rename_var(ncid, i, var_name(i))
+            if (err .ne. NF90_NOERR) then
+                call errore('nf90mpi_rename_var: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nf90mpi_inq_varid(ncid, var_name(i), vid)
+            if (err .ne. NF90_NOERR) &
+                call errore('nf90mpi_inq_varid: ', err)
+            if (vid .ne. i) &
+                call error('Unexpected varid')
+2       continue
+
+        call put_vars(ncid)
+        call check_vars(ncid)
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed: ', scratch)
+        call print_nok(nok)
+        end
+
+
+! Test nf90mpi_copy_att
+!    try with bad source or target netCDF handles, check error
+!    try with bad source or target variable handle, check error
+!    try with nonexisting attribute, check error
+!    check that NF90_GLOBAL variable for source or target works
+!    check that new attribute put works with target in define mode
+!    check that old attribute put works with target in data mode
+!    check that changing type and length of an attribute work OK
+!    try with same ncid for source and target, different variables
+!    try with same ncid for source and target, same variable
+        subroutine test_nf90mpi_copy_att()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer VARID, NATTS, ATT_LEN
+
+        integer ncid_in
+        integer ncid_out
+        integer vid
+        integer err
+        integer i
+        integer j
+        character*(NF90_MAX_NAME) name    !/* of att */
+        integer datatype                !/* of att */
+        integer(kind=MPI_OFFSET_KIND) length                  !/* of att */
+        character*1     value
+        integer nok, flags
+
+        nok = 0
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid_in)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid_out)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid_out)
+        call def_vars(ncid_out)
+
+        do 1, i = 0, numVars
+            vid = VARID(i)
+            do 2, j = 1, NATTS(i)
+                name = ATT_NAME(j,i)
+                err = nf90mpi_copy_att(ncid_in, BAD_VARID, name, &
+                                      ncid_out, vid)
+                if (err .ne. NF90_ENOTVAR) &
+                    call errore('bad var id: ', err)
+                nok = nok + 1
+                err = nf90mpi_copy_att(ncid_in, vid, name, ncid_out,  &
+                                  BAD_VARID)
+                if (err .ne. NF90_ENOTVAR) &
+                    call errore('bad var id: ', err)
+                nok = nok + 1
+                err = nf90mpi_copy_att(BAD_ID, vid, name,  &
+                      ncid_out, vid)
+                if (err .ne. NF90_EBADID) &
+                    call errore('bad ncid: ', err)
+                nok = nok + 1
+                err = nf90mpi_copy_att(ncid_in, vid, name,  &
+                      BAD_ID, vid)
+                if (err .ne. NF90_EBADID) &
+                    call errore('bad ncid: ', err)
+                nok = nok + 1
+                err = nf90mpi_copy_att(ncid_in, vid, 'noSuch', &
+                                      ncid_out, vid)
+                if (err .ne. NF90_ENOTATT) &
+                    call errore('bad attname: ', err)
+                nok = nok + 1
+                err = nf90mpi_copy_att(ncid_in, vid, name,  &
+                       ncid_out, vid)
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_copy_att: ', err)
+                nok = nok + 1
+                err = nf90mpi_copy_att(ncid_out, vid, name, &
+                                      ncid_out, vid)
+                if (err .ne. NF90_NOERR) &
+                    call errore('source = target: ', err)
+                nok = nok + 1
+2           continue
+1       continue
+
+        err = nf90mpi_close(ncid_in)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+
+!           /* Close scratch. Reopen & check attributes */
+        err = nf90mpi_close(ncid_out)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        err = nf90mpi_open(comm, scratch, NF90_WRITE, info, &
+                         ncid_out)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        call check_atts(ncid_out)
+
+!           change to define mode
+!           define single char. global att. ':a' with value 'A'
+!           This will be used as source for following copies
+        err = nf90mpi_redef(ncid_out)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_redef: ', err)
+        length = 1
+        err = nf90mpi_put_att(ncid_out, NF90_GLOBAL, 'a', 'A')
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_put_att: ', err)
+
+!           change to data mode
+!           Use scratch as both source & dest.
+!           try copy to existing att. change type & decrease length
+!           rename 1st existing att of each var (if any) 'a'
+!           if this att. exists them copy ':a' to it
+        err = nf90mpi_enddef(ncid_out)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        do 3, i = 1, numVars
+            if (NATTS(i) .gt. 0 .and. ATT_LEN(1,i) .gt. 0) then
+                err = nf90mpi_rename_att(ncid_out, i,  &
+                      att_name(1,i), 'a')
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_rename_att: ', err)
+                err = nf90mpi_copy_att(ncid_out, NF90_GLOBAL, 'a', &
+                                      ncid_out, i)
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_copy_att: ', err)
+                nok = nok + 1
+            end if
+3       continue
+        err = nf90mpi_close(ncid_out)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+
+!           /* Reopen & check */
+        err = nf90mpi_open(comm, scratch, NF90_WRITE, info, &
+                         ncid_out)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        do 4, i = 1, numVars
+            if (NATTS(i) .gt. 0 .and. ATT_LEN(1,i) .gt. 0) then
+                err = nf90mpi_inquire_attribute(ncid_out, i, 'a',  &
+                      datatype, length)
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_inquire_attribute: ', err)
+                if (datatype .ne. NF90_CHAR) &
+                    call error('Unexpected type')
+                if (length .ne. 1) &
+                    call error('Unexpected length')
+                err = nf90mpi_get_att(ncid_out, i, 'a', value)
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_get_att: ', err)
+                if (value .ne. 'A') &
+                    call error('Unexpected value')
+            end if                                                   
+4       continue                                                   
+
+        err = nf90mpi_close(ncid_out)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errorc('delete of scratch file failed', scratch)
+        call print_nok(nok)
+        end
+
+
+! Test nf90mpi_rename_att
+!    try with bad netCDF handle, check error
+!    try with bad variable handle, check error
+!    try with nonexisting att name, check error
+!    try renaming to existing att name, check error
+!    check that proper rename worked with nf90mpi_inq_attid
+!    try in data mode, check error
+        subroutine test_nf90mpi_rename_att()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer VARID, ATT_TYPE, NATTS, ATT_LEN
+        double precision hash
+        logical equal, inrange
+
+        integer ncid
+        integer vid
+        integer err, flags
+        integer i
+        integer j
+        integer  k
+        integer attnum
+        character*(NF90_MAX_NAME) atnam
+        character*(NF90_MAX_NAME) name
+        character*(NF90_MAX_NAME) oldname
+        character*(NF90_MAX_NAME) newname
+        integer nok             !/* count of valid comparisons */
+        integer datatype
+        integer attyp
+        integer(kind=MPI_OFFSET_KIND) length
+        integer(kind=MPI_OFFSET_KIND) attlength
+        integer(kind=MPI_OFFSET_KIND) ndx(1)
+        character*(MAX_NELS)    text
+        doubleprecision value(MAX_NELS)
+        doubleprecision expect
+
+        nok = 0
+
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        err = nf90mpi_rename_att(ncid, BAD_VARID, 'abc', 'newName')
+        if (err .ne. NF90_ENOTVAR) &
+            call errore('bad var id: ', err)
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+
+        do 1, i = 0, numVars
+            vid = VARID(i)
+            do 2, j = 1, NATTS(i)
+                atnam = ATT_NAME(j,i)
+                err = nf90mpi_rename_att(BAD_ID, vid, atnam,  &
+                       'newName')
+                if (err .ne. NF90_EBADID) &
+                    call errore('bad ncid: ', err)
+                err = nf90mpi_rename_att(ncid, vid, 'noSuch',  &
+                        'newName')
+                if (err .ne. NF90_ENOTATT) &
+                    call errore('bad attname: ', err)
+                newname = 'new_' // trim(atnam)
+                err = nf90mpi_rename_att(ncid, vid, atnam, newname)
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_rename_att: ', err)
+                err = nf90mpi_inquire_attribute(ncid, vid, newname, attnum=attnum)
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_inquire_attribute: ', err)
+                if (attnum .ne. j) &
+                    call error('Unexpected attnum')
+2           continue
+1       continue
+
+!           /* Close. Reopen & check */
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        err = nf90mpi_open(comm, scratch, NF90_WRITE, info,  &
+            ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+
+        do 3, i = 0, numVars
+            vid = VARID(i)
+            do 4, j = 1, NATTS(i)
+                atnam = ATT_NAME(j,i)
+                attyp = ATT_TYPE(j,i)
+                attlength = ATT_LEN(j,i)
+                newname = 'new_' // trim(atnam)
+                err = nf90mpi_inq_attname(ncid, vid, j, name)
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_inq_attname: ', err)
+                if (name .ne. newname) &
+                    call error('nf90mpi_inq_attname: unexpected name')
+                err = nf90mpi_inquire_attribute(ncid, vid, name,  &
+                    datatype, length)
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_inquire_attribute: ', err)
+                if (datatype .ne. attyp) &
+                    call error('nf90mpi_inquire_attribute: unexpected type')
+                if (length .ne. attlength) &
+                    call error('nf90mpi_inquire_attribute: unexpected length')
+                if (datatype .eq. NF90_CHAR) then
+                    err = nf90mpi_get_att(ncid, vid, name, text)
+                    if (err .ne. NF90_NOERR) &
+                        call errore('nf90mpi_get_att: ', err)
+                    do 5, k = 1, INT(attlength)
+                        ndx(1) = k
+                        expect = hash(datatype, -1, ndx)
+                        if (ichar(text(k:k)) .ne. expect) then
+                            call error( &
+                                'nf90mpi_get_att: unexpected value')
+                        else
+                            nok = nok + 1
+                        end if
+5                   continue
+                else
+                    err = nf90mpi_get_att(ncid, vid, name,  &
+                           value)
+                    if (err .ne. NF90_NOERR) &
+                        call errore('nf90mpi_get_att: ', err)
+                    do 6, k = 1, INT(attlength)
+                        ndx(1) = k
+                        expect = hash(datatype, -1, ndx)
+                        if (inRange(expect, datatype)) then
+                            if (.not. equal(value(k),expect,datatype, &
+                                            NF90_DOUBLE)) then
+                                call error( &
+                              'nf90mpi_get_att: unexpected value')
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+6                   continue
+                end if
+4           continue
+3       continue
+        call print_nok(nok)
+
+!           /* Now in data mode */
+!           /* Try making names even longer. Then restore original names */
+
+        do 7, i = 0, numVars
+            vid = VARID(i)
+            do 8, j = 1, NATTS(i)
+                atnam = ATT_NAME(j,i)
+                oldname = 'new_' // trim(atnam)
+                newname = 'even_longer_' // trim(atnam)
+                err = nf90mpi_rename_att(ncid, vid, oldname, newname)
+                if (err .ne. NF90_ENOTINDEFINE) &
+                    call errore('longer name in data mode: ', err)
+                err = nf90mpi_rename_att(ncid, vid, oldname, atnam)
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_rename_att: ', err)
+                err = nf90mpi_inquire_attribute(ncid, vid, atnam, attnum=attnum)
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_inquire_attribute: ', err)
+                if (attnum .ne. j) &
+                    call error('Unexpected attnum')
+8           continue
+7       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errori('delete of scratch file failed: ', err)
+        end
+
+
+! Test nf90mpi_del_att
+!    try with bad netCDF handle, check error
+!    try with bad variable handle, check error
+!    try with nonexisting att name, check error
+!    check that proper delete worked using:
+!      nf90mpi_inq_attid, nf90mpi_inq_natts, nf90mpi_inq_varnatts
+        subroutine test_nf90mpi_del_att()
+        use pnetcdf
+        implicit        none
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer VARID, NATTS
+
+        integer ncid
+        integer err, flags
+        integer i
+        integer j
+        integer attnum
+        integer na
+        integer numatts
+        integer vid
+        character*(NF90_MAX_NAME)  name           !/* of att */
+        integer nok             !/* count of valid comparisons */
+
+        nok = 0
+
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        err = nf90mpi_del_att(ncid, BAD_VARID, 'abc')
+        if (err .ne. NF90_ENOTVAR) then
+            call errore('bad var id: ', err)
+        else
+            nok = nok + 1
+        endif
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+
+        do 1, i = 0, numVars
+            vid = VARID(i)
+            numatts = NATTS(i)
+            do 2, j = 1, numatts
+                name = ATT_NAME(j,i)
+                err = nf90mpi_del_att(BAD_ID, vid, name)
+                if (err .ne. NF90_EBADID) then
+                    call errore('bad ncid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_del_att(ncid, vid, 'noSuch')
+                if (err .ne. NF90_ENOTATT) then
+                    call errore('bad attname: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_del_att(ncid, vid, name)
+                if (err .ne. NF90_NOERR) then
+                    call errore('nf90mpi_del_att: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nf90mpi_inquire_attribute(ncid, vid, name, attnum=attnum)
+                if (err .ne. NF90_ENOTATT) &
+                    call errore('bad attname: ', err)
+                if (i .lt. 1) then
+                    err = nf90mpi_inquire(ncid, nAttributes=na)
+                    if (err .ne. NF90_NOERR) &
+                        call errore('nf90mpi_inquire: ', err)
+                    if (na .ne. numatts-j) then
+                        call errori('natts: expected: ', numatts-j)
+                        call errori('natts: got:      ', na)
+                    endif
+                else
+                    err = nf90mpi_inquire_variable(ncid, vid, nAtts=na)
+                    if (err .ne. NF90_NOERR) &
+                        call errore('nf90mpi_inquire_variable: ', err)
+                    if (na .ne. numatts-j) then
+                        call errori('natts: expected: ', numatts-j)
+                        call errori('natts: got:      ', na)
+                    endif
+                endif
+2           continue
+1       continue
+
+!           /* Close. Reopen & check no attributes left */
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        err = nf90mpi_open(comm, scratch, NF90_WRITE,  &
+           info, ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_inquire(ncid, nAttributes=na)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_inquire: ', err)
+        if (na .ne. 0) &
+            call errori('natts: expected 0, got ', na)
+        do 3, i = 0, numVars
+            vid = VARID(i)
+            err = nf90mpi_inquire(ncid, nAttributes=na)
+            if (err .ne. NF90_NOERR) &
+                call errore('nf90mpi_inquire: ', err)
+            if (na .ne. 0) &
+                call errori('natts: expected 0, got ', na)
+3       continue
+
+!           /* restore attributes. change to data mode. try to delete */
+        err = nf90mpi_redef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_redef: ', err)
+        call put_atts(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+
+        do 4, i = 0, numVars
+            vid = VARID(i)
+            numatts = NATTS(i)
+            do 5, j = 1, numatts
+                name = ATT_NAME(j,i)
+                err = nf90mpi_del_att(ncid, vid, name)
+                if (err .ne. NF90_ENOTINDEFINE) then
+                    call errore('in data mode: ', err)
+                else
+                    nok = nok + 1
+                endif
+5           continue
+4       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errori('delete of scratch file failed: ', err)
+        call print_nok(nok)
+        end
+
+! parallel-netcdf doesn't implement set_fill, so i have not
+!    parallel-netcdfified this subroutine
+! Test nf90mpi_set_fill
+!    try with bad netCDF handle, check error
+!    try in read-only mode, check error
+!    try with bad new_fillmode, check error
+!    try in data mode, check error
+!    check that proper set to NF90_FILL works for record & non-record variables
+!    (note that it is not possible to test NF90_NOFILL mode!)
+!    close file & create again for test using attribute _FillValue
+        subroutine test_nf90mpi_set_fill()
+        use pnetcdf
+        implicit none
+#include "tests.inc"
+        ! character*2 ATT_NAME
+        ! integer VARID, ATT_TYPE, NATTS
+
+        integer ncid
+        integer vid
+        integer err, flags
+        integer i
+        integer j
+        integer old_fillmode
+        character*1 text
+        doubleprecision value
+        doubleprecision fill, fills(1)
+        integer(kind=MPI_OFFSET_KIND) index(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND) length
+        integer index2indexes
+        integer nok             !/* count of valid comparisons */
+
+        value = 0
+        nok = 0
+
+!           /* bad ncid */
+        err = nf90mpi_set_fill(BAD_ID, NF90_NOFILL, old_fillmode)
+        if (err .ne. NF90_EBADID) &
+            call errore('bad ncid: ', err)
+
+!           /* try in read-only mode */
+        err = nf90mpi_open(comm, testfile, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_open: ', err)
+        err = nf90mpi_set_fill(ncid, NF90_NOFILL, old_fillmode)
+        if (err .ne. NF90_EPERM) &
+            call errore('read-only: ', err)
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+
+!           /* create scratch */
+        flags = IOR(NF90_NOCLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+
+!           /* BAD_FILLMODE */
+        err = nf90mpi_set_fill(ncid, BAD_FILLMODE, old_fillmode)
+        if (err .ne. NF90_EINVAL) &
+            call errore('bad fillmode: ', err)
+
+!           /* proper calls */
+        err = nf90mpi_set_fill(ncid, NF90_FILL, old_fillmode)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_set_fill: ', err)
+        if (old_fillmode .ne. NF90_NOFILL) &
+            call errori('Unexpected old fill mode: ', old_fillmode)
+        err = nf90mpi_set_fill(ncid, NF90_NOFILL, old_fillmode)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_set_fill: ', err)
+        if (old_fillmode .ne. NF90_FILL) &
+            call errori('Unexpected old fill mode: ', old_fillmode)
+        err = nf90mpi_set_fill(ncid, NF90_FILL, old_fillmode)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_set_fill: ', err)
+
+!           /* define dims & vars */
+        call def_dims(ncid)
+        call def_vars(ncid)
+
+!           /* Change to data mode. Set fillmode again */
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        err = nf90mpi_set_fill(ncid, NF90_FILL, old_fillmode)
+        if (err .ne. NF90_ENOTINDEFINE) &
+            call errore('nf90mpi_set_fill: ', err)
+
+!       /* Write record number NRECS to force writing of preceding records */
+!       /* Assumes variable cr is char vector with UNLIMITED dimension */
+        err = nf90mpi_inq_varid(ncid, 'cr', vid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_inq_varid: ', err)
+        index(1) = NRECS
+        text = char(NF90_FILL_CHAR)
+        err = nf90mpi_put_var_all(ncid, vid, text, index)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_put_var_all: ', err)
+
+!           /* get all variables & check all values equal default fill */
+        do 1, i = 1, numVars
+            if (var_dimid(var_rank(i),i) .eq. RECDIM) cycle ! skip record variables
+
+            if (var_type(i) .eq. NF90_CHAR) then
+                fill = NF90_FILL_CHAR
+            else if (var_type(i) .eq. NF90_BYTE) then
+                fill = NF90_FILL_BYTE
+            else if (var_type(i) .eq. NF90_SHORT) then
+                fill = NF90_FILL_SHORT
+            else if (var_type(i) .eq. NF90_INT) then
+                fill = NF90_FILL_INT
+            else if (var_type(i) .eq. NF90_FLOAT) then
+                fill = NF90_FILL_FLOAT
+            else if (var_type(i) .eq. NF90_DOUBLE) then
+                fill = NF90_FILL_DOUBLE
+            else if (var_type(i) .eq. NF90_UBYTE) then
+                fill = NF90_FILL_UBYTE
+            else if (var_type(i) .eq. NF90_USHORT) then
+                fill = NF90_FILL_USHORT
+            else if (var_type(i) .eq. NF90_UINT) then
+                fill = NF90_FILL_UINT
+            else if (var_type(i) .eq. NF90_INT64) then
+                fill = NF90_FILL_INT64
+            else if (var_type(i) .eq. NF90_UINT64) then
+                fill = NF90_FILL_UINT64
+            else
+                stop 'test_nf90mpi_set_fill(): impossible var_type(i)'
+            end if
+
+            do 2, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                    index)
+                if (err .ne. NF90_NOERR) &
+                    call error('error in index2indexes()')
+                if (var_type(i) .eq. NF90_CHAR) then
+                    err = nf90mpi_get_var_all(ncid, i, text, index)
+                    if (err .ne. NF90_NOERR) &
+                        call errore('nf90mpi_get_var_all failed: ',err)
+                    value = ichar(text)
+                else
+                    err = nf90mpi_get_var_all(ncid, i, value, index)
+                    if (err .ne. NF90_NOERR) &
+                        call errore &
+                                 ('nf90mpi_get_var_all failed: ',err)
+                end if
+                if (value .ne. fill .and.  &
+                    abs((fill - value)/fill) .gt. 1.0e-9) then
+                    call errord('Unexpected fill value: ', value)
+                else
+                    nok = nok + 1
+                end if
+2           continue
+1       continue
+
+!       /* close scratch & create again for test using attribute _FillValue */
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, scratch, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+
+!           /* set _FillValue = 42 for all vars */
+        fill = 42
+        text = char(int(fill))
+        length = 1
+        do 3, i = 1, numVars
+            if (var_dimid(var_rank(i),i) .eq. RECDIM) cycle ! skip record variables
+
+            if (var_type(i) .eq. NF90_CHAR) then
+                err = nf90mpi_put_att(ncid, i, '_FillValue', &
+                   text)
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_put_att: ', err)
+            else
+                ! cannot use overloading, as fill's type must match with variable's
+                ! err = nf90mpi_put_att(ncid, i, '_FillValue', fill)
+                fills(1) = fill
+                err = nfmpi_put_att_double(ncid, i, '_FillValue', &
+                                           var_type(i),length,fills(1))
+                if (err .ne. NF90_NOERR) &
+                    call errore('nf90mpi_put_att: ', err)
+            end if
+3       continue
+
+!           /* data mode. write records */
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_enddef: ', err)
+        index(1) = NRECS
+        err = nf90mpi_put_var_all(ncid, vid, text, index)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_put_var_all: ', err)
+
+!           /* get all variables & check all values equal 42 */
+        do 4, i = 1, numVars
+            if (var_dimid(var_rank(i),i) .eq. RECDIM) cycle ! skip record variables
+
+            do 5, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                    index)
+                if (err .ne. NF90_NOERR) &
+                    call error('error in index2indexes')
+                if (var_type(i) .eq. NF90_CHAR) then
+                    err = nf90mpi_get_var_all(ncid, i, text, index)
+                    if (err .ne. NF90_NOERR) &
+                        call errore('nf90mpi_get_var_all failed: ',err)
+                    value = ichar(text)
+                else
+                    err = nf90mpi_get_var_all(ncid, i, value, index)
+                    if (err .ne. NF90_NOERR) &
+                        call errore &
+                                ('nf90mpi_get_var_all failed: ', err)
+                end if
+                if (value .ne. fill) then
+                    call errord(' Value expected: ', fill)
+                    call errord(' Value read:     ', value)
+                else
+                    nok = nok + 1
+                end if
+5           continue
+4       continue
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) &
+            call errore('nf90mpi_close: ', err)
+        err = nf90mpi_delete(scratch, info)
+        if (err .ne. NF90_NOERR) &
+            call errori('delete of scratch file failed: ', err)
+
+        call print_nok(nok)
+        end
+
+#if 0
+! * Test nc_set_default_format
+! *    try with bad default format
+! *    try with NULL old_formatp
+! *    try in data mode, check error
+! *    check that proper set to NC_FILL works for record & non-record variables
+! *    (note that it is not possible to test NC_NOFILL mode!)
+! *    close file & create again for test using attribute _FillValue
+      subroutine test_nf90mpi_set_default_format()
+        use pnetcdf
+      implicit none
+#include "tests.inc"
+      
+      integer ncid
+      integer err, flags
+      integer i
+      integer version
+      integer old_format
+      integer nf90mpi_get_file_version
+      
+!     /* bad format */
+      err = nf90mpi_set_default_format(3, old_format)
+      IF (err .ne. NF90_EINVAL) &
+           call errore("bad default format: status = %d", err)
+     
+!    /* Cycle through available formats. */
+      do 1 i=1, 2
+         err = nf90mpi_set_default_format(i, old_format)
+         if (err .ne. NF90_NOERR)  &
+               call errore("setting classic format: status = %d", err)
+         flags = IOR(NF90_CLOBBER, extra_flags)
+         err = nf90mpi_create(comm, scratch, flags,  &
+                      info, ncid)
+         if (err .ne. NF90_NOERR)  &
+              call errore("bad nf90mpi_create: status = %d", err)
+         err = nf90mpi_put_att_text(ncid, NF90_GLOBAL, "testatt",  &
+              "blah")
+         if (err .ne. NF90_NOERR) call errore("bad put_att: status = %d", err)
+         err = nf90mpi_close(ncid)
+         if (err .ne. NF90_NOERR) call errore("bad close: status = %d", err)
+         err = nf90mpi_get_file_version(scratch, version)
+         if (err .ne. NF90_NOERR) call errore("bad file version = %d", err)
+         if (version .ne. i) &
+              call errore("bad file version = %d", err)
+ 1    continue
+
+!    /* Remove the left-over file. */
+      err = nf90mpi_delete(scratch)
+      if (err .ne. NF90_NOERR) call errore("remove failed", err)
+      end
+
+#endif
+
+!     This function looks in a file for the netCDF magic number.
+      integer function nf90mpi_get_file_version(path, version)
+        use pnetcdf
+      implicit none
+#include "tests.inc"
+      
+      character*(*) path
+      integer version
+      character magic*4
+      integer ver
+      integer f
+      parameter (f = 10)
+
+      open(f, file=path, status='OLD', form='UNFORMATTED', &
+           access='DIRECT', recl=4)
+
+!     Assume this is not a netcdf file.
+      nf90mpi_get_file_version = NF90_ENOTNC
+      version = 0
+
+!     Read the magic number, the first 4 bytes of the file.
+      read(f, rec=1, err = 1) magic
+
+!     If the first three characters are not "CDF" we're done.
+      if (index(magic, 'CDF') .eq. 1) then
+         ver = ichar(magic(4:4))
+         if (ver .eq. 1) then
+            version = 1
+            nf90mpi_get_file_version = NF90_NOERR
+         elseif (ver .eq. 2) then
+            version = 2
+            nf90mpi_get_file_version = NF90_NOERR
+         endif
+      endif
+
+ 1    close(f)
+      return
+      end
+
+
diff --git a/test/nf90_test/tests.inc b/test/nf90_test/tests.inc
new file mode 100644
index 0000000..296fb3f
--- /dev/null
+++ b/test/nf90_test/tests.inc
@@ -0,0 +1,230 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!  $Id: tests.inc 2137 2015-10-07 23:53:04Z wkliao $ 
+!
+
+      integer, parameter :: INT1_KIND = selected_int_kind(2)
+      integer, parameter :: INT2_KIND = selected_int_kind(4)
+      integer, parameter :: INT8_KIND = selected_int_kind(18)
+
+!!!!
+! Do not tabify this unless you like hitting the 72 char limit !!!
+!!!
+#ifndef UD_TESTS_INC
+#define UD_TESTS_INC
+
+
+!/* The following prevents non-FORTRAN code from appearing in the output. */
+#if defined(__osf__)
+#   undef _POSIX_SOURCE
+#   define _POSIX_SOURCE
+#endif
+
+#define NO_NETCDF_2 1
+
+#include "../libf/nfconfig.inc"
+
+
+!/* Parameters of test data */
+
+#ifdef  NF_INT1_T
+#   define NF_B 1
+#else
+#   define NF_B 0
+#endif
+#ifdef  NF_INT2_T
+#   define NF_S 1
+#else
+#   define NF_S 0
+#endif
+! Total number of FORTRAN types:
+#define NUM_FORTRAN_TYPES (3 + NF_S + NF_B)
+#undef NF_B
+#undef NF_S
+
+#define NTYPES 11
+#define NDIMS 5
+#define NRECS 2
+#define NGATTS NTYPES
+#define RECDIM 1
+#define MAX_RANK 3
+#define MAX_NELS 64
+#define MAX_DIM_LEN 4
+#define MAX_NATTS 3
+
+#define NVARS 166
+!
+!  #define NVARS 136   when NTYPES==6
+!  #define NVARS 142   when NTYPES==7
+!  #define NVARS 148   when NTYPES==8
+!  #define NVARS 154   when NTYPES==9
+!  #define NVARS 160   when NTYPES==10
+!  #define NVARS 166   when NTYPES==11
+!  c:char, b:byte, s:short, i:int, f:float, d:double, y:ubyte, t:ushort,
+!  u:uint, x:int64, z:uint64
+!
+
+
+!/*
+! * Limits of external types (based on those in ncx.h):
+! */
+#define X_CHAR_MIN 0
+#define X_CHAR_MAX 127
+#define X_INT1_MIN (-128)
+#define X_INT1_MAX 127
+#define X_INT2_MIN (-32768)
+#define X_INT2_MAX 32767
+#define X_INT_MIN  (-2147483647-1)
+#define X_INT_MAX  2147483647
+#if 0
+#define X_REAL_MAX 3.4028234663852886e+38
+#else
+#define X_REAL_MAX 3.4028234663852886e+37
+#endif
+#define X_REAL_MIN (-X_FLOAT_MAX)
+#if 0
+#define X_DOUBLE_MAX 1.7976931348623157E+308
+#else
+#define X_DOUBLE_MAX 1.7976931348623157D+200
+#endif
+#define X_DOUBLE_MIN (-X_DOUBLE_MAX)
+#define X_INT8_MIN (-9223372036854775807_INT8_KIND)
+#define X_INT8_MAX 9223372036854775807_INT8_KIND
+#define X_UINT8_MIN (-18446744073709551615.0)
+#define X_UINT8_MAX 18446744073709551615.0
+
+#define X_BYTE_MIN X_INT1_MIN
+#define X_BYTE_MAX X_INT1_MAX
+#define X_SHORT_MIN X_INT2_MIN
+#define X_SHORT_MAX X_INT2_MAX
+#define X_FLOAT_MIN X_REAL_MIN
+#define X_FLOAT_MAX X_REAL_MAX
+
+#define X_UCHAR_MAX     255
+#define X_UCHAR_MIN     0
+#define X_UBYTE_MAX     X_UCHAR_MAX
+#define X_UBYTE_MIN     X_UCHAR_MIN
+#define X_USHORT_MAX    65535
+#define X_USHORT_MIN    0
+#define X_UINT_MAX      4294967295_INT8_KIND
+#define X_UINT_MIN      0
+
+
+!/*
+! * Examples of invalid argument values:
+! */
+#define BAD_ID -1
+#define BAD_DIMID -1
+#define BAD_VARID -2
+#define BAD_ATTNUM -1
+#define BAD_TYPE 0
+#define BAD_FILLMODE -1
+#define BAD_NAME 'a/b'
+
+
+!/*
+! * Internal data types:
+! */
+#define NFT_UNSPECIFIED 0
+#define NFT_TEXT 16
+#define NFT_CHAR NFT_TEXT
+#define NFT_INT1 17
+#define NFT_INT2 18
+#define NFT_INT 20
+#define NFT_REAL 36
+#define NFT_DOUBLE 40
+#define NFT_INT8 43
+
+
+!/*
+! * Define a macro for trimming trailing blanks from character variables.
+! */
+
+
+!
+! FORTRAN GETARG() subroutine:
+!
+#ifdef __hpux
+#   define      getarg  getarg_
+#endif
+
+
+#endif /* UD_TESTS_INC */
+
+#include "mpif.h"
+
+
+!    /* Global variables - filenames */
+
+      CHARACTER*128      testfile  !/* netCDF read-only test data */
+      CHARACTER*128      scratch   !/* netCDF test file for writing */
+
+!    /* Global variables - command-line arguments */
+
+      LOGICAL   CREATE_FILE
+      LOGICAL   READONLY
+      LOGICAL   VERBOSE
+      INTEGER   NFAILS
+      INTEGER   MAX_NMPT        !/* max num messages per test */
+
+!    /* Global variables - test data */
+
+      CHARACTER*2               DIM_NAME(NDIMS)
+      integer(kind=MPI_OFFSET_KIND) DIM_LEN(NDIMS)
+      CHARACTER*(2+MAX_RANK)    VAR_NAME(NVARS)
+      INTEGER                   VAR_TYPE(NVARS)
+      INTEGER                   VAR_RANK(NVARS)
+      INTEGER                   VAR_DIMID(MAX_RANK,NVARS)
+      integer(kind=MPI_OFFSET_KIND) VAR_SHAPE(MAX_RANK,NVARS)
+      INTEGER                   VAR_NELS(NVARS)
+      INTEGER                   VAR_NATTS(NVARS)
+      CHARACTER*2               ATTNAME(MAX_NATTS,NVARS)
+      CHARACTER*2               GATT_NAME(NGATTS)
+      INTEGER                   ATTTYPE(NGATTS,NVARS)
+      INTEGER                   GATT_TYPE(NGATTS)
+      INTEGER                   ATTLEN(MAX_NATTS,NVARS)
+      integer(kind=MPI_OFFSET_KIND) GATT_LEN(NGATTS)
+
+!    /* Miscellaneous global variables: */
+      CHARACTER*128              PROGNAME   !/* name of the program */
+      INTEGER                   COMM       !/* MPI communicator */
+
+      INTEGER                   NFAILSTOTAL
+
+!    /* Common blocks for global variables: */
+
+!/* MPI_OFFSET */
+      COMMON    /OFFSETCOM/     DIM_LEN, VAR_SHAPE, GATT_LEN 
+
+      COMMON    /MPICOM/        COMM
+      COMMON    /LOGCOM/        CREATE_FILE, &
+                                READONLY, & !/* don't change files */
+                                VERBOSE     !/* print details of tests */
+
+      COMMON    /TXTCOM/        TESTFILE, &
+                                SCRATCH, &
+                                DIM_NAME, &
+                                VAR_NAME, &
+                                ATTNAME, &
+                                GATT_NAME, &
+                                PROGNAME
+
+      COMMON    /INTCOM/        NFAILS, &  ! number of failures in specific test
+                                VAR_TYPE, &
+                                VAR_RANK, &
+                                VAR_DIMID, &
+                                VAR_NELS, &
+                                VAR_NATTS, &
+                                ATTTYPE, &
+                                GATT_TYPE, &
+                                ATTLEN, &
+                                MAX_NMPT, &
+                                NFAILSTOTAL
+
+
+      integer numTypes, numVars, numGatts, cdf_format, extra_flags, info
+      common / PROBLEM_SIZE / numTypes, numVars, numGatts, cdf_format, &
+                              extra_flags, info
+
diff --git a/test/nf90_test/util.F90 b/test/nf90_test/util.F90
new file mode 100644
index 0000000..f961d81
--- /dev/null
+++ b/test/nf90_test/util.F90
@@ -0,0 +1,1514 @@
+!
+!  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: util.F90 2284 2015-12-30 20:27:18Z wkliao $
+!
+
+      SUBROUTINE PRINT_NOK(NOK)
+      USE PNETCDF
+      IMPLICIT  NONE
+      INTEGER   NOK
+#include "tests.inc"
+
+ 123  FORMAT(I4,A)
+      IF (NFAILS .GT. 0) PRINT *, ' '
+      IF (VERBOSE) THEN
+          PRINT 123, NOK, ' good comparisons.'
+      ENDIF
+      END
+
+
+! Is value within external type range? */
+      logical FUNCTION INRANGE(VALUE, DATATYPE)
+      USE PNETCDF
+      IMPLICIT  NONE
+      DOUBLEPRECISION   VALUE
+      INTEGER           DATATYPE
+#include "tests.inc"
+
+      DOUBLEPRECISION   MIN
+      DOUBLEPRECISION   MAX
+
+      MIN = X_DOUBLE_MIN
+      MAX = X_DOUBLE_MAX
+      IF (DATATYPE .EQ. NF90_CHAR) THEN
+          MIN = X_CHAR_MIN
+          MAX = X_CHAR_MAX
+      ELSE IF (DATATYPE .EQ. NF90_BYTE) THEN
+          MIN = X_BYTE_MIN
+          MAX = X_BYTE_MAX
+      ELSE IF (DATATYPE .EQ. NF90_SHORT) THEN
+          MIN = X_SHORT_MIN
+          MAX = X_SHORT_MAX
+      ELSE IF (DATATYPE .EQ. NF90_INT) THEN
+          MIN = X_INT_MIN
+          MAX = X_INT_MAX
+      ELSE IF (DATATYPE .EQ. NF90_FLOAT) THEN
+          MIN = X_FLOAT_MIN
+          MAX = X_FLOAT_MAX
+      ELSE IF (DATATYPE .EQ. NF90_DOUBLE) THEN
+          MIN = X_DOUBLE_MIN
+          MAX = X_DOUBLE_MAX
+      ELSE IF (DATATYPE .EQ. NF90_UBYTE) THEN
+          MIN = 0
+          MAX = X_UCHAR_MAX
+      ELSE IF (DATATYPE .EQ. NF90_USHORT) THEN
+          MIN = 0
+          MAX = X_USHORT_MAX
+      ELSE IF (DATATYPE .EQ. NF90_UINT) THEN
+          MIN = 0
+          MAX = X_UINT_MAX
+      ELSE IF (DATATYPE .EQ. NF90_INT64) THEN
+          INRANGE = (VALUE .GE. X_INT8_MIN) .AND. &
+                    (VALUE .LE. X_INT8_MAX)
+          return
+      ELSE IF (DATATYPE .EQ. NF90_UINT64) THEN
+          INRANGE = (VALUE .GE. 0) .AND. &
+                    (VALUE .LE. X_UINT8_MAX)
+          return
+      ELSE
+          CALL UD_ABORT
+      END IF
+
+      INRANGE = (VALUE .GE. MIN) .AND. (VALUE .LE. MAX)
+      END
+
+
+      logical FUNCTION INRANGE_UCHAR(VALUE, DATATYPE)
+      USE PNETCDF
+      IMPLICIT  NONE
+      DOUBLEPRECISION   VALUE
+      INTEGER           DATATYPE
+#include "tests.inc"
+      LOGICAL INRANGE
+
+      IF (DATATYPE .EQ. NF90_BYTE) THEN
+          INRANGE_UCHAR = (VALUE .GE. 0) .AND. (VALUE .LE. 255)
+      ELSE
+          INRANGE_UCHAR = INRANGE(VALUE, DATATYPE)
+      END IF
+      END
+
+
+      logical FUNCTION INRANGE_FLOAT(VALUE, DATATYPE)
+      USE PNETCDF
+      IMPLICIT  NONE
+      DOUBLEPRECISION   VALUE
+      INTEGER           DATATYPE
+#include "tests.inc"
+      double precision internal_max
+
+      DOUBLEPRECISION   MIN
+      DOUBLEPRECISION   MAX
+      REAL              FVALUE
+
+      MIN = X_DOUBLE_MIN
+      MAX = X_DOUBLE_MAX
+
+      IF (DATATYPE .EQ. NF90_CHAR) THEN
+          MIN = X_CHAR_MIN
+          MAX = X_CHAR_MAX
+      ELSE IF (DATATYPE .EQ. NF90_BYTE) THEN
+          MIN = X_BYTE_MIN
+          MAX = X_BYTE_MAX
+      ELSE IF (DATATYPE .EQ. NF90_SHORT) THEN
+          MIN = X_SHORT_MIN
+          MAX = X_SHORT_MAX
+      ELSE IF (DATATYPE .EQ. NF90_INT) THEN
+          MIN = X_INT_MIN
+          MAX = X_INT_MAX
+      ELSE IF (DATATYPE .EQ. NF90_FLOAT) THEN
+          IF (internal_max(NFT_REAL) .LT. X_FLOAT_MAX) THEN
+              MIN = -internal_max(NFT_REAL)
+              MAX = internal_max(NFT_REAL)
+          ELSE
+              MIN = X_FLOAT_MIN
+              MAX = X_FLOAT_MAX
+          END IF
+      ELSE IF (DATATYPE .EQ. NF90_DOUBLE) THEN
+          IF (internal_max(NFT_REAL) .LT. X_DOUBLE_MAX) THEN
+              MIN = -internal_max(NFT_REAL)
+              MAX = internal_max(NFT_REAL)
+          ELSE
+              MIN = X_DOUBLE_MIN
+              MAX = X_DOUBLE_MAX
+          END IF
+      ELSE IF (DATATYPE .EQ. NF90_UBYTE) THEN
+          MIN = 0
+          MAX = X_UCHAR_MAX
+      ELSE IF (DATATYPE .EQ. NF90_USHORT) THEN
+          MIN = 0
+          MAX = X_USHORT_MAX
+      ELSE IF (DATATYPE .EQ. NF90_UINT) THEN
+          MIN = 0
+          MAX = X_UINT_MAX
+      ELSE IF (DATATYPE .EQ. NF90_INT64) THEN
+          MIN = X_INT8_MIN
+          MAX = X_INT8_MAX
+      ELSE IF (DATATYPE .EQ. NF90_UINT64) THEN
+          MIN = 0
+          MAX = X_UINT8_MAX
+      ELSE
+          CALL UD_ABORT
+      END IF
+
+      IF (.NOT.((VALUE .GE. MIN) .AND. (VALUE .LE. MAX))) THEN
+          INRANGE_FLOAT = .FALSE.
+      ELSE
+          FVALUE = REAL(VALUE)
+          INRANGE_FLOAT = (FVALUE .GE. MIN) .AND. (FVALUE .LE. MAX)
+      END IF
+      END
+
+
+! wrapper for inrange to handle special NF90_BYTE/uchar adjustment */
+      logical function inrange3(value, datatype, itype)
+      use pnetcdf
+      implicit          none
+      doubleprecision   value
+      integer           datatype
+      integer           itype
+#include "tests.inc"
+      logical inrange_float, inrange
+
+      if (itype .eq. NFT_REAL) then
+          inrange3 = inrange_float(value, datatype)
+      else
+          inrange3 = inrange(value, datatype)
+      end if
+      end
+
+
+!
+!  Does x == y, where one is internal and other external (netCDF)?  
+!  Use tolerant comparison based on IEEE FLT_EPSILON or DBL_EPSILON.
+!
+      logical function equal(x, y, extType, itype)
+      use pnetcdf
+      implicit  none
+      doubleprecision   x
+      doubleprecision   y
+      integer           extType         !!/* external data type */
+      integer           itype
+#include "tests.inc"
+
+      doubleprecision   epsilon
+
+      if ((extType .eq. NF90_REAL) .or. (itype .eq. NFT_REAL)) then
+          epsilon = 1.19209290E-07
+      else
+          epsilon = 2.2204460492503131E-16
+      end if
+      equal = abs(x-y) .le. epsilon * max( abs(x), abs(y))
+      end
+
+
+! Test whether two int vectors are equal. If so return 1, else 0  */
+        logical function int_vec_eq(v1, v2, n)
+      use pnetcdf
+        implicit        none
+        integer n
+        integer v1(n)
+        integer v2(n)
+#include "tests.inc"
+
+        integer i
+
+        int_vec_eq = .true.
+
+        if (n .le. 0) &
+            return
+
+        do 1, i=1, n
+            if (v1(i) .ne. v2(i)) then
+                int_vec_eq = .false.
+                return
+            end if
+1       continue
+        end
+
+
+!
+!  Generate random integer from 0 through n-1
+!  Like throwing an n-sided dice marked 0, 1, 2, ..., n-1
+!
+      integer function roll(n)
+      use pnetcdf
+      implicit  none
+#include "tests.inc"
+      integer(kind=MPI_OFFSET_KIND)   n
+
+      doubleprecision   ud_rand
+      external          ud_rand
+
+1     roll = INT((ud_rand(0) * (n-1)) + 0.5)
+      if (roll .ge. n) goto 1
+      end
+
+
+!
+!      Convert an origin-1 cumulative index to a netCDF index vector.
+!       Grosset dimension first; finest dimension last.
+!
+!      Authors: Harvey Davies, Unidata/UCAR, Boulder, Colorado
+!                Steve Emmerson, (same place)
+!
+        integer function index2ncindexes(index, rank, base, indexes)
+      use pnetcdf
+        implicit        none
+        integer         index           !!/* index to be converted */
+        integer         rank            !/* number of dimensions */
+#include "tests.inc"
+        integer(kind=MPI_OFFSET_KIND)         base(rank)      !/* base(rank) ignored */
+        integer(kind=MPI_OFFSET_KIND)         indexes(rank)   !/* returned FORTRAN indexes */
+
+        integer i
+        integer offset
+        integer intbase
+
+        if (rank .gt. 0) then
+            offset = index - 1
+            do 1, i = rank, 1, -1
+                if (base(i) .eq. 0) then
+                    index2ncindexes = 1
+                    return
+                end if
+                intbase = INT(base(i))
+                indexes(i) = 1 + mod(offset, intbase)
+                offset = offset / INT(base(i))
+1           continue
+        end if
+        index2ncindexes = 0
+        end
+
+
+!
+!      Convert an origin-1 cumulative index to a FORTRAN index vector.
+!       Finest dimension first; grossest dimension last.
+!
+!      Authors: Harvey Davies, Unidata/UCAR, Boulder, Colorado
+!                Steve Emmerson, (same place)
+!
+        integer function index2indexes(index, rank, base, indexes)
+      use pnetcdf
+        implicit        none
+        integer         index           !/* index to be converted */
+        integer         rank            !/* number of dimensions */
+#include "tests.inc"
+        integer(kind=MPI_OFFSET_KIND)         base(rank)      !/* base(rank) ignored */
+        integer(kind=MPI_OFFSET_KIND)         indexes(rank)   !/* returned FORTRAN indexes */
+
+        integer i
+        integer offset
+        integer intbase
+
+        if (rank .gt. 0) then
+            offset = index - 1
+            do 1, i = 1, rank
+                if (base(i) .eq. 0) then
+                    index2indexes = 1
+                    return
+                end if
+                intbase = INT(base(i))
+                indexes(i) = 1 + mod(offset, intbase)
+                offset = offset / INT(base(i))
+1           continue
+        end if
+        index2indexes = 0
+        end
+
+
+!
+!      Convert a FORTRAN index vector to an origin-1 cumulative index.
+!       Finest dimension first; grossest dimension last.
+!
+!      Authors: Harvey Davies, Unidata/UCAR, Boulder, Colorado
+!                Steve Emmerson, (same place)
+!
+        integer function indexes2index(rank, indexes, base)
+      use pnetcdf
+        implicit        none
+        integer         rank            !/* number of dimensions */
+        integer         indexes(rank)   !/* FORTRAN indexes */
+        integer         base(rank)      !/* base(rank) ignored */
+#include "tests.inc"
+
+        integer i
+
+        indexes2index = 0
+        if (rank .gt. 0) then
+            do 1, i = rank, 1, -1
+                indexes2index = (indexes2index-1) * base(i) + indexes(i)
+1           continue
+        end if
+        end
+
+
+! Generate data values as function of type, rank (-1 for attribute), index */
+      double precision function hash(type, rank, index) 
+      use pnetcdf
+      implicit  none
+      integer   type
+      integer   rank
+#include "tests.inc"
+      integer(kind=MPI_OFFSET_KIND)   index(*)
+
+      doubleprecision   base
+      doubleprecision   result
+      integer           d       !/* index of dimension */
+
+        !/* If vector then elements 1 & 2 are min & max. Elements 3 & 4 are */
+        !/* just < min & > max (except for NF90_CHAR & NF90_DOUBLE) */
+      hash = 0
+      if (abs(rank) .eq. 1 .and. index(1) .le. 4) then
+          if (index(1) .eq. 1) then
+              if (type .eq. NF90_CHAR) then
+                  hash = X_CHAR_MIN
+              else if (type .eq. NF90_BYTE) then
+                  hash = X_BYTE_MIN
+              else if (type .eq. NF90_SHORT) then
+                  hash = X_SHORT_MIN
+              else if (type .eq. NF90_INT) then
+                  hash = X_INT_MIN
+              else if (type .eq. NF90_FLOAT) then
+                  hash = X_FLOAT_MIN
+              else if (type .eq. NF90_DOUBLE) then
+                  hash = X_DOUBLE_MIN
+              else if (type .eq. NF90_UBYTE) then
+                  hash = 0
+              else if (type .eq. NF90_USHORT) then
+                  hash = 0
+              else if (type .eq. NF90_UINT) then
+                  hash = 0
+              else if (type .eq. NF90_INT64) then
+                  hash = X_INT_MIN - 128.0
+              else if (type .eq. NF90_UINT64) then
+                  hash = 0
+              else
+                  call ud_abort
+              end if
+          else if (index(1) .eq. 2) then
+              if (type .eq. NF90_CHAR) then
+                  hash = X_CHAR_MAX
+              else if (type .eq. NF90_BYTE) then
+                  hash = X_BYTE_MAX
+              else if (type .eq. NF90_SHORT) then
+                  hash = X_SHORT_MAX
+              else if (type .eq. NF90_INT) then
+                  hash = X_INT_MAX
+              else if (type .eq. NF90_FLOAT) then
+                  hash = X_FLOAT_MAX
+              else if (type .eq. NF90_DOUBLE) then
+                  hash = X_DOUBLE_MAX
+              else if (type .eq. NF90_UBYTE) then
+                  hash = X_UCHAR_MAX
+              else if (type .eq. NF90_USHORT) then
+                  hash = X_USHORT_MAX
+              else if (type .eq. NF90_UINT) then
+                  hash = X_UINT_MAX
+              else if (type .eq. NF90_INT64) then
+                  hash = X_INT_MAX + 128.0
+              else if (type .eq. NF90_UINT64) then
+                  hash = X_UINT_MAX + 128.0
+              else
+                  call ud_abort
+              end if
+          else if (index(1) .eq. 3) then
+              if (type .eq. NF90_CHAR) then
+                  hash = ichar('A')
+              else if (type .eq. NF90_BYTE) then
+                  hash = X_BYTE_MIN-1.0
+              else if (type .eq. NF90_SHORT) then
+                  hash = X_SHORT_MIN-1.0
+              else if (type .eq. NF90_INT) then
+                  hash = X_INT_MIN
+              else if (type .eq. NF90_FLOAT) then
+                  hash = X_FLOAT_MIN
+              else if (type .eq. NF90_DOUBLE) then
+                  hash = -1.0
+              else if (type .eq. NF90_UBYTE) then
+                  hash = -1.0
+              else if (type .eq. NF90_USHORT) then
+                  hash = -1.0
+              else if (type .eq. NF90_UINT) then
+                  hash = -1.0
+              else if (type .eq. NF90_INT64) then
+                  hash = -1.0
+              else if (type .eq. NF90_UINT64) then
+                  hash = -1.0
+              else
+                  call ud_abort
+              end if
+          else if (index(1) .eq. 4) then
+              if (type .eq. NF90_CHAR) then
+                  hash = ichar('Z')
+              else if (type .eq. NF90_BYTE) then
+                  hash = X_BYTE_MAX+1.0
+              else if (type .eq. NF90_SHORT) then
+                  hash = X_SHORT_MAX+1.0
+              else if (type .eq. NF90_INT) then
+                  hash = X_INT_MAX+1.0
+              else if (type .eq. NF90_FLOAT) then
+                  hash = X_FLOAT_MAX
+              else if (type .eq. NF90_DOUBLE) then
+                  hash = 1.0
+              else if (type .eq. NF90_UBYTE) then
+                  hash = X_UCHAR_MAX + 1.0
+              else if (type .eq. NF90_USHORT) then
+                  hash = X_USHORT_MAX + 1.0
+              else if (type .eq. NF90_UINT) then
+                  hash = X_UINT_MAX + 1.0
+              else if (type .eq. NF90_INT64) then
+                  hash = 1.0
+              else if (type .eq. NF90_UINT64) then
+                  hash = 1.0
+              else
+                  call ud_abort
+              end if
+          end if
+      else
+          if (type .eq. NF90_CHAR) then
+              base = 2
+          else if (type .eq. NF90_BYTE) then
+              base = -2
+          else if (type .eq. NF90_SHORT) then
+              base = -5
+          else if (type .eq. NF90_INT) then
+              base = -20
+          else if (type .eq. NF90_FLOAT) then
+              base = -9
+          else if (type .eq. NF90_DOUBLE) then
+              base = -10
+          else if (type .eq. NF90_UBYTE) then
+              base = 2
+          else if (type .eq. NF90_USHORT) then
+              base = 5
+          else if (type .eq. NF90_UINT) then
+              base = 20
+          else if (type .eq. NF90_INT64) then
+              base = -20
+          else if (type .eq. NF90_UINT64) then
+              base = 20
+          else
+              print*, 'Error: no such nc_type ',type
+              stop 'in hash()'
+          end if
+
+          if (rank .lt. 0) then
+              result = base * 7
+          else
+              result = base * (rank + 1)
+          end if
+
+!         /*
+!          * NB: Finest netCDF dimension assumed first.
+!          */
+          do 1, d = abs(rank), 1, -1
+              result = base * (result + index(d) - 1)
+1         continue
+          hash = result
+      end if
+      end
+
+
+! wrapper for hash to handle special NC_BYTE/uchar adjustment */
+      double precision function hash4(type, rank, index, itype)
+      use pnetcdf
+      implicit  none
+      integer   type
+      integer   rank
+#include "tests.inc"
+      double precision hash
+
+      integer(kind=MPI_OFFSET_KIND)   index(*)
+      integer   itype
+
+      hash4 = hash( type, rank, index )
+      if ((itype .eq. NFT_CHAR) .and. (type .eq. NF90_BYTE) .and.  &
+          (hash4 .ge. -128) .and. (hash4 .lt. 0)) hash4 = hash4 + 256
+      end
+
+
+      integer function char2type(letter)
+      use pnetcdf
+      implicit          none
+      character*1       letter
+#include "tests.inc"
+
+      if (letter .eq. 'c') then
+          char2type = NF90_CHAR
+      else if (letter .eq. 'b') then
+          char2type = NF90_BYTE
+      else if (letter .eq. 's') then
+          char2type = NF90_SHORT
+      else if (letter .eq. 'i') then
+          char2type = NF90_INT
+      else if (letter .eq. 'f') then
+          char2type = NF90_FLOAT
+      else if (letter .eq. 'd') then
+          char2type = NF90_DOUBLE
+      else if (letter .eq. 'y') then
+          char2type = NF90_UBYTE
+      else if (letter .eq. 't') then
+          char2type = NF90_USHORT
+      else if (letter .eq. 'u') then
+          char2type = NF90_UINT
+      else if (letter .eq. 'x') then
+          char2type = NF90_INT64
+      else if (letter .eq. 'z') then
+          char2type = NF90_UINT64
+      else
+        stop 'char2type(): invalid type-letter'
+      end if
+      end
+
+
+      subroutine init_dims(digit)
+      use pnetcdf
+      implicit          none
+      character*1       digit(NDIMS)
+#include "tests.inc"
+
+      integer   dimid                   !/* index of dimension */
+      do 1, dimid = 1, NDIMS
+          if (dimid .eq. RECDIM) then
+              dim_len(dimid) = NRECS
+          else
+              dim_len(dimid) = dimid - 1
+          endif
+          dim_name(dimid) = 'D' // digit(dimid)
+1     continue
+      end
+
+
+      subroutine init_gatts(type_letter)
+      use pnetcdf
+      implicit          none
+      character*1       type_letter(NTYPES)
+#include "tests.inc"
+
+      integer   attid
+      integer   char2type
+
+      do 1, attid = 1, numTypes
+          gatt_name(attid) = 'G' // type_letter(attid)
+          gatt_len(attid) = attid
+          gatt_type(attid) = char2type(type_letter(attid))
+1     continue
+      end
+
+
+      integer function prod(nn, sp)
+      use pnetcdf
+      implicit  none
+      integer   nn
+#include "tests.inc"
+      integer(kind=MPI_OFFSET_KIND)   sp(MAX_RANK)
+
+      integer   i
+
+      prod = 1
+      do 1, i = 1, nn
+          prod = prod * INT(sp(i))
+1     continue
+      end
+
+
+!
+!   define global variables:
+!   dim_name, dim_len, 
+!   var_name, var_type, var_rank, var_shape, var_natts, var_dimid, var_nels
+!   att_name, gatt_name, att_type, gatt_type, att_len, gatt_len
+!
+
+        subroutine init_gvars
+      use pnetcdf
+        implicit        none
+#include "tests.inc"
+        integer index2ncindexes
+
+        integer(kind=MPI_OFFSET_KIND)         max_dim_len(MAX_RANK)
+        character*1     type_letter(NTYPES)
+        character*1     digit(10)
+
+        integer rank
+        integer vn              !/* var number */
+        integer xtype           !/* index of type */
+        integer an              !/* origin-0 cumulative attribute index */
+        integer nvars
+        integer jj
+        integer n_types
+        integer tc
+        integer(kind=MPI_OFFSET_KIND) tmp(MAX_RANK)
+        integer ac              !/* attribute index */
+        integer dn              !/* dimension number */
+        integer prod            !/* function */
+        integer char2type       !/* function */
+        integer err
+
+        data    max_dim_len     /0, MAX_DIM_LEN, MAX_DIM_LEN/
+        data    type_letter     /'c', 'b', 's', 'i', 'f', 'd', 'y', &
+                                 't', 'u', 'x', 'z'/
+        data    digit           /'r', '1', '2', '3', '4', '5', &
+                                 '6', '7', '8', '9'/
+
+        max_dim_len(1) = MAX_DIM_LEN + 1
+
+        call init_dims(digit)
+
+        vn = 1
+        xtype = 1
+        an = 0
+
+!       /* Loop over variable ranks */
+        do 1, rank = 0, MAX_RANK
+            nvars = prod(rank, max_dim_len)
+
+            !/* Loop over variable shape vectors */
+            do 2, jj = 1, nvars                         !/* 1, 5, 20, 80 */
+                !/* number types of this shape */
+                if (rank .lt. 2) then
+                    n_types = numTypes                     !/* 6 */
+                else
+                    n_types = 1
+                end if
+
+                !/* Loop over external data types */
+                do 3, tc = 1, n_types                    !/* 6, 1 */
+                    var_name(vn) = type_letter(xtype)
+                    var_type(vn) = char2type(type_letter(xtype))
+                    var_rank(vn) = rank
+                    if (rank .eq. 0) then
+                        var_natts(vn) = mod(vn - 1, MAX_NATTS + 1)
+                    else
+                        var_natts(vn) = 0
+                    end if
+
+                    do 4, ac = 1, var_natts(vn)
+                        attname(ac,vn) =  &
+                            type_letter(1+mod(an, numTypes))
+                        attlen(ac,vn) = an
+                        atttype(ac,vn) = &
+                            char2type(type_letter(1+mod(an, numTypes)))
+                        an = an + 1
+4                   continue
+
+                    !/* Construct initial shape vector */
+                    err = index2ncindexes(jj, rank, max_dim_len, tmp)
+                    do 5, dn = 1, rank
+                        var_dimid(dn,vn) = INT(tmp(1+rank-dn))
+5                   continue
+
+                    var_nels(vn) = 1
+                    do 6, dn = 1, rank
+                        if (dn .lt. rank) then
+                            var_dimid(dn,vn) = var_dimid(dn,vn) + 1
+                        end if
+                        if (var_dimid(dn,vn) .gt. 9) then
+                            stop 'Invalid var_dimid vector'
+                        end if
+                        var_name(vn)(rank+2-dn:rank+2-dn) =  &
+                            digit(var_dimid(dn,vn))
+                        if (var_dimid(dn,vn) .ne. RECDIM) then
+                            var_shape(dn,vn) = var_dimid(dn,vn) - 1
+                        else
+                            var_shape(dn,vn) = NRECS
+                        end if
+                        var_nels(vn) = var_nels(vn) * INT(var_shape(dn,vn))
+6                   continue
+
+                    vn = vn + 1
+                    xtype = 1 + mod(xtype, numTypes)
+3               continue
+2           continue
+1       continue
+
+        call init_gatts(type_letter)
+        end
+
+
+! define dims defined by global variables */
+        subroutine def_dims(ncid)
+      use pnetcdf
+        implicit        none
+        integer         ncid
+#include "tests.inc"
+
+        integer         err             !/* status */
+        integer         i
+        integer         dimid           !/* dimension id */
+
+        do 1, i = 1, NDIMS
+            if (i .eq. RECDIM) then
+                err = nf90mpi_def_dim(ncid, dim_name(i), &
+                                      NF90MPI_UNLIMITED,  dimid)
+            else
+                err = nf90mpi_def_dim(ncid, dim_name(i), dim_len(i), &
+                                      dimid)
+            end if
+            if (err .ne. NF90_NOERR) then
+                call errore('nf90mpi_def_dim: ', err)
+            end if
+1       continue
+        end
+
+
+! define vars defined by global variables */
+        subroutine def_vars(ncid)
+        use pnetcdf
+        implicit        none
+        integer         ncid
+#include "tests.inc"
+
+        integer         err             !/* status */
+        integer         i
+        integer         var_id
+
+        do 1, i = 1, numVars
+            err = nf90mpi_def_var(ncid, var_name(i), var_type(i),  &
+                             var_dimid(1:var_rank(i),i), var_id)
+            if (err .ne. NF90_NOERR) then
+                call errore('nf90mpi_def_var: ', err)
+            end if
+1       continue
+        end
+
+
+! put attributes defined by global variables */
+        subroutine put_atts(ncid)
+      use pnetcdf
+        implicit        none
+        integer         ncid
+#include "tests.inc"
+        integer(kind=MPI_OFFSET_KIND) ATT_LEN_LL
+        integer VARID, NATTS, ATT_TYPE, ATT_LEN
+        CHARACTER*2 ATT_NAME
+        double precision hash
+        logical inrange
+
+        integer                 err             !/* netCDF status */
+        integer                 i               !/* variable index (0 => global 
+                                                ! * attribute */
+        integer                 k               !/* attribute index */
+        integer                 j               !/* index of attribute */
+        integer(kind=MPI_OFFSET_KIND)                 ndx(1)
+        logical                 allInRange
+        double precision        att(MAX_NELS)
+        character*(MAX_NELS+2)  catt
+
+        do 1, i = 0, numVars      !/* var 0 => NF90_GLOBAL attributes */
+            do 2, j = 1, NATTS(i)
+                if (NF90_CHAR .eq. ATT_TYPE(j,i)) then
+                    catt = ' '
+                    do 3, k = 1, ATT_LEN(j,i)
+                        ndx(1) = k
+                        catt(k:k) = char(int(hash(ATT_TYPE(j,i), -1,  &
+                                         ndx)))
+3                   continue
+!                   /*
+!                    * The following ensures that the text buffer doesn't
+!                    * start with 4 zeros (which is a CFORTRAN NULL pointer
+!                    * indicator) yet contains a zero (which causes the
+!                    * CFORTRAN interface to pass the address of the
+!                    * actual text buffer).
+!                    */
+                    catt(ATT_LEN(j,i)+1:ATT_LEN(j,i)+1) = char(1)
+                    catt(ATT_LEN(j,i)+2:ATT_LEN(j,i)+2) = char(0)
+
+                    err = nf90mpi_put_att(ncid, varid(i), ATT_NAME(j,i), &
+                                          catt(1:ATT_LEN(j,i)))
+                    if (err .ne. NF90_NOERR) then
+                        call errore('nf90mpi_put_att: ', err)
+                    end if
+                else
+                    allInRange = .true.
+                    do 4, k = 1, ATT_LEN(j,i)
+                        ndx(1) = k
+                        att(k) = hash(ATT_TYPE(j,i), -1, ndx)
+                        allInRange = allInRange .and. &
+                                     inRange(att(k), ATT_TYPE(j,i))
+4                   continue
+                    ! cannot use nf90mpi_put_att, as it checks data types
+                    ATT_LEN_LL = ATT_LEN(j,i)
+                    err = nfmpi_put_att_double(ncid, varid(i), ATT_NAME(j,i), &
+                                               ATT_TYPE(j,i), ATT_LEN_LL, att)
+                    if (allInRange) then
+                        if (err .ne. NF90_NOERR) then
+                            call errore('nf90mpi_put_att: ', err)
+                        end if
+                    ! F90 skips this error check
+                    ! else
+                    !     if (err .ne. NF90_ERANGE) then
+                    !         call errore( &
+                    !     'type-conversion range error: status = ', &
+                    !             err)
+                    !     end if
+                    end if
+                end if
+2           continue
+1       continue
+        end
+
+
+! put variables defined by global variables */
+        subroutine put_vars(ncid)
+      use pnetcdf
+        implicit        none
+        integer                 ncid
+#include "tests.inc"
+        integer index2indexes
+        double precision hash
+        logical inrange
+
+        integer(kind=MPI_OFFSET_KIND)                 start(MAX_RANK)
+        integer(kind=MPI_OFFSET_KIND)                 index(MAX_RANK)
+        integer                 err             !/* netCDF status */
+        integer                 i
+        integer                 j
+        doubleprecision         value(MAX_NELS)
+        character*(MAX_NELS+2)  text
+        logical                 allInRange
+
+        do 1, j = 1, MAX_RANK
+            start(j) = 1
+1       continue
+
+        err = nf90mpi_begin_indep_data(ncid)
+        do 2, i = 1, numVars
+            allInRange = .true.
+            do 3, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                                    index)
+                if (err .ne. NF90_NOERR) then
+                    call errori( &
+                        'Error calling index2indexes() for var ', j)
+                end if
+                if (var_name(i)(1:1) .eq. 'c') then
+                    text(j:j) =  &
+                        char(int(hash(var_type(i), var_rank(i), index)))
+                else
+                    value(j)  = hash(var_type(i), var_rank(i), index)
+                    allInRange = allInRange .and. &
+                        inRange(value(j), var_type(i))
+                end if
+3           continue
+            if (var_name(i)(1:1) .eq. 'c') then
+!               /*
+!                * The following statement ensures that the first 4
+!                * characters in 'text' are not all zeros (which is
+!                * a cfortran.h NULL indicator) and that the string
+!                * contains a zero (which will cause the address of the
+!                * actual string buffer to be passed).
+!                */
+                text(var_nels(i)+1:var_nels(i)+1) = char(1)
+                text(var_nels(i)+2:var_nels(i)+2) = char(0)
+                err = nf90mpi_put_var(ncid, i, text, start, &
+                                          var_shape(:,i))
+                if (err .ne. NF90_NOERR) then
+                    call errore('nf90mpi_put_var: ', err)
+                end if
+            else
+                err = nf90mpi_put_var(ncid, i, value, start, &
+                                            var_shape(:,i))
+                if (allInRange) then
+                    if (err .ne. NF90_NOERR) then
+                        call errore('nf90mpi_put_var: ', err)
+                    end if
+                else
+                    if (err .ne. NF90_ERANGE) then
+                        call errore( &
+                            'type-conversion range error: status = ',  &
+                            err)
+                    end if
+                end if
+            end if
+2       continue
+        err = nf90mpi_end_indep_data(ncid)
+        end
+
+
+! Create & write all of specified file using global variables */
+        subroutine write_file(filename) 
+      use pnetcdf
+        implicit        none
+        character*(*)   filename
+#include "tests.inc"
+
+        integer ncid            !/* netCDF id */
+        integer err             !/* netCDF status */
+        integer flags
+
+        flags = IOR(NF90_CLOBBER, extra_flags)
+        err = nf90mpi_create(comm, filename, flags, info, &
+                           ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_create: ', err)
+        end if
+
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+        err = nf90mpi_enddef(ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_enddef: ', err)
+        end if
+        call put_vars(ncid)
+
+        err = nf90mpi_close(ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_close: ', err)
+        end if
+        end
+
+
+!
+! check dimensions of specified file have expected name & length
+!
+        subroutine check_dims(ncid)
+      use pnetcdf
+        implicit        none
+        integer         ncid
+#include "tests.inc"
+
+        character*(NF90_MAX_NAME) name
+        integer(kind=MPI_OFFSET_KIND)                 length
+        integer                 i
+        integer                 err           !/* netCDF status */
+
+        do 1, i = 1, NDIMS
+            err = nf90mpi_inquire_dimension(ncid, i, name, length)
+            if (err .ne. NF90_NOERR) then
+                call errore('nf90mpi_inquire_dimension: ', err)
+            end if
+            if (name .ne. dim_name(i)) then
+                call errori('Unexpected name of dimension ', i)
+            end if
+            if (length .ne. dim_len(i)) then
+                call errori('Unexpected length of dimension ', i)
+            end if
+1       continue
+        end
+
+
+!
+! check variables of specified file have expected name, type, shape & values
+!
+        subroutine check_vars(ncid)
+      use pnetcdf
+        implicit        none
+        integer         ncid
+#include "tests.inc"
+        integer index2indexes
+        double precision hash
+        logical inrange, equal
+
+        integer(kind=MPI_OFFSET_KIND)                 index(MAX_RANK)
+        integer                 err             !/* netCDF status */
+        integer                 i
+        integer                 j
+        character*1             text
+        doubleprecision         value
+        integer                 datatype
+        integer                 ndims
+        integer                 natt
+        integer                 dimids(MAX_RANK)
+        logical                 isChar
+        doubleprecision         expect
+        character*(NF90_MAX_NAME) name
+        integer(kind=MPI_OFFSET_KIND)                 length
+        integer                 nok             !/* count of valid comparisons */
+
+        nok = 0
+        err = nf90mpi_begin_indep_data(ncid)
+
+        do 1, i = 1, numVars
+            isChar = var_type(i) .eq. NF90_CHAR
+            err = nf90mpi_inquire_variable(ncid, i, name, datatype, ndims, dimids,  &
+                natt)
+            if (err .ne. NF90_NOERR) then
+                call errore('nf90mpi_inquire_variable: ', err)
+            end if
+            if (name .ne. var_name(i)) then
+                call errori('Unexpected var_name for variable ', i)
+            end if
+            if (datatype .ne. var_type(i))  then
+                call errori('Unexpected type for variable ', i)
+            end if
+            if (ndims .ne. var_rank(i))  then
+                call errori('Unexpected rank for variable ', i)
+            end if
+            do 2, j = 1, ndims
+                err = nf90mpi_inquire_dimension(ncid, dimids(j), name, length)
+                if (err .ne. NF90_NOERR) then
+                    call errore('nf90mpi_inquire_dimension: ', err)
+                end if
+                if (length .ne. var_shape(j,i))  then
+                    call errori('Unexpected shape for variable ', i)
+                end if
+2           continue
+            do 3, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i),  &
+                        index)
+                if (err .ne. NF90_NOERR)  then
+                    call errori('error in index2indexes() 2, variable ', &
+                                i)
+                end if
+                expect = hash(var_type(i), var_rank(i), index )
+                if (isChar) then
+                    err = nf90mpi_get_var(ncid, i, text, index)
+                    if (err .ne. NF90_NOERR) then
+                        call errore('nf90mpi_get_var: ', err)
+                    end if
+                    if (ichar(text) .ne. expect) then
+                        call errori( &
+                    'Var value read not that expected for variable ', i)
+                    else
+                        nok = nok + 1
+                    end if
+                else
+                    err = nf90mpi_get_var(ncid, i, value, index)
+                    if (inRange(expect,var_type(i))) then
+                        if (err .ne. NF90_NOERR) then
+                            call errore('nf90mpi_get_var: ', err)
+                        else
+                            if (.not. equal(value,expect,var_type(i), &
+                                NFT_DOUBLE)) then
+                                call errori( &
+                    'Var value read not that expected for variable ', i)
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+                    end if
+                end if
+3           continue
+1       continue
+        err = nf90mpi_end_indep_data(ncid)
+        ! call print_nok(nok)
+        end
+
+
+!
+! check attributes of specified file have expected name, type, length & values
+!
+        subroutine check_atts(ncid) 
+      use pnetcdf
+        implicit        none
+        integer         ncid
+#include "tests.inc"
+        integer VARID, NATTS, ATT_TYPE, ATT_LEN
+        CHARACTER*2 ATT_NAME
+        double precision hash
+        logical inrange, equal
+
+        integer                 err             !/* netCDF status */
+        integer                 i
+        integer                 j
+        integer                 k
+        integer                 vid             !/* "variable" ID */
+        integer                 datatype
+        integer(kind=MPI_OFFSET_KIND)                 ndx(1)
+        character*(NF90_MAX_NAME) name
+        integer(kind=MPI_OFFSET_KIND)                 length
+        character*(MAX_NELS)    text
+        doubleprecision         value(MAX_NELS)
+        doubleprecision         expect
+        integer                 nok             !/* count of valid comparisons */
+
+        nok = 0
+
+        do 1, vid = 0, numVars
+            i = varid(vid)
+
+            do 2, j = 1, NATTS(i)
+                err = nf90mpi_inq_attname(ncid, i, j, name)
+                if (err .ne. NF90_NOERR) then
+                    call errore('nf90mpi_inq_attname: ', err)
+                end if
+                if (name .ne. ATT_NAME(j,i)) then
+                    call errori( &
+                       'nf90mpi_inq_attname: unexpected name for var ', i)
+                end if
+                err = nf90mpi_inquire_attribute(ncid, i, name, datatype, length)
+                if (err .ne. NF90_NOERR) then
+                    call errore('nf90mpi_inquire_attribute: ', err)
+                end if
+                if (datatype .ne. ATT_TYPE(j,i)) then
+                    call errori( &
+                           'nf90mpi_inquire_attribute: unexpected type for var ', i)
+                end if
+                if (length .ne. ATT_LEN(j,i)) then
+                    call errori( &
+                        'nf90mpi_inquire_attribute: unexpected length for var ', i)
+                end if
+                if (datatype .eq. NF90_CHAR) then
+                    err = nf90mpi_get_att(ncid, i, name, text)
+                    if (err .ne. NF90_NOERR) then
+                        call errore('nf90mpi_get_att: ', err)
+                    end if
+                    do 3, k = 1, ATT_LEN(j,i)
+                        ndx(1) = k
+                        if (ichar(text(k:k)) .ne. hash(datatype, -1,  &
+                                                       ndx)) &
+                        then
+                            call errori( &
+                'nf90mpi_get_att: unexpected value for var ', i)
+                        else
+                            nok = nok + 1
+                        end if
+3                   continue
+                else
+                    err = nf90mpi_get_att(ncid, i, name, value)
+                    do 4, k = 1, ATT_LEN(j,i)
+                        ndx(1) = k
+                        expect = hash(datatype, -1, ndx)
+                        if (inRange(expect,ATT_TYPE(j,i))) then
+                            if (err .ne. NF90_NOERR) then
+                                call errore( &
+                                    'nf90mpi_get_att: ', err)
+                            end if
+                            if (.not. equal(value(k), expect, &
+                                ATT_TYPE(j,i), NFT_DOUBLE)) then
+                                call errori( &
+                        'Att value read not that expected for var ', i)
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+4                   continue
+                end if
+2           continue
+1       continue
+        ! call print_nok(nok)
+        end
+
+
+! Check file (dims, vars, atts) corresponds to global variables */
+        subroutine check_file(filename) 
+      use pnetcdf
+        implicit        none
+        character*(*)   filename
+#include "tests.inc"
+
+        integer ncid            !/* netCDF id */
+        integer err             !/* netCDF status */
+
+        err = nf90mpi_open(comm, filename, NF90_NOWRITE, info, &
+                         ncid)
+        if (err .ne. NF90_NOERR) then
+            call errore('nf90mpi_open: ', err)
+        else
+            call check_dims(ncid)
+            call check_vars(ncid)
+            call check_atts(ncid)
+            err = nf90mpi_close (ncid)
+            if (err .ne. NF90_NOERR) then
+                call errore('nf90mpi_close: ', err)
+            end if
+        end if
+        end
+
+
+!
+! Functions for accessing attribute test data.
+!
+! NB: 'varid' is 0 for global attributes; thus, global attributes can
+! be handled in the same loop as variable attributes.
+!
+
+      integer FUNCTION VARID(VID)
+      USE PNETCDF
+      IMPLICIT NONE
+      INTEGER VID
+#include "tests.inc"
+      IF (VID .LT. 1) THEN
+          VARID = NF90_GLOBAL
+      ELSE
+          VARID = VID
+      ENDIF
+      end
+
+
+      integer FUNCTION NATTS(VID)
+      USE PNETCDF
+      IMPLICIT  NONE
+      INTEGER VID
+#include "tests.inc"
+      IF (VID .LT. 1) THEN
+          NATTS = numGatts
+      ELSE
+          NATTS = VAR_NATTS(VID)
+      ENDIF
+      END
+
+
+      character*2 FUNCTION ATT_NAME(J,VID)
+      USE PNETCDF
+      IMPLICIT  NONE
+      INTEGER J
+      INTEGER VID
+#include "tests.inc"
+      IF (VID .LT. 1) THEN
+          ATT_NAME = GATT_NAME(J)
+      ELSE
+          ATT_NAME = ATTNAME(J,VID)
+      ENDIF
+      END
+
+
+      integer FUNCTION ATT_TYPE(J,VID)
+      USE PNETCDF
+      IMPLICIT  NONE
+      INTEGER J
+      INTEGER VID
+#include "tests.inc"
+      IF (VID .LT. 1) THEN
+          ATT_TYPE = GATT_TYPE(J)
+      ELSE
+          ATT_TYPE = ATTTYPE(J,VID)
+      ENDIF
+      END
+
+
+      integer FUNCTION ATT_LEN(J,VID)
+      USE PNETCDF
+      IMPLICIT  NONE
+      INTEGER J
+      INTEGER VID
+#include "tests.inc"
+      IF (VID .LT. 1) THEN
+          ATT_LEN = INT(GATT_LEN(J))
+      ELSE
+          ATT_LEN = ATTLEN(J,VID)
+      ENDIF
+      END
+
+
+!
+! Return the minimum value of an internal type.
+!
+        DOUBLE PRECISION function internal_min(type)
+      use pnetcdf
+        implicit        none
+        integer         type
+        doubleprecision min_schar
+        doubleprecision min_short
+        doubleprecision min_int
+        ! doubleprecision min_long
+        doubleprecision max_float
+        doubleprecision max_double
+        doubleprecision min_int64
+#include "tests.inc"
+
+        if (type .eq. NFT_CHAR) then
+            internal_min = 0
+        else if (type .eq. NFT_INT1) then
+#if defined NF90_INT1_IS_C_SIGNED_CHAR
+            internal_min = min_schar()
+#elif defined NF90_INT1_IS_C_SHORT
+            internal_min = min_short()
+#elif defined NF90_INT1_IS_C_INT
+            internal_min = min_int()
+#elif defined NF90_INT1_IS_C_LONG
+            internal_min = min_long()
+#else
+            internal_min = min_schar()
+! #include "No C equivalent to Fortran INTEGER*1"
+#endif
+        else if (type .eq. NFT_INT2) then
+#if defined NF90_INT2_IS_C_SHORT
+            internal_min = min_short()
+#elif defined NF90_INT2_IS_C_INT
+            internal_min = min_int()
+#elif defined NF90_INT2_IS_C_LONG
+            internal_min = min_long()
+#else
+            internal_min = min_short()
+! #include "No C equivalent to Fortran INTEGER*2"
+#endif
+        else if (type .eq. NFT_INT) then
+#if defined NF90_INT_IS_C_INT
+            internal_min = min_int()
+#elif defined NF90_INT_IS_C_LONG
+            internal_min = min_long()
+#else
+            internal_min = min_int()
+! #include "No C equivalent to Fortran INTEGER"
+#endif
+        else if (type .eq. NFT_REAL) then
+#if defined NF90_REAL_IS_C_FLOAT
+            internal_min = -max_float()
+#elif defined NF90_REAL_IS_C_DOUBLE
+            internal_min = -max_double()
+#else
+            internal_min = -max_float()
+! #include "No C equivalent to Fortran REAL"
+#endif
+        else if (type .eq. NFT_DOUBLE) then
+#if defined NF90_DOUBLEPRECISION_IS_C_DOUBLE
+            internal_min = -max_double()
+#elif defined NF90_DOUBLEPRECISION_IS_C_FLOAT
+            internal_min = -max_float()
+#else
+            internal_min = -max_double()
+! #include "No C equivalent to Fortran DOUBLE"
+#endif
+        else if (type .eq. NFT_INT8) then
+            internal_min = min_int64()
+        else
+            stop 'internal_min(): invalid type'
+        end if
+        end
+
+
+!
+! Return the maximum value of an internal type.
+!
+        DOUBLE PRECISION function internal_max(type)
+      use pnetcdf
+        implicit        none
+        integer         type
+        doubleprecision max_schar
+        doubleprecision max_short
+        doubleprecision max_int
+        ! doubleprecision max_long
+        doubleprecision max_float
+        doubleprecision max_double
+        doubleprecision max_int64
+#include "tests.inc"
+
+        if (type .eq. NFT_CHAR) then
+            internal_max = 255
+        else if (type .eq. NFT_INT1) then
+#if defined NF90_INT1_IS_C_SIGNED_CHAR
+            internal_max = max_schar()
+#elif defined NF90_INT1_IS_C_SHORT
+            internal_max = max_short()
+#elif defined NF90_INT1_IS_C_INT
+            internal_max = max_int()
+#elif defined NF90_INT1_IS_C_LONG
+            internal_max = max_long()
+#else
+            internal_max = max_schar()
+! #include "No C equivalent to Fortran INTEGER*1"
+#endif
+        else if (type .eq. NFT_INT2) then
+#if defined NF90_INT2_IS_C_SHORT
+            internal_max = max_short()
+#elif defined NF90_INT2_IS_C_INT
+            internal_max = max_int()
+#elif defined NF90_INT2_IS_C_LONG
+            internal_max = max_long()
+#else
+            internal_max = max_short()
+! #include "No C equivalent to Fortran INTEGER*2"
+#endif
+        else if (type .eq. NFT_INT) then
+#if defined NF90_INT_IS_C_INT
+            internal_max = max_int()
+#elif defined NF90_INT_IS_C_LONG
+            internal_max = max_long()
+#else
+            internal_max = max_int()
+! #include "No C equivalent to Fortran INTEGER"
+#endif
+        else if (type .eq. NFT_REAL) then
+#if defined NF90_REAL_IS_C_FLOAT
+            internal_max = max_float()
+#elif defined NF90_REAL_IS_C_DOUBLE
+            internal_max = max_double()
+#else
+            internal_max = max_float()
+! #include "No C equivalent to Fortran REAL"
+#endif
+        else if (type .eq. NFT_DOUBLE) then
+#if defined NF90_DOUBLEPRECISION_IS_C_DOUBLE
+            internal_max = max_double()
+#elif defined NF90_DOUBLEPRECISION_IS_C_FLOAT
+            internal_max = max_float()
+#else
+            internal_max = max_double()
+! #include "No C equivalent to Fortran DOUBLE"
+#endif
+        else if (type .eq. NFT_INT8) then
+            internal_max = max_int64()
+        else
+            stop 'internal_max(): invalid type'
+        end if
+        end
+
+
+!
+! Return the minimum value of an external type.
+!
+        DOUBLE PRECISION function external_min(type)
+      use pnetcdf
+        implicit        none
+        integer         type
+#include "tests.inc"
+
+        if (type .eq. NF90_BYTE) then
+            external_min = X_BYTE_MIN
+        else if (type .eq. NF90_CHAR) then
+            external_min = X_CHAR_MIN
+        else if (type .eq. NF90_SHORT) then
+            external_min = X_SHORT_MIN
+        else if (type .eq. NF90_INT) then
+            external_min = X_INT_MIN
+        else if (type .eq. NF90_FLOAT) then
+            external_min = X_FLOAT_MIN
+        else if (type .eq. NF90_DOUBLE) then
+            external_min = X_DOUBLE_MIN
+        else if (type .eq. NF90_INT64) then
+            external_min = X_INT8_MIN
+        else
+            stop 'external_min(): invalid type'
+        end if
+        end
+
+
+!
+! Return the maximum value of an internal type.
+!
+        DOUBLE PRECISION function external_max(type)
+      use pnetcdf
+        implicit        none
+        integer         type
+#include "tests.inc"
+
+        if (type .eq. NF90_BYTE) then
+            external_max = X_BYTE_MAX
+        else if (type .eq. NF90_CHAR) then
+            external_max = X_CHAR_MAX
+        else if (type .eq. NF90_SHORT) then
+            external_max = X_SHORT_MAX
+        else if (type .eq. NF90_INT) then
+            external_max = X_INT_MAX
+        else if (type .eq. NF90_FLOAT) then
+            external_max = X_FLOAT_MAX
+        else if (type .eq. NF90_DOUBLE) then
+            external_max = X_DOUBLE_MAX
+        else if (type .eq. NF90_INT64) then
+            external_max = X_INT8_MAX
+        else
+            stop 'external_max(): invalid type'
+        end if
+        end
+
+
+!
+! Indicate whether or not a value lies in the range of an internal type.
+!
+        logical function in_internal_range(itype, value)
+      use pnetcdf
+        implicit        none
+        integer         itype
+        doubleprecision value
+#include "tests.inc"
+        double precision internal_min, internal_max
+
+        in_internal_range = value .ge. internal_min(itype) .and. &
+                            value .le. internal_max(itype)
+        end
+
diff --git a/test/nf_test/Makefile.in b/test/nf_test/Makefile.in
new file mode 100644
index 0000000..9b5c35d
--- /dev/null
+++ b/test/nf_test/Makefile.in
@@ -0,0 +1,93 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I. -I../../src/lib -I../../src/libf
+INCLUDES += -I$(srcdir)/../../src/libf
+LDFLAGS  := $(LDFLAGS) -L../common
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
+
+M4SRCS    = test_get.m4 \
+            test_put.m4  \
+            test_iget.m4 \
+            test_iput.m4
+
+M4SRCS_F  = $(M4SRCS:.m4=.F)
+
+F_SRCS    = nf_error.F \
+            nf_test.F \
+            test_read.F \
+            test_write.F \
+            util.F
+
+C_SRCS    = fortlib.c
+
+HEADERS   = tests.inc.in
+
+C_OBJS  = $(C_SRCS:.c=.o)
+F_OBJS  = $(F_SRCS:.F=.o) $(M4SRCS_F:.F=.o)
+OBJS    = $(C_OBJS) $(F_OBJS)
+
+PROGS  = nf_test
+
+GARBAGE = $(PROGS) $(M4SRCS_F) \
+          scratch.nc test.nc
+
+DIST_GARBAGE = tests.inc
+
+PACKING_LIST = $(C_SRCS) $(F_SRCS) $(M4SRCS) $(HEADERS) depend Makefile.in README
+
+all: $(PROGS)
+
+$(C_OBJS): $(srcdir)/../common/testutils.h
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+nf_test: $(OBJS) $(LIBRARY)
+	$(LINK.F90) $(OBJS) $(LDFLAGS) $(LIBS)
+
+tags: $(F_SRCS) $(C_SRCS) FORCE
+	ctags -t $(F_SRCS) $(C_SRCS) ../fortran/*.c ../libsrc/*.c
+
+# This simple testing target ensures that the test files are present
+testing check: all
+	$(RM) -f $(TEST_OUTDIR)/scratch.nc $(TEST_OUTDIR)/test.nc
+	$(TEST_SEQRUN) ./nf_test -c    -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf_test       -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf_test -c -2 -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf_test -2    -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf_test -c -5 -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf_test -5    -d $(TEST_OUTDIR)
+
+verbose_testing: all
+	$(RM) -f $(TEST_OUTDIR)/scratch.nc $(TEST_OUTDIR)/test.nc
+	$(TEST_SEQRUN) ./nf_test -v -c    -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf_test -v       -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf_test -v -c -2 -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf_test -v -2    -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf_test -v -c -5 -d $(TEST_OUTDIR)
+	$(TEST_SEQRUN) ./nf_test -v -5    -d $(TEST_OUTDIR)
+
+#test.nc: 
+#	(cd ../nc_test && $(MAKE) $(MFLAGS) nc_test && ./nc_test -c)
+#	cp ../nc_test/test.nc .
+
+ptest ptests ptest2 ptest4 ptest6 ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+include $(srcdir)/depend
+
+$(LIBRARY): ;
+
diff --git a/test/nf_test/README b/test/nf_test/README
new file mode 100644
index 0000000..c73c720
--- /dev/null
+++ b/test/nf_test/README
@@ -0,0 +1,9 @@
+This test is ported from Unidata netCDF-3.5 to test the functionality
+of the PnetCDF API Fortran interface particularly on a single processor. 
+
+The typical way to run the test includes two steps:
+
+ 	(1) create test.nc by 	"<mpirun -np 1> ./nf_test -c"
+	(2) run the test   by 	"<mpirun -np 1> ./nf_test -v"
+
+
diff --git a/test/nf_test/depend b/test/nf_test/depend
new file mode 100644
index 0000000..be7d2a9
--- /dev/null
+++ b/test/nf_test/depend
@@ -0,0 +1,31 @@
+fortlib.o: fortlib.c
+lib.o: ../../src/libf/pnetcdf.inc
+lib.o: lib.F
+lib.o: tests.inc
+nf_error.o: ../../src/libf/pnetcdf.inc
+nf_error.o: nf_error.F
+nf_error.o: tests.inc
+nf_test.o: ../../src/libf/pnetcdf.inc
+nf_test.o: nf_test.F
+nf_test.o: tests.inc
+test_get.o: ../../src/libf/pnetcdf.inc
+test_get.o: test_get.F
+test_get.o: tests.inc
+test_put.o: ../../src/libf/pnetcdf.inc
+test_put.o: test_put.F
+test_put.o: tests.inc
+test_iget.o: ../../src/libf/pnetcdf.inc
+test_iget.o: test_iget.F
+test_iget.o: tests.inc
+test_iput.o: ../../src/libf/pnetcdf.inc
+test_iput.o: test_iput.F
+test_iput.o: tests.inc
+test_read.o: ../../src/libf/pnetcdf.inc
+test_read.o: test_read.F
+test_read.o: tests.inc
+test_write.o: ../../src/libf/pnetcdf.inc
+test_write.o: test_write.F
+test_write.o: tests.inc
+util.o: ../../src/libf/pnetcdf.inc
+util.o: tests.inc
+util.o: util.F
diff --git a/test/nf_test/fortlib.c b/test/nf_test/fortlib.c
new file mode 100644
index 0000000..6d2303d
--- /dev/null
+++ b/test/nf_test/fortlib.c
@@ -0,0 +1,289 @@
+/*
+ * $Id: fortlib.c 1468 2013-10-26 16:53:18Z wkliao $
+ *
+ * This file contains support functions for FORTRAN code.  For example,
+ * under HP-UX A.09.05, the U77 library doesn't contain the exit()
+ * routine -- so we create one here.
+ *
+ * This file is heavily modified from nf_test/fortlib.c in the serial netcdf
+ * source.
+ */
+
+
+#include <stdlib.h>
+#include <limits.h>
+#include <float.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <mpinetcdf_impl.h>
+#include <mpifnetcdf.h>
+
+extern FORTRAN_API void FORT_CALL ud_exit_(int *v1);
+extern FORTRAN_API void FORT_CALL ud_abort_(int *v1);
+extern FORTRAN_API double FORT_CALL ud_rand_(int *seed);
+extern FORTRAN_API int FORT_CALL ud_shift_(int * value, int *amount);
+extern FORTRAN_API void FORT_CALL nc_ignorefpe_(int *doit);
+extern FORTRAN_API double FORT_CALL min_schar_(void);
+extern FORTRAN_API double FORT_CALL min_short_(void);
+extern FORTRAN_API double FORT_CALL min_int_(void);
+extern FORTRAN_API double FORT_CALL min_int64_(void);
+extern FORTRAN_API double FORT_CALL max_schar_(void);
+extern FORTRAN_API double FORT_CALL max_short_(void);
+extern FORTRAN_API double FORT_CALL max_int_(void);
+extern FORTRAN_API double FORT_CALL max_int64_(void);
+extern FORTRAN_API double FORT_CALL max_float_(void);
+extern FORTRAN_API double FORT_CALL max_double_(void);
+
+
+#ifdef F77_NAME_UPPER
+#define ud_exit_ UD_EXIT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define ud_exit_  ud_exit__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define ud_exit_  ud_exit
+/* Else leave name alone */
+#endif
+
+FORTRAN_API void FORT_CALL ud_exit_(int *v1) {
+	if (*v1 == 0) {
+		MPI_Finalize();
+		exit(0);
+	}
+	MPI_Abort(MPI_COMM_WORLD, *v1);
+	return;
+}
+
+#ifdef F77_NAME_UPPER
+#define ud_abort_ UD_ABORT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define ud_abort_  ud_abort__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define ud_abort_  ud_abort
+/* Else leave name alone */
+#endif
+
+FORTRAN_API void FORT_CALL ud_abort_(int *v1) {
+	MPI_Abort(MPI_COMM_WORLD, *v1);
+	return;
+}
+
+#ifdef F77_NAME_UPPER
+#define ud_rand_ UD_RAND
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define ud_rand_  ud_rand__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define ud_rand_  ud_rand
+/* Else leave name alone */
+#endif
+
+/*
+* Return a pseudo-random value between 0.0 and 1.0.
+*
+* We don't use RAND_MAX here because not all compilation
+* environments define it (e.g. gcc(1) under SunOS 4.1.3).
+*/
+FORTRAN_API double FORT_CALL ud_rand_(int *seed) {
+	if (*seed != 0)
+		srand(*seed);
+	return (rand() % 32768 )/ 32767.0;
+}
+
+#ifdef F77_NAME_UPPER
+#define ud_shift_ UD_SHIFT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define ud_shift_  ud_shift__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define ud_shift_  ud_shift
+/* Else leave name alone */
+#endif
+
+FORTRAN_API int FORT_CALL ud_shift_(int * value, int *amount) {
+	if(*amount < 0)
+		*value >>= -*amount;
+	else if (*amount > 0)
+		*value <<= *amount;
+	return *value;
+}
+
+#ifdef F77_NAME_UPPER
+#define nc_ignorefpe_ NC_IGNOREFPE
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define nc_ignorefpe_  nc_ignorefpe__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define nc_ignorefpe_  nc_ignorefpe
+/* Else leave name alone */
+#endif
+#include <signal.h>
+FORTRAN_API void FORT_CALL nc_ignorefpe_(int *doit)
+{
+	if(doit)
+		(void) signal(SIGFPE, SIG_IGN);
+}
+
+#ifdef F77_NAME_UPPER
+#define min_schar_ MIN_SCHAR
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define min_schar_  min_schar__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define min_schar_  min_schar
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL min_schar_(void) {
+	return SCHAR_MIN;
+}
+
+#ifdef F77_NAME_UPPER
+#define min_short_ MIN_SHORT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define min_short_  min_short__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define min_short_  min_short
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL min_short_(void) {
+	return SHRT_MIN;
+}
+
+#ifdef F77_NAME_UPPER
+#define min_int_ MIN_INT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define min_int_  min_int__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define min_int_  min_int
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL min_int_(void) {
+	return INT_MIN;
+}
+
+#ifdef F77_NAME_UPPER
+#define min_int64_ MIN_INT64
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define min_int64_  min_int64__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define min_int64_  min_int64
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL min_int64_(void) {
+	return INT64_MIN;
+}
+
+#ifdef F77_NAME_UPPER
+#define max_schar_ MAX_SCHAR
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define max_schar_  max_schar__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define max_schar_  max_schar
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL max_schar_(void) {
+	return SCHAR_MAX;
+}
+
+#ifdef F77_NAME_UPPER
+#define max_short_ MAX_SHORT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define max_short_  max_short__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define max_short_  max_short
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL max_short_(void) {
+	return SHRT_MAX;
+}
+
+#ifdef F77_NAME_UPPER
+#define max_int_ MAX_INT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define max_int_  max_int__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define max_int_  max_int
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL max_int_(void) {
+	return INT_MAX;
+}
+
+#ifdef F77_NAME_UPPER
+#define max_int64_ MAX_INT64
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define max_int64_  max_int64__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define max_int64_  max_int64
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL max_int64_(void) {
+	return INT64_MAX;
+}
+
+#ifdef F77_NAME_UPPER
+#define max_float_ MAX_FLOAT
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define max_float_  max_float__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define max_float_  max_float
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL max_float_(void) {
+	return FLT_MAX;
+}
+
+#ifdef F77_NAME_UPPER
+#define max_double_ MAX_DOUBLE
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define max_double_  max_double__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define max_double_  max_double
+/* Else leave name alone */
+#endif
+FORTRAN_API double FORT_CALL max_double_(void) {
+	return DBL_MAX;
+}
+
+#if 0 /* this is implemented in library src now */
+
+#ifdef F77_NAME_UPPER
+#define nfmpi_issyserr_ NFMPI_ISSYSERR
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define nfmpi_issyserr_  nfmpi_issyserr__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define nfmpi_issyserr_  nfmpi_issyserr
+/* Else leave name alone */
+#endif
+
+FORTRAN_API int FORT_CALL nfmpi_issyserr_(int * A1) {
+	if (*A1 > 0)
+		return 1;
+	else 
+		return 0;
+}
+
+
+#ifdef F77_NAME_UPPER
+#define nfmpi_delete_ NFMPI_DELETE
+#elif defined(F77_NAME_LOWER_2USCORE)
+#define nfmpi_delete_  nfmpi_delete__
+#elif !defined(F77_NAME_LOWER_USCORE)
+#define nfmpi_delete_  nfmpi_delete
+/* Else leave name alone */
+#endif
+FORTRAN_API void FORT_CALL nfmpi_delete_(char * name, int *err, int d1) {
+    char *p1;
+
+    {char *p = name + d1 - 1;
+     int  li;
+        while (*p == ' ' && p > name) p--;
+        p++;
+        p1 = (char *)malloc( p-name + 1 );
+        for (li=0; li<(p-name); li++) { p1[li] = name[li]; }
+        p1[li] = 0; 
+    }
+
+	if ( unlink(p1) != 0 )
+		*err = errno;
+	else
+		*err = 0;
+	free(p1);
+}
+
+#endif
diff --git a/test/nf_test/nf_error.F b/test/nf_test/nf_error.F
new file mode 100644
index 0000000..fdcbc88
--- /dev/null
+++ b/test/nf_test/nf_error.F
@@ -0,0 +1,81 @@
+#if 0
+    Copyright 1996, UCAR/Unidata
+    See netcdf/COPYRIGHT file for copying and redistribution conditions.
+    $Id: nf_error.F 2223 2015-12-15 16:10:30Z wkliao $
+#endif
+
+
+C
+C Use for logging error messages
+C
+        subroutine error(msg)
+        implicit        none
+        character*(*)   msg
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        nfails = nfails + 1
+        if (nfails .le. max_nmpt) print *, msg
+        end
+
+
+C
+C Use for logging error conditions
+C
+        subroutine errori(msg, i)
+        implicit        none
+        character*(*)   msg
+        integer         i
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        nfails = nfails + 1
+        if (nfails .le. max_nmpt) print *, msg, i
+        end
+
+
+C
+C Use for logging error conditions
+C
+        subroutine errord(msg, d)
+        implicit        none
+        character*(*)   msg
+        doubleprecision d
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        nfails = nfails + 1
+        if (nfails .le. max_nmpt) print *, msg, d
+        end
+
+
+C
+C Use for logging error conditions
+C
+        subroutine errorc(msg, string)
+        implicit        none
+        character*(*)   msg
+        character*(*)   string
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer MY_LEN_TRIM
+        nfails = nfails + 1
+        if (nfails .le. max_nmpt) print *, msg, 
+     +      TRIM(string) ! string(1:len_trim(string))
+        end
+
+
+C
+C Use for logging error conditions
+C
+        subroutine errore(msg, err)
+        implicit        none
+        character*(*)   msg
+        integer         err
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        nfails = nfails + 1
+        call errorc(msg, nfmpi_strerror(err))
+        end
diff --git a/test/nf_test/nf_test.F b/test/nf_test/nf_test.F
new file mode 100644
index 0000000..d563032
--- /dev/null
+++ b/test/nf_test/nf_test.F
@@ -0,0 +1,861 @@
+#if 0
+/*********************************************************************
+ *   Copyright 1996, UCAR/Unidata
+ *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ *   $Id: nf_test.F 2224 2015-12-16 06:10:36Z wkliao $
+ *********************************************************************/
+
+/*
+ * Test driver for netCDF-3 interface.  This program performs tests against
+ * the netCDF-3 specification for all user-level functions in an
+ * implementation of the netCDF library.
+ *
+ * Unless invoked with "-r" (readonly) option, must be invoked from a
+ * directory in which the invoker has write permission.
+ *
+ * Files:
+ * The read-only tests read files:
+ *     test.nc (see below)
+ *     test_get.F (used merely as an example of a non-netCDF file)
+ * 
+ * The write tests 
+ *     read test.nc (see below) 
+ *     write scratch.nc (deleted after each test)
+ * 
+ * The file test.nc is created by running nc_test with the -c (create) option.
+ */
+#endif
+
+        subroutine usage()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer MY_LEN_TRIM
+        call error('Usage: '//TRIM(progname)//
+     +             ' [-c | -hrv -n <MAX_NMPT>]')
+        call error('       nf_test [-c]')
+        call error('   [-h] Print help' )
+        call error('   [-c] Create file test.nc (Do not do tests)' )
+        call error('   [-1] test CDF-1 format' )
+        call error('   [-2] test CDF-2 format' )
+        call error('   [-5] test CDF-5 format' )
+        call error('   [-r] Just do read-only tests' )
+        call error(
+     +  '   [-d directory] directory for storing input/output files' )
+        call error('   [-v] Verbose mode' )
+        call error(
+     +  '   [-n <max>] max. number of messages per test (Default: 20)')
+        end
+
+
+        subroutine report_test
+        implicit        none
+        character*128   msg
+#include "tests.inc"
+
+        integer MY_LEN_TRIM
+        write(msg,"(A,I1)") '*** TESTING F77 '//
+     +                      TRIM(PROGNAME)//
+     +                      ' for CDF-', cdf_format
+        if (nfailsTotal .ne. 0) then
+          write(*,*) TRIM(PROGNAME)//
+     +               ' expects to see 0 failure ... '//
+     +               'Total number of failures: ', nfailsTotal
+        endif
+        call pass_fail(nfailsTotal, msg)
+        end
+
+        subroutine test(name, func)
+        implicit        none
+        character*(*)   name
+        character*25    name_str
+        integer         name_len
+        external        func
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer MY_LEN_TRIM
+        name_len = MY_LEN_TRIM(name)
+        name_str(1:name_len) = name(:)
+        name_str(name_len+1:25) = ' '
+        if (verbose) write(*, 1) name_str
+1       format('*** Testing ', a, ' ... ')
+
+        nfails = 0
+        call func()
+        nfailsTotal = nfailsTotal + nfails
+        if ( nfails .ne. 0) then
+            print *, ' '
+            print *, '  ### ', nfails, ' FAILURES TESTING ', name, 
+     +               '! Stop ... ###'
+            call report_test
+            stop
+        end if
+        end
+
+
+#if _CRAYIEEE
+! which machines need this?
+        subroutine getarg(iarg, carg)
+        implicit        none
+        integer iarg
+        character*(*)   carg
+        integer ilen
+        integer ierror
+        call PXFGETARG(iarg, carg, ilen, ierror)
+        end
+#endif
+
+        program nf_test
+#if defined(VISUAL_CPLUSPLUS)
+!       DIGITAL Visual Fortran needs DFLIB for getarg
+        USE DFLIB
+!       DIGITAL Visual Fortran needs DFPORT for iargc
+        USE DFPORT
+        implicit        none
+#elif defined(NAGf90Fortran)
+        USE F90_UNIX_ENV, only : iargc, getarg
+        implicit none
+#else
+        implicit        none
+        integer         iargc
+#endif
+#if defined(__crayx1)
+        integer         ipxfargc 
+#endif
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer         argc
+        character*80    arg
+        integer         iarg
+        integer         iopt
+        character*1     opt
+        integer         lastopt
+        logical         skiparg
+        integer         err                       
+        integer MY_LEN_TRIM
+
+        external        test_nfmpi_strerror
+        external        test_nfmpi_open
+        external        test_nfmpi_close
+        external        test_nfmpi_inq
+        external        test_nfmpi_inq_dimid
+        external        test_nfmpi_inq_dim
+        external        test_nfmpi_inq_dimlen
+        external        test_nfmpi_inq_dimname
+        external        test_nfmpi_inq_varid
+        external        test_nfmpi_inq_var
+        external        test_nfmpi_inq_natts
+        external        test_nfmpi_inq_ndims
+        external        test_nfmpi_inq_nvars
+        external        test_nfmpi_inq_unlimdim
+        external        test_nfmpi_inq_vardimid
+        external        test_nfmpi_inq_varname
+        external        test_nfmpi_inq_varnatts
+        external        test_nfmpi_inq_varndims
+        external        test_nfmpi_inq_vartype
+        external        test_nfmpi_get_var1_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_get_var1_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_get_var1_int2
+#endif
+        external        test_nfmpi_get_var1_int
+        external        test_nfmpi_get_var1_real
+        external        test_nfmpi_get_var1_double
+        external        test_nfmpi_get_var1_int8
+        external        test_nfmpi_get_var_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_get_var_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_get_var_int2
+#endif
+        external        test_nfmpi_get_var_int
+        external        test_nfmpi_get_var_real
+        external        test_nfmpi_get_var_double
+        external        test_nfmpi_get_var_int8
+        external        test_nfmpi_get_vara_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_get_vara_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_get_vara_int2
+#endif
+        external        test_nfmpi_get_vara_int
+        external        test_nfmpi_get_vara_real
+        external        test_nfmpi_get_vara_double
+        external        test_nfmpi_get_vara_int8
+        external        test_nfmpi_get_vars_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_get_vars_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_get_vars_int2
+#endif
+        external        test_nfmpi_get_vars_int
+        external        test_nfmpi_get_vars_real
+        external        test_nfmpi_get_vars_double
+        external        test_nfmpi_get_vars_int8
+
+        external        test_nfmpi_get_varm_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_get_varm_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_get_varm_int2
+#endif
+        external        test_nfmpi_get_varm_int
+        external        test_nfmpi_get_varm_real
+        external        test_nfmpi_get_varm_double
+        external        test_nfmpi_get_varm_int8
+
+        external        test_nfmpi_iget_var1_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_iget_var1_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_iget_var1_int2
+#endif
+        external        test_nfmpi_iget_var1_int
+        external        test_nfmpi_iget_var1_real
+        external        test_nfmpi_iget_var1_double
+        external        test_nfmpi_iget_var1_int8
+        external        test_nfmpi_iget_var_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_iget_var_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_iget_var_int2
+#endif
+        external        test_nfmpi_iget_var_int
+        external        test_nfmpi_iget_var_real
+        external        test_nfmpi_iget_var_double
+        external        test_nfmpi_iget_var_int8
+        external        test_nfmpi_iget_vara_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_iget_vara_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_iget_vara_int2
+#endif
+        external        test_nfmpi_iget_vara_int
+        external        test_nfmpi_iget_vara_real
+        external        test_nfmpi_iget_vara_double
+        external        test_nfmpi_iget_vara_int8
+        external        test_nfmpi_iget_vars_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_iget_vars_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_iget_vars_int2
+#endif
+        external        test_nfmpi_iget_vars_int
+        external        test_nfmpi_iget_vars_real
+        external        test_nfmpi_iget_vars_double
+        external        test_nfmpi_iget_vars_int8
+
+        external        test_nfmpi_iget_varm_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_iget_varm_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_iget_varm_int2
+#endif
+        external        test_nfmpi_iget_varm_int
+        external        test_nfmpi_iget_varm_real
+        external        test_nfmpi_iget_varm_double
+        external        test_nfmpi_iget_varm_int8
+
+        external        test_nfmpi_get_att_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_get_att_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_get_att_int2
+#endif
+        external        test_nfmpi_get_att_int
+        external        test_nfmpi_get_att_real
+        external        test_nfmpi_get_att_double
+        external        test_nfmpi_get_att_int8
+        external        test_nfmpi_inq_att
+        external        test_nfmpi_inq_attname
+        external        test_nfmpi_inq_attid
+        external        test_nfmpi_inq_attlen
+        external        test_nfmpi_inq_atttype
+        external        test_nfmpi_create
+        external        test_nfmpi_redef
+        external        test_nfmpi_enddef
+        external        test_nfmpi_sync
+        external        test_nfmpi_abort
+        external        test_nfmpi_def_dim
+        external        test_nfmpi_rename_dim
+        external        test_nfmpi_def_var
+        external        test_nfmpi_put_var1_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_put_var1_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_put_var1_int2
+#endif
+        external        test_nfmpi_put_var1_int
+        external        test_nfmpi_put_var1_real
+        external        test_nfmpi_put_var1_double
+        external        test_nfmpi_put_var1_int8
+        external        test_nfmpi_put_var_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_put_var_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_put_var_int2
+#endif
+        external        test_nfmpi_put_var_int
+        external        test_nfmpi_put_var_real
+        external        test_nfmpi_put_var_double
+        external        test_nfmpi_put_var_int8
+        external        test_nfmpi_put_vara_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_put_vara_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_put_vara_int2
+#endif
+        external        test_nfmpi_put_vara_int
+        external        test_nfmpi_put_vara_real
+        external        test_nfmpi_put_vara_double
+        external        test_nfmpi_put_vara_int8
+        external        test_nfmpi_put_vars_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_put_vars_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_put_vars_int2
+#endif
+        external        test_nfmpi_put_vars_int
+        external        test_nfmpi_put_vars_real
+        external        test_nfmpi_put_vars_double
+        external        test_nfmpi_put_vars_int8
+
+        external        test_nfmpi_put_varm_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_put_varm_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_put_varm_int2
+#endif
+        external        test_nfmpi_put_varm_int
+        external        test_nfmpi_put_varm_real
+        external        test_nfmpi_put_varm_double
+        external        test_nfmpi_put_varm_int8
+
+        external        test_nfmpi_iput_var1_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_iput_var1_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_iput_var1_int2
+#endif
+        external        test_nfmpi_iput_var1_int
+        external        test_nfmpi_iput_var1_real
+        external        test_nfmpi_iput_var1_double
+        external        test_nfmpi_iput_var1_int8
+        external        test_nfmpi_iput_var_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_iput_var_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_iput_var_int2
+#endif
+        external        test_nfmpi_iput_var_int
+        external        test_nfmpi_iput_var_real
+        external        test_nfmpi_iput_var_double
+        external        test_nfmpi_iput_var_int8
+        external        test_nfmpi_iput_vara_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_iput_vara_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_iput_vara_int2
+#endif
+        external        test_nfmpi_iput_vara_int
+        external        test_nfmpi_iput_vara_real
+        external        test_nfmpi_iput_vara_double
+        external        test_nfmpi_iput_vara_int8
+        external        test_nfmpi_iput_vars_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_iput_vars_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_iput_vars_int2
+#endif
+        external        test_nfmpi_iput_vars_int
+        external        test_nfmpi_iput_vars_real
+        external        test_nfmpi_iput_vars_double
+        external        test_nfmpi_iput_vars_int8
+
+        external        test_nfmpi_iput_varm_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_iput_varm_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_iput_varm_int2
+#endif
+        external        test_nfmpi_iput_varm_int
+        external        test_nfmpi_iput_varm_real
+        external        test_nfmpi_iput_varm_double
+        external        test_nfmpi_iput_varm_int8
+
+        external        test_nfmpi_rename_var
+        external        test_nfmpi_put_att_text
+#if defined(NF_INT1_T)
+        external        test_nfmpi_put_att_int1
+#endif
+#if defined(NF_INT2_T)
+        external        test_nfmpi_put_att_int2
+#endif
+        external        test_nfmpi_put_att_int
+        external        test_nfmpi_put_att_real
+        external        test_nfmpi_put_att_double
+        external        test_nfmpi_put_att_int8
+        external        test_nfmpi_copy_att
+        external        test_nfmpi_rename_att
+        external        test_nfmpi_del_att
+        external        test_nfmpi_set_fill
+#if 0
+        external        test_nfmpi_set_default_format
+#endif
+        external        nc_ignorefpe
+
+        call MPI_INIT(err)                        
+        comm = MPI_COMM_WORLD                   
+
+        call nc_ignorefpe(1)
+
+        testfile = 'test.nc'
+        scratch = 'scratch.nc'
+
+        nfailsTotal = 0
+        call getarg(0, progname)
+        create_file = .false.   !/* file test.nc will normally already exist */
+        readonly = .false.      !/* assume may write in test dir as default */
+        verbose = .false.
+        max_nmpt = 20
+        skiparg = .false.
+        cdf_format = 1
+        extra_flags = 0
+
+#if defined(__crayx1)
+        argc = ipxfargc()
+#else
+        argc = iargc()
+#endif
+        call getarg(0, PROGNAME)
+
+        do 1, iarg = 1, argc
+            if (skiparg) then
+                skiparg = .false.
+            else
+                call getarg(iarg, arg)
+                if (arg(1:1) .eq. '-') then
+                    lastopt = index(arg, ' ') - 1
+                    do 2, iopt = 2, lastopt
+                        opt = arg(iopt:iopt)
+                        if (opt .eq. 'c') then
+                            create_file = .true.
+                        else if (opt .eq. 'r') then
+                            readonly = .true.
+                        else if (opt .eq. 'v') then
+                            verbose = .true.
+                        else if (opt .eq. 'n') then
+                            call getarg(iarg+1, arg)
+                            ! NOTE: The UNICOS 8 fort77(1) compiler does
+                            ! not support list-directed I/O from an internal
+                            ! file -- so we use a format specification.
+                            read (arg, '(i6)') max_nmpt
+                            skiparg = .true.
+                            go to 1
+                        else if (opt .eq. '1') then
+                            cdf_format = 1
+                        else if (opt .eq. '2') then
+                            cdf_format = 2
+                            extra_flags = NF_64BIT_OFFSET
+                        else if (opt .eq. '5') then
+                            cdf_format = 5
+                            extra_flags = NF_64BIT_DATA
+                        else if (opt .eq. 'd') then
+                            call getarg(iarg+1, arg)
+                            testfile = TRIM(arg)//
+     +                                 "/test.nc"
+                            scratch = TRIM(arg) //
+     +                                 "/scratch.nc"
+                            skiparg = .true.
+                            go to 1
+                        else
+                            call usage
+                            call ud_exit(1)
+                        end if
+    2           continue
+                else
+                    call usage
+                    call ud_exit(1)
+                end if
+            end if
+1       continue
+
+        numGatts = 6
+        numVars  = 136
+        numTypes = 6
+        if (cdf_format .EQ. 5) then
+            numGatts = NGATTS
+            numVars  = NVARS
+            numTypes = NTYPES
+        endif
+
+C       PVFS2 driver has a problem of ADIOI_Set_lock when data sieving is
+C       enabled
+        call MPI_Info_create(info, err)
+C       call MPI_Info_set(info, "romio_pvfs2_posix_write", "enable",err)
+
+C       /* Initialize global variables defining test file */
+        call init_gvars
+
+        if ( create_file ) then
+            call write_file(testfile)
+            call MPI_Info_free(info, err)
+            if (nfailsTotal .eq. 0)
+     +           call ud_exit(0)
+            call ud_exit(1)
+        end if
+
+C       /* delete any existing scratch netCDF file */
+        if ( .not. readonly )
+     +      err = nfmpi_delete(scratch, MPI_INFO_NULL)
+
+C       /* Test read-only functions, using pregenerated test-file */
+        call test('nfmpi_strerror', test_nfmpi_strerror)
+        call test('nfmpi_open', test_nfmpi_open)
+        call test('nfmpi_close', test_nfmpi_close)
+        call test('nfmpi_inq', test_nfmpi_inq)
+        call test('nfmpi_inq_dimid', test_nfmpi_inq_dimid)
+        call test('nfmpi_inq_dim', test_nfmpi_inq_dim)
+        call test('nfmpi_inq_dimlen', test_nfmpi_inq_dimlen)
+        call test('nfmpi_inq_dimname', test_nfmpi_inq_dimname)
+        call test('nfmpi_inq_varid', test_nfmpi_inq_varid)
+        call test('nfmpi_inq_var', test_nfmpi_inq_var)
+        call test('nfmpi_inq_natts', test_nfmpi_inq_natts)
+        call test('nfmpi_inq_ndims', test_nfmpi_inq_ndims)
+        call test('nfmpi_inq_nvars', test_nfmpi_inq_nvars)
+        call test('nfmpi_inq_unlimdim', test_nfmpi_inq_unlimdim)
+        call test('nfmpi_inq_vardimid', test_nfmpi_inq_vardimid)
+        call test('nfmpi_inq_varname', test_nfmpi_inq_varname)
+        call test('nfmpi_inq_varnatts', test_nfmpi_inq_varnatts)
+        call test('nfmpi_inq_varndims', test_nfmpi_inq_varndims)
+        call test('nfmpi_inq_vartype', test_nfmpi_inq_vartype)
+
+        call test('nfmpi_get_var1_text', test_nfmpi_get_var1_text)
+#if defined(NF_INT1_T)
+        call test('nfmpi_get_var1_int1', test_nfmpi_get_var1_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nfmpi_get_var1_int2', test_nfmpi_get_var1_int2)
+#endif
+        call test('nfmpi_get_var1_int', test_nfmpi_get_var1_int)
+        call test('nfmpi_get_var1_real', test_nfmpi_get_var1_real)
+        call test('nfmpi_get_var1_double', test_nfmpi_get_var1_double)
+        call test('nfmpi_get_var1_int8', test_nfmpi_get_var1_int8)
+
+        call test('nfmpi_get_var_text', test_nfmpi_get_var_text)
+#if defined(NF_INT1_T)
+        call test('nfmpi_get_var_int1', test_nfmpi_get_var_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nfmpi_get_var_int2', test_nfmpi_get_var_int2)
+#endif
+        call test('nfmpi_get_var_int', test_nfmpi_get_var_int)
+        call test('nfmpi_get_var_real', test_nfmpi_get_var_real)
+        call test('nfmpi_get_var_double', test_nfmpi_get_var_double)
+        call test('nfmpi_get_var_int8', test_nfmpi_get_var_int8)
+
+        call test('nfmpi_get_vara_text', test_nfmpi_get_vara_text)
+#if defined(NF_INT1_T)
+        call test('nfmpi_get_vara_int1', test_nfmpi_get_vara_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nfmpi_get_vara_int2', test_nfmpi_get_vara_int2)
+#endif
+        call test('nfmpi_get_vara_int', test_nfmpi_get_vara_int)
+        call test('nfmpi_get_vara_real', test_nfmpi_get_vara_real)
+        call test('nfmpi_get_vara_double', test_nfmpi_get_vara_double)
+        call test('nfmpi_get_vara_int8', test_nfmpi_get_vara_int8)
+
+        call test('nfmpi_get_vars_text', test_nfmpi_get_vars_text)
+#if defined(NF_INT1_T)
+        call test('nfmpi_get_vars_int1', test_nfmpi_get_vars_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nfmpi_get_vars_int2', test_nfmpi_get_vars_int2)
+#endif
+        call test('nfmpi_get_vars_int', test_nfmpi_get_vars_int)
+        call test('nfmpi_get_vars_real', test_nfmpi_get_vars_real)
+        call test('nfmpi_get_vars_double', test_nfmpi_get_vars_double)
+        call test('nfmpi_get_vars_int8', test_nfmpi_get_vars_int8)
+
+        call test('nfmpi_get_varm_text', test_nfmpi_get_varm_text)
+#if defined(NF_INT1_T)
+        call test('nfmpi_get_varm_int1', test_nfmpi_get_varm_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nfmpi_get_varm_int2', test_nfmpi_get_varm_int2)
+#endif
+        call test('nfmpi_get_varm_int', test_nfmpi_get_varm_int)
+        call test('nfmpi_get_varm_real', test_nfmpi_get_varm_real)
+        call test('nfmpi_get_varm_double', test_nfmpi_get_varm_double)
+        call test('nfmpi_get_varm_int8', test_nfmpi_get_varm_int8)
+
+        call test('nfmpi_iget_var1_text', test_nfmpi_iget_var1_text)
+#if defined(NF_INT1_T)
+        call test('nfmpi_iget_var1_int1', test_nfmpi_iget_var1_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nfmpi_iget_var1_int2', test_nfmpi_iget_var1_int2)
+#endif
+        call test('nfmpi_iget_var1_int', test_nfmpi_iget_var1_int)
+        call test('nfmpi_iget_var1_real', test_nfmpi_iget_var1_real)
+        call test('nfmpi_iget_var1_double', test_nfmpi_iget_var1_double)
+        call test('nfmpi_iget_var1_int8', test_nfmpi_iget_var1_int8)
+
+        call test('nfmpi_iget_var_text', test_nfmpi_iget_var_text)
+#if defined(NF_INT1_T)
+        call test('nfmpi_iget_var_int1', test_nfmpi_iget_var_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nfmpi_iget_var_int2', test_nfmpi_iget_var_int2)
+#endif
+        call test('nfmpi_iget_var_int', test_nfmpi_iget_var_int)
+        call test('nfmpi_iget_var_real', test_nfmpi_iget_var_real)
+        call test('nfmpi_iget_var_double', test_nfmpi_iget_var_double)
+        call test('nfmpi_iget_var_int8', test_nfmpi_iget_var_int8)
+
+        call test('nfmpi_iget_vara_text', test_nfmpi_iget_vara_text)
+#if defined(NF_INT1_T)
+        call test('nfmpi_iget_vara_int1', test_nfmpi_iget_vara_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nfmpi_iget_vara_int2', test_nfmpi_iget_vara_int2)
+#endif
+        call test('nfmpi_iget_vara_int', test_nfmpi_iget_vara_int)
+        call test('nfmpi_iget_vara_real', test_nfmpi_iget_vara_real)
+        call test('nfmpi_iget_vara_double', test_nfmpi_iget_vara_double)
+        call test('nfmpi_iget_vara_int8', test_nfmpi_iget_vara_int8)
+
+        call test('nfmpi_iget_vars_text', test_nfmpi_iget_vars_text)
+#if defined(NF_INT1_T)
+        call test('nfmpi_iget_vars_int1', test_nfmpi_iget_vars_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nfmpi_iget_vars_int2', test_nfmpi_iget_vars_int2)
+#endif
+        call test('nfmpi_iget_vars_int', test_nfmpi_iget_vars_int)
+        call test('nfmpi_iget_vars_real', test_nfmpi_iget_vars_real)
+        call test('nfmpi_iget_vars_double', test_nfmpi_iget_vars_double)
+        call test('nfmpi_iget_vars_int8', test_nfmpi_iget_vars_int8)
+
+        call test('nfmpi_iget_varm_text', test_nfmpi_iget_varm_text)
+#if defined(NF_INT1_T)
+        call test('nfmpi_iget_varm_int1', test_nfmpi_iget_varm_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nfmpi_iget_varm_int2', test_nfmpi_iget_varm_int2)
+#endif
+        call test('nfmpi_iget_varm_int', test_nfmpi_iget_varm_int)
+        call test('nfmpi_iget_varm_real', test_nfmpi_iget_varm_real)
+        call test('nfmpi_iget_varm_double', test_nfmpi_iget_varm_double)
+        call test('nfmpi_iget_varm_int8', test_nfmpi_iget_varm_int8)
+
+        call test('nfmpi_get_att_text', test_nfmpi_get_att_text)
+#if defined(NF_INT1_T)
+        call test('nfmpi_get_att_int1', test_nfmpi_get_att_int1)
+#endif
+#if defined(NF_INT2_T)
+        call test('nfmpi_get_att_int2', test_nfmpi_get_att_int2)
+#endif
+        call test('nfmpi_get_att_int', test_nfmpi_get_att_int)
+        call test('nfmpi_get_att_real', test_nfmpi_get_att_real)
+        call test('nfmpi_get_att_double', test_nfmpi_get_att_double)
+        call test('nfmpi_get_att_int8', test_nfmpi_get_att_int8)
+        call test('nfmpi_inq_att', test_nfmpi_inq_att)
+        call test('nfmpi_inq_attname', test_nfmpi_inq_attname)
+        call test('nfmpi_inq_attid', test_nfmpi_inq_attid)
+        call test('nfmpi_inq_attlen', test_nfmpi_inq_attlen)
+        call test('nfmpi_inq_atttype', test_nfmpi_inq_atttype)
+
+C           /* Test write functions */
+        if (.not. readonly) then
+            call test('nfmpi_create', test_nfmpi_create)
+            call test('nfmpi_redef', test_nfmpi_redef)
+            call test('nfmpi_enddef', test_nfmpi_enddef)
+            call test('nfmpi_sync', test_nfmpi_sync)
+            call test('nfmpi_abort', test_nfmpi_abort)
+            call test('nfmpi_def_dim', test_nfmpi_def_dim)
+            call test('nfmpi_rename_dim', test_nfmpi_rename_dim)
+            call test('nfmpi_def_var', test_nfmpi_def_var)
+            call test('nfmpi_put_var1_text', test_nfmpi_put_var1_text)
+#if defined(NF_INT1_T)
+            call test('nfmpi_put_var1_int1', test_nfmpi_put_var1_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nfmpi_put_var1_int2', test_nfmpi_put_var1_int2)
+#endif
+            call test('nfmpi_put_var1_int', test_nfmpi_put_var1_int)
+            call test('nfmpi_put_var1_real', test_nfmpi_put_var1_real)
+            call test('nfmpi_put_var1_double', 
+     +                 test_nfmpi_put_var1_double)
+            call test('nfmpi_put_var1_int8', test_nfmpi_put_var1_int8)
+            call test('nfmpi_put_var_text', test_nfmpi_put_var_text)
+#if defined(NF_INT1_T)
+            call test('nfmpi_put_var_int1', test_nfmpi_put_var_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nfmpi_put_var_int2', test_nfmpi_put_var_int2)
+#endif
+            call test('nfmpi_put_var_int', test_nfmpi_put_var_int)
+            call test('nfmpi_put_var_real', test_nfmpi_put_var_real)
+            call test('nfmpi_put_var_double',
+     +                 test_nfmpi_put_var_double)
+            call test('nfmpi_put_var_int8', test_nfmpi_put_var_int8)
+            call test('nfmpi_put_vara_text', test_nfmpi_put_vara_text)
+#if defined(NF_INT1_T)
+            call test('nfmpi_put_vara_int1', test_nfmpi_put_vara_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nfmpi_put_vara_int2', test_nfmpi_put_vara_int2)
+#endif
+            call test('nfmpi_put_vara_int', test_nfmpi_put_vara_int)
+            call test('nfmpi_put_vara_real', test_nfmpi_put_vara_real)
+            call test('nfmpi_put_vara_double',
+     +                 test_nfmpi_put_vara_double)
+            call test('nfmpi_put_vara_int8', test_nfmpi_put_vara_int8)
+            call test('nfmpi_put_vars_text', test_nfmpi_put_vars_text)
+#if defined(NF_INT1_T)
+            call test('nfmpi_put_vars_int1', test_nfmpi_put_vars_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nfmpi_put_vars_int2', test_nfmpi_put_vars_int2)
+#endif
+            call test('nfmpi_put_vars_int', test_nfmpi_put_vars_int)
+            call test('nfmpi_put_vars_real', test_nfmpi_put_vars_real)
+            call test('nfmpi_put_vars_double',
+     +                 test_nfmpi_put_vars_double)
+            call test('nfmpi_put_vars_int8', test_nfmpi_put_vars_int8)
+
+            call test('nfmpi_put_varm_text', test_nfmpi_put_varm_text)
+#if defined(NF_INT1_T)
+            call test('nfmpi_put_varm_int1', test_nfmpi_put_varm_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nfmpi_put_varm_int2', test_nfmpi_put_varm_int2)
+#endif
+            call test('nfmpi_put_varm_int', test_nfmpi_put_varm_int)
+            call test('nfmpi_put_varm_real', test_nfmpi_put_varm_real)
+            call test('nfmpi_put_varm_double',
+     +                 test_nfmpi_put_varm_double)
+            call test('nfmpi_put_varm_int8', test_nfmpi_put_varm_int8)
+
+            call test('nfmpi_iput_var1_text', test_nfmpi_iput_var1_text)
+#if defined(NF_INT1_T)
+            call test('nfmpi_iput_var1_int1', test_nfmpi_iput_var1_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nfmpi_iput_var1_int2', test_nfmpi_iput_var1_int2)
+#endif
+            call test('nfmpi_iput_var1_int', test_nfmpi_iput_var1_int)
+            call test('nfmpi_iput_var1_real', test_nfmpi_iput_var1_real)
+            call test('nfmpi_iput_var1_double', 
+     +                 test_nfmpi_iput_var1_double)
+            call test('nfmpi_iput_var1_int8', test_nfmpi_iput_var1_int8)
+
+            call test('nfmpi_iput_var_text', test_nfmpi_iput_var_text)
+#if defined(NF_INT1_T)
+            call test('nfmpi_iput_var_int1', test_nfmpi_iput_var_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nfmpi_iput_var_int2', test_nfmpi_iput_var_int2)
+#endif
+            call test('nfmpi_iput_var_int', test_nfmpi_iput_var_int)
+            call test('nfmpi_iput_var_real', test_nfmpi_iput_var_real)
+            call test('nfmpi_iput_var_double',
+     +                 test_nfmpi_iput_var_double)
+            call test('nfmpi_iput_var_int8', test_nfmpi_iput_var_int8)
+
+            call test('nfmpi_iput_vara_text', test_nfmpi_iput_vara_text)
+#if defined(NF_INT1_T)
+            call test('nfmpi_iput_vara_int1', test_nfmpi_iput_vara_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nfmpi_iput_vara_int2', test_nfmpi_iput_vara_int2)
+#endif
+            call test('nfmpi_iput_vara_int', test_nfmpi_iput_vara_int)
+            call test('nfmpi_iput_vara_real', test_nfmpi_iput_vara_real)
+            call test('nfmpi_iput_vara_double',
+     +                 test_nfmpi_iput_vara_double)
+            call test('nfmpi_iput_vara_int8', test_nfmpi_iput_vara_int8)
+
+            call test('nfmpi_iput_vars_text', test_nfmpi_iput_vars_text)
+#if defined(NF_INT1_T)
+            call test('nfmpi_iput_vars_int1', test_nfmpi_iput_vars_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nfmpi_iput_vars_int2', test_nfmpi_iput_vars_int2)
+#endif
+            call test('nfmpi_iput_vars_int', test_nfmpi_iput_vars_int)
+            call test('nfmpi_iput_vars_real', test_nfmpi_iput_vars_real)
+            call test('nfmpi_iput_vars_double',
+     +                 test_nfmpi_iput_vars_double)
+            call test('nfmpi_iput_vars_int8', test_nfmpi_iput_vars_int8)
+
+            call test('nfmpi_iput_varm_text', test_nfmpi_iput_varm_text)
+#if defined(NF_INT1_T)
+            call test('nfmpi_iput_varm_int1', test_nfmpi_iput_varm_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nfmpi_iput_varm_int2', test_nfmpi_iput_varm_int2)
+#endif
+            call test('nfmpi_iput_varm_int', test_nfmpi_iput_varm_int)
+            call test('nfmpi_iput_varm_real', test_nfmpi_iput_varm_real)
+            call test('nfmpi_iput_varm_double',
+     +                 test_nfmpi_iput_varm_double)
+            call test('nfmpi_iput_varm_int8', test_nfmpi_iput_varm_int8)
+
+            call test('nfmpi_rename_var', test_nfmpi_rename_var)
+            call test('nfmpi_put_att_text', test_nfmpi_put_att_text)
+#if defined(NF_INT1_T)
+            call test('nfmpi_put_att_int1', test_nfmpi_put_att_int1)
+#endif
+#if defined(NF_INT2_T)
+            call test('nfmpi_put_att_int2', test_nfmpi_put_att_int2)
+#endif
+            call test('nfmpi_put_att_int', test_nfmpi_put_att_int)
+            call test('nfmpi_put_att_real', test_nfmpi_put_att_real)
+            call test('nfmpi_put_att_double',
+     +                 test_nfmpi_put_att_double)
+            call test('nfmpi_put_att_int8', test_nfmpi_put_att_int8)
+            call test('nfmpi_copy_att', test_nfmpi_copy_att)
+            call test('nfmpi_rename_att', test_nfmpi_rename_att)
+            call test('nfmpi_del_att', test_nfmpi_del_att)
+            call test('nfmpi_set_fill', test_nfmpi_set_fill)
+#if 0
+            call test('nfmpi_set_default_format',
+     +                test_nfmpi_set_default_format);
+#endif
+        end if
+
+        call MPI_Info_free(info, err)
+
+        call report_test
+
+        ! if (nfailsTotal .eq. 0) call ud_exit(0)
+        call ud_exit(0)
+        end
diff --git a/test/nf_test/test_get.m4 b/test/nf_test/test_get.m4
new file mode 100644
index 0000000..fc5da7e
--- /dev/null
+++ b/test/nf_test/test_get.m4
@@ -0,0 +1,1149 @@
+divert(-1)
+
+dnl This is m4 source.
+dnl Process using m4 to produce FORTRAN language file.
+
+changequote([,])
+
+undefine([index])dnl
+
+dnl Macros
+
+dnl Upcase(str)
+dnl
+define([Upcase],[dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)])
+
+dnl NFT_ITYPE(type)
+dnl
+define([NFT_ITYPE], [NFT_[]Upcase($1)])
+
+dnl ARITH_VAR1(itype, value)
+dnl
+define([ARITH_VAR1], [ifelse($1, text, ichar($2), $2)])
+
+dnl ARITH3(itype, value)
+dnl
+define([ARITH3], [ifelse($1, text, ichar($2($3:$3)), $2($3))])
+
+dnl  DATATYPE(funf_suffix)
+dnl
+define([DATATYPE], [dnl
+ifelse($1, text, character*MAX_NELS $2,
+ifelse($1, int1, NF_INT1_T $2$3,
+ifelse($1, int2, NF_INT2_T $2$3,
+ifelse($1, int, integer $2$3,
+ifelse($1, int8, NF_INT8_T $2$3,
+ifelse($1, real, real $2$3,
+ifelse($1, double, doubleprecision $2$3)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  DATATYPE_VAR1(funf_suffix)
+dnl
+define([DATATYPE_VAR1], [dnl
+ifelse($1, text, character $2,
+ifelse($1, int1, NF_INT1_T $2,
+ifelse($1, int2, NF_INT2_T $2,
+ifelse($1, int, integer $2,
+ifelse($1, int8, NF_INT8_T $2,
+ifelse($1, real, real $2,
+ifelse($1, double, doubleprecision $2)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl TEST_NFMPI_GET_VAR1(TYPE)
+dnl
+define([TEST_NFMPI_GET_VAR1],[dnl
+        subroutine test_nfmpi_get_var1_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes
+        double precision hash4
+        logical inRange3, in_internal_range, equal
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        integer nok      
+        integer*8 index(MAX_RANK)
+        doubleprecision expect
+        logical canConvert     
+        DATATYPE_VAR1($1, value)
+        doubleprecision val
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_begin_indep_data(ncid)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            do 2, j = 1, var_rank(i)
+                index(j) = 1
+2           continue
+            err = nfmpi_get_var1_$1(BAD_ID, i, index, value)
+            if (err .ne. NF_EBADID)
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_get_var1_$1(ncid, BAD_VARID,
+     +                  index, value)
+            if (err .ne. NF_ENOTVAR)
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                index(j) = var_shape(j,i) + 1
+                err = nfmpi_get_var1_$1(ncid, i, index, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad index: ', err)
+                endif
+                index(j) = 1
+3           continue
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                if (err .ne. NF_NOERR)
+     +              call error('error in index2indexes 1')
+                expect = hash4( var_type(i), var_rank(i), index, 
+     +                          NFT_ITYPE($1) )
+                err = nfmpi_get_var1_$1(ncid, i, index,
+     +                          value)
+                if (canConvert) then
+                    if (inRange3(expect,var_type(i), 
+     +                           NFT_ITYPE($1))) then
+                        if (in_internal_range(NFT_ITYPE($1),
+     +                                        expect)) then
+                            if (err .ne. NF_NOERR) then
+                                call errore('nfmpi_get_var1_$1: ',
+     +                                      err)
+                            else
+                                val = ARITH_VAR1($1, value)
+                                if (.not. equal(val, expect, 
+     +                                          var_type(i), 
+     +                                          NFT_ITYPE($1))) then
+                                    call errori('varid: ', i)
+                                    call errorc('var_name: ',
+     +                                  var_name(i))
+                                    call errord('unexpected: ', val)
+                                    call errord('expecting: ', expect)
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+                        else
+                            if (err .ne. NF_ERANGE)
+     +                          call errore('Range error: ', err)
+                        end if
+                    else
+                        if (err .ne. NF_NOERR .and. err .ne. NF_ERANGE)
+     +                      call errore('OK or Range error: ', err)
+                    end if
+                else
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                end if
+4           continue
+1       continue
+        err = nfmpi_end_indep_data(ncid)
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ',  err)
+        call print_nok(nok)
+        end
+])
+
+dnl TEST_NFMPI_GET_VAR(TYPE)
+dnl
+define([TEST_NFMPI_GET_VAR],[dnl
+        subroutine test_nfmpi_get_var_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes
+        double precision hash4
+        logical inRange3, in_internal_range, equal
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer nels
+        integer nok      
+        integer*8 index(MAX_RANK)
+        doubleprecision expect(MAX_NELS)
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            err = nfmpi_get_var_$1_all(BAD_ID, i, value)
+            if (err .ne. NF_EBADID)
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_get_var_$1_all(ncid, BAD_VARID, value)
+            if (err .ne. NF_ENOTVAR)
+     +          call errore('bad var id: ', err)
+            nels = 1
+            do 3, j = 1, var_rank(i)
+                nels = nels * int(var_shape(j,i))
+3           continue
+            allInExtRange = .true.
+            allInIntRange = .true.
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                if (err .ne. NF_NOERR)
+     +              call error('error in index2indexes 1')
+                expect(j) = hash4( var_type(i), var_rank(i), index, 
+     +                          NFT_ITYPE($1) )
+                if (inRange3(expect(j),var_type(i), NFT_ITYPE($1))) then
+                    allInIntRange = allInIntRange .and.
+     +                  in_internal_range(NFT_ITYPE($1), expect(j))
+                else
+                    allInExtRange = .false.
+                end if
+4           continue
+            err = nfmpi_get_var_$1_all(ncid, i, value)
+            if (canConvert) then
+                if (allInExtRange) then
+                    if (allInIntRange) then
+                        if (err .ne. NF_NOERR) 
+     +                      call errore('nfmpi_get_var_$1_all: ',
+     +                                  err)
+                    else
+                        if (err .ne. NF_ERANGE)
+     +                      call errore('Range error: ', err)
+                    endif
+                else
+                    if (err .ne. NF_NOERR  .and. err .ne. NF_ERANGE)
+     +                  call errore('Range error: ', err)
+                endif
+                do 5, j = 1, var_nels(i)
+                    if (inRange3(expect(j),var_type(i),
+     +                           NFT_ITYPE($1)) .and.
+     +                  in_internal_range(NFT_ITYPE($1),
+     +                                          expect(j))) then
+                        val = ARITH3($1, value, j)
+                        if (.not. equal(val, expect(j), 
+     +                                  var_type(i), 
+     +                                  NFT_ITYPE($1))) then
+                            call errord('unexpected: ', val)
+                            call errord('expecting: ', expect(j))
+                        else
+                            nok = nok + 1
+                        end if
+                    endif
+5               continue
+            else
+                if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+            end if
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ',  err)
+        call print_nok(nok)
+        end
+])
+
+
+dnl TEST_NFMPI_GET_VARA(TYPE)
+dnl
+define([TEST_NFMPI_GET_VARA],[dnl
+        subroutine test_nfmpi_get_vara_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash4
+        logical inRange3, in_internal_range, equal
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer nels
+        integer nslabs
+        integer nok      
+        integer*8 start(MAX_RANK)
+        integer*8 edge(MAX_RANK)
+        integer*8 index(MAX_RANK)
+        integer*8 mid(MAX_RANK)
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision expect(MAX_NELS)
+        doubleprecision val
+        integer ud_shift
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv. 
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert'
+            if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+2           continue
+            err = nfmpi_get_vara_$1_all(BAD_ID, i, start,
+     +                  edge, value)
+            if (err .ne. NF_EBADID)
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_get_vara_$1_all(ncid, BAD_VARID, start, 
+     +                           edge, value)
+            if (err .ne. NF_ENOTVAR)
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_get_vara_$1_all(ncid, i, start,
+     +                               edge, value)
+                if (canConvert .and. err .ne. NF_EINVALCOORDS)
+     +              call errore('bad index: ', err)
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nfmpi_get_vara_$1_all(ncid, i, start,
+     +                               edge, value)
+                if (canConvert .and. err .ne. NF_EEDGE)
+     +              call errore('bad edge: ', err)
+                edge(j) = 1
+3           continue
+
+C           /* Check non-scalars for correct error returned even when */
+C           /* there is nothing to get (edge(j).eq.0) */
+            if (var_rank(i) .gt. 0) then
+                do 10, j = 1, var_rank(i)
+                    edge(j) = 0
+10              continue
+                err = nfmpi_get_vara_$1_all(BAD_ID, i, start,
+     +                  edge, value)
+                if (err .ne. NF_EBADID) 
+     +              call errore('bad ncid: ', err)
+                err = nfmpi_get_vara_$1_all(ncid, BAD_VARID,
+     +                  start, edge, value)
+                if (err .ne. NF_ENOTVAR) 
+     +              call errore('bad var id: ', err)
+                do 11, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .gt. 1) then     !/* skip record dim */
+                        start(j) = var_shape(j,i) + 1
+                        err = nfmpi_get_vara_$1_all(ncid, i,
+     +                          start, edge, value)
+                        if (canConvert .and. err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                        start(j) = 1
+                    endif
+11              continue
+                err = nfmpi_get_vara_$1_all(ncid, i, start,
+     +                          edge, value)
+                if (canConvert) then
+                    if (err .ne. NF_NOERR) 
+     +                  call error(nfmpi_strerror(err))
+                else
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                endif
+                do 12, j = 1, var_rank(i)
+                    edge(j) = 1
+12              continue
+            endif
+
+C           Choose a random point dividing each dim into 2 parts
+C           get 2^rank (nslabs) slabs so defined
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+C           bits of k determine whether to get lower or upper part of dim 
+            do 5, k = 1, nslabs
+                nels = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift((k-1), -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    nels = nels * int(edge(j))
+6               continue
+                allInIntRange = .true.
+                allInExtRange = .true.
+                do 7, j = 1, nels
+                    err = index2indexes(j, var_rank(i), edge, index)
+                    if (err .ne. NF_NOERR)
+     +                  call error('error in index2indexes 1')
+                    do 8, d = 1, var_rank(i)
+                        index(d) = index(d) + start(d) - 1
+8                   continue
+                    expect(j) = hash4(var_type(i), var_rank(i), index, 
+     +                                NFT_ITYPE($1))
+                    if (inRange3(expect(j),var_type(i), 
+     +                           NFT_ITYPE($1))) then
+                        allInIntRange = 
+     +                      allInIntRange .and.
+     +                      in_internal_range(NFT_ITYPE($1), expect(j))
+                    else
+                        allInExtRange = .false.
+                    end if
+7               continue
+                err = nfmpi_get_vara_$1_all(ncid, i, start,
+     +                          edge, value)
+                if (canConvert) then
+                    if (allInExtRange) then
+                        if (allInIntRange) then
+                            if (err .ne. NF_NOERR)
+     +                          call errore(
+     +                  'nfmpi_get_vara_$1_all:', err)
+                        else
+                            if (err .ne. NF_ERANGE)
+     +                          call errore('Range error: ', err)
+                        end if
+                    else
+                        if (err .ne. NF_NOERR .and. err .ne. NF_ERANGE)
+     +                      call errore('OK or Range error: ', err)
+                    end if
+                    do 9, j = 1, nels
+                        if (inRange3(expect(j),var_type(i),
+     +                               NFT_ITYPE($1)) .and.
+     +                      in_internal_range(NFT_ITYPE($1), expect(j)))
+     +                          then
+                            val = ARITH3($1, value, j)
+                            if (.not.equal(val,expect(j),
+     +                                     var_type(i),NFT_ITYPE($1))) 
+     +                              then
+                                call error(
+     +                              'value read not that expected')
+                                if (verbose) then
+                                    call error(' ')
+                                    call errori('varid: ', i)
+                                    call errorc('var_name: ',
+     +                                  var_name(i))
+                                    call errori('element number: %d ', 
+     +                                          j)
+                                    call errord('expect: ', expect(j))
+                                    call errord('got: ', val)
+                                end if
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+9                   continue
+                else
+                    if (nels .gt. 0  .and. err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                end if
+5           continue
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errorc('nfmpi_close: ', nfmpi_strerror(err))
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_GET_VARS(TYPE)
+dnl
+define([TEST_NFMPI_GET_VARS],dnl
+[dnl
+        subroutine test_nfmpi_get_vars_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash4
+        logical inRange3, in_internal_range, equal
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer nels
+        integer nslabs
+        integer nstarts         
+        integer nok             
+        integer*8 start(MAX_RANK)
+        integer*8 edge(MAX_RANK)
+        integer*8 index(MAX_RANK)
+        integer*8 index2(MAX_RANK)
+        integer*8 mid(MAX_RANK)
+        integer*8 count(MAX_RANK)
+        integer*8 sstride(MAX_RANK)
+        integer*8 stride(MAX_RANK)
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision expect(MAX_NELS)
+        doubleprecision val
+        integer ud_shift
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv. 
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert'
+            if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+2           continue
+            err = nfmpi_get_vars_$1_all(BAD_ID, i, start,
+     +                  edge, stride, value)
+            if (err .ne. NF_EBADID)
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_get_vars_$1_all(ncid, BAD_VARID,
+     +                  start, edge, stride, 
+     +                           value)
+            if (err .ne. NF_ENOTVAR)
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_get_vars_$1_all(ncid, i, start,
+     +                               edge, stride, 
+     +                               value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad index: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nfmpi_get_vars_$1_all(ncid, i, start,
+     +                               edge, stride, 
+     +                               value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EEDGE)
+     +                  call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nfmpi_get_vars_$1_all(ncid, i, start,
+     +                               edge, stride,value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_ESTRIDE)
+     +                  call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
+3           continue
+C           Choose a random point dividing each dim into 2 parts
+C           get 2^rank (nslabs) slabs so defined
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+C           bits of k determine whether to get lower or upper part of dim
+C           choose random stride from 1 to edge
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, j-1), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        sstride(j) = 1 + roll(edge(j))
+                    else
+                        sstride(j) = 1
+                    end if
+                    nstarts = nstarts * int(stride(j))
+6               continue
+                do 7, m = 1, nstarts
+                    err = index2indexes(m, var_rank(i), sstride, 
+     +                                  index)
+                    if (err .ne. NF_NOERR)
+     +                  call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) / 
+     +                                  stride(j)
+                        nels = nels * int(count(j))
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+C                   Random choice of forward or backward 
+C    /* TODO
+C                   if ( roll(2) ) then
+C                       for (j = 0 j < var_rank(i) j++) {
+C                           index(j) += (count(j) - 1) * stride(j)
+C                           stride(j) = -stride(j)
+C                       }
+C                   end if
+C    */
+                    allInIntRange = .true.
+                    allInExtRange = .true.
+                    do 9, j = 1, nels
+                        err = index2indexes(j, var_rank(i), count, 
+     +                                      index2)
+                        if (err .ne. NF_NOERR)
+     +                      call error('error in index2indexes() 1')
+                        do 10, d = 1, var_rank(i)
+                            index2(d) = index(d) + (index2(d)-1) * 
+     +                                  stride(d)
+10                      continue
+                        expect(j) = hash4(var_type(i), var_rank(i), 
+     +                                    index2, NFT_ITYPE($1))
+                        if (inRange3(expect(j),var_type(i),
+     +                               NFT_ITYPE($1))) then
+                            allInIntRange = 
+     +                          allInIntRange .and.
+     +                          in_internal_range(NFT_ITYPE($1), 
+     +                                            expect(j))
+                        else
+                            allInExtRange = .false.
+                        end if
+9                   continue
+                    err = nfmpi_get_vars_$1_all(ncid, i, index,
+     +                                   count, stride,
+     +                                   value)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (allInIntRange) then
+                                if (err .ne. NF_NOERR)
+     +                              call error(nfmpi_strerror(err))
+                            else
+                                if (err .ne. NF_ERANGE)
+     +                              call errore('Range error: ', err)
+                            end if
+                        else
+                            if (err .ne. NF_NOERR .and.
+     +                          err .ne. NF_ERANGE)
+     +                          call errore('OK or Range error: ', err)
+                        end if
+                        do 11, j = 1, nels
+                            if (inRange3(expect(j),var_type(i),
+     +                          NFT_ITYPE($1)) .and.
+     +                          in_internal_range(NFT_ITYPE($1), 
+     +                                            expect(j))) then
+                                val = ARITH3($1, value, j)
+                                if (.not.equal(val, expect(j),
+     +                              var_type(i), NFT_ITYPE($1))) then
+                                    call error(
+     +                                  'value read not that expected')
+                                    if (verbose) then
+                                        call error(' ')
+                                        call errori('varid: ', i)
+                                        call errorc('var_name: ', 
+     +                                              var_name(i))
+                                        call errori('element number: ',
+     +                                              j)
+                                        call errord('expect: ', 
+     +                                              expect(j))
+                                        call errord('got: ', val)
+                                    end if
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+11                      continue
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_GET_VARM(TYPE)
+dnl
+define([TEST_NFMPI_GET_VARM],dnl
+[dnl
+        subroutine test_nfmpi_get_varm_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash4
+        logical inRange3, in_internal_range, equal
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer nels
+        integer nslabs
+        integer nstarts         
+        integer nok             
+        integer*8 start(MAX_RANK)
+        integer*8 edge(MAX_RANK)
+        integer*8 index(MAX_RANK)
+        integer*8 index2(MAX_RANK)
+        integer*8 mid(MAX_RANK)
+        integer*8 count(MAX_RANK)
+        integer*8 sstride(MAX_RANK)
+        integer*8 stride(MAX_RANK)
+        integer*8 imap(MAX_RANK)
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision expect(MAX_NELS)
+        doubleprecision val
+        integer ud_shift
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv. 
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assertion'
+            if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assertion'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+                imap(j) = 1
+2           continue
+            err = nfmpi_get_varm_$1_all(BAD_ID, i, start, edge,
+     +                           stride, imap, 
+     +                           value)
+            if (err .ne. NF_EBADID)
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_get_varm_$1_all(ncid, BAD_VARID, start,
+     +                           edge, stride, 
+     +                           imap, value)
+            if (err .ne. NF_ENOTVAR)
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_get_varm_$1_all(ncid, i, start,
+     +                               edge, stride, 
+     +                               imap, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad index: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nfmpi_get_varm_$1_all(ncid, i, start,
+     +                               edge, stride, 
+     +                               imap, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EEDGE)
+     +                  call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nfmpi_get_varm_$1_all(ncid, i, start,
+     +                               edge, stride, 
+     +                               imap, value)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_ESTRIDE)
+     +                  call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
+3           continue
+C           Choose a random point dividing each dim into 2 parts 
+C           get 2^rank (nslabs) slabs so defined 
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+C           /* bits of k determine whether to get lower or upper part 
+C            * of dim
+C            * choose random stride from 1 to edge */
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift((k-1), -(j-1)), 2) .ne. 0) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        stride(j) = 1+roll(edge(j))
+                    else
+                        stride(j) = 1
+                    end if
+                    sstride(j) = stride(j)
+                    nstarts = nstarts * int(stride(j))
+6               continue
+                do 7, m = 1, nstarts
+                    err = index2indexes(m, var_rank(i), sstride, index)
+                    if (err .ne. NF_NOERR)
+     +                  call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) / 
+     +                                  stride(j)
+                        nels = nels * int(count(j))
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+C                   Random choice of forward or backward 
+C    /* TODO
+C                   if ( roll(2) ) then
+C                       for (j = 0 j < var_rank(i) j++) {
+C                           index(j) += (count(j) - 1) * stride(j)
+C                           stride(j) = -stride(j)
+C                       }
+C                   end if
+C     */
+                    if (var_rank(i) .gt. 0) then
+                        imap(1) = 1
+                        do 9, j = 2, var_rank(i)
+                            imap(j) = imap(j-1) * count(j-1)
+9                       continue
+                    end if
+                    allInIntRange = .true.
+                    allInExtRange = .true.
+                    do 10, j = 1, nels
+                        err = index2indexes(j, var_rank(i), count, 
+     +                                      index2)
+                        if (err .ne. NF_NOERR)
+     +                      call error('error in index2indexes 1')
+                        do 11, d = 1, var_rank(i)
+                            index2(d) = index(d) + (index2(d)-1) * 
+     +                                  stride(d)
+11                      continue
+                        expect(j) = hash4(var_type(i), var_rank(i), 
+     +                                    index2, NFT_ITYPE($1))
+                        if (inRange3(expect(j),var_type(i),
+     +                               NFT_ITYPE($1))) then
+                            allInIntRange = 
+     +                          allInIntRange .and.
+     +                          in_internal_range(NFT_ITYPE($1),
+     +                                            expect(j))
+                        else
+                            allInExtRange = .false.
+                        end if
+10                  continue
+                    err = nfmpi_get_varm_$1_all(ncid,i,index,count,
+     +                                   stride,imap,value)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (allInIntRange) then
+                                if (err .ne. NF_NOERR)
+     +                              call error(nfmpi_strerror(err))
+                            else
+                                if (err .ne. NF_ERANGE)
+     +                              call errore('Range error: ', err)
+                            end if
+                        else
+                            if (err .ne. NF_NOERR .and.
+     +                          err .ne. NF_ERANGE)
+     +                          call errore('OK or Range error: ', err)
+                        end if
+                        do 12, j = 1, nels
+                            if (inRange3(expect(j),var_type(i),
+     +                                   NFT_ITYPE($1)) .and.
+     +                          in_internal_range(NFT_ITYPE($1),
+     +                                            expect(j))) then
+                                val = ARITH3($1, value, j)
+                                if (.not.equal(val, expect(j),
+     +                                         var_type(i), 
+     +                                         NFT_ITYPE($1))) then
+                                    call error(
+     +                                  'value read not that expected')
+                                    if (verbose) then
+                                        call error(' ')
+                                        call errori('varid: ', i)
+                                        call errorc('var_name: ', 
+     +                                          var_name(i))
+                                        call errori('element number: ',
+     +                                              j)
+                                        call errord('expect: ', 
+     +                                              expect(j))
+                                        call errord('got: ', val)
+                                    end if
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+12                      continue
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ',  err)
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_GET_ATT(TYPE)
+dnl
+define([TEST_NFMPI_GET_ATT],dnl
+[dnl
+        subroutine test_nfmpi_get_att_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer ATT_TYPE, NATTS, ATT_LEN
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer i
+        integer j
+        integer k
+        integer err
+        integer*8 ndx(1)
+        logical allInExtRange
+        logical allInIntRange
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision expect(MAX_NELS)
+        integer nok             
+        doubleprecision val
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_open: ', err)
+
+        do 1, i = 0, numVars
+            do 2, j = 1, NATTS(i)
+                canConvert = (ATT_TYPE(j,i) .eq. NF_CHAR) .eqv.
+     +                       (NFT_ITYPE($1) .eq. NFT_TEXT)
+                err = nfmpi_get_att_$1(BAD_ID, i,
+     +                  ATT_NAME(j,i), 
+     +                  value)
+                if (err .ne. NF_EBADID) 
+     +              call errore('bad ncid: ', err)
+                err = nfmpi_get_att_$1(ncid, BAD_VARID, 
+     +                              ATT_NAME(j,i), 
+     +                              value)
+                if (err .ne. NF_ENOTVAR) 
+     +              call errore('bad var id: ', err)
+                err = nfmpi_get_att_$1(ncid, i,
+     +                                 'noSuch', 
+     +                                  value)
+                if (err .ne. NF_ENOTATT) 
+     +              call errore('Bad attribute name: ', err)
+                allInIntRange = .true.
+                allInExtRange = .true.
+                do 3, k = 1, ATT_LEN(j,i)
+                    ndx(1) = k
+                    expect(k) = hash4(ATT_TYPE(j,i), -1, ndx, 
+     +                                NFT_ITYPE($1))
+                    if (inRange3(expect(k),ATT_TYPE(j,i),
+     +                           NFT_ITYPE($1))) then
+                        allInIntRange = 
+     +                      allInIntRange .and.
+     +                      in_internal_range(NFT_ITYPE($1), expect(k))
+                    else
+                        allInExtRange = .false.
+                    end if
+3               continue
+                err = nfmpi_get_att_$1(ncid, i, 
+     +                                 ATT_NAME(j,i),
+     +                                 value)
+                if (canConvert .or. ATT_LEN(j,i) .eq. 0) then
+                    if (allInExtRange) then
+                        if (allInIntRange) then
+                            if (err .ne. NF_NOERR)
+     +                           call errore('nfmpi_get_att_$1: ',
+     +                           err)
+                        else
+                            if (err .ne. NF_ERANGE)
+     +                          call errore('Range error: ', err)
+                        end if
+                    else
+                        if (err .ne. NF_NOERR .and. err .ne. NF_ERANGE)
+     +                      call errore('OK or Range error: ',
+     +                                  err)
+                    end if
+                    do 4, k = 1, ATT_LEN(j,i)
+                        if (inRange3(expect(k),ATT_TYPE(j,i),
+     +                               NFT_ITYPE($1)) .and.
+     +                      in_internal_range(NFT_ITYPE($1),
+     +                                        expect(k))) then
+                            val = ARITH3($1, value, k)
+                            if (.not.equal(val, expect(k),
+     +                                     ATT_TYPE(j,i), 
+     +                                     NFT_ITYPE($1)))then
+                                call error(
+     +                              'value read not that expected')
+                                if (verbose) then
+                                    call error(' ')
+                                    call errori('varid: ', i)
+                                    call errorc('att_name: ', 
+     +                                  ATT_NAME(j,i))
+                                    call errori('element number: ', k)
+                                    call errord('expect: ', expect(k))
+                                    call errord('got: ', val)
+                                end if
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+4                   continue
+                else
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                end if
+2           continue
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+])dnl
+
+divert(0)dnl
+dnl If you see this line, you can ignore the next one.
+C Do not edit this file. It is produced from the corresponding .m4 source */
+
+C*********************************************************************
+C   Copyright 1996, UCAR/Unidata
+C   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+C   $Id: test_get.m4 2224 2015-12-16 06:10:36Z wkliao $
+C*********************************************************************
+
+TEST_NFMPI_GET_VAR1(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_GET_VAR1(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_GET_VAR1(int2)
+#endif
+TEST_NFMPI_GET_VAR1(int)
+TEST_NFMPI_GET_VAR1(int8)
+TEST_NFMPI_GET_VAR1(real)
+TEST_NFMPI_GET_VAR1(double)
+
+TEST_NFMPI_GET_VAR(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_GET_VAR(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_GET_VAR(int2)
+#endif
+TEST_NFMPI_GET_VAR(int)
+TEST_NFMPI_GET_VAR(int8)
+TEST_NFMPI_GET_VAR(real)
+TEST_NFMPI_GET_VAR(double)
+
+TEST_NFMPI_GET_VARA(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_GET_VARA(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_GET_VARA(int2)
+#endif
+TEST_NFMPI_GET_VARA(int)
+TEST_NFMPI_GET_VARA(int8)
+TEST_NFMPI_GET_VARA(real)
+TEST_NFMPI_GET_VARA(double)
+
+TEST_NFMPI_GET_VARS(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_GET_VARS(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_GET_VARS(int2)
+#endif
+TEST_NFMPI_GET_VARS(int)
+TEST_NFMPI_GET_VARS(int8)
+TEST_NFMPI_GET_VARS(real)
+TEST_NFMPI_GET_VARS(double)
+
+TEST_NFMPI_GET_VARM(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_GET_VARM(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_GET_VARM(int2)
+#endif
+TEST_NFMPI_GET_VARM(int)
+TEST_NFMPI_GET_VARM(int8)
+TEST_NFMPI_GET_VARM(real)
+TEST_NFMPI_GET_VARM(double)
+
+TEST_NFMPI_GET_ATT(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_GET_ATT(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_GET_ATT(int2)
+#endif
+TEST_NFMPI_GET_ATT(int)
+TEST_NFMPI_GET_ATT(int8)
+TEST_NFMPI_GET_ATT(real)
+TEST_NFMPI_GET_ATT(double)
diff --git a/test/nf_test/test_iget.m4 b/test/nf_test/test_iget.m4
new file mode 100644
index 0000000..db913f1
--- /dev/null
+++ b/test/nf_test/test_iget.m4
@@ -0,0 +1,1033 @@
+divert(-1)
+
+dnl This is m4 source.
+dnl Process using m4 to produce FORTRAN language file.
+
+changequote([,])
+
+undefine([index])dnl
+
+dnl Macros
+
+dnl Upcase(str)
+dnl
+define([Upcase],[dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)])
+
+dnl NFT_ITYPE(type)
+dnl
+define([NFT_ITYPE], [NFT_[]Upcase($1)])
+
+dnl ARITH_VAR1(itype, value)
+dnl
+define([ARITH_VAR1], [ifelse($1, text, ichar($2), $2)])
+
+dnl ARITH3(itype, value)
+dnl
+define([ARITH3], [ifelse($1, text, ichar($2($3:$3)), $2($3))])
+
+dnl  DATATYPE(funf_suffix)
+dnl
+define([DATATYPE], [dnl
+ifelse($1, text, character*MAX_NELS $2,
+ifelse($1, int1, NF_INT1_T $2$3,
+ifelse($1, int2, NF_INT2_T $2$3,
+ifelse($1, int, integer $2$3,
+ifelse($1, int8, NF_INT8_T $2$3,
+ifelse($1, real, real $2$3,
+ifelse($1, double, doubleprecision $2$3)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  DATATYPE_VAR1(funf_suffix)
+dnl
+define([DATATYPE_VAR1], [dnl
+ifelse($1, text, character $2,
+ifelse($1, int1, NF_INT1_T $2,
+ifelse($1, int2, NF_INT2_T $2,
+ifelse($1, int, integer $2,
+ifelse($1, int8, NF_INT8_T $2,
+ifelse($1, real, real $2,
+ifelse($1, double, doubleprecision $2)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl TEST_NFMPI_IGET_VAR1(TYPE)
+dnl
+define([TEST_NFMPI_IGET_VAR1],[dnl
+        subroutine test_nfmpi_iget_var1_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        integer nok      
+        integer*8 index(MAX_RANK)
+        doubleprecision expect
+        logical canConvert     
+        DATATYPE_VAR1($1, value)
+        doubleprecision val
+        integer err_w, reqid(1), st(1)
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            do 2, j = 1, var_rank(i)
+                index(j) = 1
+2           continue
+            err = nfmpi_iget_var1_$1(BAD_ID,i,index,value,
+     +                               reqid(1))
+            if (err .ne. NF_EBADID)
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iget_var1_$1(ncid,BAD_VARID,
+     +                  index, value, reqid(1))
+            if (err .ne. NF_ENOTVAR)
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                index(j) = var_shape(j,i) + 1
+                err = nfmpi_iget_var1_$1(ncid,i,index,value,
+     +                               reqid(1))
+                if (err .eq. NF_NOERR)
+     +              err_w = nfmpi_wait_all(ncid, 1, reqid, st)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad index: ', err)
+                endif
+                index(j) = 1
+3           continue
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                if (err .ne. NF_NOERR)
+     +              call error('error in index2indexes 1')
+                expect = hash4( var_type(i), var_rank(i), index, 
+     +                          NFT_ITYPE($1) )
+                err = nfmpi_iget_var1_$1(ncid,i,index,value,
+     +                               reqid(1))
+                if (err .eq. NF_NOERR)
+     +              err_w = nfmpi_wait_all(ncid, 1, reqid, st)
+                if (canConvert) then
+                    if (inRange3(expect,var_type(i), 
+     +                           NFT_ITYPE($1))) then
+                        if (in_internal_range(NFT_ITYPE($1),
+     +                                        expect)) then
+                            if (st(1) .ne. 0) then
+                                call errore('nfmpi_iget_var: ',st(1))
+                            else
+                                val = ARITH_VAR1($1, value)
+                                if (.not. equal(val, expect, 
+     +                                          var_type(i), 
+     +                                          NFT_ITYPE($1))) then
+                                    call errord('unexpected: ', val)
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+                        else
+                            if (st(1) .ne. NF_ERANGE)
+     +                          call errore('Range error: ', st(1))
+                        end if
+                    else
+                        if (st(1) .ne. 0  .and. st(1) .ne. NF_ERANGE)
+     +                      call errore('OK or Range error: ', st(1))
+                    end if
+                else
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                end if
+4           continue
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ',  err)
+        call print_nok(nok)
+        end
+])
+
+dnl TEST_NFMPI_IGET_VAR(TYPE)
+dnl
+define([TEST_NFMPI_IGET_VAR],[dnl
+        subroutine test_nfmpi_iget_var_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer nels
+        integer nok      
+        integer*8 index(MAX_RANK)
+        doubleprecision expect(MAX_NELS)
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer err_w, reqid(1), st(1)      
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            err = nfmpi_iget_var_$1(BAD_ID, i, value,reqid(1))
+            if (err .ne. NF_EBADID)
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iget_var_$1(ncid, BAD_VARID, value,reqid(1))
+            if (err .ne. NF_ENOTVAR)
+     +          call errore('bad var id: ', err)
+            nels = 1
+            do 3, j = 1, var_rank(i)
+                nels = nels * int(var_shape(j,i))
+3           continue
+            allInExtRange = .true.
+            allInIntRange = .true.
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                if (err .ne. NF_NOERR)
+     +              call error('error in index2indexes 1')
+                expect(j) = hash4( var_type(i), var_rank(i), index, 
+     +                          NFT_ITYPE($1) )
+                if (inRange3(expect(j),var_type(i), NFT_ITYPE($1))) then
+                    allInIntRange = allInIntRange .and.
+     +                  in_internal_range(NFT_ITYPE($1), expect(j))
+                else
+                    allInExtRange = .false.
+                end if
+4           continue
+            err = nfmpi_iget_var_$1(ncid, i, value,reqid(1))
+            if (err .eq. NF_NOERR)
+     +          err_w = nfmpi_wait_all(ncid,1,reqid,st)
+            if (canConvert) then
+                if (allInExtRange) then
+                    if (allInIntRange) then
+                        if (st(1) .ne. 0) 
+     +                      call errore('nfmpi_iget_var: ', st(1))
+                    else
+                        if (st(1) .ne. NF_ERANGE)
+     +                      call errore('Range error: ', st(1))
+                    endif
+                else
+                    if (st(1) .ne. 0  .and. st(1) .ne. NF_ERANGE)
+     +                  call errore('Range error: ', st(1))
+                endif
+                do 5, j = 1, var_nels(i)
+                    if (inRange3(expect(j),var_type(i),
+     +                           NFT_ITYPE($1)) .and.
+     +                  in_internal_range(NFT_ITYPE($1),
+     +                                          expect(j))) then
+                        val = ARITH3($1, value, j)
+                        if (.not. equal(val, expect(j), 
+     +                                  var_type(i), 
+     +                                  NFT_ITYPE($1))) then
+                            call errord('unexpected: ', val)
+                        else
+                            nok = nok + 1
+                        end if
+                    endif
+5               continue
+            else
+                if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+            end if
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ',  err)
+        call print_nok(nok)
+        end
+])
+
+
+dnl TEST_NFMPI_IGET_VARA(TYPE)
+dnl
+define([TEST_NFMPI_IGET_VARA],[dnl
+        subroutine test_nfmpi_iget_vara_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer roll, index2indexes
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer nels
+        integer nslabs
+        integer nok      
+        integer*8 start(MAX_RANK)
+        integer*8 edge(MAX_RANK)
+        integer*8 index(MAX_RANK)
+        integer*8 mid(MAX_RANK)
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision expect(MAX_NELS)
+        doubleprecision val
+        integer ud_shift
+        integer err_w, reqid(1), st(1)      
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv. 
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert'
+            if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+2           continue
+            err = nfmpi_iget_vara_$1(BAD_ID, i, start,
+     +                  edge, value,reqid(1))
+            if (err .ne. NF_EBADID)
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iget_vara_$1(ncid, BAD_VARID, start, 
+     +                           edge, value,reqid(1))
+            if (err .ne. NF_ENOTVAR)
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_iget_vara_$1(ncid, i, start,
+     +                               edge, value,reqid(1))
+                if (canConvert .and. err .ne. NF_EINVALCOORDS)
+     +              call errore('bad index: ', err)
+                if (err .EQ. NF_NOERR)
+     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nfmpi_iget_vara_$1(ncid, i, start,
+     +                               edge, value,reqid(1))
+                if (canConvert .and. err .ne. NF_EEDGE)
+     +              call errore('bad edge: ', err)
+                if (err .EQ. NF_NOERR)
+     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                edge(j) = 1
+3           continue
+
+C           /* Check non-scalars for correct error returned even when */
+C           /* there is nothing to get (edge(j).eq.0) */
+            if (var_rank(i) .gt. 0) then
+                do 10, j = 1, var_rank(i)
+                    edge(j) = 0
+10              continue
+                err = nfmpi_iget_vara_$1(BAD_ID, i, start,
+     +                  edge, value,reqid(1))
+                if (err .ne. NF_EBADID) 
+     +              call errore('bad ncid: ', err)
+                err = nfmpi_iget_vara_$1(ncid, BAD_VARID,
+     +                  start, edge, value,reqid(1))
+                if (err .ne. NF_ENOTVAR) 
+     +              call errore('bad var id: ', err)
+                do 11, j = 1, var_rank(i)
+                    if (var_dimid(j,i) .gt. 1) then     !/* skip record dim */
+                        start(j) = var_shape(j,i) + 1
+                        err = nfmpi_iget_vara_$1(ncid, i,
+     +                          start, edge, value,reqid(1))
+                        if (canConvert .and. err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                        if (err .EQ. NF_NOERR)
+     +                      err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                        start(j) = 1
+                    endif
+11              continue
+                err = nfmpi_iget_vara_$1(ncid, i, start,
+     +                          edge, value,reqid(1))
+                if (err .EQ. NF_NOERR)
+     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                if (canConvert) then
+                    if (err .ne. NF_NOERR) then
+                        call error(nfmpi_strerror(err))
+                    endif
+                else
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                endif
+                do 12, j = 1, var_rank(i)
+                    edge(j) = 1
+12              continue
+            endif
+
+C           Choose a random point dividing each dim into 2 parts
+C           get 2^rank (nslabs) slabs so defined
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+C           bits of k determine whether to get lower or upper part of dim 
+            do 5, k = 1, nslabs
+                nels = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift((k-1), -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    nels = nels * int(edge(j))
+6               continue
+                allInIntRange = .true.
+                allInExtRange = .true.
+                do 7, j = 1, nels
+                    err = index2indexes(j, var_rank(i), edge, index)
+                    if (err .ne. NF_NOERR)
+     +                  call error('error in index2indexes 1')
+                    do 8, d = 1, var_rank(i)
+                        index(d) = index(d) + start(d) - 1
+8                   continue
+                    expect(j) = hash4(var_type(i), var_rank(i), index, 
+     +                                NFT_ITYPE($1))
+                    if (inRange3(expect(j),var_type(i), 
+     +                           NFT_ITYPE($1))) then
+                        allInIntRange = 
+     +                      allInIntRange .and.
+     +                      in_internal_range(NFT_ITYPE($1), expect(j))
+                    else
+                        allInExtRange = .false.
+                    end if
+7               continue
+                err = nfmpi_iget_vara_$1(ncid, i, start,
+     +                          edge, value,reqid(1))
+                if (err .EQ. NF_NOERR)
+     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                if (canConvert) then
+                    if (allInExtRange) then
+                        if (allInIntRange) then
+                            if (st(1) .ne. 0)
+     +                          call errore(
+     +                              'nfmpi_iget_vara_$1:',st(1))
+                        else
+                            if (st(1) .ne. NF_ERANGE)
+     +                          call errore('Range error: ', st(1))
+                        end if
+                    else
+                        if (st(1) .ne. 0 .and. st(1) .ne. NF_ERANGE)
+     +                      call errore('OK or Range error: ', st(1))
+                    end if
+                    do 9, j = 1, nels
+                        if (inRange3(expect(j),var_type(i),
+     +                               NFT_ITYPE($1)) .and.
+     +                      in_internal_range(NFT_ITYPE($1), expect(j)))
+     +                          then
+                            val = ARITH3($1, value, j)
+                            if (.not.equal(val,expect(j),
+     +                                     var_type(i),NFT_ITYPE($1))) 
+     +                              then
+                                call error(
+     +                              'value read not that expected')
+                                if (verbose) then
+                                    call error(' ')
+                                    call errori('varid: ', i)
+                                    call errorc('var_name: ',
+     +                                  var_name(i))
+                                    call errori('element number: %d ', 
+     +                                          j)
+                                    call errord('expect: ', expect(j))
+                                    call errord('got: ', val)
+                                end if
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+9                   continue
+                else
+                    if (nels .gt. 0  .and. err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                end if
+5           continue
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errorc('nfmpi_close: ', nfmpi_strerror(err))
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_IGET_VARS(TYPE)
+dnl
+define([TEST_NFMPI_IGET_VARS],dnl
+[dnl
+        subroutine test_nfmpi_iget_vars_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer roll, index2indexes
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer nels
+        integer nslabs
+        integer nstarts         
+        integer nok             
+        integer*8 start(MAX_RANK)
+        integer*8 edge(MAX_RANK)
+        integer*8 index(MAX_RANK)
+        integer*8 index2(MAX_RANK)
+        integer*8 mid(MAX_RANK)
+        integer*8 count(MAX_RANK)
+        integer*8 sstride(MAX_RANK)
+        integer*8 stride(MAX_RANK)
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision expect(MAX_NELS)
+        doubleprecision val
+        integer ud_shift
+        integer err_w, reqid(1), st(1)      
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv. 
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assert'
+            if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assert'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+2           continue
+            err = nfmpi_iget_vars_$1(BAD_ID, i, start,
+     +                  edge, stride, value,reqid(1))
+            if (err .ne. NF_EBADID)
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iget_vars_$1(ncid, BAD_VARID,
+     +                  start, edge, stride, value,reqid(1))
+            if (err .ne. NF_ENOTVAR)
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_iget_vars_$1(ncid, i, start, edge,
+     +                                    stride,value,reqid(1))
+                if (err .EQ. NF_NOERR)
+     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad index: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nfmpi_iget_vars_$1(ncid, i, start, edge,
+     +                               stride,value,reqid(1))
+                if (err .EQ. NF_NOERR)
+     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EEDGE)
+     +                  call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nfmpi_iget_vars_$1(ncid, i, start, edge,
+     +                                stride,value,reqid(1))
+                if (err .EQ. NF_NOERR)
+     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_ESTRIDE)
+     +                  call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
+3           continue
+C               Choose a random point dividing each dim into 2 parts
+C               get 2^rank (nslabs) slabs so defined
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+C           bits of k determine whether to get lower or upper part of dim
+C           choose random stride from 1 to edge
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, j-1), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        sstride(j) = 1 + roll(edge(j))
+                    else
+                        sstride(j) = 1
+                    end if
+                    nstarts = nstarts * int(stride(j))
+6               continue
+                do 7, m = 1, nstarts
+                    err = index2indexes(m, var_rank(i), sstride, 
+     +                                  index)
+                    if (err .ne. NF_NOERR)
+     +                  call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) / 
+     +                                  stride(j)
+                        nels = nels * int(count(j))
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+C                   Random choice of forward or backward 
+C    /* TODO
+C                   if ( roll(2) ) then
+C                       for (j = 0 j < var_rank(i) j++) {
+C                           index(j) += (count(j) - 1) * stride(j)
+C                           stride(j) = -stride(j)
+C                       }
+C                   end if
+C    */
+                    allInIntRange = .true.
+                    allInExtRange = .true.
+                    do 9, j = 1, nels
+                        err = index2indexes(j, var_rank(i), count, 
+     +                                      index2)
+                        if (err .ne. NF_NOERR)
+     +                      call error('error in index2indexes() 1')
+                        do 10, d = 1, var_rank(i)
+                            index2(d) = index(d) + (index2(d)-1) * 
+     +                                  stride(d)
+10                      continue
+                        expect(j) = hash4(var_type(i), var_rank(i), 
+     +                                    index2, NFT_ITYPE($1))
+                        if (inRange3(expect(j),var_type(i),
+     +                               NFT_ITYPE($1))) then
+                            allInIntRange = 
+     +                          allInIntRange .and.
+     +                          in_internal_range(NFT_ITYPE($1), 
+     +                                            expect(j))
+                        else
+                            allInExtRange = .false.
+                        end if
+9                   continue
+                    err = nfmpi_iget_vars_$1(ncid, i, index,
+     +                                    count,stride,value,reqid(1))
+                    if (err .EQ. NF_NOERR)
+     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (allInIntRange) then
+                                if (st(1) .ne. 0)
+     +                              call error(nfmpi_strerror(st(1)))
+                            else
+                                if (st(1) .ne. NF_ERANGE)
+     +                              call errore('Range error: ', st(1))
+                            end if
+                        else
+                            if (st(1) .ne. 0 .and. st(1) .ne. NF_ERANGE)
+     +                          call errore('OK or Range error: ',st(1))
+                        end if
+                        do 11, j = 1, nels
+                            if (inRange3(expect(j),var_type(i),
+     +                          NFT_ITYPE($1)) .and.
+     +                          in_internal_range(NFT_ITYPE($1), 
+     +                                            expect(j))) then
+                                val = ARITH3($1, value, j)
+                                if (.not.equal(val, expect(j),
+     +                              var_type(i), NFT_ITYPE($1))) then
+                                    call error(
+     +                                  'value read not that expected')
+                                    if (verbose) then
+                                        call error(' ')
+                                        call errori('varid: ', i)
+                                        call errorc('var_name: ', 
+     +                                              var_name(i))
+                                        call errori('element number: ',
+     +                                              j)
+                                        call errord('expect: ', 
+     +                                              expect(j))
+                                        call errord('got: ', val)
+                                    end if
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+11                      continue
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_IGET_VARM(TYPE)
+dnl
+define([TEST_NFMPI_IGET_VARM],dnl
+[dnl
+        subroutine test_nfmpi_iget_varm_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer roll, index2indexes
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err
+        logical allInExtRange   
+        logical allInIntRange   
+        integer nels
+        integer nslabs
+        integer nstarts         
+        integer nok             
+        integer*8 start(MAX_RANK)
+        integer*8 edge(MAX_RANK)
+        integer*8 index(MAX_RANK)
+        integer*8 index2(MAX_RANK)
+        integer*8 mid(MAX_RANK)
+        integer*8 count(MAX_RANK)
+        integer*8 sstride(MAX_RANK)
+        integer*8 stride(MAX_RANK)
+        integer*8 imap(MAX_RANK)
+        logical canConvert     
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision expect(MAX_NELS)
+        doubleprecision val
+        integer ud_shift
+        integer err_w, reqid(1), st(1)      
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv. 
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK)) stop 'assertion'
+            if (.not.(var_nels(i) .le. MAX_NELS)) stop 'assertion'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+                imap(j) = 1
+2           continue
+            err = nfmpi_iget_varm_$1(BAD_ID, i, start, edge,
+     +                           stride, imap, value,reqid(1))
+            if (err .ne. NF_EBADID)
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iget_varm_$1(ncid, BAD_VARID, start,
+     +                           edge, stride, imap, value,reqid(1))
+            if (err .ne. NF_ENOTVAR)
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                start(j) = var_shape(j,i) + 1
+                err = nfmpi_iget_varm_$1(ncid, i, start, edge,
+     +                                stride, imap, value,reqid(1))
+                if (err .EQ. NF_NOERR)
+     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EINVALCOORDS)
+     +                  call errore('bad index: ', err)
+                endif
+                start(j) = 1
+                edge(j) = var_shape(j,i) + 1
+                err = nfmpi_iget_varm_$1(ncid, i, start, edge,
+     +                                stride, imap, value,reqid(1))
+                if (err .EQ. NF_NOERR)
+     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_EEDGE)
+     +                  call errore('bad edge: ', err)
+                endif
+                edge(j) = 1
+                stride(j) = 0
+                err = nfmpi_iget_varm_$1(ncid, i, start, edge,
+     +                                stride, imap, value, reqid(1))
+                if (err .EQ. NF_NOERR)
+     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                if (.not. canConvert) then
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('conversion: ', err)
+                else
+                    if (err .ne. NF_ESTRIDE)
+     +                  call errore('bad stride: ', err)
+                endif
+                stride(j) = 1
+3           continue
+C           Choose a random point dividing each dim into 2 parts 
+C           get 2^rank (nslabs) slabs so defined 
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+C           /* bits of k determine whether to get lower or upper part 
+C            * of dim
+C            * choose random stride from 1 to edge */
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift((k-1), -(j-1)), 2) .ne. 0) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        stride(j) = 1+roll(edge(j))
+                    else
+                        stride(j) = 1
+                    end if
+                    sstride(j) = stride(j)
+                    nstarts = nstarts * int(stride(j))
+6               continue
+                do 7, m = 1, nstarts
+                    err = index2indexes(m, var_rank(i), sstride, index)
+                    if (err .ne. NF_NOERR)
+     +                  call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) / 
+     +                                  stride(j)
+                        nels = nels * int(count(j))
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+C                   Random choice of forward or backward 
+C    /* TODO
+C                   if ( roll(2) ) then
+C                       for (j = 0 j < var_rank(i) j++) {
+C                           index(j) += (count(j) - 1) * stride(j)
+C                           stride(j) = -stride(j)
+C                       }
+C                   end if
+C     */
+                    if (var_rank(i) .gt. 0) then
+                        imap(1) = 1
+                        do 9, j = 2, var_rank(i)
+                            imap(j) = imap(j-1) * count(j-1)
+9                       continue
+                    end if
+                    allInIntRange = .true.
+                    allInExtRange = .true.
+                    do 10, j = 1, nels
+                        err = index2indexes(j, var_rank(i), count, 
+     +                                      index2)
+                        if (err .ne. NF_NOERR)
+     +                      call error('error in index2indexes 1')
+                        do 11, d = 1, var_rank(i)
+                            index2(d) = index(d) + (index2(d)-1) * 
+     +                                  stride(d)
+11                      continue
+                        expect(j) = hash4(var_type(i), var_rank(i), 
+     +                                    index2, NFT_ITYPE($1))
+                        if (inRange3(expect(j),var_type(i),
+     +                               NFT_ITYPE($1))) then
+                            allInIntRange = 
+     +                          allInIntRange .and.
+     +                          in_internal_range(NFT_ITYPE($1),
+     +                                            expect(j))
+                        else
+                            allInExtRange = .false.
+                        end if
+10                  continue
+                    err = nfmpi_iget_varm_$1(ncid,i,index,count,
+     +                                   stride,imap, value, reqid(1))
+                    if (err .EQ. NF_NOERR)
+     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (allInIntRange) then
+                                if (st(1) .ne. 0)
+     +                              call error(nfmpi_strerror(st(1)))
+                            else
+                                if (st(1) .ne. NF_ERANGE)
+     +                              call errore('Range error: ', st(1))
+                            end if
+                        else
+                            if (st(1) .ne. 0 .and. st(1) .ne. NF_ERANGE)
+     +                          call errore('OK or Range error: ',st(1))
+                        end if
+                        do 12, j = 1, nels
+                            if (inRange3(expect(j),var_type(i),
+     +                                   NFT_ITYPE($1)) .and.
+     +                          in_internal_range(NFT_ITYPE($1),
+     +                                            expect(j))) then
+                                val = ARITH3($1, value, j)
+                                if (.not.equal(val, expect(j),
+     +                                         var_type(i), 
+     +                                         NFT_ITYPE($1))) then
+                                    call error(
+     +                                  'value read not that expected')
+                                    if (verbose) then
+                                        call error(' ')
+                                        call errori('varid: ', i)
+                                        call errorc('var_name: ', 
+     +                                          var_name(i))
+                                        call errori('element number: ',
+     +                                              j)
+                                        call errord('expect: ', 
+     +                                              expect(j))
+                                        call errord('got: ', val)
+                                    end if
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+12                      continue
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ',  err)
+        call print_nok(nok)
+        end
+])dnl
+
+divert(0)dnl
+dnl If you see this line, you can ignore the next one.
+C Do not edit this file. It is produced from the corresponding .m4 source */
+
+C*********************************************************************
+C   Copyright 1996, UCAR/Unidata
+C   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+C   $Id: test_iget.m4 2224 2015-12-16 06:10:36Z wkliao $
+C*********************************************************************
+
+TEST_NFMPI_IGET_VAR1(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IGET_VAR1(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IGET_VAR1(int2)
+#endif
+TEST_NFMPI_IGET_VAR1(int)
+TEST_NFMPI_IGET_VAR1(int8)
+TEST_NFMPI_IGET_VAR1(real)
+TEST_NFMPI_IGET_VAR1(double)
+
+TEST_NFMPI_IGET_VAR(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IGET_VAR(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IGET_VAR(int2)
+#endif
+TEST_NFMPI_IGET_VAR(int)
+TEST_NFMPI_IGET_VAR(int8)
+TEST_NFMPI_IGET_VAR(real)
+TEST_NFMPI_IGET_VAR(double)
+
+TEST_NFMPI_IGET_VARA(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IGET_VARA(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IGET_VARA(int2)
+#endif
+TEST_NFMPI_IGET_VARA(int)
+TEST_NFMPI_IGET_VARA(int8)
+TEST_NFMPI_IGET_VARA(real)
+TEST_NFMPI_IGET_VARA(double)
+
+TEST_NFMPI_IGET_VARS(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IGET_VARS(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IGET_VARS(int2)
+#endif
+TEST_NFMPI_IGET_VARS(int)
+TEST_NFMPI_IGET_VARS(int8)
+TEST_NFMPI_IGET_VARS(real)
+TEST_NFMPI_IGET_VARS(double)
+
+TEST_NFMPI_IGET_VARM(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IGET_VARM(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IGET_VARM(int2)
+#endif
+TEST_NFMPI_IGET_VARM(int)
+TEST_NFMPI_IGET_VARM(int8)
+TEST_NFMPI_IGET_VARM(real)
+TEST_NFMPI_IGET_VARM(double)
+
diff --git a/test/nf_test/test_iput.m4 b/test/nf_test/test_iput.m4
new file mode 100644
index 0000000..25670af
--- /dev/null
+++ b/test/nf_test/test_iput.m4
@@ -0,0 +1,1108 @@
+divert(-1)
+
+dnl This is m4 source.
+dnl Process using m4 to produce FORTRAN language file.
+
+changequote([,]) dnl
+
+undefine([index])dnl
+
+dnl Macros
+
+dnl Upcase(str)
+dnl
+define([Upcase],[dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)])
+
+dnl NFT_ITYPE(type)
+dnl
+define([NFT_ITYPE], [NFT_[]Upcase($1)])
+
+dnl ARITH3(itype, value)
+dnl
+define([ARITH3], [ifelse($1, text, ichar($2($3:$3)), $2($3))])
+
+dnl VAR_ELEM(itype, value)
+dnl
+define([VAR_ELEM], [ifelse($1, text, $2($3:$3), $2($3))])
+
+dnl ARITH_VAR1(itype, value)
+dnl
+define([ARITH_VAR1], [ifelse($1, text, ichar($2), $2)])
+
+dnl  DATATYPE(funf_suffix)
+dnl
+define([DATATYPE], [dnl
+ifelse($1, text, character*MAX_NELS $2,
+ifelse($1, int1, NF_INT1_T $2$3,
+ifelse($1, int2, NF_INT2_T $2$3,
+ifelse($1, int, integer $2$3,
+ifelse($1, int8, NF_INT8_T $2$3,
+ifelse($1, real, real $2$3,
+ifelse($1, double, doubleprecision $2$3)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  DATATYPE_VAR1(funf_suffix)
+dnl
+define([DATATYPE_VAR1], [dnl
+ifelse($1, text, character $2,
+ifelse($1, int1, NF_INT1_T $2,
+ifelse($1, int2, NF_INT2_T $2,
+ifelse($1, int, integer $2,
+ifelse($1, int8, NF_INT8_T $2,
+ifelse($1, real, real $2,
+ifelse($1, double, doubleprecision $2)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  MAKE_ARITH_VAR1(funf_suffix, var)
+dnl
+define([MAKE_ARITH_VAR1], [dnl
+ifelse($1, text, ichar($2), $2)[]dnl
+])
+
+dnl  MAKE_ARITH3(funf_suffix, var)
+dnl
+define([MAKE_ARITH3], [dnl
+ifelse($1, text, ichar($2($3:$3)), $2($3))[]dnl
+])
+
+dnl  MAKE_DOUBLE(funf_suffix, var)
+dnl
+define([MAKE_DOUBLE], [dnl
+ifelse($1, text, dble(ichar($2)), dble($2))[]dnl
+])
+
+dnl  MAKE_TYPE(funf_suffix, var)
+dnl
+define([MAKE_TYPE], [dnl
+ifelse($1, text, char(int($2)),
+       ifelse($1, int, INT($2),
+       ifelse($1, real, REAL($2),
+       ifelse($1, double, DBLE($2),
+       $2))))[]dnl
+])
+
+dnl  MAKE_TYPE2(funf_suffix, var_dest, var_src)
+dnl
+define([MAKE_TYPE2], [dnl
+ifelse($1, text, $2 = char(int($3)),
+       ifelse($1, int, $2 = INT($3),
+       ifelse($1, int8,
+                  if ($3 .EQ. X_INT8_MAX) then
+                      $2 = X_INT8_MAX
+                  else
+                      $2 = $3
+                  endif,
+       ifelse($1, real, $2 = REAL($3),
+       ifelse($1, double, $2 = DBLE($3),
+       $2 = $3)))))[]dnl
+])
+
+dnl TEST_NFMPI_IPUT_VAR1(TYPE)
+dnl
+define([TEST_NFMPI_IPUT_VAR1],dnl
+[dnl
+        subroutine test_nfmpi_iput_var1_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer i
+        integer j
+        integer err, flags
+        integer*8 index(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        DATATYPE_VAR1($1, value)
+        doubleprecision val
+        integer err_w, reqid(1), st(1)
+
+        value = MAKE_TYPE($1, 5)!/* any value would do - only for error cases */
+
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            do 2, j = 1, var_rank(i)
+                index(j) = 1
+2           continue
+            err = nfmpi_iput_var1_$1(BAD_ID, i, index, value,
+     +                               reqid(1))
+            if (err .ne. NF_EBADID) 
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iput_var1_$1(ncid, BAD_VARID,
+     +                           index, value,reqid(1))
+            if (err .ne. NF_ENOTVAR) 
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .gt. 1) then         !/* skip record dim */
+                    index(j) = var_shape(j,i) + 1
+                    err = nfmpi_iput_var1_$1(ncid, i,
+     +                                   index, value,reqid(1))
+                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad index: ', err)
+                    endif
+                    index(j) = 0
+                end if
+3           continue
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                if (err .ne. NF_NOERR) 
+     +              call error('error in index2indexes 1')
+                val = hash_$1(var_type(i),var_rank(i),
+     +                            index, NFT_ITYPE($1))
+                MAKE_TYPE2($1, value, val)
+                err = nfmpi_iput_var1_$1(ncid, i, index, value,
+     +                                   reqid(1))
+                if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                if (canConvert) then
+                    val = ARITH_VAR1($1, value)
+                    if (inRange3(val, var_type(i), NFT_ITYPE($1))) then
+                        if (st(1) .ne. 0)
+     +                      call error(nfmpi_strerror(st(1)))
+                    else
+                        if (err .ne. NF_ERANGE)
+     +                      call errore('Range error: ', err)
+                        err = nfmpi_cancel(ncid, 1, reqid,st)
+                    end if
+                else
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                end if
+4           continue
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed: ', 
+     +                  scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_IPUT_VAR(TYPE)
+dnl
+define([TEST_NFMPI_IPUT_VAR],dnl
+[dnl
+        subroutine test_nfmpi_iput_var_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer vid
+        integer i
+        integer j
+        integer err, flags
+        integer nels
+        integer*8 index(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* All values within external range?*/
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer err_w, reqid(1), st(1)
+
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            err = nfmpi_iput_var_$1(BAD_ID, i, value,reqid(1))
+            if (err .ne. NF_EBADID) 
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iput_var_$1(ncid, BAD_VARID, value,
+     +                                   reqid(1))
+            if (err .ne. NF_ENOTVAR) 
+     +          call errore('bad var id: ', err)
+            nels = 1
+            do 3, j = 1, var_rank(i)
+                nels = nels * int(var_shape(j,i))
+3           continue
+            allInExtRange = .true.
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                if (err .ne. NF_NOERR) 
+     +              call error('error in index2indexes 1')
+                val = hash_$1(var_type(i), var_rank(i),
+     +                        index, NFT_ITYPE($1))
+                MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                val = ARITH3($1, value, j)
+                allInExtRange = allInExtRange .and.
+     +              inRange3(val, var_type(i), NFT_ITYPE($1))
+4           continue
+            err = nfmpi_iput_var_$1(ncid, i, value,reqid(1))
+            if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +          err_w = nfmpi_wait_all(ncid, 1, reqid, st)
+                ! NF_ERANGE is not a fatal error
+
+            if (canConvert) then
+                if (allInExtRange) then
+                    if (err .ne. NF_NOERR)
+     +                  call error(nfmpi_strerror(err))
+                else
+                    if (err .ne. NF_ERANGE .and.
+     +                      var_dimid(var_rank(i),i) .ne. RECDIM)
+     +                  call errore('Range error: ', err)
+                endif
+            else
+                if (err .ne. NF_ECHAR)
+     +              call errore('wrong type: ', err)
+            endif
+1       continue
+
+C       The preceeding has written nothing for record variables, now try
+C       again with more than 0 records.
+
+C       Write record number NRECS to force writing of preceding records.
+C       Assumes variable cr is char vector with UNLIMITED dimension.
+
+        err = nfmpi_inq_varid(ncid, "cr", vid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_inq_varid: ', err)
+        index(1) = NRECS
+        err = nfmpi_iput_var1_text(ncid, vid, index, 'x',reqid(1))
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_iput_var1_text: ', err)
+        else
+            err_w = nfmpi_wait_all(ncid, 1, reqid, st)
+        endif
+
+        do 5 i = 1, numVars
+C           Only test record variables here
+            if (var_rank(i) .ge. 1 .and.
+     +          var_dimid(var_rank(i),i) .eq. RECDIM) then
+                canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+                if (var_rank(i) .gt. MAX_RANK)
+     +              stop 'var_rank(i) .gt. MAX_RANK'
+                if (var_nels(i) .gt. MAX_NELS)
+     +              stop 'var_nels(i) .gt. MAX_NELS'
+
+                nels = 1
+                do 6 j = 1, var_rank(i)
+                    nels = nels * int(var_shape(j,i))
+6               continue
+                allInExtRange = .true.
+                do 7, j = 1, nels
+                    err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                    if (err .ne. NF_NOERR) 
+     +                  call error('error in index2indexes()')
+                    val = hash_$1(var_type(i), var_rank(i),
+     +                            index, NFT_ITYPE($1))
+                    MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                    val = ARITH3($1, value, j)
+                    allInExtRange = allInExtRange .and.
+     +                  inRange3(val, var_type(i), NFT_ITYPE($1))
+7               continue
+                err = nfmpi_iput_var_$1(ncid, i, value,reqid(1))
+                if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +              err_w = nfmpi_wait_all(ncid, 1, reqid, st)
+                    ! NF_ERANGE is not a fatal error?
+                if (canConvert) then
+                    if (allInExtRange) then
+                        if (err .ne. NF_NOERR)
+     +                      call error(nfmpi_strerror(err))
+                    else
+                        if (err .ne. NF_ERANGE)
+     +                      call errore('range error: ', err)
+                    endif
+                else
+                    if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                endif
+            endif
+5       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed: ', 
+     +                  scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_IPUT_VARA(TYPE)
+dnl
+define([TEST_NFMPI_IPUT_VARA],dnl
+[dnl
+        subroutine test_nfmpi_iput_vara_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer i
+        integer j
+        integer k
+        integer d
+        integer err, flags
+        integer nslabs
+        integer nels
+        integer*8 start(MAX_RANK)
+        integer*8 edge(MAX_RANK)
+        integer*8 mid(MAX_RANK)
+        integer*8 index(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* all values within external range? */
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer ud_shift
+        integer err_w, reqid(1), st(1)
+
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK))
+     +          stop 'assert(var_rank(i) .le. MAX_RANK)'
+            if (.not.(var_nels(i) .le. MAX_NELS))
+     +          stop 'assert(var_nels(i) .le. MAX_NELS)'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+2           continue
+            err = nfmpi_iput_vara_$1(BAD_ID, i, start,
+     +                  edge, value,reqid(1))
+            if (err .ne. NF_EBADID) 
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iput_vara_$1(ncid, BAD_VARID,
+     +                  start, edge, value,reqid(1))
+            if (err .ne. NF_ENOTVAR) 
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_iput_vara_$1(ncid, i, start, 
+     +                                   edge, value,reqid(1))
+                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +                  err_w = nfmpi_wait_all(ncid, 1, reqid, st)
+                        ! NF_ERANGE is not a fatal error
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                    edge(j) = var_shape(j,i) + 1
+                    err = nfmpi_iput_vara_$1(ncid, i, start, 
+     +                                   edge, value,reqid(1))
+                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +                  err_w = nfmpi_wait_all(ncid, 1, reqid, st)
+                        ! NF_ERANGE is not a fatal error
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EEDGE)
+     +                      call errore('bad edge: ', err)
+                    endif
+                    edge(j) = 1
+                end if
+3           continue
+
+C           /* Check correct error returned even when nothing to put */
+            do 20, j = 1, var_rank(i)
+                  edge(j) = 0
+20          continue
+            err = nfmpi_iput_vara_$1(BAD_ID, i, start,
+     +              edge, value,reqid(1))
+            if (err .ne. NF_EBADID) 
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iput_vara_$1(ncid, BAD_VARID,
+     +              start, edge, value,reqid(1))
+            if (err .ne. NF_ENOTVAR) 
+     +          call errore('bad var id: ', err)
+            do 21, j = 1, var_rank(i)
+                if (var_dimid(j,i) .gt. 1) then     ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_iput_vara_$1(ncid, i, start,
+     +                      edge, value,reqid(1))
+                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +                  err_w = nfmpi_wait_all(ncid, 1, reqid, st)
+                        ! NF_ERANGE is not a fatal error
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                endif
+21          continue
+            err = nfmpi_iput_vara_$1(ncid, i, start, edge, value,
+     +                                   reqid(1))
+            if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +          err_w = nfmpi_wait_all(ncid, 1, reqid, st)
+                ! NF_ERANGE is not a fatal error
+            if (canConvert) then
+                if (st(1) .ne. 0) 
+     +              call error(nfmpi_strerror(st(1)))
+            else
+                if (err .ne. NF_ECHAR)
+     +              call errore('wrong type: ', err)
+            endif
+            do 22, j = 1, var_rank(i)
+                  edge(j) = 1
+22          continue
+
+
+            !/* Choose a random point dividing each dim into 2 parts */
+            !/* Put 2^rank (nslabs) slabs so defined */
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+                !/* bits of k determine whether to put lower or upper part of dim */
+            do 5, k = 1, nslabs
+                nels = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    nels = nels * int(edge(j))
+6               continue
+                allInExtRange = .true.
+                do 7, j = 1, nels
+                    err = index2indexes(j, var_rank(i), edge, index)
+                    if (err .ne. NF_NOERR) 
+     +                  call error('error in index2indexes 1')
+                    do 8, d = 1, var_rank(i)
+                        index(d) = index(d) + start(d) - 1
+8                   continue
+                    val = hash_$1(var_type(i), var_rank(i),
+     +                            index, NFT_ITYPE($1))
+                    MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                    val = ARITH3($1, value, j)
+                    allInExtRange = allInExtRange .and.
+     +                  inRange3(val, var_type(i), NFT_ITYPE($1))
+7               continue
+                err = nfmpi_iput_vara_$1(ncid, i, start,
+     +                  edge, value,reqid(1))
+                if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +              err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                    ! NF_ERANGE is not a fatal error?
+                if (canConvert) then
+                    if (allInExtRange) then
+                        if (st(1) .ne. 0) 
+     +                      call error(nfmpi_strerror(st(1)))
+                    else
+                        if (err .ne. NF_ERANGE)
+     +                      call errore('range error: ', err)
+                    end if
+                else
+                    if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                end if
+5           continue
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed: ', 
+     +          scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_IPUT_VARS(TYPE)
+dnl
+define([TEST_NFMPI_IPUT_VARS],dnl
+[dnl
+        subroutine test_nfmpi_iput_vars_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err, flags
+        integer nels
+        integer nslabs
+        integer nstarts        !/* number of different starts */
+        integer*8 start(MAX_RANK)
+        integer*8 edge(MAX_RANK)
+        integer*8 index(MAX_RANK)
+        integer*8 index2(MAX_RANK)
+        integer*8 mid(MAX_RANK)
+        integer*8 count(MAX_RANK)
+        integer*8 sstride(MAX_RANK)
+        integer*8 stride(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* all values within external range? */
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer ud_shift
+        integer err_w, reqid(1), st(1)
+
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK))
+     +          stop 'assert(var_rank(i) .le. MAX_RANK)'
+            if (.not.(var_nels(i) .le. MAX_NELS))
+     +          stop 'assert(var_nels(i) .le. MAX_NELS)'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+2           continue
+            err = nfmpi_iput_vars_$1(BAD_ID, i, start,
+     +                  edge, stride, value,reqid(1))
+            if (err .ne. NF_EBADID) 
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iput_vars_$1(ncid, BAD_VARID, start,
+     +                           edge, stride, 
+     +                           value,reqid(1))
+            if (err .ne. NF_ENOTVAR) 
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .ne. RECDIM) then    ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_iput_vars_$1(ncid, i, start,
+     +                                   edge, stride, 
+     +                                   value,reqid(1))
+                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                        ! NF_ERANGE is not a fatal error?
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                          call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                    edge(j) = var_shape(j,i) + 1
+                    err = nfmpi_iput_vars_$1(ncid, i, start,
+     +                                   edge, stride, 
+     +                                   value,reqid(1))
+                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                        ! NF_ERANGE is not a fatal error?
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EEDGE)
+     +                      call errore('bad edge: ', err)
+                    endif
+                    edge(j) = 1
+                    stride(j) = 0
+                    err = nfmpi_iput_vars_$1(ncid, i, start,
+     +                                   edge, stride, 
+     +                                   value,reqid(1))
+                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                        ! NF_ERANGE is not a fatal error?
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_ESTRIDE)
+     +                      call errore('bad stride: ', err)
+                    endif
+                    stride(j) = 1
+                end if
+3           continue
+            !/* Choose a random point dividing each dim into 2 parts */
+            !/* Put 2^rank (nslabs) slabs so defined */
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+            !/* bits of k determine whether to put lower or upper part of dim */
+            !/* choose random stride from 1 to edge */
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        stride(j) = 1+roll(edge(j))
+                    else
+                        stride(j) = 1
+                    end if
+                    sstride(j) = stride(j)
+                    nstarts = nstarts * int(stride(j))
+6               continue
+                do 7, m = 1, nstarts
+                    err = index2indexes(m, var_rank(i), sstride, index)
+                    if (err .ne. NF_NOERR)
+     +                  call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) / stride(j)
+                        nels = nels * int(count(j))
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+                    !/* Random choice of forward or backward */
+C/* TODO
+C                   if ( roll(2) ) {
+C                       for (j = 1 j .lt. var_rank(i) j++) {
+C                           index(j) += (count(j) - 1) * stride(j)
+C                           stride(j) = -stride(j)
+C                       }
+C                   }
+C*/
+                    allInExtRange = .true.
+                    do 9, j = 1, nels
+                        err = index2indexes(j, var_rank(i), count, 
+     +                                      index2)
+                        if (err .ne. NF_NOERR)
+     +                      call error('error in index2indexes')
+                        do 10, d = 1, var_rank(i)
+                            index2(d) = index(d) + 
+     +                                  (index2(d)-1) * stride(d)
+10                      continue
+                        val = hash_$1(var_type(i), var_rank(i),
+     +                                index2, NFT_ITYPE($1))
+                        MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                        val = ARITH3($1, value, j)
+                        allInExtRange = allInExtRange .and.
+     +                      inRange3(val, var_type(i), 
+     +                               NFT_ITYPE($1))
+9                   continue
+                    err = nfmpi_iput_vars_$1(ncid, i, index,
+     +                                   count, stride,
+     +                                   value,reqid(1))
+                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (st(1) .ne. 0) 
+     +                          call error(nfmpi_strerror(st(1)))
+                        else
+                            if (err .ne. NF_ERANGE)
+     +                          call errore('range error: ', err)
+                        end if
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed:', 
+     +          scratch)
+        end
+])dnl
+
+
+dnl  since parallel-netcdf doesn't have varm type, we haven't completed the
+dnl  parallel-netcdf-ification of these routines
+dnl TEST_NFMPI_IPUT_VARM(TYPE)
+dnl
+define([TEST_NFMPI_IPUT_VARM],dnl
+[dnl
+        subroutine test_nfmpi_iput_varm_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err, flags
+        integer nels
+        integer nslabs
+        integer nstarts        !/* number of different starts */
+        integer*8 start(MAX_RANK)
+        integer*8 edge(MAX_RANK)
+        integer*8 index(MAX_RANK)
+        integer*8 index2(MAX_RANK)
+        integer*8 mid(MAX_RANK)
+        integer*8 count(MAX_RANK)
+        integer*8 sstride(MAX_RANK)
+        integer*8 stride(MAX_RANK)
+        integer*8 imap(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* all values within external range? */
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer ud_shift
+        integer err_w, reqid(1), st(1)
+
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK))
+     +          stop 'assert(var_rank(i) .le. MAX_RANK)'
+            if (.not.(var_nels(i) .le. MAX_NELS))
+     +          stop 'assert(var_nels(i) .le. MAX_NELS)'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+                imap(j) = 1
+2           continue
+            err = nfmpi_iput_varm_$1(BAD_ID, i, start,
+     +                           edge, stride, imap, 
+     +                           value,reqid(1))
+            if (err .ne. NF_EBADID) 
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_iput_varm_$1(ncid, BAD_VARID, start,
+     +                           edge, stride, 
+     +                           imap, value,reqid(1))
+            if (err .ne. NF_ENOTVAR) 
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_iput_varm_$1(ncid, i, start,
+     +                                   edge, stride, 
+     +                                   imap, value,reqid(1))
+                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                        ! NF_ERANGE is not a fatal error?
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                    edge(j) = var_shape(j,i) + 1
+                    err = nfmpi_iput_varm_$1(ncid, i, start,
+     +                                   edge, stride, 
+     +                                   imap, value,reqid(1))
+                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                        ! NF_ERANGE is not a fatal error?
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EEDGE)
+     +                      call errore('bad edge: ', err)
+                    endif
+                    edge(j) = 1
+                    stride(j) = 0
+                    err = nfmpi_iput_varm_$1(ncid, i, start,
+     +                                   edge, stride, 
+     +                                   imap, value,reqid(1))
+                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                        ! NF_ERANGE is not a fatal error?
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_ESTRIDE)
+     +                      call errore('bad stride: ', err)
+                    endif
+                    stride(j) = 1
+                end if
+3           continue
+            !/* Choose a random point dividing each dim into 2 parts */
+            !/* Put 2^rank (nslabs) slabs so defined */
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+            !/* bits of k determine whether to put lower or upper part of dim */
+            !/* choose random stride from 1 to edge */
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        stride(j) = 1+roll(edge(j))
+                    else
+                        stride(j) = 1
+                    end if
+                    sstride(j) = stride(j)
+                    nstarts = nstarts * int(stride(j))
+6               continue
+                do 7, m = 1, nstarts
+                    err = index2indexes(m, var_rank(i), sstride, index)
+                    if (err .ne. NF_NOERR)
+     +                  call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) / stride(j)
+                        nels = nels * int(count(j))
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+                    !/* Random choice of forward or backward */
+C/* TODO
+C                   if ( roll(2) ) then
+C                       do 9, j = 1, var_rank(i)
+C                           index(j) = index(j) + 
+C     +                         (count(j) - 1) * stride(j)
+C                           stride(j) = -stride(j)
+C9                      continue
+C                   end if
+C*/
+                    if (var_rank(i) .gt. 0) then
+                        imap(1) = 1
+                        do 10, j = 2, var_rank(i)
+                            imap(j) = imap(j-1) * count(j-1)
+10                      continue
+                    end if
+                    allInExtRange = .true.
+                    do 11 j = 1, nels
+                        err = index2indexes(j, var_rank(i), count, 
+     +                                      index2)
+                        if (err .ne. NF_NOERR)
+     +                      call error('error in index2indexes')
+                        do 12, d = 1, var_rank(i)
+                            index2(d) = index(d) + 
+     +                          (index2(d)-1) * stride(d)
+12                      continue
+                        val = hash_$1(var_type(i),var_rank(i), 
+     +                                index2, NFT_ITYPE($1))
+                        MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                        val = ARITH3($1, value, j)
+                        allInExtRange = allInExtRange .and.
+     +                      inRange3(val, var_type(i), 
+     +                               NFT_ITYPE($1))
+11                  continue
+                    err = nfmpi_iput_varm_$1(ncid,i,index,count,
+     +                                   stride,imap,
+     +                                   value,reqid(1))
+                    if (err .eq. NF_NOERR .or. err .eq. NF_ERANGE)
+     +                  err_w = nfmpi_wait_all(ncid,1,reqid,st)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (st(1) .ne. 0)
+     +                          call error(nfmpi_strerror(st(1)))
+                        else
+                            if (err .ne. NF_ERANGE)
+     +                          call errore('range error: ', err)
+                        end if
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed:', 
+     +          scratch)
+        end
+])dnl
+
+
+divert(0)dnl
+dnl If you see this line, you can ignore the next one.
+C Do not edit this file. It is produced from the corresponding .m4 source */
+
+C********************************************************************
+C   Copyright 1996, UCAR/Unidata
+C   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+C   $Id: test_iput.m4 2232 2015-12-16 22:16:52Z wkliao $
+C********************************************************************
+
+TEST_NFMPI_IPUT_VAR1(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IPUT_VAR1(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IPUT_VAR1(int2)
+#endif
+TEST_NFMPI_IPUT_VAR1(int)
+TEST_NFMPI_IPUT_VAR1(int8)
+TEST_NFMPI_IPUT_VAR1(real)
+TEST_NFMPI_IPUT_VAR1(double)
+
+TEST_NFMPI_IPUT_VAR(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IPUT_VAR(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IPUT_VAR(int2)
+#endif
+TEST_NFMPI_IPUT_VAR(int)
+TEST_NFMPI_IPUT_VAR(int8)
+TEST_NFMPI_IPUT_VAR(real)
+TEST_NFMPI_IPUT_VAR(double)
+
+TEST_NFMPI_IPUT_VARA(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IPUT_VARA(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IPUT_VARA(int2)
+#endif
+TEST_NFMPI_IPUT_VARA(int)
+TEST_NFMPI_IPUT_VARA(int8)
+TEST_NFMPI_IPUT_VARA(real)
+TEST_NFMPI_IPUT_VARA(double)
+
+TEST_NFMPI_IPUT_VARS(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IPUT_VARS(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IPUT_VARS(int2)
+#endif
+TEST_NFMPI_IPUT_VARS(int)
+TEST_NFMPI_IPUT_VARS(int8)
+TEST_NFMPI_IPUT_VARS(real)
+TEST_NFMPI_IPUT_VARS(double)
+
+TEST_NFMPI_IPUT_VARM(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_IPUT_VARM(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_IPUT_VARM(int2)
+#endif
+TEST_NFMPI_IPUT_VARM(int)
+TEST_NFMPI_IPUT_VARM(int8)
+TEST_NFMPI_IPUT_VARM(real)
+TEST_NFMPI_IPUT_VARM(double)
diff --git a/test/nf_test/test_put.m4 b/test/nf_test/test_put.m4
new file mode 100644
index 0000000..841cd1b
--- /dev/null
+++ b/test/nf_test/test_put.m4
@@ -0,0 +1,1518 @@
+divert(-1)
+
+dnl This is m4 source.
+dnl Process using m4 to produce FORTRAN language file.
+
+changequote([,]) dnl
+
+undefine([index])dnl
+
+dnl Macros
+
+dnl Upcase(str)
+dnl
+define([Upcase],[dnl
+translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)])
+
+dnl NFT_ITYPE(type)
+dnl
+define([NFT_ITYPE], [NFT_[]Upcase($1)])
+
+dnl ARITH3(itype, value)
+dnl
+define([ARITH3], [ifelse($1, text, ichar($2($3:$3)), $2($3))])
+
+dnl VAR_ELEM(itype, value)
+dnl
+define([VAR_ELEM], [ifelse($1, text, $2($3:$3), $2($3))])
+
+dnl ARITH_VAR1(itype, value)
+dnl
+define([ARITH_VAR1], [ifelse($1, text, ichar($2), $2)])
+
+dnl  DATATYPE(funf_suffix)
+dnl
+define([DATATYPE], [dnl
+ifelse($1, text, character*MAX_NELS $2,
+ifelse($1, int1, NF_INT1_T $2$3,
+ifelse($1, int2, NF_INT2_T $2$3,
+ifelse($1, int, integer $2$3,
+ifelse($1, int8, NF_INT8_T $2$3,
+ifelse($1, real, real $2$3,
+ifelse($1, double, doubleprecision $2$3)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  DATATYPE_VAR1(funf_suffix)
+dnl
+define([DATATYPE_VAR1], [dnl
+ifelse($1, text, character $2,
+ifelse($1, int1, NF_INT1_T $2,
+ifelse($1, int2, NF_INT2_T $2,
+ifelse($1, int, integer $2,
+ifelse($1, int8, NF_INT8_T $2,
+ifelse($1, real, real $2,
+ifelse($1, double, doubleprecision $2)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+)[]dnl
+])
+
+dnl  MAKE_ARITH_VAR1(funf_suffix, var)
+dnl
+define([MAKE_ARITH_VAR1], [dnl
+ifelse($1, text, ichar($2), $2)[]dnl
+])
+
+dnl  MAKE_ARITH3(funf_suffix, var)
+dnl
+define([MAKE_ARITH3], [dnl
+ifelse($1, text, ichar($2($3:$3)), $2($3))[]dnl
+])
+
+dnl  MAKE_DOUBLE(funf_suffix, var)
+dnl
+define([MAKE_DOUBLE], [dnl
+ifelse($1, text, dble(ichar($2)), dble($2))[]dnl
+])
+
+dnl  MAKE_TYPE(funf_suffix, var)
+dnl
+define([MAKE_TYPE], [dnl
+ifelse($1, text, char(int($2)),
+       ifelse($1, int, INT($2),
+       ifelse($1, real, REAL($2),
+       ifelse($1, double, DBLE($2),
+       $2))))[]dnl
+])
+
+dnl  MAKE_TYPE2(funf_suffix, var_dest, var_src)
+dnl
+define([MAKE_TYPE2], [dnl
+ifelse($1, text, $2 = char(int($3)),
+       ifelse($1, int, $2 = INT($3),
+       ifelse($1, int8, 
+                  if ($3 .EQ. X_INT8_MAX) then 
+                      $2 = X_INT8_MAX 
+                  else 
+                      $2 = $3
+                  endif, 
+       ifelse($1, real, $2 = REAL($3),
+       ifelse($1, double, $2 = DBLE($3),
+       $2 = $3)))))[]dnl
+])
+
+dnl HASH(TYPE)
+dnl
+define([HASH],
+[dnl
+C
+C ensure hash value within range for internal TYPE
+C
+        doubleprecision function hash_$1(type, rank, index, itype)
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer type
+        integer rank
+        integer*8 index(1)
+        integer itype
+        doubleprecision minimum
+        doubleprecision maximum
+        doubleprecision internal_min, internal_max, hash4
+
+        minimum = internal_min(itype)
+        maximum = internal_max(itype)
+
+        hash_$1 = max(minimum, min(maximum, hash4( type, rank,
+     +      index, itype)))
+        end
+])dnl
+
+
+dnl CHECK_VARS(TYPE)
+dnl
+define([CHECK_VARS],dnl
+[dnl
+C
+C check all vars in file which are (text/numeric) compatible with TYPE
+C
+        subroutine check_vars_$1(filename)
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        character*(*)   filename
+        integer  ncid          !/* netCDF id */
+        integer*8 index(MAX_RANK)
+        integer  err
+        integer  d
+        integer  i
+        integer  j
+        DATATYPE_VAR1($1, value)
+        integer datatype
+        integer ndims
+        integer dimids(MAX_RANK)
+        integer ngatts
+        doubleprecision expect
+        character*(NF_MAX_NAME) name
+        integer*8 length
+        logical canConvert      !/* Both text or both numeric */
+        integer nok             !/* count of valid comparisons */
+        doubleprecision val
+        integer  intindex
+
+        nok = 0
+
+        err = nfmpi_open(comm, filename, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_begin_indep_data(ncid)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (canConvert)  then
+                err = nfmpi_inq_var(ncid, i, name, datatype, ndims,
+     +                              dimids, ngatts)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_inq_var: ', err)
+                if (name .ne. var_name(i))
+     +              call error('Unexpected var_name')
+                if (datatype .ne. var_type(i))
+     +              call error('Unexpected type')
+                if (ndims .ne. var_rank(i))
+     +              call error('Unexpected rank')
+                do 2, j = 1, ndims
+                    err = nfmpi_inq_dim(ncid, dimids(j), name, 
+     +                   length)
+                    if (err .ne. NF_NOERR)
+     +                  call errore('nfmpi_inq_dim: ', err)
+                    if (length .ne. var_shape(j,i))
+     +                  call error('Unexpected shape')
+2               continue
+                do 3, j = 1, var_nels(i)
+                    err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                                  index)
+                    if (err .ne. NF_NOERR)
+     +                  call error('error in index2indexes()')
+                    expect = hash4( var_type(i), var_rank(i), index, 
+     +                             NFT_ITYPE($1))
+                    err = nfmpi_get_var1_$1(ncid, i, index, 
+     +                      value)
+                    if (inRange3(expect,datatype,NFT_ITYPE($1)))  then
+                        if (in_internal_range(NFT_ITYPE($1), 
+     +                                        expect)) then
+                            if (err .ne. NF_NOERR)  then
+                                call errore
+     +                         ('nfmpi_get_var1_$1: ',
+     +                          err)
+                            else
+                                val = MAKE_ARITH_VAR1($1,value)
+                                if (.not.equal(
+     +                              val,
+     +                              expect,var_type(i),
+     +                              NFT_ITYPE($1)))  then
+                                    call error(
+     +                          'Var value read not that expected')
+                                    if (verbose)  then
+                                        call error(' ')
+                                        call errori('varid: %d', i)
+                                        call errorc('var_name: ', 
+     +                                          var_name(i))
+                                        call error('index:')
+                                        do 4, d = 1, var_rank(i)
+                                            intindex = int(index(d))
+                                            call errori(' ', intindex)
+4                                       continue
+                                        call errord('expect: ', expect)
+                                        call errord('got: ',  val)
+                                    end if
+                                else
+                                    nok = nok + 1
+                                end if
+                            end if
+                        end if
+                    end if
+3               continue
+            end if
+1       continue
+        err = nfmpi_end_indep_data(ncid)
+        err = nfmpi_close (ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl CHECK_ATTS(TYPE)         numeric only
+dnl
+define([CHECK_ATTS],dnl
+[dnl
+C/* 
+C *  check all attributes in file which are (text/numeric) compatible with TYPE
+C *  ignore any attributes containing values outside range of TYPE
+C */
+        subroutine check_atts_$1(ncid)
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer ATT_TYPE, NATTS, ATT_LEN
+        double precision hash4
+        logical equal, inRange3, in_internal_range
+
+        integer ncid
+        integer  err
+        integer  i
+        integer  j
+        integer  k
+        integer*8 ndx(1)
+        DATATYPE($1, value, (MAX_NELS))
+        integer datatype
+        doubleprecision expect(MAX_NELS)
+        integer*8 length
+        integer nInExtRange     !/* number values within external range */
+        integer nInIntRange     !/* number values within internal range */
+        logical canConvert      !/* Both text or both numeric */
+        integer nok             !/* count of valid comparisons */
+        doubleprecision val
+
+        nok = 0
+
+        do 1, i = 0, numVars
+            do 2, j = 1, NATTS(i)
+                canConvert = (ATT_TYPE(j,i) .eq. NF_CHAR) .eqv.
+     +                       (NFT_ITYPE($1) .eq. NFT_TEXT)
+                if (canConvert) then
+                    err = nfmpi_inq_att(ncid, i, ATT_NAME(j,i), 
+     +                               datatype, length)
+                    if (err .ne. NF_NOERR)
+     +                  call errore('nfmpi_inq_att: ', err)
+                    if (datatype .ne. ATT_TYPE(j,i))
+     +                  call error('nfmpi_inq_att: unexpected type')
+                    if (length .ne. ATT_LEN(j,i))
+     +                  call error('nfmpi_inq_att: unexpected length')
+                    if (.not.(length .le. MAX_NELS))
+     +                  stop 'assert(length .le. MAX_NELS)'
+                    nInIntRange = 0
+                    nInExtRange = 0
+                    do 4, k = 1, int(length)
+                        ndx(1) = k
+                        expect(k) = hash4( datatype, -1, ndx, 
+     +                                    NFT_ITYPE($1))
+                        if (inRange3(expect(k), datatype, 
+     +                               NFT_ITYPE($1))) then
+                            nInExtRange = nInExtRange + 1
+                            if (in_internal_range(NFT_ITYPE($1),
+     +                                            expect(k)))
+     +                          nInIntRange = nInIntRange + 1
+                        end if
+4                   continue
+                    err = nfmpi_get_att_$1(ncid, i, 
+     +                                  ATT_NAME(j,i), value)
+                    if (nInExtRange .eq. length .and. 
+     +                  nInIntRange .eq. length) then
+                        if (err .ne. NF_NOERR)
+     +                      call error(nfmpi_strerror(err))
+                    else
+                        if (err .ne. NF_NOERR .and. err .ne. NF_ERANGE)
+     +                      call errore('OK or Range error: ', err)
+                    end if
+                    do 3, k = 1, int(length)
+                        if (inRange3(expect(k),datatype,NFT_ITYPE($1))
+     +                          .and. 
+     +                          in_internal_range(NFT_ITYPE($1), 
+     +                                            expect(k))) then
+                            val = MAKE_ARITH3($1,value,k)
+                            if (.not.equal(
+     +                          val,
+     +                          expect(k),datatype,
+     +                          NFT_ITYPE($1))) then
+                                call error(
+     +                              'att. value read not that expected')
+                                if (verbose) then
+                                    call error(' ')
+                                    call errori('varid: ', i)
+                                    call errorc('att_name: ', 
+     +                                  ATT_NAME(j,i))
+                                    call errori('element number: ', k)
+                                    call errord('expect: ', expect(k))
+                                    call errord('got: ',  val)
+                                end if
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+3                   continue
+                end if                                               
+2           continue
+1       continue
+
+        call print_nok(nok)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_PUT_VAR1(TYPE)
+dnl
+define([TEST_NFMPI_PUT_VAR1],dnl
+[dnl
+        subroutine test_nfmpi_put_var1_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer i
+        integer j
+        integer err, flags
+        integer*8 index(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        DATATYPE_VAR1($1, value)
+        doubleprecision val
+
+        value = MAKE_TYPE($1, 5)!/* any value would do - only for error cases */
+
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        err = nfmpi_begin_indep_data(ncid)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            do 2, j = 1, var_rank(i)
+                index(j) = 1
+2           continue
+            err = nfmpi_put_var1_$1(BAD_ID, i, index, value)
+            if (err .ne. NF_EBADID) 
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_put_var1_$1(ncid, BAD_VARID,
+     +                           index, value)
+            if (err .ne. NF_ENOTVAR) 
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .gt. 1) then         !/* skip record dim */
+                    index(j) = var_shape(j,i) + 1
+                    err = nfmpi_put_var1_$1(ncid, i,
+     +                                   index, value)
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad index: ', err)
+                    endif
+                    index(j) = 0
+                end if
+3           continue
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                if (err .ne. NF_NOERR) 
+     +              call error('error in index2indexes 1')
+                val = hash_$1(var_type(i),var_rank(i),
+     +                            index, NFT_ITYPE($1))
+                MAKE_TYPE2($1, value, val)
+                err = nfmpi_put_var1_$1(ncid, i, index, value)
+                if (canConvert) then
+                    val = ARITH_VAR1($1, value)
+                    if (inRange3(val, var_type(i), NFT_ITYPE($1))) then
+                        if (err .ne. NF_NOERR)
+     +                      call error(nfmpi_strerror(err))
+                    else
+                        if (err .ne. NF_ERANGE)
+     +                      call errore('Range error: ', err)
+                    end if
+                else
+                    if (err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                end if
+4           continue
+1       continue
+        err = nfmpi_end_indep_data(ncid)
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed: ', 
+     +                  scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_PUT_VAR(TYPE)
+dnl
+define([TEST_NFMPI_PUT_VAR],dnl
+[dnl
+        subroutine test_nfmpi_put_var_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer vid
+        integer i
+        integer j
+        integer err, flags
+        integer nels
+        integer*8 index(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* All values within external range?*/
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        err = nfmpi_begin_indep_data(ncid)
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            err = nfmpi_put_var_$1(BAD_ID, i, value)
+            if (err .ne. NF_EBADID) 
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_put_var_$1(ncid, BAD_VARID, value)
+            if (err .ne. NF_ENOTVAR) 
+     +          call errore('bad var id: ', err)
+            nels = 1
+            do 3, j = 1, var_rank(i)
+                nels = nels * int(var_shape(j,i))
+3           continue
+            allInExtRange = .true.
+            do 4, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                if (err .ne. NF_NOERR) 
+     +              call error('error in index2indexes 1')
+                val = hash_$1(var_type(i), var_rank(i),
+     +                        index, NFT_ITYPE($1))
+                MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                val = ARITH3($1, value, j)
+                allInExtRange = allInExtRange .and.
+     +              inRange3(val, var_type(i), NFT_ITYPE($1))
+4           continue
+            err = nfmpi_put_var_$1(ncid, i, value)
+            if (canConvert) then
+                if (allInExtRange) then
+                    if (err .ne. NF_NOERR)
+     +                  call error(nfmpi_strerror(err))
+                else
+                    if (err .ne. NF_ERANGE .and.
+     +                      var_dimid(var_rank(i),i) .ne. RECDIM)
+     +                  call errore('Range error: ', err)
+                endif
+            else
+                if (err .ne. NF_ECHAR)
+     +              call errore('wrong type: ', err)
+            endif
+1       continue
+        err = nfmpi_end_indep_data(ncid)
+
+C       The preceeding has written nothing for record variables, now try
+C       again with more than 0 records.
+
+C       Write record number NRECS to force writing of preceding records.
+C       Assumes variable cr is char vector with UNLIMITED dimension.
+
+        err = nfmpi_inq_varid(ncid, "cr", vid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_inq_varid: ', err)
+        index(1) = NRECS
+        err = nfmpi_begin_indep_data(ncid)
+        err = nfmpi_put_var1_text(ncid, vid, index, 'x')
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_put_var1_text: ', err)
+
+        do 5 i = 1, numVars
+C           Only test record variables here
+            if (var_rank(i) .ge. 1 .and.
+     +          var_dimid(var_rank(i),i) .eq. RECDIM) then
+                canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+                if (var_rank(i) .gt. MAX_RANK)
+     +              stop 'var_rank(i) .gt. MAX_RANK'
+                if (var_nels(i) .gt. MAX_NELS)
+     +              stop 'var_nels(i) .gt. MAX_NELS'
+                err = nfmpi_put_var_$1(BAD_ID, i, value)
+
+                nels = 1
+                do 6 j = 1, var_rank(i)
+                    nels = nels * int(var_shape(j,i))
+6               continue
+                allInExtRange = .true.
+                do 7, j = 1, nels
+                    err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                    if (err .ne. NF_NOERR) 
+     +                  call error('error in index2indexes()')
+                    val = hash_$1(var_type(i), var_rank(i),
+     +                            index, NFT_ITYPE($1))
+                    MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                    val = ARITH3($1, value, j)
+                    allInExtRange = allInExtRange .and.
+     +                  inRange3(val, var_type(i), NFT_ITYPE($1))
+7               continue
+                err = nfmpi_put_var_$1(ncid, i, value)
+                if (canConvert) then
+                    if (allInExtRange) then
+                        if (err .ne. NF_NOERR)
+     +                      call error(nfmpi_strerror(err))
+                    else
+                        if (err .ne. NF_ERANGE)
+     +                      call errore('range error: ', err)
+                    endif
+                else
+                    if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                endif
+            endif
+5       continue
+        err = nfmpi_end_indep_data(ncid)
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed: ', 
+     +                  scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_PUT_VARA(TYPE)
+dnl
+define([TEST_NFMPI_PUT_VARA],dnl
+[dnl
+        subroutine test_nfmpi_put_vara_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer i
+        integer j
+        integer k
+        integer d
+        integer err, flags
+        integer nslabs
+        integer nels
+        integer*8 start(MAX_RANK)
+        integer*8 edge(MAX_RANK)
+        integer*8 mid(MAX_RANK)
+        integer*8 index(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* all values within external range? */
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer ud_shift
+
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK))
+     +          stop 'assert(var_rank(i) .le. MAX_RANK)'
+            if (.not.(var_nels(i) .le. MAX_NELS))
+     +          stop 'assert(var_nels(i) .le. MAX_NELS)'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+2           continue
+            err = nfmpi_put_vara_$1_all(BAD_ID, i, start,
+     +                  edge, value)
+            if (err .ne. NF_EBADID) 
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_put_vara_$1_all(ncid, BAD_VARID,
+     +                  start, edge, value)
+            if (err .ne. NF_ENOTVAR) 
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_put_vara_$1_all(ncid, i, start, 
+     +                                   edge, value)
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                    edge(j) = var_shape(j,i) + 1
+                    err = nfmpi_put_vara_$1_all(ncid, i, start, 
+     +                                   edge, value)
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EEDGE)
+     +                      call errore('bad edge: ', err)
+                    endif
+                    edge(j) = 1
+                end if
+3           continue
+
+C           /* Check correct error returned even when nothing to put */
+            do 20, j = 1, var_rank(i)
+                edge(j) = 0
+20          continue
+            err = nfmpi_put_vara_$1_all(BAD_ID, i, start,
+     +          edge, value)
+            if (err .ne. NF_EBADID) 
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_put_vara_$1_all(ncid, BAD_VARID,
+     +          start, edge, value)
+            if (err .ne. NF_ENOTVAR) 
+     +          call errore('bad var id: ', err)
+            do 21, j = 1, var_rank(i)
+                if (var_dimid(j,i) .gt. 1) then     ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_put_vara_$1_all(ncid, i,
+     +                      start, edge, value)
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                endif
+21          continue
+
+! wkliao: this test below of put_vara is redundant and incorrectly uses the
+!         value[] set from the previously iteration. There is no such test
+!         in put_vars and put_varm.
+!
+!           err = nfmpi_put_vara_$1_all(ncid, i, start,
+!    +          edge, value)
+!           if (canConvert) then
+!               if (err .ne. NF_NOERR) 
+!    +              call error(nfmpi_strerror(err))
+!           else
+!               if (err .ne. NF_ECHAR)
+!    +              call errore('wrong type: ', err)
+!           endif
+
+            do 22, j = 1, var_rank(i)
+                edge(j) = 1
+22          continue
+
+
+            !/* Choose a random point dividing each dim into 2 parts */
+            !/* Put 2^rank (nslabs) slabs so defined */
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+            !/* bits of k determine whether to put lower or upper part of dim */
+            do 5, k = 1, nslabs
+                nels = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    nels = nels * int(edge(j))
+6               continue
+                allInExtRange = .true.
+                do 7, j = 1, nels
+                    err = index2indexes(j, var_rank(i), edge, index)
+                    if (err .ne. NF_NOERR) 
+     +                  call error('error in index2indexes 1')
+                    do 8, d = 1, var_rank(i)
+                        index(d) = index(d) + start(d) - 1
+8                   continue
+                    val = hash_$1(var_type(i), var_rank(i),
+     +                            index, NFT_ITYPE($1))
+                    MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                    val = ARITH3($1, value, j)
+                    allInExtRange = allInExtRange .and.
+     +                  inRange3(val, var_type(i), NFT_ITYPE($1))
+7               continue
+                err = nfmpi_put_vara_$1_all(ncid, i, start,
+     +                  edge, value)
+                if (canConvert) then
+                    if (allInExtRange) then
+                        if (err .ne. NF_NOERR) 
+     +                      call error(nfmpi_strerror(err))
+                    else
+                        if (err .ne. NF_ERANGE)
+     +                      call errore('range error: ', err)
+                    end if
+                else
+                    if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                  call errore('wrong type: ', err)
+                end if
+5           continue
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed: ', 
+     +          scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_PUT_VARS(TYPE)
+dnl
+define([TEST_NFMPI_PUT_VARS],dnl
+[dnl
+        subroutine test_nfmpi_put_vars_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        double precision hash_$1
+        logical inRange3
+        integer roll, index2indexes
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err, flags
+        integer nels
+        integer nslabs
+        integer nstarts        !/* number of different starts */
+        integer*8 start(MAX_RANK)
+        integer*8 edge(MAX_RANK)
+        integer*8 index(MAX_RANK)
+        integer*8 index2(MAX_RANK)
+        integer*8 mid(MAX_RANK)
+        integer*8 count(MAX_RANK)
+        integer*8 sstride(MAX_RANK)
+        integer*8 stride(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* all values within external range? */
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer ud_shift
+
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK))
+     +          stop 'assert(var_rank(i) .le. MAX_RANK)'
+            if (.not.(var_nels(i) .le. MAX_NELS))
+     +          stop 'assert(var_nels(i) .le. MAX_NELS)'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+2           continue
+            err = nfmpi_put_vars_$1_all(BAD_ID, i, start,
+     +                  edge, stride, value)
+            if (err .ne. NF_EBADID) 
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_put_vars_$1_all(ncid, BAD_VARID, start,
+     +                           edge, stride, 
+     +                           value)
+            if (err .ne. NF_ENOTVAR) 
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .ne. RECDIM) then    ! skip record dim
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_put_vars_$1_all(ncid, i, start,
+     +                                   edge, stride, 
+     +                                   value)
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                          call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                    edge(j) = var_shape(j,i) + 1
+                    err = nfmpi_put_vars_$1_all(ncid, i, start,
+     +                                   edge, stride, 
+     +                                   value)
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EEDGE)
+     +                      call errore('bad edge: ', err)
+                    endif
+                    edge(j) = 1
+                    stride(j) = 0
+                    err = nfmpi_put_vars_$1_all(ncid, i, start,
+     +                                   edge, stride, 
+     +                                   value)
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_ESTRIDE)
+     +                      call errore('bad stride: ', err)
+                    endif
+                    stride(j) = 1
+                end if
+3           continue
+            !/* Choose a random point dividing each dim into 2 parts */
+            !/* Put 2^rank (nslabs) slabs so defined */
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+            !/* bits of k determine whether to put lower or upper part of dim */
+            !/* choose random stride from 1 to edge */
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        stride(j) = 1+roll(edge(j))
+                    else
+                        stride(j) = 1
+                    end if
+                    sstride(j) = stride(j)
+                    nstarts = nstarts * INT(stride(j))
+6               continue
+                do 7, m = 1, nstarts
+                    err = index2indexes(m, var_rank(i), sstride, index)
+                    if (err .ne. NF_NOERR)
+     +                  call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) / stride(j)
+                        nels = nels * int(count(j))
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+                    !/* Random choice of forward or backward */
+C/* TODO
+C                   if ( roll(2) ) {
+C                       for (j = 1 j .lt. var_rank(i) j++) {
+C                           index(j) += (count(j) - 1) * stride(j)
+C                           stride(j) = -stride(j)
+C                       }
+C                   }
+C*/
+                    allInExtRange = .true.
+                    do 9, j = 1, nels
+                        err = index2indexes(j, var_rank(i), count, 
+     +                                      index2)
+                        if (err .ne. NF_NOERR)
+     +                      call error('error in index2indexes')
+                        do 10, d = 1, var_rank(i)
+                            index2(d) = index(d) + 
+     +                                  (index2(d)-1) * stride(d)
+10                      continue
+                        val = hash_$1(var_type(i), var_rank(i),
+     +                                index2, NFT_ITYPE($1))
+                        MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                        val = ARITH3($1, value, j)
+                        allInExtRange = allInExtRange .and.
+     +                      inRange3(val, var_type(i), 
+     +                               NFT_ITYPE($1))
+9                   continue
+                    err = nfmpi_put_vars_$1_all(ncid, i, index,
+     +                                   count, stride,
+     +                                   value)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (err .ne. NF_NOERR) 
+     +                          call error(nfmpi_strerror(err))
+                        else
+                            if (err .ne. NF_ERANGE)
+     +                          call errore('range error: ', err)
+                        end if
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed:', 
+     +          scratch)
+        end
+])dnl
+
+
+dnl  since parallel-netcdf doesn't have varm type, we haven't completed the
+dnl  parallel-netcdf-ification of these routines
+dnl TEST_NFMPI_PUT_VARM(TYPE)
+dnl
+define([TEST_NFMPI_PUT_VARM],dnl
+[dnl
+        subroutine test_nfmpi_put_varm_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes, roll
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer d
+        integer i
+        integer j
+        integer k
+        integer m
+        integer err, flags
+        integer nels
+        integer nslabs
+        integer nstarts        !/* number of different starts */
+        integer*8 start(MAX_RANK)
+        integer*8 edge(MAX_RANK)
+        integer*8 index(MAX_RANK)
+        integer*8 index2(MAX_RANK)
+        integer*8 mid(MAX_RANK)
+        integer*8 count(MAX_RANK)
+        integer*8 sstride(MAX_RANK)
+        integer*8 stride(MAX_RANK)
+        integer*8 imap(MAX_RANK)
+        logical canConvert      !/* Both text or both numeric */
+        logical allInExtRange   !/* all values within external range? */
+        DATATYPE($1, value, (MAX_NELS))
+        doubleprecision val
+        integer ud_shift
+
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+
+        do 1, i = 1, numVars
+            canConvert = (var_type(i) .eq. NF_CHAR) .eqv.
+     +                   (NFT_ITYPE($1) .eq. NFT_TEXT)
+            if (.not.(var_rank(i) .le. MAX_RANK))
+     +          stop 'assert(var_rank(i) .le. MAX_RANK)'
+            if (.not.(var_nels(i) .le. MAX_NELS))
+     +          stop 'assert(var_nels(i) .le. MAX_NELS)'
+            do 2, j = 1, var_rank(i)
+                start(j) = 1
+                edge(j) = 1
+                stride(j) = 1
+                imap(j) = 1
+2           continue
+            err = nfmpi_put_varm_$1_all(BAD_ID, i, start,
+     +                           edge, stride, imap, 
+     +                           value)
+            if (err .ne. NF_EBADID) 
+     +          call errore('bad ncid: ', err)
+            err = nfmpi_put_varm_$1_all(ncid, BAD_VARID, start,
+     +                           edge, stride, 
+     +                           imap, value)
+            if (err .ne. NF_ENOTVAR) 
+     +          call errore('bad var id: ', err)
+            do 3, j = 1, var_rank(i)
+                if (var_dimid(j,i) .ne. RECDIM) then    !/* skip record dim */
+                    start(j) = var_shape(j,i) + 1
+                    err = nfmpi_put_varm_$1_all(ncid, i, start,
+     +                                   edge, stride, 
+     +                                   imap, value)
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EINVALCOORDS)
+     +                      call errore('bad start: ', err)
+                    endif
+                    start(j) = 1
+                    edge(j) = var_shape(j,i) + 1
+                    err = nfmpi_put_varm_$1_all(ncid, i, start,
+     +                                   edge, stride, 
+     +                                   imap, value)
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_EEDGE)
+     +                      call errore('bad edge: ', err)
+                    endif
+                    edge(j) = 1
+                    stride(j) = 0
+                    err = nfmpi_put_varm_$1_all(ncid, i, start,
+     +                                   edge, stride, 
+     +                                   imap, value)
+                    if (.not. canConvert) then
+                        if (err .ne. NF_ECHAR)
+     +                      call errore('conversion: ', err)
+                    else
+                        if (err .ne. NF_ESTRIDE)
+     +                      call errore('bad stride: ', err)
+                    endif
+                    stride(j) = 1
+                end if
+3           continue
+            !/* Choose a random point dividing each dim into 2 parts */
+            !/* Put 2^rank (nslabs) slabs so defined */
+            nslabs = 1
+            do 4, j = 1, var_rank(i)
+                mid(j) = roll( var_shape(j,i) )
+                nslabs = nslabs * 2
+4           continue
+            !/* bits of k determine whether to put lower or upper part of dim */
+            !/* choose random stride from 1 to edge */
+            do 5, k = 1, nslabs
+                nstarts = 1
+                do 6, j = 1, var_rank(i)
+                    if (mod(ud_shift(k-1, -(j-1)), 2) .eq. 1) then
+                        start(j) = 1
+                        edge(j) = mid(j)
+                    else
+                        start(j) = 1 + mid(j)
+                        edge(j) = var_shape(j,i) - mid(j)
+                    end if
+                    if (edge(j) .gt. 0) then
+                        stride(j) = 1+roll(edge(j))
+                    else
+                        stride(j) = 1
+                    end if
+                    sstride(j) = stride(j)
+                    nstarts = nstarts * INT(stride(j))
+6               continue
+                do 7, m = 1, nstarts
+                    err = index2indexes(m, var_rank(i), sstride, index)
+                    if (err .ne. NF_NOERR)
+     +                  call error('error in index2indexes')
+                    nels = 1
+                    do 8, j = 1, var_rank(i)
+                        count(j) = 1 + (edge(j) - index(j)) / stride(j)
+                        nels = nels * int(count(j))
+                        index(j) = index(j) + start(j) - 1
+8                   continue
+                    !/* Random choice of forward or backward */
+C/* TODO
+C                   if ( roll(2) ) then
+C                       do 9, j = 1, var_rank(i)
+C                           index(j) = index(j) + 
+C     +                         (count(j) - 1) * stride(j)
+C                           stride(j) = -stride(j)
+C9                      continue
+C                   end if
+C*/
+                    if (var_rank(i) .gt. 0) then
+                        imap(1) = 1
+                        do 10, j = 2, var_rank(i)
+                            imap(j) = imap(j-1) * count(j-1)
+10                      continue
+                    end if
+                    allInExtRange = .true.
+                    do 11 j = 1, nels
+                        err = index2indexes(j, var_rank(i), count, 
+     +                                      index2)
+                        if (err .ne. NF_NOERR)
+     +                      call error('error in index2indexes')
+                        do 12, d = 1, var_rank(i)
+                            index2(d) = index(d) + 
+     +                          (index2(d)-1) * stride(d)
+12                      continue
+                        val = hash_$1(var_type(i),var_rank(i), 
+     +                                index2, NFT_ITYPE($1))
+                        MAKE_TYPE2($1, VAR_ELEM($1, value, j), val)
+                        val = ARITH3($1, value, j)
+                        allInExtRange = allInExtRange .and.
+     +                      inRange3(val, var_type(i), 
+     +                               NFT_ITYPE($1))
+11                  continue
+                    err = nfmpi_put_varm_$1_all(ncid,i,index,count,
+     +                                   stride,imap,
+     +                                   value)
+                    if (canConvert) then
+                        if (allInExtRange) then
+                            if (err .ne. NF_NOERR)
+     +                          call error(nfmpi_strerror(err))
+                        else
+                            if (err .ne. NF_ERANGE)
+     +                          call errore('range error: ', err)
+                        end if
+                    else
+                        if (nels .gt. 0 .and. err .ne. NF_ECHAR)
+     +                      call errore('wrong type: ', err)
+                    end if
+7               continue
+5           continue
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_close: ', err)
+
+        call check_vars_$1(scratch)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed:', 
+     +          scratch)
+        end
+])dnl
+
+
+dnl TEST_NFMPI_PUT_ATT(TYPE)         numeric only
+dnl
+define([TEST_NFMPI_PUT_ATT],dnl
+[dnl
+        subroutine test_nfmpi_put_att_$1()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer ATT_TYPE, NATTS, ATT_LEN
+        integer*8 ATT_LEN_LL
+        double precision hash_$1
+        logical inRange3
+
+        integer ncid
+        integer i
+        integer j
+        integer k
+        integer*8 ndx(1)
+        integer err, flags
+        DATATYPE($1, value, (MAX_NELS))
+        logical allInExtRange  !/* all values within external range? */
+        doubleprecision val
+
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+
+        do 1, i = 0, numVars
+            do 2, j = 1, NATTS(i)
+                if (.not.(ATT_TYPE(j,i) .eq. NF_CHAR)) then
+                    ATT_LEN_LL = ATT_LEN(j,i)
+                    if (.not.((ATT_LEN_LL .le. MAX_NELS)))
+     +                  stop 'assert(ATT_LEN_LL .le. MAX_NELS)'
+                    err = nfmpi_put_att_$1(BAD_ID, i,
+     +                                  ATT_NAME(j,i), 
+     +                                  ATT_TYPE(j,i), 
+     +                                  ATT_LEN_LL, value)
+                    if (err .ne. NF_EBADID)
+     +                  call errore('bad ncid: ', err)
+                    err = nfmpi_put_att_$1(ncid, BAD_VARID,
+     +                  ATT_NAME(j,i), 
+     +                  ATT_TYPE(j,i), ATT_LEN_LL, value)
+                    if (err .ne. NF_ENOTVAR)
+     +                  call errore('bad var id: ', err)
+                    err = nfmpi_put_att_$1(ncid, i,
+     +                  ATT_NAME(j,i), BAD_TYPE, 
+     +                  ATT_LEN_LL, value)
+                    if (err .ne. NF_EBADTYPE)
+     +                  call errore('bad type: ', err)
+                    allInExtRange = .true.
+                    do 3, k = 1, int(ATT_LEN_LL)
+                        ndx(1) = k
+                        val = hash_$1(ATT_TYPE(j,i),
+     +                                -1, ndx, NFT_ITYPE($1))
+                        MAKE_TYPE2($1, VAR_ELEM($1, value, k), val)
+                        val = ARITH3($1, value, k)
+                        allInExtRange = allInExtRange .and.
+     +                      inRange3(val, ATT_TYPE(j,i), 
+     +                               NFT_ITYPE($1))
+3                   continue
+                    err = nfmpi_put_att_$1(ncid, i, ATT_NAME(j,i), 
+     +                                  ATT_TYPE(j,i), ATT_LEN_LL, 
+     +                                  value)
+                    if (allInExtRange) then
+                        if (err .ne. NF_NOERR)
+     +                      call error(nfmpi_strerror(err))
+                    else
+                        if (err .ne. NF_ERANGE)
+     +                      call errore('range error: ', err)
+                    end if
+                end if
+2           continue
+1       continue
+
+        call check_atts_$1(ncid)
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed:', 
+     +          scratch)
+        end
+])dnl
+
+divert(0)dnl
+dnl If you see this line, you can ignore the next one.
+C Do not edit this file. It is produced from the corresponding .m4 source */
+
+C********************************************************************
+C   Copyright 1996, UCAR/Unidata
+C   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+C   $Id: test_put.m4 2232 2015-12-16 22:16:52Z wkliao $
+C********************************************************************
+
+HASH(text)
+#ifdef NF_INT1_T
+HASH(int1)
+#endif
+#ifdef NF_INT2_T
+HASH(int2)
+#endif
+HASH(int)
+HASH(int8)
+HASH(real)
+HASH(double)
+
+CHECK_VARS(text)
+#ifdef NF_INT1_T
+CHECK_VARS(int1)
+#endif
+#ifdef NF_INT2_T
+CHECK_VARS(int2)
+#endif
+CHECK_VARS(int)
+CHECK_VARS(int8)
+CHECK_VARS(real)
+CHECK_VARS(double)
+
+CHECK_ATTS(text)
+#ifdef NF_INT1_T
+CHECK_ATTS(int1)
+#endif
+#ifdef NF_INT2_T
+CHECK_ATTS(int2)
+#endif
+CHECK_ATTS(int)
+CHECK_ATTS(int8)
+CHECK_ATTS(real)
+CHECK_ATTS(double)
+
+TEST_NFMPI_PUT_VAR1(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_PUT_VAR1(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_PUT_VAR1(int2)
+#endif
+TEST_NFMPI_PUT_VAR1(int)
+TEST_NFMPI_PUT_VAR1(int8)
+TEST_NFMPI_PUT_VAR1(real)
+TEST_NFMPI_PUT_VAR1(double)
+
+TEST_NFMPI_PUT_VAR(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_PUT_VAR(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_PUT_VAR(int2)
+#endif
+TEST_NFMPI_PUT_VAR(int)
+TEST_NFMPI_PUT_VAR(int8)
+TEST_NFMPI_PUT_VAR(real)
+TEST_NFMPI_PUT_VAR(double)
+
+TEST_NFMPI_PUT_VARA(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_PUT_VARA(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_PUT_VARA(int2)
+#endif
+TEST_NFMPI_PUT_VARA(int)
+TEST_NFMPI_PUT_VARA(int8)
+TEST_NFMPI_PUT_VARA(real)
+TEST_NFMPI_PUT_VARA(double)
+
+TEST_NFMPI_PUT_VARS(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_PUT_VARS(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_PUT_VARS(int2)
+#endif
+TEST_NFMPI_PUT_VARS(int)
+TEST_NFMPI_PUT_VARS(int8)
+TEST_NFMPI_PUT_VARS(real)
+TEST_NFMPI_PUT_VARS(double)
+
+TEST_NFMPI_PUT_VARM(text)
+#ifdef NF_INT1_T
+TEST_NFMPI_PUT_VARM(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_PUT_VARM(int2)
+#endif
+TEST_NFMPI_PUT_VARM(int)
+TEST_NFMPI_PUT_VARM(int8)
+TEST_NFMPI_PUT_VARM(real)
+TEST_NFMPI_PUT_VARM(double)
+
+        subroutine test_nfmpi_put_att_text()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer ATT_TYPE, NATTS, ATT_LEN
+        integer*8 ATT_LEN_LL
+        double precision hash
+
+        integer ncid
+        integer i
+        integer j
+        integer*8 k
+        integer err, flags
+        character*MAX_NELS value
+
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+
+        do 1, i = 0, numVars
+            do 2, j = 1, NATTS(i)
+                if (ATT_TYPE(j,i) .eq. NF_CHAR) then
+                    ATT_LEN_LL = ATT_LEN(j,i)
+                    if (.not.(ATT_LEN_LL .le. MAX_NELS))
+     +                  stop 'assert(ATT_LEN_LL .le. MAX_NELS)'
+                    err = nfmpi_put_att_text(BAD_ID, i,
+     +                  ATT_NAME(j,i), ATT_LEN_LL, value)
+                    if (err .ne. NF_EBADID)
+     +                  call errore('bad ncid: ', err)
+                    err = nfmpi_put_att_text(ncid, BAD_VARID, 
+     +                                    ATT_NAME(j,i), 
+     +                                    ATT_LEN_LL, value)
+                    if (err .ne. NF_ENOTVAR)
+     +                  call errore('bad var id: ', err)
+                    do 3, k = 1, int(ATT_LEN_LL)
+                        value(k:k) = char(int(hash(ATT_TYPE(j,i),
+     +                                             -1, k)))
+3                   continue
+                    err = nfmpi_put_att_text(ncid, i, ATT_NAME(j,i), 
+     +                  ATT_LEN_LL, value)
+                    if (err .ne. NF_NOERR)
+     +                  call error(nfmpi_strerror(err))
+                end if
+2           continue
+1       continue
+
+        call check_atts_text(ncid)
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed:', 
+     +          scratch)
+        end
+
+#ifdef NF_INT1_T
+TEST_NFMPI_PUT_ATT(int1)
+#endif
+#ifdef NF_INT2_T
+TEST_NFMPI_PUT_ATT(int2)
+#endif
+TEST_NFMPI_PUT_ATT(int)
+TEST_NFMPI_PUT_ATT(int8)
+TEST_NFMPI_PUT_ATT(real)
+TEST_NFMPI_PUT_ATT(double)
diff --git a/test/nf_test/test_read.F b/test/nf_test/test_read.F
new file mode 100644
index 0000000..b4355b6
--- /dev/null
+++ b/test/nf_test/test_read.F
@@ -0,0 +1,1437 @@
+C*********************************************************************
+C   Copyright 1996, UCAR/Unidata
+C   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+C   $Id: test_read.F 2296 2016-01-06 21:19:36Z wkliao $
+C*********************************************************************
+
+C Test nfmpi_strerror.
+C    Try on a bad error status.
+C    Test for each defined error status.
+C
+        subroutine test_nfmpi_strerror()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer         MY_LEN_TRIM
+        integer         number_of_messages
+        parameter       (number_of_messages = 27)
+
+        integer         i, msg_len
+        integer         status(number_of_messages)
+        character*80    message, unknown_err_msg
+        character*80    msg(number_of_messages)
+        integer         nok
+
+        data    status(1)  / NF_NOERR/
+        data    status(2)  / NF_EBADID /
+        data    status(3)  / NF_EEXIST /
+        data    status(4)  / NF_EINVAL /
+        data    status(5)  / NF_EPERM /
+        data    status(6)  / NF_ENOTINDEFINE /
+        data    status(7)  / NF_EINDEFINE /
+        data    status(8)  / NF_EINVALCOORDS /
+        data    status(9)  / NF_EMAXDIMS /
+        data    status(10) / NF_ENAMEINUSE /
+        data    status(11) / NF_ENOTATT /
+        data    status(12) / NF_EMAXATTS /
+        data    status(13) / NF_EBADTYPE /
+        data    status(14) / NF_EBADDIM /
+        data    status(15) / NF_EUNLIMPOS /
+        data    status(16) / NF_EMAXVARS /
+        data    status(17) / NF_ENOTVAR /
+        data    status(18) / NF_EGLOBAL /
+        data    status(19) / NF_ENOTNC /
+        data    status(20) / NF_ESTS /
+        data    status(21) / NF_EMAXNAME /
+        data    status(22) / NF_EUNLIMIT /
+        data    status(23) / NF_ENORECVARS /
+        data    status(24) / NF_ECHAR /
+        data    status(25) / NF_EEDGE /
+        data    status(26) / NF_ESTRIDE /
+        data    status(27) / NF_EBADNAME /
+
+        data msg(1)  / 'No error' /
+        data msg(2)  / 'NetCDF: Not a valid ID' /
+        data msg(3)  / 'NetCDF: File exists && NC_NOCLOBBER' /
+        data msg(4)  / 'NetCDF: Invalid argument' /
+        data msg(5)  / 'NetCDF: Write to read only' /
+        data msg(6)  / 'NetCDF: Operation not allowed in data mode' /
+        data msg(7)  / 'NetCDF: Operation not allowed in define mode' /
+        data msg(8)  / 'NetCDF: Index exceeds dimension bound' /
+        data msg(9)  / 'NetCDF: NC_MAX_DIMS exceeded' /
+        data msg(10) / 'NetCDF: String match to name in use' /
+        data msg(11) / 'NetCDF: Attribute not found' /
+        data msg(12) / 'NetCDF: NC_MAX_ATTRS exceeded' /
+        data msg(13)
+     +  / 'NetCDF: Not a valid data type or _FillValue type mismatch' /
+        data msg(14) / 'NetCDF: Invalid dimension ID or name' /
+        data msg(15) / 'NetCDF: NC_UNLIMITED in the wrong index' /
+        data msg(16) / 'NetCDF: NC_MAX_VARS exceeded' /
+        data msg(17) / 'NetCDF: Variable not found' /
+        data msg(18) / 'NetCDF: Action prohibited on NC_GLOBAL varid' /
+        data msg(19) / 'NetCDF: Unknown file format' /
+        data msg(20) / 'NetCDF: In Fortran, string too short' /
+        data msg(21) / 'NetCDF: NC_MAX_NAME exceeded' /
+        data msg(22) / 'NetCDF: NC_UNLIMITED size already in use' /
+        data msg(23)
+     +  / 'NetCDF: nc_rec op when there are no record vars' /
+        data msg(24)
+     +  /'NetCDF: Attempt to convert between text & numbers'/
+        data msg(25) / 'NetCDF: Start+count exceeds dimension bound' /
+        data msg(26) / 'NetCDF: Illegal stride' /
+        data msg(27) / 'NetCDF: Name contains illegal characters' /
+
+        nok = 0
+
+C       /* Try on a bad error status */
+        message = nfmpi_strerror(-666)!/* should fail */
+C       pnetcdf differs from serial netcdf in that we report the error
+C       code along with the message.
+
+        unknown_err_msg = "Unknown Error"
+        msg_len = LEN(TRIM(unknown_err_msg))
+        if (message(1:msg_len) .ne. unknown_err_msg(1:msg_len)) then
+            call errorc('nfmpi_strerror on bad error status returned: ',
+     +          message)
+        else
+            nok = nok + 1
+        endif
+
+C       /* Try on each legitimate error status */
+        do 1, i=1, number_of_messages
+            message = nfmpi_strerror(status(i))
+            if (message .ne. msg(i)) then
+                call error('nfmpi_strerror() should return "' 
+     +                     // msg(i) // '"')
+            else
+                nok = nok + 1
+            endif
+1       continue
+        call print_nok(nok)
+        end
+
+
+C Test nfmpi_open.
+C If in read-only section of tests,
+C    Try to open a non-existent netCDF file, check error return.
+C    Open a file that is not a netCDF file, check error return.
+C    Open a netCDF file with a bad mode argument, check error return.
+C    Open a netCDF file with NFMPI_NOWRITE mode, try to write, check error.
+C    Try to open a netcdf twice, check whether returned netcdf ids different.
+C If in writable section of tests,
+C    Open a netCDF file with NFMPI_WRITE mode, write something, close it.
+C On exit, any open netCDF files are closed.
+        subroutine test_nfmpi_open()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer err, flags
+        integer ncid
+        integer ncid2
+        integer nok
+
+        nok = 0
+
+!       Try to open a nonexistent file, this call should fail
+        err = nfmpi_open(comm, 'tooth-fairy.nc', NF_NOWRITE, info, ncid)
+
+!       On some systems, opening an nonexisting file will actually create the
+!       file. In this case, we print the error messages on screen and move on
+!       to the next test, instead of aborting the entire test.
+
+        if (err .eq. NF_NOERR) then
+            print*,
+     +    'opening a nonexistent file expects to fail, but got NF_NOERR'
+        elseif (err .ne. NF_ENOENT) then
+            print*,
+     +    'opening a nonexistent file expects NF_ENOENT, but got ',err
+        else
+C            print*, "Expected error message complaining: "//
+C     +              "File tooth-fairy.nc does not exist"
+            nok = nok + 1
+        endif
+
+C       /* Open a file that is not a netCDF file. */
+        err = nfmpi_open(comm, 'nf_test', NF_NOWRITE, info, ncid)!/* should fail */
+        if (err .ne. NF_ENOTNC .and. err .ne. NF_EOFILE) then
+            call errore('nfmpi_open of non-netCDF file: ', err)
+        else
+            nok = nok + 1
+        endif
+
+C       /* Open a netCDF file in read-only mode, check that write fails */
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_open: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_redef(ncid)    !/* should fail */
+        if (err .ne. NF_EPERM)
+     +      call error('nfmpi_redef of read-only file should fail')
+C       /* Opened OK, see if can open again and get a different netCDF ID */
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid2)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_open: ', err)
+        else
+            err = nfmpi_close(ncid2)
+            nok = nok + 1
+        end if
+        if (ncid2 .eq. ncid)
+     +      call error(
+     +  'netCDF IDs for first and second
+     +   nfmpi_open calls should differ')
+
+        if (.not. readonly) then        !/* tests using netCDF scratch file */
+            flags = IOR(NF_NOCLOBBER, extra_flags)
+            err = nfmpi_create(comm, scratch, flags, info, ncid2)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_create: ', err)
+            else 
+                err = nfmpi_close(ncid2)
+            end if
+            err = nfmpi_open(comm, scratch, NF_WRITE, info, ncid2)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_open: ', err)
+            else 
+                err = nfmpi_close(ncid2)
+                nok = nok + 1
+            end if
+            err = nfmpi_delete(scratch, info)
+            if (err .ne. NF_NOERR) 
+     +          call errorc('delete of scratch file failed: ', scratch)
+        end if
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+C 
+C Test nfmpi_close.
+C    Try to close a netCDF file twice, check whether second close fails.
+C    Try on bad handle, check error return.
+C    Try in define mode and data mode.
+C
+        subroutine test_nfmpi_close()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer err, flags
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+
+C       /* Close a netCDF file twice, second time should fail */
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_close failed: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_EBADID) then
+            call error('nfmpi_close of closed file should have failed')
+        else
+            nok = nok + 1
+        endif
+
+C       /* Try with a bad netCDF ID */
+        err = nfmpi_close(BAD_ID)!/* should fail */
+        if (err .ne. NF_EBADID) then
+            call errore(
+     +         'nfmpi_close with bad netCDF ID returned wrong error: ', 
+     +         err)
+        else
+            nok = nok + 1
+        endif
+
+C       /* Close in data mode */
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_close in data mode failed: ', err)
+        else
+            nok = nok + 1
+        endif
+
+        if (.not. readonly) then        !/* tests using netCDF scratch file */
+            flags = IOR(NF_NOCLOBBER, extra_flags)
+            err = nfmpi_create(comm, scratch, flags, info, ncid)
+            if (err .ne. NF_NOERR) 
+     +          call errore('nfmpi_create: ', err)
+            err = nfmpi_close(ncid)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_close in define mode: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_delete(scratch, info)
+            if (err .ne. NF_NOERR) then
+                call errorc('delete of scratch file failed: ', 
+     +              scratch)
+            else
+                nok = nok + 1
+            endif
+        end if
+        call print_nok(nok)
+        end
+
+
+C Test nfmpi_inq.
+C    Try on bad handle, check error return.
+C    Try in data mode, check returned values.
+C    Try asking for subsets of info.
+C If in writable section of tests,
+C    Try in define mode, after adding an unlimited dimension, variable.
+C On exit, any open netCDF files are closed.
+        subroutine test_nfmpi_inq()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer ncid2                   !/* for scratch netCDF dataset */
+        integer ndims                   !/* number of dimensions */
+        integer nvars                   !/* number of variables */
+        integer ngatts                  !/* number of global attributes */
+        integer recdim                  !/* id of unlimited dimension */
+        integer err, flags
+        integer ndims0
+        integer nvars0
+        integer ngatts0
+        integer recdim0
+        integer did
+        integer vid
+        integer*8 length
+        integer VDIMS(1)
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        
+C       /* Try on bad handle */
+        err = nfmpi_inq(BAD_ID, ndims, nvars, ngatts, recdim)
+        if (err .ne. NF_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+        
+        err = nfmpi_inq(ncid, ndims, nvars, ngatts, recdim)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_inq: ', err)
+        else if (ndims .ne. NDIMS) then
+            call errori
+     +      ('nfmpi_inq: wrong number of dimensions returned: ', ndims)
+        else if (nvars .ne. numVars) then
+            call errori
+     +      ('nfmpi_inq: wrong number of variables returned: ', nvars)
+        else if (ngatts .ne. numGatts) then
+            call errori(
+     +          'nfmpi_inq: wrong number of global atts returned: ',
+     +          ngatts)
+        else if (recdim .ne. RECDIM) then
+            call errori
+     +      ('nfmpi_inq: wrong record dimension ID returned: ', recdim)
+        else
+            nok = nok + 1
+        end if
+
+        if (.not. readonly) then        !/* tests using netCDF scratch file */
+            flags = IOR(NF_NOCLOBBER, extra_flags)
+            err = nfmpi_create(comm, scratch, flags, info, ncid2)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_create: ', err)
+            else                !/* add dim, var, gatt, check inq */
+                err = nfmpi_enddef(ncid2) !/* enter data mode */
+                err = nfmpi_inq(ncid2, ndims0, nvars0, 
+     +              ngatts0, recdim0)
+                if (err .ne. NF_NOERR) then
+                    call errore('nfmpi_inq: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_redef(ncid2) !/* enter define mode */
+C               /* Check that inquire still works in define mode */
+                err = nfmpi_inq(ncid2, ndims, nvars, ngatts, recdim)
+                if (err .ne. NF_NOERR) then
+                    call errore('nfmpi_inq in define mode: ', err)
+                else if (ndims .ne. ndims0) then
+                    call errori
+     +              ('nfmpi_inq in define mode: ndims wrong, ', ndims)
+                else if (nvars .ne. nvars0) then
+                    call errori
+     +              ('nfmpi_inq in define mode: nvars wrong, ', nvars)
+                else if (ngatts .ne. ngatts0) then
+                    call errori(
+     +              'nfmpi_inq in define mode: ngatts wrong, ', ngatts)
+                    print *, ' expected ', ngatts0
+                else if (recdim .ne. recdim0) then
+                    call errori
+     +              ('nfmpi_inq in define mode: recdim wrong, ', recdim)
+                else
+                    nok = nok + 1
+                end if
+
+C               /* Add dim, var, global att */
+                length = 1
+                err = nfmpi_def_dim(ncid2, 'inqd', length, did)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_def_dim: ', err)
+                VDIMS(1) = 0
+                err = nfmpi_def_var(ncid2, 'inqv', NF_FLOAT, 
+     +                0, VDIMS, vid)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_def_var: ', err)
+
+                length = len('stuff')
+                err = nfmpi_put_att_text(ncid2, NF_GLOBAL, 'inqa', 
+     +                                length, 'stuff')
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_put_att_text: ', err)
+
+C               /* Make sure nfmpi_inq sees the additions while in define mode */
+                err = nfmpi_inq(ncid2, ndims, nvars, ngatts, recdim)
+                if (err .ne. NF_NOERR) then
+                    call errore('nfmpi_inq in define mode: ', err)
+                else if (ndims .ne. ndims0 + 1) then
+                    call errori
+     +              ('nfmpi_inq in define mode: ndims wrong, ', ndims)
+                else if (nvars .ne. nvars0 + 1) then
+                    call errori
+     +              ('nfmpi_inq in define mode: nvars wrong, ', nvars)
+                else if (ngatts .ne. ngatts0 + 1) then
+                    call errori
+     +              ('nfmpi_inq in define mode: ngatts wrong, ', ngatts)
+                    print *, ' expected (added attr)', ngatts0 + 1
+                else
+                    nok = nok + 1
+                end if
+                err = nfmpi_enddef(ncid2)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_enddef: ', err)
+
+C               /* Make sure nfmpi_inq stills sees additions in data mode */
+                err = nfmpi_inq(ncid2, ndims, nvars, ngatts, recdim)
+                if (err .ne. NF_NOERR) then
+                    call errore('nfmpi_inq failed in data mode: ',err)
+                else if (ndims .ne. ndims0 + 1) then
+                    call errori
+     +              ('nfmpi_inq in define mode: ndims wrong, ', ndims)
+                else if (nvars .ne. nvars0 + 1) then
+                    call errori
+     +              ('nfmpi_inq in define mode: nvars wrong, ', nvars)
+                else if (ngatts .ne. ngatts0 + 1) then
+                    call errori
+     +              ('nfmpi_inq in define mode: ngatts wrong, ', ngatts)
+                else
+                    nok = nok + 1
+                end if
+                err = nfmpi_close(ncid2)
+                err = nfmpi_delete(scratch, info)
+                if (err .ne. NF_NOERR)
+     +              call errorc('delete of scratch file failed: ', 
+     +                  scratch)
+            end if
+        end if
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_natts()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer ngatts                  !/* number of global attributes */
+        integer err
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_inq_natts(BAD_ID, ngatts)
+        if (err .ne. NF_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_inq_natts(ncid, ngatts)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_inq_natts: ', err)
+        else if (ngatts .ne. numGatts) then
+            call errori
+     +      ('nfmpi_inq_natts: wrong number of global atts returned, ',
+     +        ngatts)
+        else
+            nok = nok + 1
+        end if
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_ndims()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer ndims
+        integer err
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_inq_ndims(BAD_ID, ndims)
+        if (err .ne. NF_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_inq_ndims(ncid, ndims)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_inq_ndims: ', err)
+        else if (ndims .ne. NDIMS) then
+            call errori
+     +      ('nfmpi_inq_ndims: wrong number returned, ', ndims)
+        else
+            nok = nok + 1
+        end if
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_nvars()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer nvars
+        integer err
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_inq_nvars(BAD_ID, nvars)
+        if (err .ne. NF_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_inq_nvars(ncid, nvars)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_inq_nvars: ', err)
+        else if (nvars .ne. numVars) then
+            call errori
+     +      ('nfmpi_inq_nvars: wrong number returned, ', nvars)
+        else
+            nok = nok + 1
+        end if
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_unlimdim()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer unlimdim
+        integer err
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_inq_unlimdim(BAD_ID, unlimdim)
+        if (err .ne. NF_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_inq_unlimdim(ncid, unlimdim)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_inq_unlimdim: ', err)
+        else if (unlimdim .ne. RECDIM) then
+            call errori
+     +      ('nfmpi_inq_unlimdim: wrong number returned, ', unlimdim)
+            print *, 'expected ', RECDIM
+        else
+            nok = nok + 1
+        end if
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_dimid()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer dimid
+        integer i
+        integer err
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_inq_dimid(ncid, 'noSuch', dimid)
+        if (err .ne. NF_EBADDIM) then
+            call errore('bad dim name: ', err)
+        else
+            nok = nok + 1
+        endif
+        do 1, i = 1, NDIMS
+            err = nfmpi_inq_dimid(BAD_ID, dim_name(i), dimid)
+            if (err .ne. NF_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_dimid(ncid, dim_name(i), dimid)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_dimid: ', err)
+            else if (dimid .ne. i) then
+                call errori('expected ', i)
+                call errori('got ', dimid)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_dim()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer i
+        integer err
+        character*(NF_MAX_NAME) name
+        integer*8 length
+        integer intlen
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, NDIMS
+            err = nfmpi_inq_dim(BAD_ID, i, name, length)
+            if (err .ne. NF_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_dim(ncid, BAD_DIMID, name, length)
+            if (err .ne. NF_EBADDIM) then
+                call errore('bad dimid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_dim(ncid, i, name, length)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_dim: ', err)
+            else if (dim_name(i) .ne. name)  then
+                call errorc('name unexpected: ', name)
+                print *, ' expected ', dim_name(i),' for the ',i,'entry'
+            else if (dim_len(i) .ne. length) then
+                intlen = int(length)
+                call errori('size unexpected: ', intlen)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_dimlen()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer i
+        integer err
+        integer*8 length
+        integer intlen
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, NDIMS
+            err = nfmpi_inq_dimlen(BAD_ID, i, length)
+            if (err .ne. NF_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_dimlen(ncid, BAD_DIMID, length)
+            if (err .ne. NF_EBADDIM)
+     +          call errore('bad dimid: ', err)
+            err = nfmpi_inq_dimlen(ncid, i, length)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_dimlen: ', err)
+            else if (dim_len(i) .ne. length) then
+                intlen = int(length)
+                call errori('size unexpected: ', intlen)
+                print *, 'expected ', dim_len(i),' for the ',i,'entry'
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_dimname()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer i
+        integer err
+        character*(NF_MAX_NAME)  name
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, NDIMS
+            err = nfmpi_inq_dimname(BAD_ID, i, name)
+            if (err .ne. NF_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nfmpi_inq_dimname(ncid, BAD_DIMID, name)
+            if (err .ne. NF_EBADDIM) then
+                call errore('bad dimid: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nfmpi_inq_dimname(ncid, i, name)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_dimname: ', err)
+            else if (dim_name(i) .ne. name)  then
+                call errorc('name unexpected: ', name)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_varid()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer vid
+        integer i
+        integer err
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+
+        err = nfmpi_inq_varid(ncid, 'noSuch', vid)
+        if (err .ne. NF_ENOTVAR)
+     +      call errore('bad ncid: ', err)
+
+        do 1, i = 1, numVars
+            err = nfmpi_inq_varid(BAD_ID, var_name(i), vid)
+            if (err .ne. NF_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nfmpi_inq_varid(ncid, var_name(i), vid)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_varid: ', err)
+            else if (vid .ne. i) then
+                call errori('varid unexpected: ', vid)
+            else
+                nok = nok + 1
+            endif
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_var()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        logical int_vec_eq
+
+        integer ncid
+        integer i
+        integer err
+        character*(NF_MAX_NAME) name
+        integer datatype
+        integer ndims
+        integer dimids(MAX_RANK)
+        integer na
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            err = nfmpi_inq_var(BAD_ID, i, name, datatype, ndims, 
+     +            dimids, na)
+            if (err .ne. NF_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_var(ncid,BAD_VARID,name,datatype,ndims,
+     +                       dimids,na)
+            if (err .ne. NF_ENOTVAR) then
+                call errore('bad var id: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_var(ncid, i, name, datatype, ndims, dimids, 
+     +                       na)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_var: ', err)
+            else if (var_name(i) .ne. name)  then
+                call errorc('name unexpected: ', name)
+            else if (var_type(i) .ne. datatype) then
+                call errori('type unexpected: ', datatype)
+            else if (var_rank(i) .ne. ndims) then
+                call errori('ndims expected: ', ndims)
+            else if (.not.int_vec_eq(var_dimid(1,i),dimids,ndims)) then
+                call error('unexpected dimid')
+            else if (var_natts(i) .ne. na) then
+                call errori('natts unexpected: ', na)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_vardimid()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        logical int_vec_eq
+
+        integer ncid
+        integer i
+        integer err
+        integer dimids(MAX_RANK)
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            err = nfmpi_inq_vardimid(BAD_ID, i, dimids)
+            if (err .ne. NF_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_vardimid(ncid, BAD_VARID, dimids)
+            if (err .ne. NF_ENOTVAR) then
+                call errore('bad var id: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_vardimid(ncid, i, dimids)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_vardimid: ', err)
+            else if (.not.int_vec_eq(var_dimid(1,i), dimids, 
+     +               var_rank(i))) then
+                call error('unexpected dimid')
+                print *, ' for variable ', i
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_varname()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer i
+        integer err
+        character*(NF_MAX_NAME) name
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            err = nfmpi_inq_varname(BAD_ID, i, name)
+            if (err .ne. NF_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_varname(ncid, BAD_VARID, name)
+            if (err .ne. NF_ENOTVAR) then
+                call errore('bad var id: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_varname(ncid, i, name)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_varname: ', err)
+            else if (var_name(i) .ne. name)  then
+                call errorc('name unexpected: ', name)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_varnatts()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer VARID, NATTS
+
+        integer ncid
+        integer i
+        integer err
+        integer na
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 0, numVars    ! start with global attributes
+            err = nfmpi_inq_varnatts(BAD_ID, i, na)
+            if (err .ne. NF_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nfmpi_inq_varnatts(ncid, BAD_VARID, na)
+            if (err .ne. NF_ENOTVAR) then
+                call errore('bad var id: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nfmpi_inq_varnatts(ncid, VARID(i), na)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_varnatts: ', err)
+            else if (NATTS(i) .ne. na) then ! works for global attributes
+                call errori('natts unexpected: ', na)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_varndims()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer i
+        integer err
+        integer ndims
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            err = nfmpi_inq_varndims(BAD_ID, i, ndims)
+            if (err .ne. NF_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nfmpi_inq_varndims(ncid, BAD_VARID, ndims)
+            if (err .ne. NF_ENOTVAR) then
+                call errore('bad var id: ', err)
+            else
+                nok = nok + 1
+            end if
+            err = nfmpi_inq_varndims(ncid, i, ndims)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_varndims: ', err)
+            else if (var_rank(i) .ne. ndims) then
+                call errori('ndims unexpected: ', ndims)
+            else
+                nok = nok + 1
+            end if
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_vartype()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer i
+        integer err
+        integer datatype
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 1, i = 1, numVars
+            err = nfmpi_inq_vartype(BAD_ID, i, datatype)
+            if (err .ne. NF_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_vartype(ncid, BAD_VARID, datatype)
+            if (err .ne. NF_ENOTVAR) then
+                call errore('bad var id: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_vartype(ncid, i, datatype)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_vartype: ', err)
+            else if (var_type(i) .ne. datatype) then
+                call errori('type unexpected: ', datatype)
+                nok = nok + 1
+            end if
+1       continue
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_att()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer ATT_TYPE, NATTS, ATT_LEN
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        integer t
+        integer*8 n
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_open: ', err)
+
+        do 1, i = 0, numVars
+            do 2, j = 1, NATTS(i)
+                err = nfmpi_inq_att(BAD_ID, i, ATT_NAME(j,i), t, n)
+                if (err .ne. NF_EBADID) then
+                    call errore('bad ncid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_inq_att
+     +                     (ncid, BAD_VARID, ATT_NAME(j,i), t, n)
+                if (err .ne. NF_ENOTVAR) then
+                    call errore('bad var id: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_inq_att(ncid, i, 'noSuch', t, n)
+                if (err .ne. NF_ENOTATT) then
+                    call errore('Bad attribute name: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_inq_att(ncid, i, ATT_NAME(j,i), t, n)
+                if (err .ne. NF_NOERR) then
+                    call error(nfmpi_strerror(err))
+                else
+                    if (t .ne. ATT_TYPE(j,i))
+     +                  call error('type not that expected')
+                    if (n .ne. ATT_LEN(j,i)) 
+     +                  call error('length not that expected')
+                    nok = nok + 1
+                end if
+2           continue
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_attlen()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer NATTS, ATT_LEN
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        integer*8 len
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+
+        do 1, i = 0, numVars
+            err = nfmpi_inq_attlen(ncid, i, 'noSuch', len)
+            if (err .ne. NF_ENOTATT) then
+                call errore('Bad attribute name: ', err)
+            else
+                nok = nok + 1
+            endif
+            do 2, j = 1, NATTS(i)
+                err = nfmpi_inq_attlen(BAD_ID, i, 
+     +             ATT_NAME(j,i), len)
+                if (err .ne. NF_EBADID) then
+                    call errore('bad ncid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_inq_attlen
+     +                (ncid, BAD_VARID, ATT_NAME(j,i), len)
+                if (err .ne. NF_ENOTVAR) then
+                    call errore('bad varid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_inq_attlen(ncid, i, ATT_NAME(j,i), len)
+                if (err .ne. NF_NOERR) then
+                    call error(nfmpi_strerror(err))
+                else
+                    if (len .ne. ATT_LEN(j,i))
+     +                  call error('len not that expected')
+                    nok = nok + 1
+                end if
+2           continue
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_atttype()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer ATT_TYPE, NATTS
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        integer datatype
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+
+        do 1, i = 0, numVars
+            err = nfmpi_inq_atttype(ncid, i, 'noSuch', datatype)
+            if (err .ne. NF_ENOTATT) then
+                call errore('Bad attribute name: ', err)
+            else
+                nok = nok + 1
+            endif
+            do 2, j = 1, NATTS(i)
+                err = nfmpi_inq_atttype
+     +                (BAD_ID, i, ATT_NAME(j,i), datatype)
+                if (err .ne. NF_EBADID) then
+                    call errore('bad ncid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_inq_atttype(ncid, BAD_VARID, ATT_NAME(j,i), 
+     +                               datatype)
+                if (err .ne. NF_ENOTVAR) then
+                    call errore('bad varid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_inq_atttype
+     +                (ncid, i, ATT_NAME(j,i), datatype)
+                if (err .ne. NF_NOERR) then
+                    call error(nfmpi_strerror(err))
+                else
+                    if (datatype .ne. ATT_TYPE(j,i))
+     +                  call error('type not that expected')
+                    nok = nok + 1
+                end if
+2           continue
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_attname()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer NATTS
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        character*(NF_MAX_NAME) name
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+
+        do 1, i = 0, numVars
+            err = nfmpi_inq_attname(ncid, i, BAD_ATTNUM, name)
+            if (err .ne. NF_ENOTATT) then
+                call errore('Bad attribute number: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_attname(ncid, i, NATTS(i)+1, name)
+            if (err .ne. NF_ENOTATT) then
+                call errore('Bad attribute number: ', err)
+            else
+                nok = nok + 1
+            endif
+            do 2, j = 1, NATTS(i)
+                err = nfmpi_inq_attname(BAD_ID, i, j, name)
+                if (err .ne. NF_EBADID) then
+                    call errore('bad ncid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_inq_attname(ncid, BAD_VARID, j, name)
+                if (err .ne. NF_ENOTVAR) then
+                    call errore('bad var id: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_inq_attname(ncid, i, j, name)
+                if (err .ne. NF_NOERR) then
+                    call error(nfmpi_strerror(err))
+                else
+                    if (ATT_NAME(j,i) .ne. name)
+     +                  call error('name not that expected')
+                    nok = nok + 1
+                end if
+2           continue
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
+
+
+        subroutine test_nfmpi_inq_attid()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer NATTS
+
+        integer ncid
+        integer i
+        integer j
+        integer err
+        integer attnum
+        integer nok
+
+        nok = 0
+
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+
+        do 1, i = 0, numVars
+            err = nfmpi_inq_attid(ncid, i, 'noSuch', attnum)
+            if (err .ne. NF_ENOTATT) then
+                call errore('Bad attribute name: ', err)
+            else
+                nok = nok + 1
+            endif
+            do 2, j = 1, NATTS(i)
+                err = nfmpi_inq_attid(BAD_ID, i, 
+     +                ATT_NAME(j,i), attnum)
+                if (err .ne. NF_EBADID) then
+                    call errore('bad ncid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_inq_attid(ncid, BAD_VARID, ATT_NAME(j,i), 
+     +                             attnum)
+                if (err .ne. NF_ENOTVAR) then
+                    call errore('bad varid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_inq_attid(ncid, i, 
+     +               ATT_NAME(j,i), attnum)
+                if (err .ne. NF_NOERR) then
+                    call error(nfmpi_strerror(err))
+                else
+                    if (attnum .ne. j)
+     +                  call error('attnum not that expected')
+                    nok = nok + 1
+                end if
+2           continue
+1       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        call print_nok(nok)
+        end
diff --git a/test/nf_test/test_write.F b/test/nf_test/test_write.F
new file mode 100644
index 0000000..92ced17
--- /dev/null
+++ b/test/nf_test/test_write.F
@@ -0,0 +1,1740 @@
+C********************************************************************
+C   Copyright 1996, UCAR/Unidata
+C   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+C   $Id: test_write.F 2224 2015-12-16 06:10:36Z wkliao $
+C********************************************************************
+
+
+C Test nfmpi_create
+C    For mode in NF_NOCLOBBER, NF_CLOBBER do:
+C       create netcdf file 'scratch.nc' with no data, close it
+C       test that it can be opened, do nfmpi_inq to check nvars = 0, etc.
+C    Try again in NF_NOCLOBBER mode, check error return
+C On exit, delete this file
+        subroutine test_nfmpi_create()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer clobber         !/* 0 for NF_NOCLOBBER, 1 for NF_CLOBBER */
+        integer err
+        integer ncid
+        integer ndims           !/* number of dimensions */
+        integer nvars           !/* number of variables */
+        integer ngatts          !/* number of global attributes */
+        integer recdim          !/* id of unlimited dimension */
+        integer flags
+        integer nok
+
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        nok = 0
+        do 1, clobber = 0, 1
+            err = nfmpi_create(comm, scratch, flags,  info, ncid)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_create: ', err)
+            end if
+            nok = nok + 1
+            err = nfmpi_close(ncid)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_close: ', err)
+            end if
+            err = nfmpi_open(comm, scratch, NF_NOWRITE, info, ncid)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_open: ', err)
+            end if
+            err = nfmpi_inq(ncid, ndims, nvars, ngatts, recdim)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq: ', err)
+            else if (ndims .ne. 0) then
+                call errori(
+     +              'nfmpi_inq: wrong number of dimensions returned, ',
+     +              ndims)
+            else if (nvars .ne. 0) then
+                call errori(
+     +              'nfmpi_inq: wrong number of variables returned, ',
+     +              nvars)
+            else if (ngatts .ne. 0) then
+                call errori(
+     +              'nfmpi_inq: wrong number of global atts returned, ',
+     +              ngatts)
+            else if (recdim .ge. 1) then
+                call errori(
+     +              'nfmpi_inq: wrong record dimension ID returned, ',
+     +              recdim)
+            end if
+            err = nfmpi_close(ncid)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_close: ', err)
+            end if
+
+            flags = IOR(NF_CLOBBER, extra_flags)
+1       continue
+
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags,  info, ncid)
+        if (err .ne. NF_EEXIST) then
+            call errore('attempt to overwrite file: ', err)
+        end if
+        nok = nok + 1
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR) then
+            call errori('delete of scratch file failed: ', err)
+        end if
+        call print_nok(nok)
+        end
+
+
+C Test nfmpi_redef 
+C (In fact also tests nfmpi_enddef - called from test_nfmpi_enddef)
+C    BAD_ID
+C    attempt redef (error) & enddef on read-only file
+C    create file, define dims & vars. 
+C    attempt put var (error)
+C    attempt redef (error) & enddef.
+C    put vars
+C    attempt def new dims (error)
+C    redef
+C    def new dims, vars.
+C    put atts
+C    enddef
+C    put vars
+C    close
+C    check file: vars & atts
+        subroutine test_nfmpi_redef()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer         title_len
+        parameter       (title_len = 9)
+
+        integer                 ncid            !/* netcdf id */
+        integer                 dimid           !/* dimension id */
+        integer                 vid             !/* variable id */
+        integer                 err
+        character*(title_len)   title
+        doubleprecision         var
+        character*(NF_MAX_NAME) name
+        integer*8               start(1)
+        integer*8               length
+        integer                 intlen
+        integer                 dimids(1)
+        integer                 nok, flags
+        nok = 0
+
+        title = 'Not funny'
+
+C           /* BAD_ID tests */
+        err = nfmpi_redef(BAD_ID)
+        if (err .ne. NF_EBADID) then
+            call errore('bad ncid: ', err)
+        endif
+        nok = nok + 1
+        err = nfmpi_enddef(BAD_ID)
+        if (err .ne. NF_EBADID) then
+            call errore('bad ncid: ', err)
+        endif
+        nok = nok + 1
+
+C           /* read-only tests */
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_redef(ncid)
+        if (err .ne. NF_EPERM) then
+            call errore('nfmpi_redef in NF_NOWRITE mode: ', err)
+        endif
+        nok = nok + 1
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_ENOTINDEFINE) then
+            call errore('nfmpi_redef in NF_NOWRITE mode: ', err)
+        endif
+        nok = nok + 1
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_close: ', err)
+
+C           /* tests using scratch file */
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+        err = nfmpi_inq_varid(ncid, 'd', vid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_inq_varid: ', err)
+        var = 1.0
+c       should not enter indep mode in define mode
+        err = nfmpi_begin_indep_data(ncid)       
+        if (err .ne. NF_EINDEFINE)
+     +    call errore('nfmpi_begin_indep_data... in define mode: ', err)
+        start(1) = 0
+        err = nfmpi_put_var1_double(ncid, vid, start, var)
+        if (err .ne. NF_EINDEFINE)
+     +      call errore('nfmpi_put_var... in define mode: ', err)
+        err = nfmpi_end_indep_data(ncid)
+        if (err .ne. NF_ENOTINDEP)
+     +    call errore('nfmpi_end_indep_data... not in indep mode: ',err)
+        err = nfmpi_redef(ncid)
+        if (err .ne. NF_EINDEFINE) then
+            call errore('nfmpi_redef in define mode: ', err)
+        endif
+        nok = nok + 1
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        call put_vars(ncid)
+        length = 8
+        err = nfmpi_def_dim(ncid, 'abc', length, dimid)
+        if (err .ne. NF_ENOTINDEFINE)
+     +      call errore('nfmpi_def_dim in define mode: ', err)
+        err = nfmpi_redef(ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_redef: ', err)
+        endif
+        nok = nok + 1
+        length = 8
+        err = nfmpi_def_dim(ncid, 'abc', length, dimid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_def_dim: ', err)
+        dimids(1) = 0
+        err = nfmpi_def_var(ncid, 'abc', NF_INT, 0, dimids, vid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_def_var: ', err)
+        length = len(title)
+        err = nfmpi_put_att_text(ncid, NF_GLOBAL, 'title', length, 
+     +                        title)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_put_att_text: ', err)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        var = 1.0
+        err = nfmpi_end_indep_data(ncid)
+        if (err .ne. NF_ENOTINDEP)
+     +     call errore('nfmpi_end_indep_data: in collective mode: ',err)
+        err = nfmpi_begin_indep_data(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_begin_indep_data: ', err)
+        err = nfmpi_put_var1_double(ncid, vid, start, var)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_put_var1_double: ', err)
+        err = nfmpi_end_indep_data(ncid)       
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_end_indep_data: ', err)
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_close: ', err)
+
+C           /* check scratch file written as expected */
+        call check_file(scratch)
+        err = nfmpi_open(comm, scratch, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_inq_dim(ncid, dimid, name, length)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_inq_dim: ', err)
+        if (name .ne. "abc")
+     +      call errori('Unexpected dim name in netCDF ', ncid)
+        if (length .ne. 8) then
+            intlen = int(length)
+            call errori('Unexpected dim length: ', intlen)
+        end if
+        err = nfmpi_begin_indep_data(ncid)
+        err = nfmpi_get_var1_double(ncid, vid, start, var)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_get_var1_double: ', err)
+        if (var .ne. 1.0)
+     +      call errori(
+     +          'nfmpi_get_var1_double: unexpected value in netCDF '
+     +          , ncid)
+        err = nfmpi_end_indep_data(ncid)
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errori('delete failed for netCDF: ', err)
+        call print_nok(nok)
+        end
+
+C Test nfmpi_enddef 
+C Simply calls test_nfmpi_redef which tests both nfmpi_redef & nfmpi_enddef
+
+        subroutine test_nfmpi_enddef()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        call test_nfmpi_redef
+        end
+
+
+C Test nfmpi_sync
+C    try with bad handle, check error
+C    try in define mode, check error
+C    try writing with one handle, reading with another on same netCDF
+        subroutine test_nfmpi_sync()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncidw         !/* netcdf id for writing */
+        integer ncidr         !/* netcdf id for reading */
+        integer err
+        integer nok, flags
+
+        nok = 0
+C           /* BAD_ID test */
+        err = nfmpi_sync(BAD_ID)
+        if (err .ne. NF_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+
+C           /* create scratch file & try nfmpi_sync in define mode */
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncidw)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        err = nfmpi_sync(ncidw)
+        if (err .ne. NF_EINDEFINE) then
+            call errore('nfmpi_sync called in define mode: ', err)
+        else
+            nok = nok + 1
+        endif
+
+C           /* write using same handle */
+        call def_dims(ncidw)
+        call def_vars(ncidw)
+        call put_atts(ncidw)
+        err = nfmpi_enddef(ncidw)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        call put_vars(ncidw)
+        err = nfmpi_sync(ncidw)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_sync of ncidw failed: ', err)
+        else
+            nok = nok + 1
+        endif
+
+C           /* open another handle, nfmpi_sync, read (check) */
+        err = nfmpi_open(comm, scratch, NF_NOWRITE, info, ncidr)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_sync(ncidr)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_sync of ncidr failed: ', err)
+        else
+            nok = nok + 1
+        endif
+        call check_dims(ncidr)
+        call check_atts(ncidr)
+        call check_vars(ncidr)
+
+C           /* close both handles */
+        err = nfmpi_close(ncidr)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        err = nfmpi_close(ncidw)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errori('delete of scratch file failed: ', err)
+        call print_nok(nok)
+        end
+
+
+C Test nfmpi_abort
+C    try with bad handle, check error
+C    try in define mode before anything written, check that file was deleted
+C    try after nfmpi_enddef, nfmpi_redef, define new dims, vars, atts
+C    try after writing variable
+        subroutine test_nfmpi_abort()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid          !/* netcdf id */
+        integer err
+        integer ndims
+        integer nvars
+        integer ngatts
+        integer recdim
+        integer nok, flags
+
+        nok = 0
+
+C           /* BAD_ID test */
+        err = nfmpi_abort(BAD_ID)
+        if (err .ne. NF_EBADID) then
+            call errore('bad ncid: status = ', err)
+        else
+            nok = nok + 1
+        endif
+
+C           /* create scratch file & try nfmpi_abort in define mode */
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+        err = nfmpi_abort(ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_abort of ncid failed: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_close(ncid)    !/* should already be closed */
+        if (err .ne. NF_EBADID)
+     +      call errore('bad ncid: ', err)
+        err = nfmpi_delete(scratch, info)    !/* should already be deleted */
+        if (err .eq. NF_NOERR)
+     +      call errori('scratch file should not exist: ', err)
+
+C            create scratch file
+C            do nfmpi_enddef & nfmpi_redef
+C            define new dims, vars, atts
+C            try nfmpi_abort: should restore previous state (no dims, vars, atts)
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        err = nfmpi_redef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_redef: ', err)
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+        err = nfmpi_abort(ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_abort of ncid failed: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_close(ncid)    !/* should already be closed */
+        if (err .ne. NF_EBADID)
+     +      call errore('bad ncid: ', err)
+        err = nfmpi_open(comm, scratch, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_inq (ncid, ndims, nvars, ngatts, recdim)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_inq: ', err)
+        if (ndims .ne. 0)
+     +      call errori('ndims should be ', 0)
+        if (nvars .ne. 0)
+     +      call errori('nvars should be ', 0)
+        if (ngatts .ne. 0)
+     +      call errori('ngatts should be ', 0)
+        err = nfmpi_close (ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+
+C           /* try nfmpi_abort in data mode - should just close */
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        call put_vars(ncid)
+        err = nfmpi_abort(ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_abort of ncid failed: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_close(ncid)       !/* should already be closed */
+        if (err .ne. NF_EBADID)
+     +      call errore('bad ncid: ', err)
+        call check_file(scratch)
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errori('delete of scratch file failed: ', err)
+        call print_nok(nok)
+        end
+
+
+C Test nfmpi_def_dim
+C    try with bad netCDF handle, check error
+C    try in data mode, check error
+C    check that returned id is one more than previous id
+C    try adding same dimension twice, check error
+C    try with illegal sizes, check error
+C    make sure unlimited size works, shows up in nfmpi_inq_unlimdim
+C    try to define a second unlimited dimension, check error
+        subroutine test_nfmpi_def_dim()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer err             !/* status */
+        integer i
+        integer dimid         !/* dimension id */
+        integer*8 length
+        integer nok, flags
+
+        nok = 0
+
+C           /* BAD_ID test */
+        length = 8
+        err = nfmpi_def_dim(BAD_ID, 'abc', length, dimid)
+        if (err .ne. NF_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+
+C           /* data mode test */
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        length = 8
+        err = nfmpi_def_dim(ncid, 'abc', length, dimid)
+        if (err .ne. NF_ENOTINDEFINE) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+
+C           /* define-mode tests: unlimited dim */
+        err = nfmpi_redef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_redef: ', err)
+        err = nfmpi_def_dim(ncid, dim_name(1), NFMPI_UNLIMITED, dimid)
+        if (err .ne. NF_NOERR)  then
+            call errore('nfmpi_def_dim: ', err)
+        else
+            nok = nok + 1
+        endif
+        if (dimid .ne. 1) 
+     +      call errori('Unexpected dimid: ', dimid)
+        err = nfmpi_inq_unlimdim(ncid, dimid)
+        if (err .ne. NF_NOERR) 
+     +      call errore('nfmpi_inq_unlimdim: ', err)
+        if (dimid .ne. RECDIM) 
+     +      call error('Unexpected recdim: ')
+        err = nfmpi_inq_dimlen(ncid, dimid, length)
+        if (length .ne. 0) 
+     +      call errori('Unexpected length: ', 0)
+        err = nfmpi_def_dim(ncid, 'abc', NFMPI_UNLIMITED, dimid)
+        if (err .ne. NF_EUNLIMIT) then
+            call errore('2nd unlimited dimension: ', err)
+        else
+            nok = nok + 1
+        endif
+
+C           /* define-mode tests: remaining dims */
+        do 1, i = 2, NDIMS
+            err = nfmpi_def_dim(ncid, dim_name(i-1), dim_len(i), 
+     +                       dimid)
+            if (err .ne. NF_ENAMEINUSE) then
+                call errore('duplicate name: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_def_dim(ncid, BAD_NAME, dim_len(i), dimid)
+            if (err .ne. NF_EBADNAME) then
+                call errore('bad name: ', err)
+            else
+                nok = nok + 1
+            endif
+            length = NFMPI_UNLIMITED - 1
+            err = nfmpi_def_dim(ncid, dim_name(i), length,
+     +                       dimid)
+            if (err .ne. NF_EDIMSIZE) then
+                call errore('bad size: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_def_dim(ncid, dim_name(i), 
+     &               dim_len(i), dimid)
+            if (err .ne. NF_NOERR)  then
+                call errore('nfmpi_def_dim: ', err)
+            else
+                nok = nok + 1
+            endif
+            if (dimid .ne. i) 
+     +          call errori('Unexpected dimid: ', 0)
+1       continue
+
+C           /* Following just to expand unlimited dim */
+        call def_vars(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        call put_vars(ncid)
+
+C           /* Check all dims */
+        call check_dims(ncid)
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errori('delete of scratch file failed: ', err)
+        call print_nok(nok)
+        end
+
+
+C Test nfmpi_rename_dim
+C    try with bad netCDF handle, check error
+C    check that proper rename worked with nfmpi_inq_dim
+C    try renaming to existing dimension name, check error
+C    try with bad dimension handle, check error
+        subroutine test_nfmpi_rename_dim()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer err             !/* status */
+        character*(NF_MAX_NAME) name
+        integer nok, flags
+
+        nok = 0
+
+C           /* BAD_ID test */
+        err = nfmpi_rename_dim(BAD_ID, 1, 'abc')
+        if (err .ne. NF_EBADID) then
+            call errore('bad ncid: ', err)
+        else
+            nok = nok + 1
+        endif
+
+C           /* main tests */
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        err = nfmpi_rename_dim(ncid, BAD_DIMID, 'abc')
+        if (err .ne. NF_EBADDIM) then
+            call errore('bad dimid: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_rename_dim(ncid, 3, 'abc')
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_rename_dim: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_inq_dimname(ncid, 3, name)
+        if (name .ne. 'abc')
+     +      call errorc('Unexpected name: ', name)
+        err = nfmpi_rename_dim(ncid, 1, 'abc')
+        if (err .ne. NF_ENAMEINUSE) then
+            call errore('duplicate name: ', err)
+        else
+            nok = nok + 1
+        endif
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errori('delete of scratch file failed: ', err)
+        call print_nok(nok)
+        end
+
+
+C Test nfmpi_def_var
+C    try with bad netCDF handle, check error
+C    try with bad name, check error
+C    scalar tests:
+C      check that proper define worked with nfmpi_inq_var
+C      try redefining an existing variable, check error
+C      try with bad datatype, check error
+C      try with bad number of dimensions, check error
+C      try in data mode, check error
+C    check that returned id is one more than previous id
+C    try with bad dimension ids, check error
+        subroutine test_nfmpi_def_var()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer vid
+        integer err             !/* status */
+        integer i
+        integer ndims
+        integer na
+        character*(NF_MAX_NAME) name
+        integer dimids(MAX_RANK)
+        integer datatype
+        integer nok, flags
+
+        nok = 0
+
+C           /* BAD_ID test */
+        err = nfmpi_def_var(BAD_ID, 'abc', NF_SHORT, 0, dimids, vid)
+        if (err .ne. NF_EBADID) then
+            call errore('bad ncid: status = ', err)
+        else
+            nok = nok + 1
+        endif
+
+C           /* scalar tests */
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        err = nfmpi_def_var(ncid, 'abc', NF_SHORT, 0, dimids, vid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_def_var: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_inq_var(ncid, vid, name, datatype, ndims, dimids, 
+     +                   na)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_inq_var: ', err)
+        if (name .ne. 'abc')
+     +      call errorc('Unexpected name: ', name)
+        if (datatype .ne. NF_SHORT)
+     +      call error('Unexpected datatype')
+        if (ndims .ne. 0)
+     +      call error('Unexpected rank')
+        err = nfmpi_def_var(ncid, BAD_NAME, NF_SHORT, 0, dimids, vid)
+        if (err .ne. NF_EBADNAME) then
+            call errore('bad name: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_def_var(ncid, 'abc', NF_SHORT, 0, dimids, vid)
+        if (err .ne. NF_ENAMEINUSE) then
+            call errore('duplicate name: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_def_var(ncid, 'ABC', BAD_TYPE, -1, dimids, vid)
+        if (err .ne. NF_EBADTYPE) then
+            call errore('bad type: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_def_var(ncid, 'ABC', NF_SHORT, -1, dimids, vid)
+        if (err .ne. NF_EINVAL) then
+            call errore('bad rank: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        err = nfmpi_def_var(ncid, 'ABC', NF_SHORT, 0, dimids, vid)
+        if (err .ne. NF_ENOTINDEFINE) then
+            call errore('nfmpi_def_var called in data mode: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed: ', scratch)
+
+C           /* general tests using global vars */
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        do 1, i = 1, numVars
+            err = nfmpi_def_var(ncid, var_name(i), var_type(i), 
+     +                       var_rank(i), var_dimid(1,i), vid)
+            if (err .ne. NF_NOERR)  then
+                call errore('nfmpi_def_var: ', err)
+            else
+                nok = nok + 1
+            endif
+            if (vid .ne. i)
+     +          call error('Unexpected varid')
+1       continue
+
+C           /* try bad dim ids */
+        dimids(1) = BAD_DIMID
+        err = nfmpi_def_var(ncid, 'abc', NF_SHORT, 1, dimids, vid)
+        if (err .ne. NF_EBADDIM) then
+            call errore('bad dim ids: ', err)
+        else
+            nok = nok + 1
+        endif
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed: ', scratch)
+        call print_nok(nok)
+        end
+
+
+C Test nfmpi_rename_var
+C    try with bad netCDF handle, check error
+C    try with bad variable handle, check error
+C    try renaming to existing variable name, check error
+C    check that proper rename worked with nfmpi_inq_varid
+C    try in data mode, check error
+        subroutine test_nfmpi_rename_var()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid
+        integer vid
+        integer err
+        integer i
+        character*(NF_MAX_NAME) name
+        integer nok, flags
+
+        nok = 0
+
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        err = nfmpi_rename_var(ncid, BAD_VARID, 'newName')
+        if (err .ne. NF_ENOTVAR) then
+            call errore('bad var id: ', err)
+        else
+            nok = nok + 1
+        endif
+        call def_dims(ncid)
+        call def_vars(ncid)
+
+C           /* Prefix "new_" to each name */
+        do 1, i = 1, numVars
+            err = nfmpi_rename_var(BAD_ID, i, 'newName')
+            if (err .ne. NF_EBADID) then
+                call errore('bad ncid: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_rename_var(ncid, i, var_name(numVars))
+            if (err .ne. NF_ENAMEINUSE) then
+                call errore('duplicate name: ', err)
+            else
+                nok = nok + 1
+            endif
+            name = 'new_' // var_name(i)
+            err = nfmpi_rename_var(ncid, i, name)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_rename_var: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_varid(ncid, name, vid)
+            if (err .ne. NF_NOERR)
+     +          call errore('nfmpi_inq_varid: ', err)
+            if (vid .ne. i)
+     +          call error('Unexpected varid')
+1       continue
+
+C           /* Change to data mode */
+C           /* Try making names even longer. Then restore original names */
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        do 2, i = 1, numVars
+            name = 'even_longer_' // var_name(i)
+            err = nfmpi_rename_var(ncid, i, name)
+            if (err .ne. NF_ENOTINDEFINE) then
+                call errore('longer name in data mode: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_rename_var(ncid, i, var_name(i))
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_rename_var: ', err)
+            else
+                nok = nok + 1
+            endif
+            err = nfmpi_inq_varid(ncid, var_name(i), vid)
+            if (err .ne. NF_NOERR)
+     +          call errore('nfmpi_inq_varid: ', err)
+            if (vid .ne. i)
+     +          call error('Unexpected varid')
+2       continue
+
+        call put_vars(ncid)
+        call check_vars(ncid)
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed: ', scratch)
+        call print_nok(nok)
+        end
+
+
+C Test nfmpi_copy_att
+C    try with bad source or target netCDF handles, check error
+C    try with bad source or target variable handle, check error
+C    try with nonexisting attribute, check error
+C    check that NF_GLOBAL variable for source or target works
+C    check that new attribute put works with target in define mode
+C    check that old attribute put works with target in data mode
+C    check that changing type and length of an attribute work OK
+C    try with same ncid for source and target, different variables
+C    try with same ncid for source and target, same variable
+        subroutine test_nfmpi_copy_att()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer VARID, NATTS, ATT_LEN
+
+        integer ncid_in
+        integer ncid_out
+        integer vid
+        integer err
+        integer i
+        integer j
+        character*(NF_MAX_NAME) name    !/* of att */
+        integer datatype                !/* of att */
+        integer*8 length  !/* of att */
+        character*1     value
+        integer nok, flags
+
+        nok = 0
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid_in)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid_out)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid_out)
+        call def_vars(ncid_out)
+
+        do 1, i = 0, numVars
+            vid = VARID(i)
+            do 2, j = 1, NATTS(i)
+                name = ATT_NAME(j,i)
+                err = nfmpi_copy_att(ncid_in, BAD_VARID, name,
+     +                                ncid_out, vid)
+                if (err .ne. NF_ENOTVAR)
+     +              call errore('bad var id: ', err)
+                nok = nok + 1
+                err = nfmpi_copy_att(ncid_in, vid, name, ncid_out, 
+     +                            BAD_VARID)
+                if (err .ne. NF_ENOTVAR)
+     +              call errore('bad var id: ', err)
+                nok = nok + 1
+                err = nfmpi_copy_att(BAD_ID, vid, name, 
+     +                ncid_out, vid)
+                if (err .ne. NF_EBADID)
+     +              call errore('bad ncid: ', err)
+                nok = nok + 1
+                err = nfmpi_copy_att(ncid_in, vid, name, 
+     +                BAD_ID, vid)
+                if (err .ne. NF_EBADID)
+     +              call errore('bad ncid: ', err)
+                nok = nok + 1
+                err = nfmpi_copy_att(ncid_in, vid, 'noSuch',
+     +                                ncid_out, vid)
+                if (err .ne. NF_ENOTATT)
+     +              call errore('bad attname: ', err)
+                nok = nok + 1
+                err = nfmpi_copy_att(ncid_in, vid, name, 
+     +                 ncid_out, vid)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_copy_att: ', err)
+                nok = nok + 1
+                err = nfmpi_copy_att(ncid_out, vid, name,
+     +                                ncid_out, vid)
+                if (err .ne. NF_NOERR)
+     +              call errore('source = target: ', err)
+                nok = nok + 1
+2           continue
+1       continue
+
+        err = nfmpi_close(ncid_in)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+
+C           /* Close scratch. Reopen & check attributes */
+        err = nfmpi_close(ncid_out)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        err = nfmpi_open(comm, scratch, NF_WRITE, info, ncid_out)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        call check_atts(ncid_out)
+
+C           change to define mode
+C           define single char. global att. ':a' with value 'A'
+C           This will be used as source for following copies
+        err = nfmpi_redef(ncid_out)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_redef: ', err)
+        length = 1
+        err = nfmpi_put_att_text(ncid_out, NF_GLOBAL, 'a', length, 'A')
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_put_att_text: ', err)
+
+C           change to data mode
+C           Use scratch as both source & dest.
+C           try copy to existing att. change type & decrease length
+C           rename 1st existing att of each var (if any) 'a'
+C           if this att. exists them copy ':a' to it
+        err = nfmpi_enddef(ncid_out)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        do 3, i = 1, numVars
+            if (NATTS(i) .gt. 0 .and. ATT_LEN(1,i) .gt. 0) then
+                err = nfmpi_rename_att(ncid_out, i, 
+     +                att_name(1,i), 'a')
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_rename_att: ', err)
+                err = nfmpi_copy_att(ncid_out, NF_GLOBAL, 'a',
+     +                                ncid_out, i)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_copy_att: ', err)
+                nok = nok + 1
+            end if
+3       continue
+        err = nfmpi_close(ncid_out)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+
+C           /* Reopen & check */
+        err = nfmpi_open(comm, scratch, NF_WRITE, info, ncid_out)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        do 4, i = 1, numVars
+            if (NATTS(i) .gt. 0 .and. ATT_LEN(1,i) .gt. 0) then
+                err = nfmpi_inq_att(ncid_out, i, 'a', 
+     +                datatype, length)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_inq_att: ', err)
+                if (datatype .ne. NF_CHAR)
+     +              call error('Unexpected type')
+                if (length .ne. 1)
+     +              call error('Unexpected length')
+                err = nfmpi_get_att_text(ncid_out, i, 'a', value)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_get_att_text: ', err)
+                if (value .ne. 'A')
+     +              call error('Unexpected value')
+            end if                                                   
+4       continue                                                   
+
+        err = nfmpi_close(ncid_out)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errorc('delete of scratch file failed', scratch)
+        call print_nok(nok)
+        end
+
+
+C Test nfmpi_rename_att
+C    try with bad netCDF handle, check error
+C    try with bad variable handle, check error
+C    try with nonexisting att name, check error
+C    try renaming to existing att name, check error
+C    check that proper rename worked with nfmpi_inq_attid
+C    try in data mode, check error
+        subroutine test_nfmpi_rename_att()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer MY_LEN_TRIM
+        character*2 ATT_NAME
+        integer VARID, ATT_TYPE, NATTS, ATT_LEN
+        double precision hash
+        logical equal, inrange
+
+        integer ncid
+        integer vid
+        integer err, flags
+        integer i
+        integer j
+        integer  k
+        integer attnum
+        character*(NF_MAX_NAME) atnam
+        character*(NF_MAX_NAME) name
+        character*(NF_MAX_NAME) oldname
+        character*(NF_MAX_NAME) newname
+        integer nok             !/* count of valid comparisons */
+        integer datatype
+        integer attyp
+        integer*8 length
+        integer*8 attlength
+        integer*8 ndx(1)
+        character*(MAX_NELS)    text
+        doubleprecision value(MAX_NELS)
+        doubleprecision expect
+
+        nok = 0
+
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        err = nfmpi_rename_att(ncid, BAD_VARID, 'abc', 'newName')
+        if (err .ne. NF_ENOTVAR)
+     +      call errore('bad var id: ', err)
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+
+        do 1, i = 0, numVars
+            vid = VARID(i)
+            do 2, j = 1, NATTS(i)
+                atnam = ATT_NAME(j,i)
+                err = nfmpi_rename_att(BAD_ID, vid, atnam, 
+     +                 'newName')
+                if (err .ne. NF_EBADID)
+     +              call errore('bad ncid: ', err)
+                err = nfmpi_rename_att(ncid, vid, 'noSuch', 
+     +                  'newName')
+                if (err .ne. NF_ENOTATT)
+     +              call errore('bad attname: ', err)
+                newname = 'new_' // TRIM(atnam)
+                err = nfmpi_rename_att(ncid, vid, atnam, newname)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_rename_att: ', err)
+                err = nfmpi_inq_attid(ncid, vid, newname, attnum)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_inq_attid: ', err)
+                if (attnum .ne. j)
+     +              call error('Unexpected attnum')
+2           continue
+1       continue
+
+C           /* Close. Reopen & check */
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        err = nfmpi_open(comm, scratch, NF_WRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+
+        do 3, i = 0, numVars
+            vid = VARID(i)
+            do 4, j = 1, NATTS(i)
+                atnam = ATT_NAME(j,i)
+                attyp = ATT_TYPE(j,i)
+                attlength = ATT_LEN(j,i)
+                newname = 'new_' // TRIM(atnam)
+                err = nfmpi_inq_attname(ncid, vid, j, name)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_inq_attname: ', err)
+                if (name .ne. newname)
+     +              call error('nfmpi_inq_attname: unexpected name')
+                err = nfmpi_inq_att(ncid, vid, name, 
+     +              datatype, length)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_inq_att: ', err)
+                if (datatype .ne. attyp)
+     +              call error('nfmpi_inq_att: unexpected type')
+                if (length .ne. attlength)
+     +              call error('nfmpi_inq_att: unexpected length')
+                if (datatype .eq. NF_CHAR) then
+                    err = nfmpi_get_att_text(ncid, vid, name, text)
+                    if (err .ne. NF_NOERR)
+     +                  call errore('nfmpi_get_att_text: ', err)
+                    do 5, k = 1, ATT_LEN(j,i)
+                        ndx(1) = k
+                        expect = hash(datatype, -1, ndx)
+                        if (ichar(text(k:k)) .ne. expect) then
+                            call error(
+     +                          'nfmpi_get_att_text: unexpected value')
+                        else
+                            nok = nok + 1
+                        end if
+5                   continue
+                else
+                    err = nfmpi_get_att_double(ncid, vid, name, 
+     +                     value)
+                    if (err .ne. NF_NOERR)
+     +                  call errore('nfmpi_get_att_double: ', err)
+                    do 6, k = 1, ATT_LEN(j,i)
+                        ndx(1) = k
+                        expect = hash(datatype, -1, ndx)
+                        if (inRange(expect, datatype)) then
+                            if (.not. equal(value(k),expect,datatype,
+     +                                      NF_DOUBLE)) then
+                                call error(
+     +                        'nfmpi_get_att_double: unexpected value')
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+6                   continue
+                end if
+4           continue
+3       continue
+        call print_nok(nok)
+
+C           /* Now in data mode */
+C           /* Try making names even longer. Then restore original names */
+
+        do 7, i = 0, numVars
+            vid = VARID(i)
+            do 8, j = 1, NATTS(i)
+                atnam = ATT_NAME(j,i)
+                oldname = 'new_' // TRIM(atnam)
+                newname = 'even_longer_' // TRIM(atnam)
+                err = nfmpi_rename_att(ncid, vid, oldname, newname)
+                if (err .ne. NF_ENOTINDEFINE)
+     +              call errore('longer name in data mode: ', err)
+                err = nfmpi_rename_att(ncid, vid, oldname, atnam)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_rename_att: ', err)
+                err = nfmpi_inq_attid(ncid, vid, atnam, attnum)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_inq_attid: ', err)
+                if (attnum .ne. j)
+     +              call error('Unexpected attnum')
+8           continue
+7       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errori('delete of scratch file failed: ', err)
+        end
+
+
+C Test nfmpi_del_att
+C    try with bad netCDF handle, check error
+C    try with bad variable handle, check error
+C    try with nonexisting att name, check error
+C    check that proper delete worked using:
+C      nfmpi_inq_attid, nfmpi_inq_natts, nfmpi_inq_varnatts
+        subroutine test_nfmpi_del_att()
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        character*2 ATT_NAME
+        integer VARID, NATTS
+
+        integer ncid
+        integer err, flags
+        integer i
+        integer j
+        integer attnum
+        integer na
+        integer numatts
+        integer vid
+        character*(NF_MAX_NAME)  name           !/* of att */
+        integer nok             !/* count of valid comparisons */
+
+        nok = 0
+
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        err = nfmpi_del_att(ncid, BAD_VARID, 'abc')
+        if (err .ne. NF_ENOTVAR) then
+            call errore('bad var id: ', err)
+        else
+            nok = nok + 1
+        endif
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+
+        do 1, i = 0, numVars
+            vid = VARID(i)
+            numatts = NATTS(i)
+            do 2, j = 1, numatts
+                name = ATT_NAME(j,i)
+                err = nfmpi_del_att(BAD_ID, vid, name)
+                if (err .ne. NF_EBADID) then
+                    call errore('bad ncid: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_del_att(ncid, vid, 'noSuch')
+                if (err .ne. NF_ENOTATT) then
+                    call errore('bad attname: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_del_att(ncid, vid, name)
+                if (err .ne. NF_NOERR) then
+                    call errore('nfmpi_del_att: ', err)
+                else
+                    nok = nok + 1
+                endif
+                err = nfmpi_inq_attid(ncid, vid, name, attnum)
+                if (err .ne. NF_ENOTATT)
+     +              call errore('bad attname: ', err)
+                if (i .lt. 1) then
+                    err = nfmpi_inq_natts(ncid, na)
+                    if (err .ne. NF_NOERR)
+     +                  call errore('nfmpi_inq_natts: ', err)
+                    if (na .ne. numatts-j) then
+                        call errori('natts: expected: ', numatts-j)
+                        call errori('natts: got:      ', na)
+                    end if
+                end if
+                err = nfmpi_inq_varnatts(ncid, vid, na)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_inq_natts: ', err)
+                if (na .ne. numatts-j) then
+                    call errori('natts: expected: ', numatts-j)
+                    call errori('natts: got:      ', na)
+                end if
+2           continue
+1       continue
+
+C           /* Close. Reopen & check no attributes left */
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        err = nfmpi_open(comm, scratch, NF_WRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_inq_natts(ncid, na)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_inq_natts: ', err)
+        if (na .ne. 0)
+     +      call errori('natts: expected 0, got ', na)
+        do 3, i = 0, numVars
+            vid = VARID(i)
+            err = nfmpi_inq_varnatts(ncid, vid, na)
+            if (err .ne. NF_NOERR)
+     +          call errore('nfmpi_inq_natts: ', err)
+            if (na .ne. 0)
+     +          call errori('natts: expected 0, got ', na)
+3       continue
+
+C           /* restore attributes. change to data mode. try to delete */
+        err = nfmpi_redef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_redef: ', err)
+        call put_atts(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+
+        do 4, i = 0, numVars
+            vid = VARID(i)
+            numatts = NATTS(i)
+            do 5, j = 1, numatts
+                name = ATT_NAME(j,i)
+                err = nfmpi_del_att(ncid, vid, name)
+                if (err .ne. NF_ENOTINDEFINE) then
+                    call errore('in data mode: ', err)
+                else
+                    nok = nok + 1
+                endif
+5           continue
+4       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errori('delete of scratch file failed: ', err)
+        call print_nok(nok)
+        end
+
+C parallel-netcdf doesn't implement set_fill, so i have not
+C    parallel-netcdfified this subroutine
+C Test nfmpi_set_fill
+C    try with bad netCDF handle, check error
+C    try in read-only mode, check error
+C    try with bad new_fillmode, check error
+C    try in data mode, check error
+C    check that proper set to NF_FILL works for record & non-record variables
+C    (note that it is not possible to test NF_NOFILL mode!)
+C    close file & create again for test using attribute _FillValue
+        subroutine test_nfmpi_set_fill()
+        implicit none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        ! character*2 ATT_NAME
+        ! integer VARID, ATT_TYPE, NATTS
+
+        integer MY_LEN_TRIM
+        integer ncid
+        integer vid
+        integer err, flags
+        integer i
+        integer j
+        integer old_fillmode
+        character*1 text
+        doubleprecision value
+        doubleprecision fill
+        integer*8 index(MAX_RANK)
+        integer*8 length
+        integer index2indexes
+        integer nok             !/* count of valid comparisons */
+
+        value = 0
+        nok = 0
+
+C           /* bad ncid */
+        err = nfmpi_set_fill(BAD_ID, NF_NOFILL, old_fillmode)
+        if (err .ne. NF_EBADID)
+     +      call errore('bad ncid: ', err)
+
+C           /* try in read-only mode */
+        err = nfmpi_open(comm, testfile, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_open: ', err)
+        err = nfmpi_set_fill(ncid, NF_NOFILL, old_fillmode)
+        if (err .ne. NF_EPERM)
+     +      call errore('read-only: ', err)
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+
+C           /* create scratch */
+        flags = IOR(NF_NOCLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+
+C           /* BAD_FILLMODE */
+        err = nfmpi_set_fill(ncid, BAD_FILLMODE, old_fillmode)
+        if (err .ne. NF_EINVAL)
+     +      call errore('bad fillmode: ', err)
+
+C           /* proper calls */
+        err = nfmpi_set_fill(ncid, NF_FILL, old_fillmode)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_set_fill: ', err)
+        if (old_fillmode .ne. NF_NOFILL)
+     +      call errori('Unexpected old fill mode: ', old_fillmode)
+        err = nfmpi_set_fill(ncid, NF_NOFILL, old_fillmode)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_set_fill: ', err)
+        if (old_fillmode .ne. NF_FILL)
+     +      call errori('Unexpected old fill mode: ', old_fillmode)
+        err = nfmpi_set_fill(ncid, NF_FILL, old_fillmode)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_set_fill: ', err)
+
+C           /* define dims & vars */
+        call def_dims(ncid)
+        call def_vars(ncid)
+
+C           /* Change to data mode. Set fillmode again */
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        err = nfmpi_set_fill(ncid, NF_FILL, old_fillmode)
+        if (err .ne. NF_ENOTINDEFINE)
+     +      call errore('nfmpi_set_fill: ', err)
+
+C       /* Write record number NRECS to force writing of preceding records */
+C       /* Assumes variable cr is char vector with UNLIMITED dimension */
+        err = nfmpi_inq_varid(ncid, 'cr', vid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_inq_varid: ', err)
+        index(1) = NRECS
+        text = char(NF_FILL_CHAR)
+        err = nfmpi_put_var1_text_all(ncid, vid, index, text)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_put_var1_text_all: ', err)
+
+C           /* get all variables & check all values equal default fill */
+        do 1, i = 1, numVars
+            if (var_dimid(var_rank(i),i) .eq. RECDIM) go to 1 ! skip record variables
+
+            if (var_type(i) .eq. NF_CHAR) then
+                fill = NF_FILL_CHAR
+            else if (var_type(i) .eq. NF_BYTE) then
+                fill = NF_FILL_BYTE
+            else if (var_type(i) .eq. NF_SHORT) then
+                fill = NF_FILL_SHORT
+            else if (var_type(i) .eq. NF_INT) then
+                fill = NF_FILL_INT
+            else if (var_type(i) .eq. NF_FLOAT) then
+                fill = NF_FILL_FLOAT
+            else if (var_type(i) .eq. NF_DOUBLE) then
+                fill = NF_FILL_DOUBLE
+            else if (var_type(i) .eq. NF_UBYTE) then
+                fill = NF_FILL_UBYTE
+            else if (var_type(i) .eq. NF_USHORT) then
+                fill = NF_FILL_USHORT
+            else if (var_type(i) .eq. NF_UINT) then
+                fill = NF_FILL_UINT
+            else if (var_type(i) .eq. NF_INT64) then
+                fill = NF_FILL_INT64
+            else if (var_type(i) .eq. NF_UINT64) then
+                ! cycle  ! skip uint64
+                fill = NF_FILL_UINT64
+            else
+                print *, 'Unexpected type : ', var_type(i)
+                stop 'test_nfmpi_set_fill(): impossible var_type(i)'
+            end if
+
+            do 2, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                if (err .ne. NF_NOERR)
+     +              call error('error in index2indexes()')
+                if (var_type(i) .eq. NF_CHAR) then
+                    err = nfmpi_get_var1_text_all(ncid, i, index, text)
+                    if (err .ne. NF_NOERR)
+     +                  call errore('nfmpi_get_var1_text_all failed: ',
+     +                              err)
+                    value = ichar(text)
+                else
+                    err = nfmpi_get_var1_double_all(ncid, i, index, 
+     +                 value)
+                    if (err .ne. NF_NOERR)
+     +                  call errore
+     +                           ('nfmpi_get_var1_double_all failed: ',
+     +                            err)
+                end if
+                if (value .ne. fill .and. 
+     +              abs((fill - value)/fill) .gt. 1.0e-9) then
+                    print *, 'var_name : ',
+     +              TRIM(var_name(i))
+                    print *, 'var_type : ', var_type(i)
+                    print *, 'fill : ', fill
+                    call errord('Unexpected fill value: ', value)
+                else
+                    nok = nok + 1
+                end if
+2           continue
+1       continue
+
+C       /* close scratch & create again for test using attribute _FillValue */
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, scratch, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: ', err)
+            return
+        end if
+        call def_dims(ncid)
+        call def_vars(ncid)
+
+C           /* set _FillValue = 42 for all vars */
+        fill = 42
+        text = char(int(fill))
+        length = 1
+        do 3, i = 1, numVars
+            if (var_type(i) .eq. NF_CHAR) then
+                err = nfmpi_put_att_text(ncid, i, '_FillValue', length,
+     +              text)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_put_att_text: ', err)
+            else
+                err = nfmpi_put_att_double(ncid, i, '_FillValue',
+     +                                  var_type(i),length,fill)
+                if (err .ne. NF_NOERR)
+     +              call errore('nfmpi_put_att_double: ', err)
+            end if
+3       continue
+
+C           /* data mode. write records */
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_enddef: ', err)
+        index(1) = NRECS
+        err = nfmpi_put_var1_text_all(ncid, vid, index, text)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_put_var1_text_all: ', err)
+
+C           /* get all variables & check all values equal 42 */
+        do 4, i = 1, numVars
+            if (var_dimid(var_rank(i),i) .eq. RECDIM) go to 4 ! skip record variables
+            do 5, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                if (err .ne. NF_NOERR)
+     +              call error('error in index2indexes')
+                if (var_type(i) .eq. NF_CHAR) then
+                    err = nfmpi_get_var1_text_all(ncid, i, index, text)
+                    if (err .ne. NF_NOERR)
+     +                  call errore('nfmpi_get_var1_text_all failed: ',
+     +                              err)
+                    value = ichar(text)
+                else
+                    err = nfmpi_get_var1_double_all(ncid, i, 
+     +                     index, value)
+                    if (err .ne. NF_NOERR)
+     +                  call errore
+     +                          ('nfmpi_get_var1_double_all failed: ',
+     +                           err)
+                end if
+                if (value .ne. fill) then
+                    call errord(' Value expected: ', fill)
+                    call errord(' Value read:     ', value)
+                else
+                    nok = nok + 1
+                end if
+5           continue
+4       continue
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR)
+     +      call errore('nfmpi_close: ', err)
+        err = nfmpi_delete(scratch, info)
+        if (err .ne. NF_NOERR)
+     +      call errori('delete of scratch file failed: ', err)
+        call print_nok(nok)
+        end
+
+#if 0
+C * Test nc_set_default_format
+C *    try with bad default format
+C *    try with NULL old_formatp
+C *    try in data mode, check error
+C *    check that proper set to NC_FILL works for record & non-record variables
+C *    (note that it is not possible to test NC_NOFILL mode!)
+C *    close file & create again for test using attribute _FillValue
+      subroutine test_nfmpi_set_default_format()
+      implicit none
+        include "pnetcdf.inc"
+#include "tests.inc"
+      
+      integer ncid
+      integer err, flags
+      integer i
+      integer version
+      integer old_format
+      integer nfmpi_get_file_version
+      
+C     /* bad format */
+      err = nfmpi_set_default_format(3, old_format)
+      if (err .ne. NF_EINVAL)
+     +     call errore("bad default format: status = %d", err)
+     
+C    /* Cycle through available formats. */
+      do 1 i=1, 2
+         err = nfmpi_set_default_format(i, old_format)
+         if (err .ne. NF_NOERR) 
+     +       call errore("setting classic format: status = %d", err)
+         flags = IOR(NF_CLOBBER, extra_flags)
+         err = nfmpi_create(comm, scratch, flags, info, ncid)
+         if (err .ne. NF_NOERR) 
+     +       call errore("bad nfmpi_create: status = %d", err)
+         err = nfmpi_put_att_text(ncid, NF_GLOBAL, "testatt", 
+     +       4, "blah")
+         if (err .ne. NF_NOERR)
+     +       call errore("bad put_att: status = %d", err)
+         err = nfmpi_close(ncid)
+         if (err .ne. NF_NOERR)
+     +       call errore("bad close: status = %d", err)
+         err = nfmpi_get_file_version(scratch, version)
+         if (err .ne. NF_NOERR) call errore("bad file version = %d",err)
+         if (version .ne. i)
+     +       call errore("bad file version = %d", err)
+ 1    continue
+
+C    /* Remove the left-over file. */
+      err = nfmpi_delete(scratch)
+      if (err .ne. NF_NOERR) call errore("remove failed", err)
+      end
+
+#endif
+
+C     This function looks in a file for the netCDF magic number.
+      integer function nfmpi_get_file_version(path, version)
+      implicit none
+        include "pnetcdf.inc"
+#include "tests.inc"
+      
+      character*(*) path
+      integer version
+      character magic*4
+      integer ver
+      integer f
+      parameter (f = 10)
+
+      open(f, file=path, status='OLD', form='UNFORMATTED',
+     +     access='DIRECT', recl=4)
+
+C     Assume this is not a netcdf file.
+      nfmpi_get_file_version = NF_ENOTNC
+      version = 0
+
+C     Read the magic number, the first 4 bytes of the file.
+      read(f, rec=1, err = 1) magic
+
+C     If the first three characters are not "CDF" we're done.
+      if (index(magic, 'CDF') .eq. 1) then
+         ver = ichar(magic(4:4))
+         if (ver .eq. 1) then
+            version = 1
+            nfmpi_get_file_version = NF_NOERR
+         elseif (ver .eq. 2) then
+            version = 2
+            nfmpi_get_file_version = NF_NOERR
+         endif
+      endif
+
+ 1    close(f)
+      return
+      end
+
+
diff --git a/test/nf_test/tests.inc.in b/test/nf_test/tests.inc.in
new file mode 100644
index 0000000..9bcd322
--- /dev/null
+++ b/test/nf_test/tests.inc.in
@@ -0,0 +1,234 @@
+!
+!  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!  $Id: tests.inc.in 2289 2016-01-02 08:26:40Z wkliao $
+!
+
+!!!!
+! Do not tabify this unless you like hitting the 72 char limit !!!
+!!!
+#ifndef UD_TESTS_INC
+#define UD_TESTS_INC
+
+
+!/* The following prevents non-FORTRAN code from appearing in the output. */
+#if defined(__osf__)
+#   undef _POSIX_SOURCE
+#   define _POSIX_SOURCE
+#endif
+
+#define NO_NETCDF_2 1
+
+#include "nfconfig.inc"
+
+
+!/* Parameters of test data */
+
+#ifdef  NF_INT1_T
+#   define NF_B 1
+#else
+#   define NF_B 0
+#endif
+#ifdef  NF_INT2_T
+#   define NF_S 1
+#else
+#   define NF_S 0
+#endif
+! Total number of FORTRAN types:
+#define NUM_FORTRAN_TYPES (3 + NF_S + NF_B)
+#undef NF_B
+#undef NF_S
+
+#define NTYPES 11
+#define NDIMS 5
+#define NRECS 2
+#define NGATTS NTYPES
+#define RECDIM 1
+#define MAX_RANK 3
+#define MAX_NELS 64
+#define MAX_DIM_LEN 4
+#define MAX_NATTS 3
+
+#define NVARS 166
+!
+!  #define NVARS 136   when NTYPES==6
+!  #define NVARS 142   when NTYPES==7
+!  #define NVARS 148   when NTYPES==8
+!  #define NVARS 154   when NTYPES==9
+!  #define NVARS 160   when NTYPES==10
+!  #define NVARS 166   when NTYPES==11
+!  c:char, b:byte, s:short, i:int, f:float, d:double, y:ubyte, t:ushort,
+!  u:uint, x:int64, z:uint64
+!
+
+!
+!  Limits of external types (based on those in ncx.h):
+!
+! Note: In CDF format specification, NC_CHAR is for text characters, which
+! is considered an 8-bit unsigned integer. Since it is for printable text
+! characters, its values should range from 0 (X_CHAR_MIN) to 255 (X_CHAR_MAX).
+!
+#define X_CHAR_MIN 0
+#define X_CHAR_MAX 255
+#define X_INT1_MIN (-128)
+#define X_INT1_MAX 127
+#define X_INT2_MIN (-32768)
+#define X_INT2_MAX 32767
+#define X_INT_MIN  (-2147483647-1)
+#define X_INT_MAX  2147483647
+#if 0
+#define X_REAL_MAX 3.4028234663852886e+38
+#else
+#define X_REAL_MAX 3.4028234663852886e+37
+#endif
+#define X_REAL_MIN (-X_FLOAT_MAX)
+#if 0
+#define X_DOUBLE_MAX 1.7976931348623157E+308
+#else
+#define X_DOUBLE_MAX 1.7976931348623157D+200
+#endif
+#define X_DOUBLE_MIN (-X_DOUBLE_MAX)
+#define X_INT8_MIN @PNF_X_INT8_MIN@
+#define X_INT8_MAX @PNF_X_INT8_MAX@
+#define X_UINT8_MIN 0
+#define X_UINT8_MAX 18446744073709551615.0
+
+#define X_BYTE_MIN X_INT1_MIN
+#define X_BYTE_MAX X_INT1_MAX
+#define X_SHORT_MIN X_INT2_MIN
+#define X_SHORT_MAX X_INT2_MAX
+#define X_FLOAT_MIN X_REAL_MIN
+#define X_FLOAT_MAX X_REAL_MAX
+
+#define X_UCHAR_MAX     255
+#define X_UCHAR_MIN     0
+#define X_UBYTE_MAX     X_UCHAR_MAX
+#define X_UBYTE_MIN     X_UCHAR_MIN
+#define X_USHORT_MAX    65535
+#define X_USHORT_MIN    0
+#define X_UINT_MAX      @PNF_X_UINT_MAX@
+#define X_UINT_MIN      0
+
+!/*
+! * Examples of invalid argument values:
+! */
+#define BAD_ID -1
+#define BAD_DIMID -1
+#define BAD_VARID -2
+#define BAD_ATTNUM -1
+#define BAD_TYPE 0
+#define BAD_FILLMODE -1
+#define BAD_NAME 'a/b'
+
+
+!/*
+! * Internal data types: (in memory)
+! */
+#define NFT_UNSPECIFIED 0
+! #define NFT_UCHAR 1
+#define NFT_TEXT 16
+#define NFT_CHAR NFT_TEXT
+#define NFT_INT1 17
+! #define NFT_SCHAR NFT_INT1
+#define NFT_INT2 18
+#define NFT_INT 20
+#define NFT_REAL 36
+#define NFT_DOUBLE 40
+! #define NFT_USHORT 41
+! #define NFT_UINT   42
+#define NFT_INT8 43
+! #define NFT_UINT8 44
+
+
+!/*
+! * Define a macro for trimming trailing blanks from character variables.
+! */
+#define TRIM(string) string(1:MY_LEN_TRIM(string))
+
+
+!
+! FORTRAN GETARG() subroutine:
+!
+#ifdef __hpux
+#   define      getarg  getarg_
+#endif
+
+
+#endif /* UD_TESTS_INC */
+
+#include "mpif.h"
+
+
+!    /* Global variables - filenames */
+
+      CHARACTER*80      testfile  !/* netCDF read-only test data */
+      CHARACTER*80      scratch   !/* netCDF test file for writing */
+
+!    /* Global variables - command-line arguments */
+
+      LOGICAL   CREATE_FILE
+      LOGICAL   READONLY
+      LOGICAL   VERBOSE
+      INTEGER   NFAILS
+      INTEGER   MAX_NMPT        !/* max num messages per test */
+
+!    /* Global variables - test data */
+
+      CHARACTER*2               DIM_NAME(NDIMS)
+      INTEGER*8                 DIM_LEN(NDIMS)
+      CHARACTER*(2+MAX_RANK)    VAR_NAME(NVARS)
+      INTEGER                   VAR_TYPE(NVARS)
+      INTEGER                   VAR_RANK(NVARS)
+      INTEGER                   VAR_DIMID(MAX_RANK,NVARS)
+      INTEGER*8                 VAR_SHAPE(MAX_RANK,NVARS)
+      INTEGER                   VAR_NELS(NVARS)
+      INTEGER                   VAR_NATTS(NVARS)
+      CHARACTER*2               ATTNAME(MAX_NATTS,NVARS)
+      CHARACTER*2               GATT_NAME(NGATTS)
+      INTEGER                   ATTTYPE(NGATTS,NVARS)
+      INTEGER                   GATT_TYPE(NGATTS)
+      INTEGER                   ATTLEN(MAX_NATTS,NVARS)
+      INTEGER*8                 GATT_LEN(NGATTS)
+
+!    /* Miscellaneous global variables: */
+      CHARACTER*128              PROGNAME   !/* name of the program */
+      INTEGER                   COMM       !/* MPI communicator */
+
+      INTEGER                   NFAILSTOTAL
+
+!    /* Common blocks for global variables: */
+
+!/* MPI_OFFSET */
+      COMMON    /OFFSETCOM/     DIM_LEN, VAR_SHAPE, GATT_LEN 
+
+      COMMON    /MPICOM/        COMM
+      COMMON    /LOGCOM/        CREATE_FILE,
+     *                          READONLY, !/* don't change files */
+     *                          VERBOSE   !/* print details of tests */
+
+      COMMON    /TXTCOM/        TESTFILE,
+     *                          SCRATCH,
+     *                          DIM_NAME,
+     *                          VAR_NAME,
+     *                          ATTNAME,
+     *                          GATT_NAME,
+     *                          PROGNAME
+
+      COMMON    /INTCOM/        NFAILS,   !/* number of failures in 
+     *                                    ! * specific test */
+     *                          VAR_TYPE,
+     *                          VAR_RANK,
+     *                          VAR_DIMID,
+     *                          VAR_NELS,
+     *                          VAR_NATTS,
+     *                          ATTTYPE,
+     *                          GATT_TYPE,
+     *                          ATTLEN,
+     *                          MAX_NMPT,
+     *                          NFAILSTOTAL
+
+      integer numTypes, numVars, numGatts, cdf_format, extra_flags, info
+      common / PROBLEM_SIZE / numTypes, numVars, numGatts, cdf_format,
+     +                        extra_flags, info
+
diff --git a/test/nf_test/util.F b/test/nf_test/util.F
new file mode 100644
index 0000000..834449d
--- /dev/null
+++ b/test/nf_test/util.F
@@ -0,0 +1,1531 @@
+!*********************************************************************
+!   Copyright 1996, UCAR/Unidata
+!   See netcdf/COPYRIGHT file for copying and redistribution conditions.
+!   $Id: util.F 2284 2015-12-30 20:27:18Z wkliao $
+!********************************************************************/
+
+      SUBROUTINE PRINT_NOK(NOK)
+      IMPLICIT  NONE
+      INTEGER   NOK
+      include "pnetcdf.inc"
+#include "tests.inc"
+
+ 123  FORMAT(I4,A)
+      IF (NFAILS .GT. 0) PRINT *, ' '
+      IF (VERBOSE) THEN
+          PRINT 123, NOK, ' good comparisons.'
+      ENDIF
+      END
+
+
+! Is value within external type range? */
+      logical FUNCTION INRANGE(VALUE, DATATYPE)
+      IMPLICIT  NONE
+      DOUBLEPRECISION   VALUE
+      INTEGER           DATATYPE
+      include "pnetcdf.inc"
+#include "tests.inc"
+
+      DOUBLEPRECISION   MIN
+      DOUBLEPRECISION   MAX
+
+      MIN = X_DOUBLE_MIN
+      MAX = X_DOUBLE_MAX
+
+      IF (DATATYPE .EQ. NF_CHAR) THEN
+          MIN = X_CHAR_MIN
+          MAX = X_CHAR_MAX
+      ELSE IF (DATATYPE .EQ. NF_BYTE) THEN
+          MIN = X_BYTE_MIN
+          MAX = X_BYTE_MAX
+      ELSE IF (DATATYPE .EQ. NF_SHORT) THEN
+          MIN = X_SHORT_MIN
+          MAX = X_SHORT_MAX
+      ELSE IF (DATATYPE .EQ. NF_INT) THEN
+          MIN = X_INT_MIN
+          MAX = X_INT_MAX
+      ELSE IF (DATATYPE .EQ. NF_FLOAT) THEN
+          MIN = X_FLOAT_MIN
+          MAX = X_FLOAT_MAX
+      ELSE IF (DATATYPE .EQ. NF_DOUBLE) THEN
+          MIN = X_DOUBLE_MIN
+          MAX = X_DOUBLE_MAX
+      ELSE IF (DATATYPE .EQ. NF_UBYTE) THEN
+          MIN = 0
+          MAX = X_UCHAR_MAX
+      ELSE IF (DATATYPE .EQ. NF_USHORT) THEN
+          MIN = 0
+          MAX = X_USHORT_MAX
+      ELSE IF (DATATYPE .EQ. NF_UINT) THEN
+          MIN = 0
+          MAX = X_UINT_MAX
+      ELSE IF (DATATYPE .EQ. NF_INT64) THEN
+          INRANGE = (VALUE .GE. X_INT8_MIN) .AND. 
+     +              (VALUE .LE. X_INT8_MAX)
+          return
+      ELSE IF (DATATYPE .EQ. NF_UINT64) THEN
+          INRANGE = (VALUE .GE. 0) .AND. 
+     +              (VALUE .LE. X_UINT8_MAX)
+          return
+      ELSE
+          CALL UD_ABORT
+      END IF
+
+      INRANGE = (VALUE .GE. MIN) .AND. (VALUE .LE. MAX)
+      END
+
+
+      logical FUNCTION INRANGE_UCHAR(VALUE, DATATYPE)
+      IMPLICIT  NONE
+      DOUBLEPRECISION   VALUE
+      INTEGER           DATATYPE
+      include "pnetcdf.inc"
+#include "tests.inc"
+      LOGICAL INRANGE
+
+      IF (DATATYPE .EQ. NF_BYTE) THEN
+          INRANGE_UCHAR = (VALUE .GE. 0) .AND. (VALUE .LE. 255)
+      ELSE
+          INRANGE_UCHAR = INRANGE(VALUE, DATATYPE)
+      END IF
+      END
+
+
+      logical FUNCTION INRANGE_FLOAT(VALUE, DATATYPE)
+      IMPLICIT  NONE
+      DOUBLEPRECISION   VALUE
+      INTEGER           DATATYPE
+      include "pnetcdf.inc"
+#include "tests.inc"
+      double precision internal_max
+
+      DOUBLEPRECISION   MIN
+      DOUBLEPRECISION   MAX
+      REAL              FVALUE
+
+      MIN = X_DOUBLE_MIN
+      MAX = X_DOUBLE_MAX
+
+      IF (DATATYPE .EQ. NF_CHAR) THEN
+          MIN = X_CHAR_MIN
+          MAX = X_CHAR_MAX
+      ELSE IF (DATATYPE .EQ. NF_BYTE) THEN
+          MIN = X_BYTE_MIN
+          MAX = X_BYTE_MAX
+      ELSE IF (DATATYPE .EQ. NF_SHORT) THEN
+          MIN = X_SHORT_MIN
+          MAX = X_SHORT_MAX
+      ELSE IF (DATATYPE .EQ. NF_INT) THEN
+          MIN = X_INT_MIN
+          MAX = X_INT_MAX
+      ELSE IF (DATATYPE .EQ. NF_FLOAT) THEN
+          IF (internal_max(NFT_REAL) .LT. X_FLOAT_MAX) THEN
+              MIN = -internal_max(NFT_REAL)
+              MAX = internal_max(NFT_REAL)
+          ELSE
+              MIN = X_FLOAT_MIN
+              MAX = X_FLOAT_MAX
+          END IF
+      ELSE IF (DATATYPE .EQ. NF_DOUBLE) THEN
+          IF (internal_max(NFT_REAL) .LT. X_DOUBLE_MAX) THEN
+              MIN = -internal_max(NFT_REAL)
+              MAX = internal_max(NFT_REAL)
+          ELSE
+              MIN = X_DOUBLE_MIN
+              MAX = X_DOUBLE_MAX
+          END IF
+      ELSE IF (DATATYPE .EQ. NF_UBYTE) THEN
+          MIN = 0
+          MAX = X_UCHAR_MAX
+      ELSE IF (DATATYPE .EQ. NF_USHORT) THEN
+          MIN = 0
+          MAX = X_USHORT_MAX
+      ELSE IF (DATATYPE .EQ. NF_UINT) THEN
+          MIN = 0
+          MAX = X_UINT_MAX
+      ELSE IF (DATATYPE .EQ. NF_INT64) THEN
+          MIN = X_INT8_MIN
+          MAX = X_INT8_MAX
+      ELSE IF (DATATYPE .EQ. NF_UINT64) THEN
+          MIN = 0
+          MAX = X_UINT8_MAX
+      ELSE
+          CALL UD_ABORT
+      END IF
+
+      IF (.NOT.((VALUE .GE. MIN) .AND. (VALUE .LE. MAX))) THEN
+          INRANGE_FLOAT = .FALSE.
+      ELSE
+          FVALUE = real(VALUE)
+          INRANGE_FLOAT = (FVALUE .GE. MIN) .AND. (FVALUE .LE. MAX)
+      END IF
+      END
+
+
+! wrapper for inrange to handle special NF_BYTE/uchar adjustment */
+      logical function inrange3(value, datatype, itype)
+      implicit          none
+      doubleprecision   value
+      integer           datatype
+      integer           itype
+      include "pnetcdf.inc"
+#include "tests.inc"
+      logical inrange_float, inrange
+
+      if (itype .eq. NFT_REAL) then
+          inrange3 = inrange_float(value, datatype)
+      else
+          inrange3 = inrange(value, datatype)
+      end if
+      end
+
+
+!
+!  Does x == y, where one is internal and other external (netCDF)?  
+!  Use tolerant comparison based on IEEE FLT_EPSILON or DBL_EPSILON.
+!
+      logical function equal(x, y, extType, itype)
+      implicit  none
+      doubleprecision   x
+      doubleprecision   y
+      integer           extType         !!/* external data type */
+      integer           itype
+      include "pnetcdf.inc"
+#include "tests.inc"
+
+      doubleprecision   epsilon
+
+      if ((extType .eq. NF_REAL) .or. (itype .eq. NFT_REAL)) then
+          epsilon = 1.19209290E-07
+      else
+          epsilon = 2.2204460492503131E-16
+      end if
+      equal = abs(x-y) .le. epsilon * max( abs(x), abs(y))
+      end
+
+
+! Test whether two int vectors are equal. If so return 1, else 0  */
+        logical function int_vec_eq(v1, v2, n)
+        implicit        none
+        integer n
+        integer v1(n)
+        integer v2(n)
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer i
+
+        int_vec_eq = .true.
+
+        if (n .le. 0)
+     +      return
+
+        do 1, i=1, n
+            if (v1(i) .ne. v2(i)) then
+                int_vec_eq = .false.
+                return
+            end if
+1       continue
+        end
+
+
+!
+!  Generate random integer from 0 through n-1
+!  Like throwing an n-sided dice marked 0, 1, 2, ..., n-1
+!
+      integer function roll(n)
+      implicit  none
+      include "pnetcdf.inc"
+#include "tests.inc"
+      integer*8   n
+
+      doubleprecision   ud_rand
+      external          ud_rand
+
+1     roll = int((ud_rand(0) * (n-1)) + 0.5)
+      if (roll .ge. n) goto 1
+      end
+
+
+!
+!      Convert an origin-1 cumulative index to a netCDF index vector.
+!       Grosset dimension first; finest dimension last.
+!
+!      Authors: Harvey Davies, Unidata/UCAR, Boulder, Colorado
+!                Steve Emmerson, (same place)
+!
+        integer function index2ncindexes(index, rank, base, indexes)
+        implicit        none
+        integer         index           !!/* index to be converted */
+        integer         rank            !/* number of dimensions */
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer*8 base(rank)      !/* base(rank) ignored */
+        integer*8 indexes(rank)   !/* returned FORTRAN indexes */
+
+        integer i
+        integer offset
+        integer intbase
+
+        if (rank .gt. 0) then
+            offset = index - 1
+            do 1, i = rank, 1, -1
+                if (base(i) .eq. 0) then
+                    index2ncindexes = 1
+                    return
+                end if
+                intbase = int(base(i))
+                indexes(i) = 1 + mod(offset, intbase)
+                offset = offset / intbase
+1           continue
+        end if
+        index2ncindexes = 0
+        end
+
+
+!
+!      Convert an origin-1 cumulative index to a FORTRAN index vector.
+!       Finest dimension first; grossest dimension last.
+!
+!      Authors: Harvey Davies, Unidata/UCAR, Boulder, Colorado
+!                Steve Emmerson, (same place)
+!
+        integer function index2indexes(index, rank, base, indexes)
+        implicit        none
+        integer         index           !/* index to be converted */
+        integer         rank            !/* number of dimensions */
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer*8  base(rank)      !/* base(rank) ignored */
+        integer*8  indexes(rank)   !/* returned FORTRAN indexes */
+
+        integer i
+        integer offset
+        integer intbase
+
+        if (rank .gt. 0) then
+            offset = index - 1
+            do 1, i = 1, rank
+                if (base(i) .eq. 0) then
+                    index2indexes = 1
+                    return
+                end if
+                intbase = int(base(i))
+                indexes(i) = 1 + mod(offset, intbase)
+                offset = offset / intbase
+1           continue
+        end if
+        index2indexes = 0
+        end
+
+
+!
+!      Convert a FORTRAN index vector to an origin-1 cumulative index.
+!       Finest dimension first; grossest dimension last.
+!
+!      Authors: Harvey Davies, Unidata/UCAR, Boulder, Colorado
+!                Steve Emmerson, (same place)
+!
+        integer function indexes2index(rank, indexes, base)
+        implicit        none
+        integer         rank            !/* number of dimensions */
+        integer         indexes(rank)   !/* FORTRAN indexes */
+        integer         base(rank)      !/* base(rank) ignored */
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer i
+
+        indexes2index = 0
+        if (rank .gt. 0) then
+            do 1, i = rank, 1, -1
+                indexes2index = (indexes2index-1) * base(i) + indexes(i)
+1           continue
+        end if
+        end
+
+
+! Generate data values as function of type, rank (-1 for attribute), index */
+      double precision function hash(type, rank, index) 
+      implicit  none
+      integer   type
+      integer   rank
+      include "pnetcdf.inc"
+#include "tests.inc"
+      integer*8 index(*)
+
+      doubleprecision   base
+      doubleprecision   result
+      integer           d       !/* index of dimension */
+
+        !/* If vector then elements 1 & 2 are min & max. Elements 3 & 4 are */
+        !/* just < min & > max (except for NF_CHAR & NF_DOUBLE) */
+      hash = 0
+      if (abs(rank) .eq. 1 .and. index(1) .le. 4) then
+          if (index(1) .eq. 1) then
+              if (type .eq. NF_CHAR) then
+                  hash = X_CHAR_MIN
+              else if (type .eq. NF_BYTE) then
+                  hash = X_BYTE_MIN
+              else if (type .eq. NF_SHORT) then
+                  hash = X_SHORT_MIN
+              else if (type .eq. NF_INT) then
+                  hash = X_INT_MIN
+              else if (type .eq. NF_FLOAT) then
+                  hash = X_FLOAT_MIN
+              else if (type .eq. NF_DOUBLE) then
+                  hash = X_DOUBLE_MIN
+              else if (type .eq. NF_UBYTE) then
+                  hash = 0
+              else if (type .eq. NF_USHORT) then
+                  hash = 0
+              else if (type .eq. NF_UINT) then
+                  hash = 0
+              else if (type .eq. NF_INT64) then
+                  hash = X_INT_MIN - 128.0
+              else if (type .eq. NF_UINT64) then
+                  hash = 0
+              else
+                  print*, 'Error: no such nc_type ',type
+                  call ud_abort
+              end if
+          else if (index(1) .eq. 2) then
+              if (type .eq. NF_CHAR) then
+                  hash = X_CHAR_MAX
+              else if (type .eq. NF_BYTE) then
+                  hash = X_BYTE_MAX
+              else if (type .eq. NF_SHORT) then
+                  hash = X_SHORT_MAX
+              else if (type .eq. NF_INT) then
+                  hash = X_INT_MAX
+              else if (type .eq. NF_FLOAT) then
+                  hash = X_FLOAT_MAX
+              else if (type .eq. NF_DOUBLE) then
+                  hash = X_DOUBLE_MAX
+              else if (type .eq. NF_UBYTE) then
+                  hash = X_UCHAR_MAX
+              else if (type .eq. NF_USHORT) then
+                  hash = X_USHORT_MAX
+              else if (type .eq. NF_UINT) then
+                  hash = X_UINT_MAX
+              else if (type .eq. NF_INT64) then
+                  hash = X_INT_MAX + 128.0
+              else if (type .eq. NF_UINT64) then
+                  hash = X_UINT_MAX + 128.0
+              else
+                  print*, 'Error: no such nc_type ',type
+                  call ud_abort
+              end if
+          else if (index(1) .eq. 3) then
+              if (type .eq. NF_CHAR) then
+                  hash = ichar('A')
+              else if (type .eq. NF_BYTE) then
+                  hash = X_BYTE_MIN-1.0
+              else if (type .eq. NF_SHORT) then
+                  hash = X_SHORT_MIN-1.0
+              else if (type .eq. NF_INT) then
+                  hash = X_INT_MIN
+              else if (type .eq. NF_FLOAT) then
+                  hash = X_FLOAT_MIN
+              else if (type .eq. NF_DOUBLE) then
+                  hash = -1.0
+              else if (type .eq. NF_UBYTE) then
+                  hash = -1.0
+              else if (type .eq. NF_USHORT) then
+                  hash = -1.0
+              else if (type .eq. NF_UINT) then
+                  hash = -1.0
+              else if (type .eq. NF_INT64) then
+                  hash = -1.0
+              else if (type .eq. NF_UINT64) then
+                  hash = -1.0
+              else
+                  print*, 'Error: no such nc_type ',type
+                  call ud_abort
+              end if
+          else if (index(1) .eq. 4) then
+              if (type .eq. NF_CHAR) then
+                  hash = ichar('Z')
+              else if (type .eq. NF_BYTE) then
+                  hash = X_BYTE_MAX+1.0
+              else if (type .eq. NF_SHORT) then
+                  hash = X_SHORT_MAX+1.0
+              else if (type .eq. NF_INT) then
+                  hash = X_INT_MAX+1.0
+              else if (type .eq. NF_FLOAT) then
+                  hash = X_FLOAT_MAX
+              else if (type .eq. NF_DOUBLE) then
+                  hash = 1.0
+              else if (type .eq. NF_UBYTE) then
+                  hash = X_UCHAR_MAX + 1.0
+              else if (type .eq. NF_USHORT) then
+                  hash = X_USHORT_MAX + 1.0
+              else if (type .eq. NF_UINT) then
+                  hash = X_UINT_MAX + 1.0
+              else if (type .eq. NF_INT64) then
+                  hash = 1.0
+              else if (type .eq. NF_UINT64) then
+                  hash = 1.0
+              else
+                  print*, 'Error: no such nc_type ',type
+                  call ud_abort
+              end if
+          end if
+      else
+          if (type .eq. NF_CHAR) then
+              base = 2
+          else if (type .eq. NF_BYTE) then
+              base = -2
+          else if (type .eq. NF_SHORT) then
+              base = -5
+          else if (type .eq. NF_INT) then
+              base = -20
+          else if (type .eq. NF_FLOAT) then
+              base = -9
+          else if (type .eq. NF_DOUBLE) then
+              base = -10
+          else if (type .eq. NF_UBYTE) then
+              base = 2
+          else if (type .eq. NF_USHORT) then
+              base = 5
+          else if (type .eq. NF_UINT) then
+              base = 20
+          else if (type .eq. NF_INT64) then
+              base = -20
+          else if (type .eq. NF_UINT64) then
+              base = 20
+          else
+              print*, 'Error: no such nc_type ',type
+              stop 'in hash()'
+          end if
+
+          if (rank .lt. 0) then
+              result = base * 7
+          else
+              result = base * (rank + 1)
+          end if
+
+!         /*
+!          * NB: Finest netCDF dimension assumed first.
+!          */
+          do 1, d = abs(rank), 1, -1
+              result = base * (result + index(d) - 1)
+1         continue
+          hash = result
+      end if
+      end
+
+
+! wrapper for hash to handle special NC_BYTE/uchar adjustment */
+      double precision function hash4(type, rank, index, itype)
+      implicit  none
+      integer   type
+      integer   rank
+      include "pnetcdf.inc"
+#include "tests.inc"
+      double precision hash
+
+      integer*8 index(*)
+      integer   itype
+
+      hash4 = hash( type, rank, index )
+      if ((itype .eq. NFT_CHAR) .and. (type .eq. NF_BYTE) .and. 
+     +    (hash4 .ge. -128) .and. (hash4 .lt. 0)) hash4 = hash4 + 256
+      end
+
+
+      integer function char2type(letter)
+      implicit          none
+      character*1       letter
+      include "pnetcdf.inc"
+#include "tests.inc"
+
+      if (letter .eq. 'c') then
+          char2type = NF_CHAR
+      else if (letter .eq. 'b') then
+          char2type = NF_BYTE
+      else if (letter .eq. 's') then
+          char2type = NF_SHORT
+      else if (letter .eq. 'i') then
+          char2type = NF_INT
+      else if (letter .eq. 'f') then
+          char2type = NF_FLOAT
+      else if (letter .eq. 'd') then
+          char2type = NF_DOUBLE
+      else if (letter .eq. 'y') then
+          char2type = NF_UBYTE
+      else if (letter .eq. 't') then
+          char2type = NF_USHORT
+      else if (letter .eq. 'u') then
+          char2type = NF_UINT
+      else if (letter .eq. 'x') then
+          char2type = NF_INT64
+      else if (letter .eq. 'z') then
+          char2type = NF_UINT64
+      else
+        stop 'char2type(): invalid type-letter'
+      end if
+      end
+
+
+      subroutine init_dims(digit)
+      implicit          none
+      character*1       digit(NDIMS)
+      include "pnetcdf.inc"
+#include "tests.inc"
+
+      integer   dimid                   !/* index of dimension */
+      do 1, dimid = 1, NDIMS
+          if (dimid .eq. RECDIM) then
+              dim_len(dimid) = NRECS
+          else
+              dim_len(dimid) = dimid - 1
+          endif
+          dim_name(dimid) = 'D' // digit(dimid)
+1     continue
+      end
+
+
+      subroutine init_gatts(type_letter)
+      implicit          none
+      character*1       type_letter(NTYPES)
+      include "pnetcdf.inc"
+#include "tests.inc"
+
+      integer   attid
+      integer   char2type
+
+      do 1, attid = 1, numTypes
+          gatt_name(attid) = 'G' // type_letter(attid)
+          gatt_len(attid) = attid
+          gatt_type(attid) = char2type(type_letter(attid))
+1     continue
+      end
+
+
+      integer function prod(nn, sp)
+      implicit  none
+      integer   nn
+      include "pnetcdf.inc"
+#include "tests.inc"
+      integer*8 sp(MAX_RANK)
+
+      integer   i
+
+      prod = 1
+      do 1, i = 1, nn
+          prod = prod * int(sp(i))
+1     continue
+      end
+
+
+!
+!   define global variables:
+!   dim_name, dim_len, 
+!   var_name, var_type, var_rank, var_shape, var_natts, var_dimid, var_nels
+!   att_name, gatt_name, att_type, gatt_type, att_len, gatt_len
+!
+
+        subroutine init_gvars
+        implicit        none
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2ncindexes
+
+        integer*8       max_dim_len(MAX_RANK)
+        character*1     type_letter(NTYPES)
+        character*1     digit(10)
+
+        integer rank
+        integer vn              !/* var number */
+        integer xtype           !/* index of type */
+        integer an              !/* origin-0 cumulative attribute index */
+        integer nvars
+        integer jj
+        integer n_types
+        integer tc
+        integer*8 tmp(MAX_RANK)
+        integer ac              !/* attribute index */
+        integer dn              !/* dimension number */
+        integer prod            !/* function */
+        integer char2type       !/* function */
+        integer err
+
+        data    max_dim_len     /0, MAX_DIM_LEN, MAX_DIM_LEN/
+        data    type_letter     /'c', 'b', 's', 'i', 'f', 'd', 'y',
+     +                           't', 'u', 'x', 'z'/
+        data    digit           /'r', '1', '2', '3', '4', '5',
+     +                           '6', '7', '8', '9'/
+
+        max_dim_len(1) = MAX_DIM_LEN + 1
+
+        call init_dims(digit)
+
+        vn = 1
+        xtype = 1
+        an = 0
+
+!       /* Loop over variable ranks */
+        do 1, rank = 0, MAX_RANK
+            nvars = prod(rank, max_dim_len)
+
+            !/* Loop over variable shape vectors */
+            do 2, jj = 1, nvars                         !/* 1, 5, 20, 80 */
+                !/* number types of this shape */
+                if (rank .lt. 2) then
+                    n_types = numTypes                     !/* 6 */
+                else
+                    n_types = 1
+                end if
+
+                !/* Loop over external data types */
+                do 3, tc = 1, n_types                    !/* 6, 1 */
+                    var_name(vn) = type_letter(xtype)
+                    var_type(vn) = char2type(type_letter(xtype))
+                    var_rank(vn) = rank
+                    if (rank .eq. 0) then
+                        var_natts(vn) = mod(vn - 1, MAX_NATTS + 1)
+                    else
+                        var_natts(vn) = 0
+                    end if
+
+                    do 4, ac = 1, var_natts(vn)
+                        attname(ac,vn) = 
+     +                      type_letter(1+mod(an, numTypes))
+                        attlen(ac,vn) = an
+                        atttype(ac,vn) =
+     +                      char2type(type_letter(1+mod(an, numTypes)))
+                        an = an + 1
+4                   continue
+
+                    !/* Construct initial shape vector */
+                    err = index2ncindexes(jj, rank, max_dim_len, tmp)
+                    do 5, dn = 1, rank
+                        var_dimid(dn,vn) = int(tmp(1+rank-dn))
+5                   continue
+
+                    var_nels(vn) = 1
+                    do 6, dn = 1, rank
+                        if (dn .lt. rank) then
+                            var_dimid(dn,vn) = var_dimid(dn,vn) + 1
+                        end if
+                        if (var_dimid(dn,vn) .gt. 9) then
+                            stop 'Invalid var_dimid vector'
+                        end if
+                        var_name(vn)(rank+2-dn:rank+2-dn) = 
+     +                      digit(var_dimid(dn,vn))
+                        if (var_dimid(dn,vn) .ne. RECDIM) then
+                            var_shape(dn,vn) = var_dimid(dn,vn) - 1
+                        else
+                            var_shape(dn,vn) = NRECS
+                        end if
+                        var_nels(vn) = var_nels(vn) *
+     +                                 int(var_shape(dn,vn))
+6                   continue
+
+                    vn = vn + 1
+                    xtype = 1 + mod(xtype, numTypes)
+3               continue
+2           continue
+1       continue
+
+        call init_gatts(type_letter)
+        end
+
+
+! define dims defined by global variables */
+        subroutine def_dims(ncid)
+        implicit        none
+        integer         ncid
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer         err             !/* status */
+        integer         i
+        integer         dimid           !/* dimension id */
+
+        do 1, i = 1, NDIMS
+            if (i .eq. RECDIM) then
+                err = nfmpi_def_dim(ncid, dim_name(i), NFMPI_UNLIMITED,
+     +                           dimid)
+            else
+                err = nfmpi_def_dim(ncid, dim_name(i), dim_len(i),
+     +                           dimid)
+            end if
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_def_dim: ', err)
+            end if
+1       continue
+        end
+
+
+! define vars defined by global variables */
+        subroutine def_vars(ncid)
+        implicit        none
+        integer         ncid
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer         err             !/* status */
+        integer         i
+        integer         var_id
+
+        do 1, i = 1, numVars
+            err = nfmpi_def_var(ncid, var_name(i), var_type(i), 
+     +                       var_rank(i), var_dimid(1,i), var_id)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_def_var: ', err)
+            end if
+1       continue
+        end
+
+
+! put attributes defined by global variables */
+        subroutine put_atts(ncid)
+        implicit        none
+        integer         ncid
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer VARID, NATTS, ATT_TYPE, ATT_LEN
+        integer*8   ATT_LEN_LL
+        CHARACTER*2 ATT_NAME
+        double precision hash
+        logical inrange
+
+        integer                 err             !/* netCDF status */
+        integer                 i               !/* variable index (0 => global 
+                                                ! * attribute */
+        integer                 k               !/* attribute index */
+        integer                 j               !/* index of attribute */
+        integer*8               ndx(1)
+        logical                 allInRange
+        doubleprecision         att(MAX_NELS)
+        character*(MAX_NELS+2)  catt
+
+        do 1, i = 0, numVars      !/* var 0 => NF_GLOBAL attributes */
+            do 2, j = 1, NATTS(i)
+                if (NF_CHAR .eq. ATT_TYPE(j,i)) then
+                    catt = ' '
+                    do 3, k = 1, ATT_LEN(j,i)
+                        ndx(1) = k
+                        catt(k:k) = char(int(hash(ATT_TYPE(j,i), -1, 
+     +                                   ndx)))
+3                   continue
+!                   /*
+!                    * The following ensures that the text buffer doesn't
+!                    * start with 4 zeros (which is a CFORTRAN NULL pointer
+!                    * indicator) yet contains a zero (which causes the
+!                    * CFORTRAN interface to pass the address of the
+!                    * actual text buffer).
+!                    */
+                    catt(ATT_LEN(j,i)+1:ATT_LEN(j,i)+1) = char(1)
+                    catt(ATT_LEN(j,i)+2:ATT_LEN(j,i)+2) = char(0)
+
+                    ATT_LEN_LL = ATT_LEN(j,i)
+                    err = nfmpi_put_att_text(ncid, varid(i), 
+     +                                    ATT_NAME(j,i),
+     +                                    ATT_LEN_LL, catt)
+                    if (err .ne. NF_NOERR) then
+                        call errore('nfmpi_put_att_text: ', err)
+                    end if
+                else
+                    allInRange = .true.
+                    do 4, k = 1, ATT_LEN(j,i)
+                        ndx(1) = k
+                        att(k) = hash(ATT_TYPE(j,i), -1, ndx)
+                        allInRange = allInRange .and.
+     +                               inRange(att(k), ATT_TYPE(j,i))
+4                   continue
+                    ATT_LEN_LL = ATT_LEN(j,i)
+                    err = nfmpi_put_att_double(ncid, varid(i),
+     +                                      ATT_NAME(j,i),
+     +                                      ATT_TYPE(j,i),
+     +                                      ATT_LEN_LL, att)
+                    if (allInRange) then
+                        if (err .ne. NF_NOERR) then
+                            call errore('nfmpi_put_att_double: ', err)
+                        end if
+                    else
+                        if (err .ne. NF_ERANGE) then
+                            call errore(
+     +                  'type-conversion range error: status = ',
+     +                          err)
+                        end if
+                    end if
+                end if
+2           continue
+1       continue
+        end
+
+
+! put variables defined by global variables */
+        subroutine put_vars(ncid)
+        implicit        none
+        integer                 ncid
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes
+        double precision hash
+        logical inrange
+
+        integer*8               start(MAX_RANK)
+        integer*8               index(MAX_RANK)
+        integer                 err             !/* netCDF status */
+        integer                 i
+        integer                 j
+        doubleprecision         value(MAX_NELS)
+        character*(MAX_NELS+2)  text
+        logical                 allInRange
+
+        do 1, j = 1, MAX_RANK
+            start(j) = 1
+1       continue
+
+        do 2, i = 1, numVars
+            allInRange = .true.
+            do 3, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                              index)
+                if (err .ne. NF_NOERR) then
+                    call errori(
+     +                  'Error calling index2indexes() for var ', j)
+                end if
+                if (var_name(i)(1:1) .eq. 'c') then
+                    text(j:j) = 
+     +                  char(int(hash(var_type(i), var_rank(i), index)))
+                else
+                    value(j)  = hash(var_type(i), var_rank(i), index)
+                    allInRange = allInRange .and.
+     +                  inRange(value(j), var_type(i))
+                end if
+3           continue
+            if (var_name(i)(1:1) .eq. 'c') then
+!               /*
+!                * The following statement ensures that the first 4
+!                * characters in 'text' are not all zeros (which is
+!                * a cfortran.h NULL indicator) and that the string
+!                * contains a zero (which will cause the address of the
+!                * actual string buffer to be passed).
+!                */
+                text(var_nels(i)+1:var_nels(i)+1) = char(1)
+                text(var_nels(i)+2:var_nels(i)+2) = char(0)
+                err = nfmpi_put_vara_text_all(ncid, i, start,
+     +                                    var_shape(1,i), text)
+                if (err .ne. NF_NOERR) then
+                    call errore('nfmpi_put_vara_text_all: ', err)
+                end if
+            else
+                err = nfmpi_put_vara_double_all(ncid, i, start,
+     +                                      var_shape(1,i), value)
+                if (allInRange) then
+                    if (err .ne. NF_NOERR) then
+                        call errore('nfmpi_put_vara_double_all: ', err)
+                    end if
+                else
+                    if (err .ne. NF_ERANGE) then
+                        call errore('put_vars '//
+     +                      'type-conversion range error: status = ', 
+     +                      err)
+                    end if
+                end if
+            end if
+2       continue
+        end
+
+
+! Create & write all of specified file using global variables */
+        subroutine write_file(filename) 
+        implicit        none
+        character*(*)   filename
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer MY_LEN_TRIM
+        integer ncid            !/* netCDF id */
+        integer err             !/* netCDF status */
+        integer flags
+
+        flags = IOR(NF_CLOBBER, extra_flags)
+        err = nfmpi_create(comm, filename, flags, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_create: '//
+     +           TRIM(filename), err)
+        end if
+
+        call def_dims(ncid)
+        call def_vars(ncid)
+        call put_atts(ncid)
+        err = nfmpi_enddef(ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_enddef: ', err)
+        end if
+        call put_vars(ncid)
+
+        err = nfmpi_close(ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_close: ', err)
+        end if
+        end
+
+
+!
+! check dimensions of specified file have expected name & length
+!
+        subroutine check_dims(ncid)
+        implicit        none
+        integer         ncid
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        character*(NF_MAX_NAME) name
+        integer*8               length
+        integer                 i
+        integer                 err           !/* netCDF status */
+
+        do 1, i = 1, NDIMS
+            err = nfmpi_inq_dim(ncid, i, name, length)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_dim: ', err)
+            end if
+            if (name .ne. dim_name(i)) then
+                call errori('Unexpected name of dimension ', i)
+            end if
+            if (length .ne. dim_len(i)) then
+                call errori('Unexpected length of dimension ', i)
+            end if
+1       continue
+        end
+
+
+!
+! check variables of specified file have expected name, type, shape & values
+!
+        subroutine check_vars(ncid)
+        implicit        none
+        integer         ncid
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer index2indexes
+        double precision hash
+        logical inrange, equal
+
+        integer*8               index(MAX_RANK)
+        integer                 err             !/* netCDF status */
+        integer                 i
+        integer                 j
+        character*1             text
+        doubleprecision         value
+        integer                 datatype
+        integer                 ndims
+        integer                 natt
+        integer                 dimids(MAX_RANK)
+        logical                 isChar
+        doubleprecision         expect
+        character*(NF_MAX_NAME) name
+        integer*8               length
+        integer                 nok             !/* count of valid comparisons */
+
+        nok = 0
+        err = nfmpi_begin_indep_data(ncid)
+
+        do 1, i = 1, numVars
+            isChar = var_type(i) .eq. NF_CHAR
+            err = nfmpi_inq_var(ncid, i, name, datatype, ndims, dimids, 
+     +          natt)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_inq_var: ', err)
+            end if
+            if (name .ne. var_name(i)) then
+                call errori('Unexpected var_name for variable ', i)
+            end if
+            if (datatype .ne. var_type(i))  then
+                call errori('Unexpected type for variable ', i)
+            end if
+            if (ndims .ne. var_rank(i))  then
+                call errori('Unexpected rank for variable ', i)
+            end if
+            do 2, j = 1, ndims
+                err = nfmpi_inq_dim(ncid, dimids(j), name, length)
+                if (err .ne. NF_NOERR) then
+                    call errore('nfmpi_inq_dim: ', err)
+                end if
+                if (length .ne. var_shape(j,i))  then
+                    call errori('Unexpected shape for variable ', i)
+                end if
+2           continue
+            do 3, j = 1, var_nels(i)
+                err = index2indexes(j, var_rank(i), var_shape(1,i), 
+     +                  index)
+                if (err .ne. NF_NOERR)  then
+                    call errori('error in index2indexes() 2, variable ',
+     +                          i)
+                end if
+                expect = hash(var_type(i), var_rank(i), index )
+                if (isChar) then
+                    err = nfmpi_get_var1_text(ncid, i, index, text)
+                    if (err .ne. NF_NOERR) then
+                        call errore('nfmpi_get_var1_text: ', err)
+                    end if
+                    if (ichar(text) .ne. expect) then
+                        call errori(
+     +              'Var value read not that expected for variable ', i)
+                        call errord(' expecting ',expect)
+                        call errori(' but got ', ichar(text))
+                    else
+                        nok = nok + 1
+                    end if
+                else
+                    err = nfmpi_get_var1_double(ncid, i, index, 
+     +                     value)
+                    if (inRange(expect,var_type(i))) then
+                        if (err .ne. NF_NOERR) then
+                            call errore('nfmpi_get_var1_double: ', err)
+                        else
+                            if (.not. equal(value,expect,var_type(i),
+     +                          NFT_DOUBLE)) then
+                                call errori(
+     +              'Var value read not that expected for variable ', i)
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+                    end if
+                end if
+3           continue
+1       continue
+        err = nfmpi_end_indep_data(ncid)
+        ! call print_nok(nok)
+        end
+
+
+!
+! check attributes of specified file have expected name, type, length & values
+!
+        subroutine check_atts(ncid) 
+        implicit        none
+        integer         ncid
+        include "pnetcdf.inc"
+#include "tests.inc"
+        integer VARID, NATTS, ATT_TYPE, ATT_LEN
+        CHARACTER*2 ATT_NAME
+        double precision hash
+        logical inrange, equal
+
+        integer                 err             !/* netCDF status */
+        integer                 i
+        integer                 j
+        integer                 k
+        integer                 vid             !/* "variable" ID */
+        integer                 datatype
+        integer*8               ndx(1)
+        character*(NF_MAX_NAME) name
+        integer*8               length
+        character*(MAX_NELS)    text
+        doubleprecision         value(MAX_NELS)
+        doubleprecision         expect
+        integer                 nok             !/* count of valid comparisons */
+
+        nok = 0
+
+        do 1, vid = 0, numVars
+            i = varid(vid)
+
+            do 2, j = 1, NATTS(i)
+                err = nfmpi_inq_attname(ncid, i, j, name)
+                if (err .ne. NF_NOERR) then
+                    call errore('nfmpi_inq_attname: ', err)
+                end if
+                if (name .ne. ATT_NAME(j,i)) then
+                    call errori(
+     +                 'nfmpi_inq_attname: unexpected name for var ', i)
+                end if
+                err = nfmpi_inq_att(ncid, i, name, datatype, length)
+                if (err .ne. NF_NOERR) then
+                    call errore('nfmpi_inq_att: ', err)
+                end if
+                if (datatype .ne. ATT_TYPE(j,i)) then
+                    call errori(
+     +                     'nfmpi_inq_att: unexpected type for var ', i)
+                end if
+                if (length .ne. ATT_LEN(j,i)) then
+                    call errori(
+     +                  'nfmpi_inq_att: unexpected length for var ', i)
+                end if
+                if (datatype .eq. NF_CHAR) then
+                    err = nfmpi_get_att_text(ncid, i, name, text)
+                    if (err .ne. NF_NOERR) then
+                        call errore('nfmpi_get_att_text: ', err)
+                    end if
+                    do 3, k = 1, ATT_LEN(j,i)
+                        ndx(1) = k
+                        if (ichar(text(k:k)) .ne. hash(datatype, -1, 
+     +                                                 ndx))
+     +                  then
+                            call errori(
+     +          'nfmpi_get_att_text: unexpected value for var ', i)
+                        else
+                            nok = nok + 1
+                        end if
+3                   continue
+                else
+                    err = nfmpi_get_att_double(ncid, i, name, value)
+                    do 4, k = 1, ATT_LEN(j,i)
+                        ndx(1) = k
+                        expect = hash(datatype, -1, ndx)
+                        if (inRange(expect,ATT_TYPE(j,i))) then
+                            if (err .ne. NF_NOERR) then
+                                call errore(
+     +                              'nfmpi_get_att_double: ', err)
+                            end if
+                            if (.not. equal(value(k), expect,
+     +                          ATT_TYPE(j,i), NFT_DOUBLE)) then
+                                call errori(
+     +                  'Att value read not that expected for var ', i)
+                            else
+                                nok = nok + 1
+                            end if
+                        end if
+4                   continue
+                end if
+2           continue
+1       continue
+        ! call print_nok(nok)
+        end
+
+
+! Check file (dims, vars, atts) corresponds to global variables */
+        subroutine check_file(filename) 
+        implicit        none
+        character*(*)   filename
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        integer ncid            !/* netCDF id */
+        integer err             !/* netCDF status */
+
+        err = nfmpi_open(comm, filename, NF_NOWRITE, info, ncid)
+        if (err .ne. NF_NOERR) then
+            call errore('nfmpi_open: ', err)
+        else
+            call check_dims(ncid)
+            call check_vars(ncid)
+            call check_atts(ncid)
+            err = nfmpi_close (ncid)
+            if (err .ne. NF_NOERR) then
+                call errore('nfmpi_close: ', err)
+            end if
+        end if
+        end
+
+
+!
+! Functions for accessing attribute test data.
+!
+! NB: 'varid' is 0 for global attributes; thus, global attributes can
+! be handled in the same loop as variable attributes.
+!
+
+      integer FUNCTION VARID(VID)
+      IMPLICIT NONE
+      INTEGER VID
+      include "pnetcdf.inc"
+#include "tests.inc"
+      IF (VID .LT. 1) THEN
+          VARID = NF_GLOBAL
+      ELSE
+          VARID = VID
+      ENDIF
+      end
+
+
+      integer FUNCTION NATTS(VID)
+      IMPLICIT  NONE
+      INTEGER VID
+      include "pnetcdf.inc"
+#include "tests.inc"
+      IF (VID .LT. 1) THEN
+          NATTS = numGatts
+      ELSE
+          NATTS = VAR_NATTS(VID)
+      ENDIF
+      END
+
+
+      character*2 FUNCTION ATT_NAME(J,VID)
+      IMPLICIT  NONE
+      INTEGER J
+      INTEGER VID
+      include "pnetcdf.inc"
+#include "tests.inc"
+      IF (VID .LT. 1) THEN
+          ATT_NAME = GATT_NAME(J)
+      ELSE
+          ATT_NAME = ATTNAME(J,VID)
+      ENDIF
+      END
+
+
+      integer FUNCTION ATT_TYPE(J,VID)
+      IMPLICIT  NONE
+      INTEGER J
+      INTEGER VID
+      include "pnetcdf.inc"
+#include "tests.inc"
+      IF (VID .LT. 1) THEN
+          ATT_TYPE = GATT_TYPE(J)
+      ELSE
+          ATT_TYPE = ATTTYPE(J,VID)
+      ENDIF
+      END
+
+
+      integer FUNCTION ATT_LEN(J,VID)
+      IMPLICIT  NONE
+      INTEGER J
+      INTEGER VID
+      include "pnetcdf.inc"
+#include "tests.inc"
+      IF (VID .LT. 1) THEN
+          ATT_LEN = int(GATT_LEN(J))
+      ELSE
+          ATT_LEN = ATTLEN(J,VID)
+      ENDIF
+      END
+
+
+!
+! Return the minimum value of an internal type.
+!
+        doubleprecision function internal_min(type)
+        implicit        none
+        integer         type
+        doubleprecision min_schar
+        doubleprecision min_short
+        doubleprecision min_int
+        ! doubleprecision min_long
+        doubleprecision max_float
+        doubleprecision max_double
+        doubleprecision min_int64
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        if (type .eq. NFT_CHAR) then
+            internal_min = 0
+        else if (type .eq. NFT_INT1) then
+#if defined NF_INT1_IS_C_SIGNED_CHAR
+            internal_min = min_schar()
+#elif defined NF_INT1_IS_C_SHORT
+            internal_min = min_short()
+#elif defined NF_INT1_IS_C_INT
+            internal_min = min_int()
+#elif defined NF_INT1_IS_C_LONG
+            internal_min = min_long()
+#else
+            internal_min = min_schar()
+! #include "No C equivalent to Fortran INTEGER*1"
+#endif
+        else if (type .eq. NFT_INT2) then
+#if defined NF_INT2_IS_C_SHORT
+            internal_min = min_short()
+#elif defined NF_INT2_IS_C_INT
+            internal_min = min_int()
+#elif defined NF_INT2_IS_C_LONG
+            internal_min = min_long()
+#else
+            internal_min = min_short()
+! #include "No C equivalent to Fortran INTEGER*2"
+#endif
+        else if (type .eq. NFT_INT) then
+#if defined NF_INT_IS_C_INT
+            internal_min = min_int()
+#elif defined NF_INT_IS_C_LONG
+            internal_min = min_long()
+#else
+            internal_min = min_int()
+! #include "No C equivalent to Fortran INTEGER"
+#endif
+        else if (type .eq. NFT_REAL) then
+#if defined NF_REAL_IS_C_FLOAT
+            internal_min = -max_float()
+#elif defined NF_REAL_IS_C_DOUBLE
+            internal_min = -max_double()
+#else
+            internal_min = -max_float()
+! #include "No C equivalent to Fortran REAL"
+#endif
+        else if (type .eq. NFT_DOUBLE) then
+#if defined NF_DOUBLEPRECISION_IS_C_DOUBLE
+            internal_min = -max_double()
+#elif defined NF_DOUBLEPRECISION_IS_C_FLOAT
+            internal_min = -max_float()
+#else
+            internal_min = -max_double()
+! #include "No C equivalent to Fortran DOUBLE"
+#endif
+        else if (type .eq. NFT_INT8) then
+            internal_min = min_int64()
+        else
+            stop 'internal_min(): invalid type'
+        end if
+        end
+
+
+!
+! Return the maximum value of an internal type.
+!
+        doubleprecision function internal_max(type)
+        implicit        none
+        integer         type
+        doubleprecision max_schar
+        doubleprecision max_short
+        doubleprecision max_int
+        ! doubleprecision max_long
+        doubleprecision max_float
+        doubleprecision max_double
+        doubleprecision max_int64
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        if (type .eq. NFT_CHAR) then
+            internal_max = 255
+        else if (type .eq. NFT_INT1) then
+#if defined NF_INT1_IS_C_SIGNED_CHAR
+            internal_max = max_schar()
+#elif defined NF_INT1_IS_C_SHORT
+            internal_max = max_short()
+#elif defined NF_INT1_IS_C_INT
+            internal_max = max_int()
+#elif defined NF_INT1_IS_C_LONG
+            internal_max = max_long()
+#else
+            internal_max = max_schar()
+! #include "No C equivalent to Fortran INTEGER*1"
+#endif
+        else if (type .eq. NFT_INT2) then
+#if defined NF_INT2_IS_C_SHORT
+            internal_max = max_short()
+#elif defined NF_INT2_IS_C_INT
+            internal_max = max_int()
+#elif defined NF_INT2_IS_C_LONG
+            internal_max = max_long()
+#else
+            internal_max = max_short()
+! #include "No C equivalent to Fortran INTEGER*2"
+#endif
+        else if (type .eq. NFT_INT) then
+#if defined NF_INT_IS_C_INT
+            internal_max = max_int()
+#elif defined NF_INT_IS_C_LONG
+            internal_max = max_long()
+#else
+            internal_max = max_int()
+! #include "No C equivalent to Fortran INTEGER"
+#endif
+        else if (type .eq. NFT_REAL) then
+#if defined NF_REAL_IS_C_FLOAT
+            internal_max = max_float()
+#elif defined NF_REAL_IS_C_DOUBLE
+            internal_max = max_double()
+#else
+            internal_max = max_float()
+! #include "No C equivalent to Fortran REAL"
+#endif
+        else if (type .eq. NFT_DOUBLE) then
+#if defined NF_DOUBLEPRECISION_IS_C_DOUBLE
+            internal_max = max_double()
+#elif defined NF_DOUBLEPRECISION_IS_C_FLOAT
+            internal_max = max_float()
+#else
+            internal_max = max_double()
+! #include "No C equivalent to Fortran DOUBLE"
+#endif
+        else if (type .eq. NFT_INT8) then
+            internal_max = max_int64()
+        else
+            stop 'internal_max(): invalid type'
+        end if
+        end
+
+
+!
+! Return the minimum value of an external type.
+!
+        doubleprecision function external_min(type)
+        implicit        none
+        integer         type
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        if (type .eq. NF_BYTE) then
+            external_min = X_BYTE_MIN
+        else if (type .eq. NF_CHAR) then
+            external_min = X_CHAR_MIN
+        else if (type .eq. NF_SHORT) then
+            external_min = X_SHORT_MIN
+        else if (type .eq. NF_INT) then
+            external_min = X_INT_MIN
+        else if (type .eq. NF_FLOAT) then
+            external_min = X_FLOAT_MIN
+        else if (type .eq. NF_DOUBLE) then
+            external_min = X_DOUBLE_MIN
+        else if (type .eq. NF_INT64) then
+            external_min = X_INT8_MIN
+        else
+            stop 'external_min(): invalid type'
+        end if
+        end
+
+
+!
+! Return the maximum value of an internal type.
+!
+        doubleprecision function external_max(type)
+        implicit        none
+        integer         type
+        include "pnetcdf.inc"
+#include "tests.inc"
+
+        if (type .eq. NF_BYTE) then
+            external_max = X_BYTE_MAX
+        else if (type .eq. NF_CHAR) then
+            external_max = X_CHAR_MAX
+        else if (type .eq. NF_SHORT) then
+            external_max = X_SHORT_MAX
+        else if (type .eq. NF_INT) then
+            external_max = X_INT_MAX
+        else if (type .eq. NF_FLOAT) then
+            external_max = X_FLOAT_MAX
+        else if (type .eq. NF_DOUBLE) then
+            external_max = X_DOUBLE_MAX
+        else if (type .eq. NF_INT64) then
+            external_max = X_INT8_MAX
+        else
+            stop 'external_max(): invalid type'
+        end if
+        end
+
+
+!
+! Indicate whether or not a value lies in the range of an internal type.
+!
+        logical function in_internal_range(itype, value)
+        implicit        none
+        integer         itype
+        doubleprecision value
+        include "pnetcdf.inc"
+#include "tests.inc"
+        double precision internal_min, internal_max
+
+        in_internal_range = value .ge. internal_min(itype) .and.
+     +                      value .le. internal_max(itype)
+        end
+
+! Returns length of string ignoring trailing blanks 
+       INTEGER FUNCTION MY_LEN_TRIM(STRING)
+           CHARACTER*(*) STRING
+           DO I = LEN(STRING), 1, -1
+               IF (STRING(I:I) .NE. ' ') go to 10
+           ENDDO
+ 10        MY_LEN_TRIM = I
+       END ! FUNCTION MY_LEN_TRIM
+
diff --git a/test/nonblocking/Makefile.in b/test/nonblocking/Makefile.in
new file mode 100644
index 0000000..b65dc9c
--- /dev/null
+++ b/test/nonblocking/Makefile.in
@@ -0,0 +1,140 @@
+#
+# Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I../../src/lib -I$(srcdir)/../common
+FPPFLAGS += -I../../src/libf @FC_MODINC at ../../src/libf90 @FC_MODINC at ../common
+LDFLAGS  := -L../common $(LDFLAGS)
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
+ifeq (@PNC_DEBUG@, yes)
+CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
+endif
+
+C_SRCS   = mcoll_perf.c \
+           test_bput.c \
+           interleaved.c \
+           i_varn_int64.c \
+           bput_varn_uint.c \
+           flexible_bput.c \
+           wait_after_indep.c \
+           column_wise.c \
+           req_all.c \
+           i_varn_indef.c
+
+F77_SRCS = mcoll_testf77.f \
+           test_bputf77.f
+
+F90_SRCS = mcoll_testf.f90 \
+           test_bputf.f90
+
+PROGS     = $(C_SRCS:.c=)
+OBJS      = $(C_SRCS:.c=.o)
+ifeq (@has_fortran@, yes)
+PROGS     += $(F77_SRCS:.f=)   $(F90_SRCS:.f90=)
+OBJS      += $(F77_SRCS:.f=.o) $(F90_SRCS:.f90=.o)
+endif
+
+GARBAGE      = $(PROGS) *.nc
+PACKING_LIST = $(C_SRCS) $(F77_SRCS) $(F90_SRCS) Makefile.in README depend
+
+all: $(PROGS)
+
+$(C_SRCS:.c=.o): $(srcdir)/../common/testutils.h
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+mcoll_perf: mcoll_perf.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+test_bput: test_bput.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+i_varn_int64: i_varn_int64.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+bput_varn_uint: bput_varn_uint.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+interleaved: interleaved.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+flexible_bput: flexible_bput.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+wait_after_indep: wait_after_indep.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+column_wise: column_wise.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+req_all: req_all.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+i_varn_indef: i_varn_indef.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+mcoll_testf77: mcoll_testf77.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+mcoll_testf: mcoll_testf.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+test_bputf: test_bputf.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+test_bputf77: test_bputf77.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+check testing verbose_check verbose_testing: $(PROGS)
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc*
+	for i in $(PROGS); do ( \
+	$(TEST_SEQRUN) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+# Some of these tests are designed to run on one process,
+# # Run them on 4 processes to see if they can handle well
+# Some of these tests are designed to run on 4 processes,
+# # Run them on 2, 4, and 6 processes to see if they can handle well
+TEST_MPIRUN_2  = $(subst NP,2,$(TEST_MPIRUN))
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+TEST_MPIRUN_6  = $(subst NP,6,$(TEST_MPIRUN))
+
+ptest4: $(PROGS)
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc $(TEST_OUTDIR)/redef1.nc
+	for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_4) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest2 : $(PROGS)
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc $(TEST_OUTDIR)/redef1.nc
+	for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_2) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest6 : $(PROGS)
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc $(TEST_OUTDIR)/redef1.nc
+	for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_6) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest: ptest4
+ptests: ptest2 ptest4 ptest6
+ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+include $(srcdir)/depend
+
+$(LIBRARY): ;
+
diff --git a/test/nonblocking/README b/test/nonblocking/README
new file mode 100644
index 0000000..876c74e
--- /dev/null
+++ b/test/nonblocking/README
@@ -0,0 +1,12 @@
+There are two test cases in this directory.
+(1) C test case
+This test case test non-blocking functions.
+mpiexec -n 4 mcoll_perf  //test the blocking I/O and non-blocking I/O
+
+The default path to write output is "./". 
+
+You can change the path and output path:
+mpiexec -n 4 mcoll_perf -f testfile.nc
+
+(2) Fortran test case
+mpiexec -n 4 mcoll_testf
diff --git a/test/nonblocking/bput_varn_uint.c b/test/nonblocking/bput_varn_uint.c
new file mode 100644
index 0000000..7ec48d2
--- /dev/null
+++ b/test/nonblocking/bput_varn_uint.c
@@ -0,0 +1,494 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: bput_varn_uint.c 2219 2015-12-11 22:30:03Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example tests nonblocking buffered write varn APIs, including
+ * ncmpi_bput_varn_uint() and ncmpi_bput_varn(),
+ * It first writes a sequence of requests with arbitrary array indices and
+ * lengths to four variables of type NC_UINT, and reads back.
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o bput_varn_uint bput_varn_uint.c -lpnetcdf
+ *    % mpiexec -n 4 ./bput_varn_uint /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             Y = 4 ;
+ *             X = 10 ;
+ *    variables:
+ *            uint var0(Y, X) ;
+ *            uint var1(Y, X) ;
+ *            uint var2(Y, X) ;
+ *            uint var3(Y, X) ;
+ *    data:
+ *
+ *     var0 =
+ *      3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+ *      0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+ *      1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+ *      0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *
+ *     var1 =
+ *      2, 2, 2, 0, 0, 3, 3, 1, 0, 0,
+ *      3, 1, 1, 1, 2, 0, 0, 1, 1, 1,
+ *      0, 0, 1, 2, 2, 2, 3, 3, 0, 0,
+ *      3, 3, 3, 1, 0, 0, 0, 2, 2, 2 ;
+ *
+ *     var2 =
+ *      1, 1, 1, 3, 3, 2, 2, 0, 3, 3,
+ *      2, 0, 0, 0, 1, 3, 3, 0, 0, 0,
+ *      3, 3, 0, 1, 1, 1, 2, 2, 3, 3,
+ *      2, 2, 2, 0, 3, 3, 3, 1, 1, 1 ;
+ *
+ *     var3 =
+ *      0, 0, 0, 2, 2, 1, 1, 3, 2, 2,
+ *      1, 3, 3, 3, 0, 2, 2, 3, 3, 3,
+ *      2, 2, 3, 0, 0, 0, 1, 1, 2, 2,
+ *      1, 1, 1, 3, 2, 2, 2, 0, 0, 0 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+#define ERR \
+    if (err != NC_NOERR) { \
+        printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
+        nerrs++; \
+    }
+
+#define ERRS(n,a) { \
+    int _i; \
+    for (_i=0; _i<(n); _i++) { \
+        if ((a)[_i] != NC_NOERR) { \
+            printf("Error at line=%d: err[%d] %s\n", __LINE__, _i, \
+                   ncmpi_strerror((a)[_i])); \
+            nerrs++; \
+        } \
+    } \
+}
+
+static
+void clear_file_contents(int ncid, int *varid)
+{
+    int i, err, rank;
+    unsigned int *w_buffer = (unsigned int*) malloc(NY*NX * sizeof(unsigned int));
+    for (i=0; i<NY*NX; i++) w_buffer[i] = 99999;
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    for (i=0; i<4; i++) {
+        err = ncmpi_put_var_uint_all(ncid, varid[i], w_buffer);
+        if (err != NC_NOERR) printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));
+    }
+    free(w_buffer);
+}
+
+static
+int check_contents_for_fail(int ncid, int *varid)
+{
+    /* all processes read entire variables back and check contents */
+    int i, j, err, nprocs;
+    unsigned int expected[4][NY*NX] = {{3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+                                        0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+                                        1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+                                        0, 0, 0, 2, 1, 1, 1, 3, 3, 3},
+                                       {2, 2, 2, 0, 0, 3, 3, 1, 0, 0,
+                                        3, 1, 1, 1, 2, 0, 0, 1, 1, 1,
+                                        0, 0, 1, 2, 2, 2, 3, 3, 0, 0,
+                                        3, 3, 3, 1, 0, 0, 0, 2, 2, 2},
+                                       {1, 1, 1, 3, 3, 2, 2, 0, 3, 3,
+                                        2, 0, 0, 0, 1, 3, 3, 0, 0, 0,
+                                        3, 3, 0, 1, 1, 1, 2, 2, 3, 3,
+                                        2, 2, 2, 0, 3, 3, 3, 1, 1, 1},
+                                       {0, 0, 0, 2, 2, 1, 1, 3, 2, 2,
+                                        1, 3, 3, 3, 0, 2, 2, 3, 3, 3,
+                                        2, 2, 3, 0, 0, 0, 1, 1, 2, 2,
+                                        1, 1, 1, 3, 2, 2, 2, 0, 0, 0}};
+
+    unsigned int *r_buffer = (unsigned int*) malloc(NY*NX * sizeof(unsigned int));
+
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    if (nprocs > 4) MPI_Barrier(MPI_COMM_WORLD);
+
+    for (i=0; i<4; i++) {
+        for (j=0; j<NY*NX; j++) r_buffer[j] = 99999;
+        err = ncmpi_get_var_uint_all(ncid, varid[i], r_buffer);
+        if (err != NC_NOERR) printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));
+
+        /* check if the contents of buf are expected */
+        for (j=0; j<NY*NX; j++) {
+            if (expected[i][j] >= nprocs) continue;
+            if (r_buffer[j] != expected[i][j]) {
+                printf("Expected read buf[%d][%d]=%u, but got %u\n",
+                       i,j,expected[i][j],r_buffer[j]);
+                free(r_buffer);
+                return 1;
+            }
+        }
+    }
+    free(r_buffer);
+    return 0;
+}
+
+static int
+check_num_pending_reqs(int ncid, int expected, int lineno)
+/* check if PnetCDF can reports expected number of pending requests */
+{
+    int err, n_pendings;
+    err = ncmpi_inq_nreqs(ncid, &n_pendings);
+    if (err != NC_NOERR) printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));
+    if (n_pendings != expected) {
+        printf("Error at line %d: expect %d pending requests but got %d\n",
+               lineno, expected, n_pendings);
+        return 1;
+    }
+    return 0;
+}
+
+static
+void check_attached_buffer_usage(int ncid,
+                                 MPI_Offset expected_size,
+                                 MPI_Offset expected_usage,
+                                 int lineno)
+/* check attached buf usage */
+{
+    int err, rank;
+    MPI_Offset usage, buf_size;
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    if (rank >= 4) return;
+
+    err = ncmpi_inq_buffer_size(ncid, &buf_size);
+    if (err != NC_NOERR) printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));
+    if (expected_size != buf_size)
+        printf("Error at line %d: expect buffer size %lld but got %lld\n",
+               lineno, expected_size, buf_size);
+
+    err = ncmpi_inq_buffer_usage(ncid, &usage);
+    if (err != NC_NOERR) printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));
+    if (expected_usage != usage)
+        printf("Error at line %d: expect buffer usage %lld but got %lld\n",
+               lineno, expected_usage, usage);
+}
+
+/* swap two rows, a and b, of a 2D array */
+static
+void permute(MPI_Offset *a, MPI_Offset *b)
+{
+    int i;
+    MPI_Offset tmp;
+    for (i=0; i<NDIMS; i++) {
+        tmp = a[i]; a[i] = b[i]; b[i] = tmp;
+    }
+}
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int i, j, k, rank, nprocs, verbose=0, err, nerrs=0;
+    int ncid, cmode, varid[4], dimid[2], nreqs, reqs[4], sts[4];
+    unsigned int *buffer[4];
+    int num_segs[4] = {4, 6, 5, 4};
+    int req_lens[4], my_nsegs[4];
+    MPI_Offset **starts[4], **counts[4];
+    MPI_Offset n_starts[4][6][2] = {{{0,5}, {1,0}, {2,6}, {3,0}, {0,0}, {0,0}},
+                                    {{0,3}, {0,8}, {1,5}, {2,0}, {2,8}, {3,4}},
+                                    {{0,7}, {1,1}, {1,7}, {2,2}, {3,3}, {0,0}},
+                                    {{0,0}, {1,4}, {2,3}, {3,7}, {0,0}, {0,0}}};
+    MPI_Offset n_counts[4][6][2] = {{{1,2}, {1,1}, {1,2}, {1,3}, {0,0}, {0,0}},
+                                    {{1,2}, {1,2}, {1,2}, {1,2}, {1,2}, {1,3}},
+                                    {{1,1}, {1,3}, {1,3}, {1,1}, {1,1}, {0,0}},
+                                    {{1,3}, {1,1}, {1,3}, {1,3}, {0,0}, {0,0}}};
+
+    /* n_starts[0][][] n_counts[0][][] indicate the following: ("-" means skip)
+              -  -  -  -  -  X  X  -  -  - 
+              X  -  -  -  -  -  -  -  -  - 
+              -  -  -  -  -  -  X  X  -  - 
+              X  X  X  -  -  -  -  -  -  - 
+       n_starts[1][][] n_counts[1][][] indicate the following pattern.
+              -  -  -  X  X  -  -  -  X  X 
+              -  -  -  -  -  X  X  -  -  - 
+              X  X  -  -  -  -  -  -  X  X 
+              -  -  -  -  X  X  X  -  -  - 
+       n_starts[2][][] n_counts[2][][] indicate the following pattern.
+              -  -  -  -  -  -  -  X  -  - 
+              -  X  X  X  -  -  -  X  X  X 
+              -  -  X  -  -  -  -  -  -  - 
+              -  -  -  X  -  -  -  -  -  - 
+       n_starts[3][][] n_counts[3][][] indicate the following pattern.
+              X  X  X  -  -  -  -  -  -  - 
+              -  -  -  -  X  -  -  -  -  - 
+              -  -  -  X  X  X  -  -  -  - 
+              -  -  -  -  -  -  -  X  X  X 
+     */
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for bput_varn_uint ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    if (verbose && nprocs != 4 && rank == 0)
+        printf("Warning: %s is intended to run on 4 processes\n",argv[0]);
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_UINT, NDIMS, dimid, &varid[0]); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_UINT, NDIMS, dimid, &varid[1]); ERR
+    err = ncmpi_def_var(ncid, "var2", NC_UINT, NDIMS, dimid, &varid[2]); ERR
+    err = ncmpi_def_var(ncid, "var3", NC_UINT, NDIMS, dimid, &varid[3]); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* allocate space for starts and counts */
+    starts[0] = (MPI_Offset**) malloc(4 * 6 * sizeof(MPI_Offset*));
+    counts[0] = (MPI_Offset**) malloc(4 * 6 * sizeof(MPI_Offset*));
+    starts[0][0] = (MPI_Offset*) calloc(4 * 6 * NDIMS, sizeof(MPI_Offset));
+    counts[0][0] = (MPI_Offset*) calloc(4 * 6 * NDIMS, sizeof(MPI_Offset));
+    for (i=1; i<4; i++) {
+        starts[i] = starts[i-1] + 6;
+        counts[i] = counts[i-1] + 6;
+        starts[i][0] = starts[i-1][0] + 6 * NDIMS;
+        counts[i][0] = counts[i-1][0] + 6 * NDIMS;
+    }
+    for (i=0; i<4; i++) {
+        for (j=1; j<6; j++) {
+            starts[i][j] = starts[i][j-1] + NDIMS;
+            counts[i][j] = counts[i][j-1] + NDIMS;
+        }
+    }
+
+    /* set values for starts and counts */
+    for (i=0; i<4; i++) {
+        int n = (i + rank) % 4;
+        my_nsegs[i] = num_segs[n]; /* number of segments for this request */
+        for (j=0; j<6; j++) {
+            for (k=0; k<NDIMS; k++) {
+                starts[i][j][k] = n_starts[n][j][k];
+                counts[i][j][k] = n_counts[n][j][k];
+            }
+        }
+    }
+
+    /* test error code: NC_ENULLABUF */
+    err = ncmpi_bput_varn_uint(ncid, varid[0], 1, NULL, NULL, NULL, &reqs[0]);
+    if (err != NC_ENULLABUF) {
+        printf("Error at line %d: expecting error code NC_ENULLABUF but got %s\n",
+               __LINE__, nc_err_code_name(err));
+        nerrs++;
+    }
+
+    /* only rank 0, 1, 2, and 3 do I/O:
+     * each of ranks 0 to 3 write 4 nonblocking requests */
+    nreqs = 4;
+    if (rank >= 4) nreqs = 0;
+
+    /* bufsize must be max of data type converted before and after */
+    MPI_Offset bufsize = 0;
+
+    /* calculate length of each varn request and allocate write buffer */
+    for (i=0; i<nreqs; i++) {
+        req_lens[i] = 0; /* total length this request */
+        for (j=0; j<my_nsegs[i]; j++) {
+            MPI_Offset req_len=1;
+            for (k=0; k<NDIMS; k++)
+                req_len *= counts[i][j][k];
+            req_lens[i] += req_len;
+        }
+        if (verbose) printf("req_lens[%d]=%d\n",i,req_lens[i]);
+
+        /* allocate I/O buffer and initialize its contents */
+        buffer[i] = (unsigned int*) malloc(req_lens[i] * sizeof(unsigned int));
+        for (j=0; j<req_lens[i]; j++) buffer[i][j] = rank;
+        bufsize += req_lens[i];
+    }
+    bufsize *= sizeof(unsigned int);
+
+    /* give PnetCDF a space to buffer the nonblocking requests */
+    if (bufsize > 0) {
+        err = ncmpi_buffer_attach(ncid, bufsize); ERR
+    }
+    if (verbose) printf("%d: Attach buffer size %lld\n", rank, bufsize);
+
+    /* test error code: NC_ENULLSTART */
+    err = ncmpi_bput_varn_uint(ncid, varid[0], 1, NULL, NULL, NULL, &reqs[0]);
+    if (rank < 4 && err != NC_ENULLSTART) {
+        printf("Error at line %d: expecting error code NC_ENULLSTART but got %s\n",
+               __LINE__, nc_err_code_name(err));
+        nerrs++;
+    }
+
+    /* write usning varn API, one bput call per variable */
+    clear_file_contents(ncid, varid);
+    for (i=0; i<nreqs; i++) {
+        err = ncmpi_bput_varn_uint(ncid, varid[i], my_nsegs[i], starts[i],
+                                   counts[i], buffer[i], &reqs[i]);
+        ERR
+    }
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    check_attached_buffer_usage(ncid, bufsize, bufsize, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    check_attached_buffer_usage(ncid, bufsize, 0, __LINE__);
+
+    /* all processes read entire variables back and check contents */
+    nerrs += check_contents_for_fail(ncid, varid);
+
+    /* permute write order: so starts[*] are not in an increasing order:
+     * swap segment 0 with segment 2 and swap segment 1 with segment 3
+     */
+    for (i=0; i<nreqs; i++) {
+        permute(starts[i][0],starts[i][2]); permute(counts[i][0],counts[i][2]);
+        permute(starts[i][1],starts[i][3]); permute(counts[i][1],counts[i][3]);
+    }
+
+    /* write using varn API, one bput call per variable */
+    clear_file_contents(ncid, varid);
+    for (i=0; i<nreqs; i++) {
+        err = ncmpi_bput_varn_uint(ncid, varid[i], my_nsegs[i], starts[i],
+                                   counts[i], buffer[i], &reqs[i]);
+        ERR
+    }
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    check_attached_buffer_usage(ncid, bufsize, bufsize, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    check_attached_buffer_usage(ncid, bufsize, 0, __LINE__);
+
+    /* all processes read entire variables back and check contents */
+    nerrs += check_contents_for_fail(ncid, varid);
+
+    for (i=0; i<nreqs; i++) free(buffer[i]);
+
+    /* test flexible API, using a noncontiguous buftype */
+    clear_file_contents(ncid, varid);
+    for (i=0; i<nreqs; i++) {
+        MPI_Datatype buftype;
+        MPI_Type_vector(req_lens[i], 1, 2, MPI_UNSIGNED, &buftype);
+        MPI_Type_commit(&buftype);
+        buffer[i] = (unsigned int*)malloc(req_lens[i]*2*sizeof(unsigned int));
+        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank;
+
+        err = ncmpi_bput_varn(ncid, varid[i], my_nsegs[i], starts[i],
+                              counts[i], buffer[i], 1, buftype, &reqs[i]);
+        ERR
+        MPI_Type_free(&buftype);
+    }
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    check_attached_buffer_usage(ncid, bufsize, bufsize, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    check_attached_buffer_usage(ncid, bufsize, 0, __LINE__);
+
+    /* all processes read entire variables back and check contents */
+    nerrs += check_contents_for_fail(ncid, varid);
+
+    /* permute back to original order */
+    for (i=0; i<nreqs; i++) {
+        permute(starts[i][0],starts[i][2]); permute(counts[i][0],counts[i][2]);
+        permute(starts[i][1],starts[i][3]); permute(counts[i][1],counts[i][3]);
+    }
+
+    /* test flexible API, using a noncontiguous buftype, one bput call per
+     * variable */
+    clear_file_contents(ncid, varid);
+    for (i=0; i<nreqs; i++) {
+        MPI_Datatype buftype;
+        MPI_Type_vector(req_lens[i], 1, 2, MPI_UNSIGNED, &buftype);
+        MPI_Type_commit(&buftype);
+        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank;
+
+        err = ncmpi_bput_varn(ncid, varid[i], my_nsegs[i], starts[i],
+                              counts[i], buffer[i], 1, buftype, &reqs[i]);
+        ERR
+        MPI_Type_free(&buftype);
+    }
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    check_attached_buffer_usage(ncid, bufsize, bufsize, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    check_attached_buffer_usage(ncid, bufsize, 0, __LINE__);
+
+    /* all processes read entire variables back and check contents */
+    nerrs += check_contents_for_fail(ncid, varid);
+
+    /* free the buffer space for bput */
+    if (bufsize > 0) {
+        err = ncmpi_buffer_detach(ncid); ERR
+    }
+
+    /* test error code: NC_ENULLABUF */
+    err = ncmpi_inq_buffer_usage(ncid, NULL);
+    if (err != NC_ENULLABUF) {
+        printf("expecting error code NC_ENULLABUF but got %s\n",
+               nc_err_code_name(err));
+        nerrs++;
+    }
+
+    err = ncmpi_close(ncid); ERR
+
+    for (i=0; i<nreqs; i++) free(buffer[i]);
+    free(starts[0][0]);
+    free(counts[0][0]);
+    free(starts[0]);
+    free(counts[0]);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/nonblocking/column_wise.c b/test/nonblocking/column_wise.c
new file mode 100644
index 0000000..cea39e4
--- /dev/null
+++ b/test/nonblocking/column_wise.c
@@ -0,0 +1,227 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: column_wise.c 2216 2015-12-08 05:47:19Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example tests a number of nonblocking API calls, each writes a single
+ * column of a 2D integer array. Each process writes NX columns and any two
+ * consecutive columns are of nprocs columns distance apart from each other. In
+ * this case, the fileview of each process interleaves with all other processes.
+ * If simply concatenating fileviews of all the nonblocking calls will result
+ * in a fileview that violates the MPI-IO requirement on the fileview of which
+ * flattened file offsets must be monotonically non-decreasing. PnetCDF handles
+ * this case by breaking down each nonblocking call into a lsit of offset-length
+ * pairs, merging the pairs across multiple nonblocking calls, and sorting
+ * them into an increasing order. The sorted pairs are used to construct a
+ * fileview that meets the monotonically non-decreasing offset requirement,
+ * and thus the nonblocking requests can be serviced by a single MPI-IO call. 
+ * 
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o column_wise column_wise.c -lpnetcdf
+ *    % mpiexec -l -n 4 ./column_wise /pvfs2/wkliao/testfile.nc
+ *    0:  0: myOff=  0 myNX=  4
+ *    1:  1: myOff=  4 myNX=  4
+ *    2:  2: myOff=  8 myNX=  4
+ *    3:  3: myOff= 12 myNX=  4
+ *    0:  0: start=  0   0 count= 10   1
+ *    1:  1: start=  0   1 count= 10   1
+ *    2:  2: start=  0   2 count= 10   1
+ *    3:  3: start=  0   3 count= 10   1
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            Y = 10 ;
+ *            X = 16 ;
+ *    variables:
+ *            int var(Y, X) ;
+ *    data:
+ *
+ *     var =
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ *      0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* getopt() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 10
+#define NX 4
+
+#define ERR {if(err!=NC_NOERR){nerrs++; printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}}
+
+int main(int argc, char** argv)
+{
+    extern int optind;
+    char filename[256];
+    int i, j, nerrs=0, rank, nprocs, err, myNX, G_NX, myOff, num_reqs;
+    int ncid, cmode, varid, dimid[2], *reqs, *sts, **buf;
+    MPI_Offset start[2], count[2];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for iput/iget interleaved access ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* the global array is NY * (NX * nprocs) */
+    G_NX  = NX * nprocs;
+    myOff = NX * rank;
+    myNX  = NX;
+
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "X", G_NX, &dimid[1]);
+    ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimid, &varid);
+    ERR
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* First, fill the entire array with zeros, using a blocking I/O.
+       Every process writes a subarray of size NY * myNX */
+    buf    = (int**) malloc(myNX * sizeof(int*));
+    buf[0] = (int*)  calloc(NY * myNX, sizeof(int));
+    start[0] = 0;   start[1] = myOff;
+    count[0] = NY;  count[1] = myNX;
+    err = ncmpi_put_vara_int_all(ncid, varid, start, count, buf[0]);
+    free(buf[0]);
+
+    /* initialize the buffer with rank ID. Also make the case interesting,
+       by allocatsing buffersd separately */
+    for (i=0; i<myNX; i++) {
+        buf[i] = (int*) malloc(NY * sizeof(int));
+        for (j=0; j<NY; j++) buf[i][j] = rank;
+    }
+
+    reqs = (int*) malloc(myNX * sizeof(int));
+    sts  = (int*) malloc(myNX * sizeof(int));
+
+    /* each proc writes myNX single columns of the 2D array */
+    start[0]  = 0;   start[1] = rank;
+    count[0]  = NY;  count[1] = 1;
+
+    num_reqs = 0;
+    for (i=0; i<myNX; i++) {
+        err = ncmpi_iput_vara_int(ncid, varid, start, count, buf[i],
+                                  &reqs[num_reqs++]);
+        ERR
+        start[1] += nprocs;
+    }
+    err = ncmpi_wait_all(ncid, num_reqs, reqs, sts);
+    ERR
+
+    /* check status of all requests */
+    for (i=0; i<num_reqs; i++) {
+        if (reqs[i] != NC_REQ_NULL) { /* add in PnetCDF v1.7.0 */
+            printf("Error: request ID %d fails to be set to NC_REQ_NULL\n",i);
+            nerrs++;
+        }
+        if (sts[i] != NC_NOERR) {
+            printf("Error: nonblocking write fails on request %d (%s)\n",
+                   i, ncmpi_strerror(sts[i]));
+            nerrs++;
+        }
+    }
+
+    /* read back using the same access pattern */
+    for (i=0; i<myNX; i++)
+        for (j=0; j<NY; j++) buf[i][j] = -1;
+
+    /* each proc reads myNX single columns of the 2D array */
+    start[0]  = 0;   start[1] = rank;
+    count[0]  = NY;  count[1] = 1;
+
+    num_reqs = 0;
+    for (i=0; i<myNX; i++) {
+        err = ncmpi_iget_vara_int(ncid, varid, start, count, buf[i],
+                                  &reqs[num_reqs++]);
+        ERR
+        start[1] += nprocs;
+    }
+    err = ncmpi_wait_all(ncid, num_reqs, reqs, sts);
+    ERR
+
+    /* check status of all requests */
+    for (i=0; i<num_reqs; i++)
+        if (sts[i] != NC_NOERR) {
+            printf("Error: nonblocking write fails on request %d (%s)\n",
+                   i, ncmpi_strerror(sts[i]));
+            nerrs++;
+        }
+
+    for (i=0; i<myNX; i++) {
+        for (j=0; j<NY; j++)
+            if (buf[i][j] != rank) {
+                printf("Error: expect buf[%d][%d]=%d but got %d\n",i,j,rank,buf[i][j]);
+                nerrs++;
+            }
+    }
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    free(sts);
+    free(reqs);
+    for (i=0; i<myNX; i++) free(buf[i]);
+    free(buf);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/nonblocking/depend b/test/nonblocking/depend
new file mode 100644
index 0000000..f4e3b8c
--- /dev/null
+++ b/test/nonblocking/depend
@@ -0,0 +1,14 @@
+mcoll_perf.c.o: mcoll_perf.c
+mcoll_testf77:  mcoll_testf77.f
+mcoll_testf.o:  mcoll_testf.f90
+test_bput.o:    test_bput.c
+test_bputf.o:   test_bputf.f90
+test_bputf77.o: test_bputf77.f
+interleaved.o:  interleaved.c
+i_varn_int64.o: i_varn_int64.c
+bput_varn_uint.o: bput_varn_uint.c
+flexible_bput.o: flexible_bput.c
+wait_after_indep.o: wait_after_indep.c
+column_wise.o: column_wise.c
+req_all.o: req_all.c
+i_varn_indef.o: i_varn_indef.c
diff --git a/test/nonblocking/flexible_bput.c b/test/nonblocking/flexible_bput.c
new file mode 100644
index 0000000..2f32dfa
--- /dev/null
+++ b/test/nonblocking/flexible_bput.c
@@ -0,0 +1,270 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: flexible_bput.c 2134 2015-10-03 04:24:18Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This example tests PnetCDF nonblocking buffered flexible varm API, i.e.
+ * ncmpi_bput_varm() to write a 2D array double variable of size NY x NX*nproc
+ * in parallel. In particular, we use a noncontiguous buffer type, a
+ * noncontiguous imap[], and integer type in memory and double in file that
+ * require a type conversion.
+ *
+ * The data partitioning patterns on the variable is column-wise.
+ * The local buffer has ghost cells surrounded along both dimensions.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicc -O2 -o flexible_bput flexible_bput.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 4 ./flexible_bput /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            Y = 6 ;
+ *            X = 16 ;
+ *    variables:
+ *            double var(Y, X) ;
+ *    data:
+ *            
+ *    var =
+ *      0,  6, 12, 18, 0,  6, 12, 18, 0,  6, 12, 18, 0,  6, 12, 18,
+ *      1,  7, 13, 19, 1,  7, 13, 19, 1,  7, 13, 19, 1,  7, 13, 19,
+ *      2,  8, 14, 20, 2,  8, 14, 20, 2,  8, 14, 20, 2,  8, 14, 20,
+ *      3,  9, 15, 21, 3,  9, 15, 21, 3,  9, 15, 21, 3,  9, 15, 21,
+ *      4, 10, 16, 22, 4, 10, 16, 22, 4, 10, 16, 22, 4, 10, 16, 22,
+ *      5, 11, 17, 23, 5, 11, 17, 23, 5, 11, 17, 23, 5, 11, 17, 23 ;
+ *    }
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 6
+#define NX 4
+#define GHOST 2
+
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); nerrs++;}}
+
+#define INIT_PUT_BUF(buf) \
+    for (i=0; i<array_of_sizes[0]; i++) { \
+        for (j=0; j<array_of_sizes[1]; j++) { \
+            if (i < GHOST || GHOST+array_of_subsizes[0] <= i || \
+                j < GHOST || GHOST+array_of_subsizes[1] <= j) \
+                buf[i][j] = -1; \
+            else \
+                buf[i][j] = (i-GHOST)*array_of_subsizes[1]+(j-GHOST); \
+        } \
+    }
+
+#define CHECK_PUT_BUF(buf) \
+    for (i=0; i<array_of_sizes[0]; i++) { \
+        for (j=0; j<array_of_sizes[1]; j++) { \
+            if (i < GHOST || GHOST+array_of_subsizes[0] <= i || \
+                j < GHOST || GHOST+array_of_subsizes[1] <= j) { \
+                if (buf[i][j] != -1) { \
+                    printf("Error: put buffer altered buffer[%d][%d]=%f\n", \
+                           i,j,(double)buf[i][j]); \
+                    nerrs++; \
+                } \
+            } \
+            else { \
+                if (buf[i][j] != (i-GHOST)*array_of_subsizes[1]+(j-GHOST)) { \
+                    printf("Error: put buffer altered buffer[%d][%d]=%f\n", \
+                           i,j,(double)buf[i][j]); \
+                    nerrs++; \
+                } \
+            } \
+        } \
+    }
+
+#define INIT_GET_BUF(buf) \
+    for (i=0; i<array_of_sizes[0]; i++) \
+        for (j=0; j<array_of_sizes[1]; j++) \
+            buf[i][j] = -2;
+
+#define CHECK_GET_BUF(buf) \
+    for (i=0; i<array_of_sizes[0]; i++) { \
+        for (j=0; j<array_of_sizes[1]; j++) { \
+            if (i < GHOST || GHOST+array_of_subsizes[0] <= i || \
+                j < GHOST || GHOST+array_of_subsizes[1] <= j) { \
+                if (buf[i][j] != -2) { \
+                    printf("Unexpected get buffer[%d][%d]=%f\n", \
+                           i,j,(double)buf[i][j]); \
+                    nerrs++; \
+                } \
+            } \
+            else { \
+                if (buf[i][j] != (i-GHOST)*array_of_subsizes[1]+(j-GHOST)) { \
+                    printf("Unexpected get buffer[%d][%d]=%f\n", \
+                           i,j,(double)buf[i][j]); \
+                    nerrs++; \
+                } \
+            } \
+        } \
+    }
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int i, j, rank, nprocs, err, nerrs=0, req, status;
+    int ncid, cmode, varid, dimid[2];
+    int array_of_sizes[2], array_of_subsizes[2], array_of_starts[2];
+    int    buf_int[NX+2*GHOST][NY+2*GHOST];
+    double buf_dbl[NX+2*GHOST][NY+2*GHOST];
+    MPI_Offset start[2], count[2], stride[2], imap[2];
+    MPI_Datatype  subarray;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for flexible bput_varm ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* define 2 dimensions */
+    err = ncmpi_def_dim(ncid, "Y", NY,        &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX*nprocs, &dimid[1]); ERR
+
+    /* define a variable of size NY * (NX * nprocs) */
+    err = ncmpi_def_var(ncid, "var", NC_DOUBLE, 2, dimid, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+     start[0] = 0;  start[1] = NX * rank;
+     count[0] = NY; count[1] = NX;
+    stride[0] = 1; stride[1] = 1;
+      imap[0] = 1;   imap[1] = NY; /* would be {NX, 1} if not transposing */
+
+    /* var is partitioned along X dimension in a matrix transported way */
+    array_of_sizes[0]    = NX + 2*GHOST;
+    array_of_sizes[1]    = NY + 2*GHOST;
+    array_of_subsizes[0] = NX;
+    array_of_subsizes[1] = NY;
+    array_of_starts[0]   = GHOST;
+    array_of_starts[1]   = GHOST;
+    MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                             array_of_starts, MPI_ORDER_C, MPI_INT, &subarray);
+    MPI_Type_commit(&subarray);
+
+    /* calling a nonblocking bput_varm flexible API -------------------------*/
+    /* initiate put buffer contents */
+    INIT_PUT_BUF(buf_int)
+
+    MPI_Offset bufsize = sizeof(double);
+    for (i=0; i<2; i++) bufsize *= count[i];
+    err = ncmpi_buffer_attach(ncid, bufsize); ERR
+
+    err = ncmpi_bput_varm(ncid, varid, start, count, stride, imap, buf_int,
+                          1, subarray, &req);
+    ERR
+    err = ncmpi_wait_all(ncid, 1, &req, &status); ERR
+    err = status; ERR
+
+    /* check the contents of put buffer */
+    CHECK_PUT_BUF(buf_int)
+
+    err = ncmpi_buffer_detach(ncid); ERR
+
+    /* read back using a blocking get_varm flexible API ---------------------*/
+    /* initiate get buffer contents */
+    INIT_GET_BUF(buf_int)
+
+    /* calling a blocking flexible API */
+    err = ncmpi_get_varm_all(ncid, varid, start, count, stride, imap, buf_int,
+                             1, subarray);
+    ERR
+
+    /* check the contents of get buffer */
+    CHECK_GET_BUF(buf_int)
+
+    MPI_Type_free(&subarray);
+
+    /* test case for no type conversion =====================================*/
+    MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                             array_of_starts, MPI_ORDER_C, MPI_DOUBLE,
+                             &subarray);
+    MPI_Type_commit(&subarray);
+
+    /* calling a nonblocking bput_varm flexible API -------------------------*/
+    /* initiate put buffer contents */
+    INIT_PUT_BUF(buf_dbl)
+
+    err = ncmpi_buffer_attach(ncid, bufsize); ERR
+
+    err = ncmpi_bput_varm(ncid, varid, start, count, stride, imap, buf_dbl,
+                          1, subarray, &req);
+    ERR
+    err = ncmpi_wait_all(ncid, 1, &req, &status); ERR
+    err = status; ERR
+
+    /* check the contents of put buffer */
+    CHECK_PUT_BUF(buf_dbl)
+
+    err = ncmpi_buffer_detach(ncid); ERR
+
+    /* read back using a blocking get_varm flexible API ---------------------*/
+    /* initiate get buffer contents */
+    INIT_GET_BUF(buf_dbl)
+
+    /* calling a blocking flexible API */
+    err = ncmpi_get_varm_all(ncid, varid, start, count, stride, imap, buf_dbl,
+                             1, subarray);
+    ERR
+
+    /* check the contents of get buffer */
+    CHECK_GET_BUF(buf_dbl)
+
+    MPI_Type_free(&subarray);
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/nonblocking/i_varn_indef.c b/test/nonblocking/i_varn_indef.c
new file mode 100644
index 0000000..84299dc
--- /dev/null
+++ b/test/nonblocking/i_varn_indef.c
@@ -0,0 +1,574 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: i_varn_indef.c 2219 2015-12-11 22:30:03Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example tests posting nonblocking varn APIs, including
+ * ncmpi_iput_varn_longlong(), ncmpi_iget_varn_longlong(), ncmpi_iput_varn(),
+ * and ncmpi_iget_varn(), in define mode.
+ * It first writes a sequence of requests with arbitrary array indices and
+ * lengths to four variables of type NC_INT64, and reads back.
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o i_varn_indef i_varn_indef.c -lpnetcdf
+ *    % mpiexec -n 4 ./i_varn_indef /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             Y = 4 ;
+ *             X = 10 ;
+ *    variables:
+ *            int64 var0(Y, X) ;
+ *            int64 var1(Y, X) ;
+ *            int64 var2(Y, X) ;
+ *            int64 var3(Y, X) ;
+ *    data:
+ *
+ *     var0 =
+ *      3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+ *      0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+ *      1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+ *      0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *
+ *     var1 =
+ *      2, 2, 2, 0, 0, 3, 3, 1, 0, 0,
+ *      3, 1, 1, 1, 2, 0, 0, 1, 1, 1,
+ *      0, 0, 1, 2, 2, 2, 3, 3, 0, 0,
+ *      3, 3, 3, 1, 0, 0, 0, 2, 2, 2 ;
+ *
+ *     var2 =
+ *      1, 1, 1, 3, 3, 2, 2, 0, 3, 3,
+ *      2, 0, 0, 0, 1, 3, 3, 0, 0, 0,
+ *      3, 3, 0, 1, 1, 1, 2, 2, 3, 3,
+ *      2, 2, 2, 0, 3, 3, 3, 1, 1, 1 ;
+ *
+ *     var3 =
+ *      0, 0, 0, 2, 2, 1, 1, 3, 2, 2,
+ *      1, 3, 3, 3, 0, 2, 2, 3, 3, 3,
+ *      2, 2, 3, 0, 0, 0, 1, 1, 2, 2,
+ *      1, 1, 1, 3, 2, 2, 2, 0, 0, 0 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+#define ERR \
+    if (err != NC_NOERR) { \
+        printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
+        nerrs++; \
+    }
+
+#define ERRS(n,a) { \
+    int _i; \
+    for (_i=0; _i<(n); _i++) { \
+        if ((a)[_i] != NC_NOERR) { \
+            printf("Error at line=%d: err[%d] %s\n", __LINE__, _i, \
+                   ncmpi_strerror((a)[_i])); \
+            nerrs++; \
+        } \
+    } \
+}
+
+static
+void clear_file_contents(int ncid, int *varid)
+{
+    int i, err, rank;
+    long long *w_buffer = (long long*) malloc(NY*NX * sizeof(long long));
+    for (i=0; i<NY*NX; i++) w_buffer[i] = -1;
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    for (i=0; i<4; i++) {
+        err = ncmpi_put_var_longlong_all(ncid, varid[i], w_buffer);
+        if (err != NC_NOERR) printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));
+    }
+    free(w_buffer);
+}
+
+static
+int check_contents_for_fail(int ncid, int *varid, int lineno)
+{
+    /* all processes read entire variables back and check contents */
+    int i, j, err, nprocs;
+    long long expected[4][NY*NX] = {{3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+                                     0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+                                     1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+                                     0, 0, 0, 2, 1, 1, 1, 3, 3, 3},
+                                    {2, 2, 2, 0, 0, 3, 3, 1, 0, 0,
+                                     3, 1, 1, 1, 2, 0, 0, 1, 1, 1,
+                                     0, 0, 1, 2, 2, 2, 3, 3, 0, 0,
+                                     3, 3, 3, 1, 0, 0, 0, 2, 2, 2},
+                                    {1, 1, 1, 3, 3, 2, 2, 0, 3, 3,
+                                     2, 0, 0, 0, 1, 3, 3, 0, 0, 0,
+                                     3, 3, 0, 1, 1, 1, 2, 2, 3, 3,
+                                     2, 2, 2, 0, 3, 3, 3, 1, 1, 1},
+                                    {0, 0, 0, 2, 2, 1, 1, 3, 2, 2,
+                                     1, 3, 3, 3, 0, 2, 2, 3, 3, 3,
+                                     2, 2, 3, 0, 0, 0, 1, 1, 2, 2,
+                                     1, 1, 1, 3, 2, 2, 2, 0, 0, 0}};
+
+    long long *r_buffer = (long long*) malloc(NY*NX * sizeof(long long));
+
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    if (nprocs > 4) MPI_Barrier(MPI_COMM_WORLD);
+
+    for (i=0; i<4; i++) {
+        for (j=0; j<NY*NX; j++) r_buffer[j] = -1;
+        err = ncmpi_get_var_longlong_all(ncid, varid[i], r_buffer);
+        if (err != NC_NOERR) printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));
+
+        /* check if the contents of buf are expected */
+        for (j=0; j<NY*NX; j++) {
+            if (expected[i][j] >= nprocs) continue;
+            if (r_buffer[j] != expected[i][j]) {
+                printf("Error from line %d: Expected read buf[%d][%d]=%lld, but got %lld\n",
+                       lineno,i,j,expected[i][j],r_buffer[j]);
+                free(r_buffer);
+                return 1;
+            }
+        }
+    }
+    free(r_buffer);
+    return 0;
+}
+
+static int
+check_num_pending_reqs(int ncid, int expected, int lineno)
+/* check if PnetCDF can reports expected number of pending requests */
+{
+    int err, n_pendings;
+    err = ncmpi_inq_nreqs(ncid, &n_pendings);
+    if (err != NC_NOERR) printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));
+    if (n_pendings != expected) {
+        printf("Error at line %d: expect %d pending requests but got %d\n",
+               lineno, expected, n_pendings);
+        return 1;
+    }
+    return 0;
+}
+
+/* swap two rows, a and b, of a 2D array */
+static
+void permute(MPI_Offset *a, MPI_Offset *b)
+{
+    int i;
+    MPI_Offset tmp;
+    for (i=0; i<NDIMS; i++) {
+        tmp = a[i]; a[i] = b[i]; b[i] = tmp;
+    }
+}
+
+int main(int argc, char** argv)
+{
+    char filename[256], *varname[4];
+    int i, j, k, rank, nprocs, verbose=0, err, nerrs=0, bufsize=0;
+    int ncid, cmode, varid[4], dimid[2], nreqs, reqs[12], sts[4];
+    long long *buffer[4], *cbuffer[4], *rbuffer[4];
+    int num_segs[4] = {4, 6, 5, 4};
+    int req_lens[4], my_nsegs[4];
+    MPI_Datatype buftype[4];
+    MPI_Offset **starts[4], **counts[4];
+    MPI_Offset n_starts[4][6][2] = {{{0,5}, {1,0}, {2,6}, {3,0}, {0,0}, {0,0}},
+                                    {{0,3}, {0,8}, {1,5}, {2,0}, {2,8}, {3,4}},
+                                    {{0,7}, {1,1}, {1,7}, {2,2}, {3,3}, {0,0}},
+                                    {{0,0}, {1,4}, {2,3}, {3,7}, {0,0}, {0,0}}};
+    MPI_Offset n_counts[4][6][2] = {{{1,2}, {1,1}, {1,2}, {1,3}, {0,0}, {0,0}},
+                                    {{1,2}, {1,2}, {1,2}, {1,2}, {1,2}, {1,3}},
+                                    {{1,1}, {1,3}, {1,3}, {1,1}, {1,1}, {0,0}},
+                                    {{1,3}, {1,1}, {1,3}, {1,3}, {0,0}, {0,0}}};
+
+    /* n_starts[0][][] n_counts[0][][] indicate the following: ("-" means skip)
+              -  -  -  -  -  X  X  -  -  - 
+              X  -  -  -  -  -  -  -  -  - 
+              -  -  -  -  -  -  X  X  -  - 
+              X  X  X  -  -  -  -  -  -  - 
+       n_starts[1][][] n_counts[1][][] indicate the following pattern.
+              -  -  -  X  X  -  -  -  X  X 
+              -  -  -  -  -  X  X  -  -  - 
+              X  X  -  -  -  -  -  -  X  X 
+              -  -  -  -  X  X  X  -  -  - 
+       n_starts[2][][] n_counts[2][][] indicate the following pattern.
+              -  -  -  -  -  -  -  X  -  - 
+              -  X  X  X  -  -  -  X  X  X 
+              -  -  X  -  -  -  -  -  -  - 
+              -  -  -  X  -  -  -  -  -  - 
+       n_starts[3][][] n_counts[3][][] indicate the following pattern.
+              X  X  X  -  -  -  -  -  -  - 
+              -  -  -  -  X  -  -  -  -  - 
+              -  -  -  X  X  X  -  -  -  - 
+              -  -  -  -  -  -  -  X  X  X 
+     */
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for iput/iget varn in define mode ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    if (verbose && nprocs != 4 && rank == 0)
+        printf("Warning: %s is intended to run on 4 processes\n",argv[0]);
+
+    /* allocate space for starts and counts */
+    starts[0] = (MPI_Offset**) malloc(4 * 6 * sizeof(MPI_Offset*));
+    counts[0] = (MPI_Offset**) malloc(4 * 6 * sizeof(MPI_Offset*));
+    starts[0][0] = (MPI_Offset*) calloc(4 * 6 * NDIMS, sizeof(MPI_Offset));
+    counts[0][0] = (MPI_Offset*) calloc(4 * 6 * NDIMS, sizeof(MPI_Offset));
+    for (i=1; i<4; i++) {
+        starts[i] = starts[i-1] + 6;
+        counts[i] = counts[i-1] + 6;
+        starts[i][0] = starts[i-1][0] + 6 * NDIMS;
+        counts[i][0] = counts[i-1][0] + 6 * NDIMS;
+    }
+    for (i=0; i<4; i++) {
+        for (j=1; j<6; j++) {
+            starts[i][j] = starts[i][j-1] + NDIMS;
+            counts[i][j] = counts[i][j-1] + NDIMS;
+        }
+    }
+
+    /* set values for starts and counts */
+    for (i=0; i<4; i++) {
+        int n = (i + rank) % 4;
+        my_nsegs[i] = num_segs[n]; /* number of segments for this request */
+        for (j=0; j<6; j++) {
+            for (k=0; k<NDIMS; k++) {
+                starts[i][j][k] = n_starts[n][j][k];
+                counts[i][j][k] = n_counts[n][j][k];
+            }
+        }
+    }
+
+    /* only rank 0, 1, 2, and 3 do I/O:
+     * each of ranks 0 to 3 write 4 nonblocking requests */
+    nreqs = 4;
+    if (rank >= 4) {
+        nreqs = 0;
+        for (i=0; i<4; i++) my_nsegs[i] = 0;
+    }
+
+    /* calculate length of each varn request and allocate write buffer */
+    for (i=0; i<nreqs; i++) {
+        req_lens[i] = 0; /* total length this request */
+        for (j=0; j<my_nsegs[i]; j++) {
+            MPI_Offset req_len=1;
+            for (k=0; k<NDIMS; k++)
+                req_len *= counts[i][j][k];
+            req_lens[i] += req_len;
+        }
+        if (verbose) printf("req_lens[%d]=%d\n",i,req_lens[i]);
+
+        /* allocate I/O buffer and initialize its contents */
+        buffer[i] = (long long*) malloc(req_lens[i] * sizeof(long long));
+        for (j=0; j<req_lens[i]; j++) buffer[i][j] = rank;
+    }
+    varname[0] = "var0";
+    varname[1] = "var1";
+    varname[2] = "var2";
+    varname[3] = "var3";
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]); ERR
+
+    /* post write requests while still in define mode */
+    for (i=0; i<4; i++) {
+        err = ncmpi_def_var(ncid, varname[i], NC_INT64, NDIMS, dimid, &varid[i]);
+        ERR
+
+        err = ncmpi_iput_varn_longlong(ncid, varid[i], my_nsegs[i], starts[i],
+                                       counts[i], buffer[i], &reqs[i]);
+        ERR
+    }
+
+    /* test error code: NC_ENULLSTART */
+    err = ncmpi_iput_varn_longlong(ncid, varid[0], 1, NULL, NULL,
+                                   NULL, &reqs[4]);
+    if (err != NC_ENULLSTART) {
+        printf("expecting error code NC_ENULLSTART but got %s\n",
+               nc_err_code_name(err));
+        nerrs++;
+    }
+
+    err = ncmpi_enddef(ncid); ERR
+
+    /* clear the file contents using a blocking API, before commit the
+     * nonblocking requests posted in define mode */
+    clear_file_contents(ncid, varid);
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* all processes read entire variables back and check contents */
+    nerrs += check_contents_for_fail(ncid, varid, __LINE__);
+
+    err = ncmpi_close(ncid); ERR
+
+    /* try with buffer being a single contiguous space ----------------------*/
+    for (i=0; i<nreqs; i++) bufsize += req_lens[i];
+    if (bufsize>0) cbuffer[0] = (long long*) malloc(bufsize * sizeof(long long));
+    for (i=1; i<nreqs; i++) cbuffer[i] = cbuffer[i-1] + req_lens[i-1];
+    for (i=0; i<bufsize; i++) cbuffer[0][i] = rank;
+
+    /* create a new file for writing */
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]); ERR
+
+    /* post write requests while still in define mode */
+    for (i=0; i<4; i++) {
+        err = ncmpi_def_var(ncid, varname[i], NC_INT64, NDIMS, dimid, &varid[i]);
+        ERR
+
+        err = ncmpi_iput_varn_longlong(ncid, varid[i], my_nsegs[i], starts[i],
+                                       counts[i], cbuffer[i], &reqs[i]);
+        ERR
+    }
+
+    err = ncmpi_enddef(ncid); ERR
+
+    /* clear the file contents using a blocking API, before commit the
+     * nonblocking requests posted in define mode */
+    clear_file_contents(ncid, varid);
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* all processes read entire variables back and check contents */
+    nerrs += check_contents_for_fail(ncid, varid, __LINE__);
+
+    err = ncmpi_close(ncid); ERR
+
+    /* permute write order: so starts[*] are not in an increasing order:
+     * swap segment 0 with segment 2 and swap segment 1 with segment 3
+     */
+    for (i=0; i<nreqs; i++) {
+        permute(starts[i][0], starts[i][2]); permute(counts[i][0], counts[i][2]);
+        permute(starts[i][1], starts[i][3]); permute(counts[i][1], counts[i][3]);
+    }
+
+    /* create a new file for writing */
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]); ERR
+
+    /* write requests request while still in define mode */
+    for (i=0; i<4; i++) {
+        err = ncmpi_def_var(ncid, varname[i], NC_INT64, NDIMS, dimid, &varid[i]);
+        ERR
+
+        err = ncmpi_iput_varn_longlong(ncid, varid[i], my_nsegs[i], starts[i],
+                                       counts[i], buffer[i], &reqs[i]);
+        ERR
+    }
+
+    /* post read requests while still in define mode */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) cbuffer[i][j] = -1;
+        err = ncmpi_iget_varn_longlong(ncid, varid[i], my_nsegs[i], starts[i],
+                                       counts[i], cbuffer[i], &reqs[4+i]);
+        ERR
+    }
+
+    err = ncmpi_enddef(ncid); ERR
+
+    /* clear the file contents using a blocking API, before commit the
+     * nonblocking requests posted in define mode */
+    clear_file_contents(ncid, varid);
+    nerrs += check_num_pending_reqs(ncid, nreqs*2, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* all processes read entire variables back and check contents */
+    nerrs += check_contents_for_fail(ncid, varid, __LINE__);
+
+    /* commit read requests */
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs+4, sts);
+    ERRS(nreqs, sts)
+
+    err = ncmpi_close(ncid); ERR
+
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) {
+            if (cbuffer[i][j] != rank) {
+                printf("Error at line %d: expecting cbuffer[%d][%d]=%d but got %lld\n",
+                       __LINE__,i,j,rank,cbuffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
+    for (i=0; i<nreqs; i++) free(buffer[i]);
+
+    /* test flexible APIs ---------------------------------------------------*/
+    for (i=0; i<nreqs; i++) {
+        MPI_Type_vector(req_lens[i], 1, 2, MPI_LONG_LONG, &buftype[i]);
+        MPI_Type_commit(&buftype[i]);
+        buffer[i] = (long long*) malloc(req_lens[i] * 2 * sizeof(long long));
+        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank;
+        rbuffer[i] = (long long*) malloc(req_lens[i] * 2 * sizeof(long long));
+        for (j=0; j<req_lens[i]*2; j++) rbuffer[i][j] = -1;
+    }
+
+    /* create a new file for writing */
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]); ERR
+
+    /* write requests request while still in define mode */
+    for (i=0; i<4; i++) {
+        err = ncmpi_def_var(ncid, varname[i], NC_INT64, NDIMS, dimid, &varid[i]);
+        ERR
+
+        err = ncmpi_iput_varn(ncid, varid[i], my_nsegs[i], starts[i], counts[i],
+                              buffer[i], 1, buftype[i], &reqs[i]); ERR
+        ERR
+    }
+
+    /* test flexible get API, using a noncontiguous buftype */
+    for (i=0; i<nreqs; i++) {
+        err = ncmpi_iget_varn(ncid, varid[i], my_nsegs[i], starts[i], counts[i],
+                              rbuffer[i], 1, buftype[i], &reqs[i+4]);
+        ERR
+    }
+
+    for (i=0; i<nreqs; i++) MPI_Type_free(&buftype[i]);
+
+    /* read using a contiguous buffer. First swap back the starts[] and counts[].
+     * swap segment 0 with segment 2 and swap segment 1 with segment 3
+     */
+    for (i=0; i<nreqs; i++) {
+        permute(starts[i][0], starts[i][2]); permute(counts[i][0], counts[i][2]);
+        permute(starts[i][1], starts[i][3]); permute(counts[i][1], counts[i][3]);
+    }
+
+    for (i=0; i<bufsize; i++) cbuffer[0][i] = -1;
+    for (i=0; i<nreqs; i++) {
+        err = ncmpi_iget_varn_longlong(ncid, varid[i], my_nsegs[i], starts[i],
+                                       counts[i], cbuffer[i], &reqs[i+8]);
+        ERR
+    }
+
+    err = ncmpi_enddef(ncid); ERR
+
+    /* clear the file contents using a blocking API, before commit the
+     * nonblocking requests posted in define mode */
+    clear_file_contents(ncid, varid);
+    nerrs += check_num_pending_reqs(ncid, nreqs*3, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* all processes read entire variables back and check contents */
+    nerrs += check_contents_for_fail(ncid, varid, __LINE__);
+
+    /* flush nonblocking 1st batch read requests */
+    nerrs += check_num_pending_reqs(ncid, nreqs*2, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs+4, sts);
+    ERRS(nreqs, sts)
+
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]*2; j++) {
+            if (j%2 && rbuffer[i][j] != -1) {
+                printf("Error at line %d: expecting rbuffer[%d][%d]=-1 but got %lld\n",
+                       __LINE__,i,j,rbuffer[i][j]);
+                nerrs++;
+            }
+            if (j%2 == 0 && rbuffer[i][j] != rank) {
+                printf("Error at line %d: expecting rbuffer[%d][%d]=%d but got %lld\n",
+                       __LINE__,i,j,rank,rbuffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
+    /* flush nonblocking 2nd batch read requests */
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs+8, sts);
+    ERRS(nreqs, sts)
+
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) {
+            if (cbuffer[i][j] != rank) {
+                printf("Error at line %d: expecting buffer[%d][%d]=%d but got %lld\n",
+                       __LINE__,i,j,rank,cbuffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    if (bufsize>0) free(cbuffer[0]);
+    for (i=0; i<nreqs; i++) free(buffer[i]);
+    free(starts[0][0]);
+    free(counts[0][0]);
+    free(starts[0]);
+    free(counts[0]);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/nonblocking/i_varn_int64.c b/test/nonblocking/i_varn_int64.c
new file mode 100644
index 0000000..8dfa1a5
--- /dev/null
+++ b/test/nonblocking/i_varn_int64.c
@@ -0,0 +1,501 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: i_varn_int64.c 2219 2015-12-11 22:30:03Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example tests nonblocking varn APIs, including
+ * ncmpi_iput_varn_longlong(), ncmpi_iget_varn_longlong(), ncmpi_iput_varn(),
+ * and ncmpi_iget_varn().
+ * It first writes a sequence of requests with arbitrary array indices and
+ * lengths to four variables of type NC_INT64, and reads back.
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o i_varn_int64 i_varn_int64.c -lpnetcdf
+ *    % mpiexec -n 4 ./i_varn_int64 /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             Y = 4 ;
+ *             X = 10 ;
+ *    variables:
+ *            int64 var0(Y, X) ;
+ *            int64 var1(Y, X) ;
+ *            int64 var2(Y, X) ;
+ *            int64 var3(Y, X) ;
+ *    data:
+ *
+ *     var0 =
+ *      3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+ *      0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+ *      1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+ *      0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *
+ *     var1 =
+ *      2, 2, 2, 0, 0, 3, 3, 1, 0, 0,
+ *      3, 1, 1, 1, 2, 0, 0, 1, 1, 1,
+ *      0, 0, 1, 2, 2, 2, 3, 3, 0, 0,
+ *      3, 3, 3, 1, 0, 0, 0, 2, 2, 2 ;
+ *
+ *     var2 =
+ *      1, 1, 1, 3, 3, 2, 2, 0, 3, 3,
+ *      2, 0, 0, 0, 1, 3, 3, 0, 0, 0,
+ *      3, 3, 0, 1, 1, 1, 2, 2, 3, 3,
+ *      2, 2, 2, 0, 3, 3, 3, 1, 1, 1 ;
+ *
+ *     var3 =
+ *      0, 0, 0, 2, 2, 1, 1, 3, 2, 2,
+ *      1, 3, 3, 3, 0, 2, 2, 3, 3, 3,
+ *      2, 2, 3, 0, 0, 0, 1, 1, 2, 2,
+ *      1, 1, 1, 3, 2, 2, 2, 0, 0, 0 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+#define ERR \
+    if (err != NC_NOERR) { \
+        printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
+        nerrs++; \
+    }
+
+#define ERRS(n,a) { \
+    int _i; \
+    for (_i=0; _i<(n); _i++) { \
+        if ((a)[_i] != NC_NOERR) { \
+            printf("Error at line=%d: err[%d] %s\n", __LINE__, _i, \
+                   ncmpi_strerror((a)[_i])); \
+            nerrs++; \
+        } \
+    } \
+}
+
+static
+void clear_file_contents(int ncid, int *varid)
+{
+    int i, err, rank;
+    long long *w_buffer = (long long*) malloc(NY*NX * sizeof(long long));
+    for (i=0; i<NY*NX; i++) w_buffer[i] = -1;
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    for (i=0; i<4; i++) {
+        err = ncmpi_put_var_longlong_all(ncid, varid[i], w_buffer);
+        if (err != NC_NOERR) printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));
+    }
+    free(w_buffer);
+}
+
+static
+int check_contents_for_fail(int ncid, int *varid)
+{
+    /* all processes read entire variables back and check contents */
+    int i, j, err, nprocs;
+    long long expected[4][NY*NX] = {{3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+                                     0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+                                     1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+                                     0, 0, 0, 2, 1, 1, 1, 3, 3, 3},
+                                    {2, 2, 2, 0, 0, 3, 3, 1, 0, 0,
+                                     3, 1, 1, 1, 2, 0, 0, 1, 1, 1,
+                                     0, 0, 1, 2, 2, 2, 3, 3, 0, 0,
+                                     3, 3, 3, 1, 0, 0, 0, 2, 2, 2},
+                                    {1, 1, 1, 3, 3, 2, 2, 0, 3, 3,
+                                     2, 0, 0, 0, 1, 3, 3, 0, 0, 0,
+                                     3, 3, 0, 1, 1, 1, 2, 2, 3, 3,
+                                     2, 2, 2, 0, 3, 3, 3, 1, 1, 1},
+                                    {0, 0, 0, 2, 2, 1, 1, 3, 2, 2,
+                                     1, 3, 3, 3, 0, 2, 2, 3, 3, 3,
+                                     2, 2, 3, 0, 0, 0, 1, 1, 2, 2,
+                                     1, 1, 1, 3, 2, 2, 2, 0, 0, 0}};
+
+    long long *r_buffer = (long long*) malloc(NY*NX * sizeof(long long));
+
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    if (nprocs > 4) MPI_Barrier(MPI_COMM_WORLD);
+
+    for (i=0; i<4; i++) {
+        for (j=0; j<NY*NX; j++) r_buffer[j] = -1;
+        err = ncmpi_get_var_longlong_all(ncid, varid[i], r_buffer);
+        if (err != NC_NOERR) printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));
+
+        /* check if the contents of buf are expected */
+        for (j=0; j<NY*NX; j++) {
+            if (expected[i][j] >= nprocs) continue;
+            if (r_buffer[j] != expected[i][j]) {
+                printf("Expected read buf[%d][%d]=%lld, but got %lld\n",
+                       i,j,expected[i][j],r_buffer[j]);
+                free(r_buffer);
+                return 1;
+            }
+        }
+    }
+    free(r_buffer);
+    return 0;
+}
+
+static int
+check_num_pending_reqs(int ncid, int expected, int lineno)
+/* check if PnetCDF can reports expected number of pending requests */
+{
+    int err, n_pendings;
+    err = ncmpi_inq_nreqs(ncid, &n_pendings);
+    if (err != NC_NOERR) printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));
+    if (n_pendings != expected) {
+        printf("Error at line %d: expect %d pending requests but got %d\n",
+               lineno, expected, n_pendings);
+        return 1;
+    }
+    return 0;
+}
+
+/* swap two rows, a and b, of a 2D array */
+static
+void permute(MPI_Offset *a, MPI_Offset *b)
+{
+    int i;
+    MPI_Offset tmp;
+    for (i=0; i<NDIMS; i++) {
+        tmp = a[i]; a[i] = b[i]; b[i] = tmp;
+    }
+}
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int i, j, k, rank, nprocs, verbose=0, err, nerrs=0, bufsize=0;
+    int ncid, cmode, varid[4], dimid[2], nreqs, reqs[4], sts[4];
+    long long *buffer[4], *cbuffer[4];
+    int num_segs[4] = {4, 6, 5, 4};
+    int req_lens[4], my_nsegs[4];
+    MPI_Offset **starts[4], **counts[4];
+    MPI_Offset n_starts[4][6][2] = {{{0,5}, {1,0}, {2,6}, {3,0}, {0,0}, {0,0}},
+                                    {{0,3}, {0,8}, {1,5}, {2,0}, {2,8}, {3,4}},
+                                    {{0,7}, {1,1}, {1,7}, {2,2}, {3,3}, {0,0}},
+                                    {{0,0}, {1,4}, {2,3}, {3,7}, {0,0}, {0,0}}};
+    MPI_Offset n_counts[4][6][2] = {{{1,2}, {1,1}, {1,2}, {1,3}, {0,0}, {0,0}},
+                                    {{1,2}, {1,2}, {1,2}, {1,2}, {1,2}, {1,3}},
+                                    {{1,1}, {1,3}, {1,3}, {1,1}, {1,1}, {0,0}},
+                                    {{1,3}, {1,1}, {1,3}, {1,3}, {0,0}, {0,0}}};
+
+    /* n_starts[0][][] n_counts[0][][] indicate the following: ("-" means skip)
+              -  -  -  -  -  X  X  -  -  - 
+              X  -  -  -  -  -  -  -  -  - 
+              -  -  -  -  -  -  X  X  -  - 
+              X  X  X  -  -  -  -  -  -  - 
+       n_starts[1][][] n_counts[1][][] indicate the following pattern.
+              -  -  -  X  X  -  -  -  X  X 
+              -  -  -  -  -  X  X  -  -  - 
+              X  X  -  -  -  -  -  -  X  X 
+              -  -  -  -  X  X  X  -  -  - 
+       n_starts[2][][] n_counts[2][][] indicate the following pattern.
+              -  -  -  -  -  -  -  X  -  - 
+              -  X  X  X  -  -  -  X  X  X 
+              -  -  X  -  -  -  -  -  -  - 
+              -  -  -  X  -  -  -  -  -  - 
+       n_starts[3][][] n_counts[3][][] indicate the following pattern.
+              X  X  X  -  -  -  -  -  -  - 
+              -  -  -  -  X  -  -  -  -  - 
+              -  -  -  X  X  X  -  -  -  - 
+              -  -  -  -  -  -  -  X  X  X 
+     */
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for iput/iget varn ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    if (verbose && nprocs != 4 && rank == 0)
+        printf("Warning: %s is intended to run on 4 processes\n",argv[0]);
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_INT64, NDIMS, dimid, &varid[0]); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT64, NDIMS, dimid, &varid[1]); ERR
+    err = ncmpi_def_var(ncid, "var2", NC_INT64, NDIMS, dimid, &varid[2]); ERR
+    err = ncmpi_def_var(ncid, "var3", NC_INT64, NDIMS, dimid, &varid[3]); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* allocate space for starts and counts */
+    starts[0] = (MPI_Offset**) malloc(4 * 6 * sizeof(MPI_Offset*));
+    counts[0] = (MPI_Offset**) malloc(4 * 6 * sizeof(MPI_Offset*));
+    starts[0][0] = (MPI_Offset*) calloc(4 * 6 * NDIMS, sizeof(MPI_Offset));
+    counts[0][0] = (MPI_Offset*) calloc(4 * 6 * NDIMS, sizeof(MPI_Offset));
+    for (i=1; i<4; i++) {
+        starts[i] = starts[i-1] + 6;
+        counts[i] = counts[i-1] + 6;
+        starts[i][0] = starts[i-1][0] + 6 * NDIMS;
+        counts[i][0] = counts[i-1][0] + 6 * NDIMS;
+    }
+    for (i=0; i<4; i++) {
+        for (j=1; j<6; j++) {
+            starts[i][j] = starts[i][j-1] + NDIMS;
+            counts[i][j] = counts[i][j-1] + NDIMS;
+        }
+    }
+
+    /* set values for starts and counts */
+    for (i=0; i<4; i++) {
+        int n = (i + rank) % 4;
+        my_nsegs[i] = num_segs[n]; /* number of segments for this request */
+        for (j=0; j<6; j++) {
+            for (k=0; k<NDIMS; k++) {
+                starts[i][j][k] = n_starts[n][j][k];
+                counts[i][j][k] = n_counts[n][j][k];
+            }
+        }
+    }
+
+    /* test error code: NC_ENULLSTART */
+    err = ncmpi_iput_varn_longlong(ncid, varid[0], 1, NULL, NULL,
+                                   NULL, &reqs[0]);
+    if (err != NC_ENULLSTART) {
+        printf("expecting error code NC_ENULLSTART but got %s\n",
+               nc_err_code_name(err));
+        nerrs++;
+    }
+
+    /* only rank 0, 1, 2, and 3 do I/O:
+     * each of ranks 0 to 3 write 4 nonblocking requests */
+    nreqs = 4;
+    if (rank >= 4) nreqs = 0;
+
+    /* calculate length of each varn request and allocate write buffer */
+    for (i=0; i<nreqs; i++) {
+        req_lens[i] = 0; /* total length this request */
+        for (j=0; j<my_nsegs[i]; j++) {
+            MPI_Offset req_len=1;
+            for (k=0; k<NDIMS; k++)
+                req_len *= counts[i][j][k];
+            req_lens[i] += req_len;
+        }
+        if (verbose) printf("req_lens[%d]=%d\n",i,req_lens[i]);
+
+        /* allocate I/O buffer and initialize its contents */
+        buffer[i] = (long long*) malloc(req_lens[i] * sizeof(long long));
+        for (j=0; j<req_lens[i]; j++) buffer[i][j] = rank;
+    }
+
+    /* write using varn API */
+    clear_file_contents(ncid, varid);
+    for (i=0; i<nreqs; i++) {
+        err = ncmpi_iput_varn_longlong(ncid, varid[i], my_nsegs[i], starts[i],
+                                       counts[i], buffer[i], &reqs[i]);
+        ERR
+    }
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* all processes read entire variables back and check contents */
+    nerrs += check_contents_for_fail(ncid, varid);
+
+    /* try with buffer being a single contiguous space */
+    for (i=0; i<nreqs; i++) bufsize += req_lens[i];
+    if (bufsize>0) cbuffer[0] = (long long*) malloc(bufsize * sizeof(long long));
+    for (i=1; i<nreqs; i++) cbuffer[i] = cbuffer[i-1] + req_lens[i-1];
+    for (i=0; i<bufsize; i++) cbuffer[0][i] = rank;
+
+    /* write usning varn API */
+    clear_file_contents(ncid, varid);
+    for (i=0; i<nreqs; i++) {
+        err = ncmpi_iput_varn_longlong(ncid, varid[i], my_nsegs[i], starts[i],
+                                       counts[i], cbuffer[i], &reqs[i]);
+        ERR
+    }
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* all processes read entire variables back and check contents */
+    nerrs += check_contents_for_fail(ncid, varid);
+
+    /* permute write order: so starts[*] are not in an increasing order:
+     * swap segment 0 with segment 2 and swap segment 1 with segment 3
+     */
+    for (i=0; i<nreqs; i++) {
+        permute(starts[i][0], starts[i][2]); permute(counts[i][0], counts[i][2]);
+        permute(starts[i][1], starts[i][3]); permute(counts[i][1], counts[i][3]);
+    }
+
+    /* write usning varn API */
+    clear_file_contents(ncid, varid);
+    for (i=0; i<nreqs; i++) {
+        err = ncmpi_iput_varn_longlong(ncid, varid[i], my_nsegs[i], starts[i],
+                                       counts[i], buffer[i], &reqs[i]);
+        ERR
+    }
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* all processes read entire variables back and check contents */
+    nerrs += check_contents_for_fail(ncid, varid);
+
+    /* read using get_varn API and check contents */
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) buffer[i][j] = -1;
+        err = ncmpi_iget_varn_longlong(ncid, varid[i], my_nsegs[i], starts[i],
+                                       counts[i], buffer[i], &reqs[i]);
+        ERR
+    }
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) {
+            if (buffer[i][j] != rank) {
+                printf("Error at line %d: expecting buffer[%d][%d]=%d but got %lld\n",
+                       __LINE__,i,j,rank,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
+    for (i=0; i<nreqs; i++) free(buffer[i]);
+
+    /* test flexible put API, using a noncontiguous buftype */
+    clear_file_contents(ncid, varid);
+    for (i=0; i<nreqs; i++) {
+        MPI_Datatype buftype;
+        MPI_Type_vector(req_lens[i], 1, 2, MPI_LONG_LONG, &buftype);
+        MPI_Type_commit(&buftype);
+        buffer[i] = (long long*) malloc(req_lens[i] * 2 * sizeof(long long));
+        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = rank;
+
+        err = ncmpi_iput_varn(ncid, varid[i], my_nsegs[i], starts[i],
+                              counts[i], buffer[i], 1, buftype, &reqs[i]);
+        ERR
+        MPI_Type_free(&buftype);
+    }
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    /* all processes read entire variables back and check contents */
+    nerrs += check_contents_for_fail(ncid, varid);
+
+    /* test flexible get API, using a noncontiguous buftype */
+    for (i=0; i<nreqs; i++) {
+        MPI_Datatype buftype;
+        MPI_Type_vector(req_lens[i], 1, 2, MPI_LONG_LONG, &buftype);
+        MPI_Type_commit(&buftype);
+        for (j=0; j<req_lens[i]*2; j++) buffer[i][j] = -1;
+        err = ncmpi_iget_varn(ncid, varid[i], my_nsegs[i], starts[i],
+                              counts[i], buffer[i], 1, buftype, &reqs[i]);
+        ERR
+        MPI_Type_free(&buftype);
+    }
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]*2; j++) {
+            if (j%2 && buffer[i][j] != -1) {
+                printf("Error at line %d: expecting buffer[%d][%d]=-1 but got %lld\n",
+                       __LINE__,i,j,buffer[i][j]);
+                nerrs++;
+            }
+            if (j%2 == 0 && buffer[i][j] != rank) {
+                printf("Error at line %d: expecting buffer[%d][%d]=%d but got %lld\n",
+                       __LINE__,i,j,rank,buffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
+    /* read back using a contiguous buffer. First swap back the starts[] and counts[].
+     * swap segment 0 with segment 2 and swap segment 1 with segment 3
+     */
+    for (i=0; i<nreqs; i++) {
+        permute(starts[i][0], starts[i][2]); permute(counts[i][0], counts[i][2]);
+        permute(starts[i][1], starts[i][3]); permute(counts[i][1], counts[i][3]);
+    }
+
+    for (i=0; i<bufsize; i++) cbuffer[0][i] = -1;
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) buffer[i][j] = -1;
+        err = ncmpi_iget_varn_longlong(ncid, varid[i], my_nsegs[i], starts[i],
+                                       counts[i], cbuffer[i], &reqs[i]);
+        ERR
+    }
+    nerrs += check_num_pending_reqs(ncid, nreqs, __LINE__);
+    err = ncmpi_wait_all(ncid, nreqs, reqs, sts);
+    ERRS(nreqs, sts)
+
+    for (i=0; i<nreqs; i++) {
+        for (j=0; j<req_lens[i]; j++) {
+            if (cbuffer[i][j] != rank) {
+                printf("Error at line %d: expecting buffer[%d][%d]=%d but got %lld\n",
+                       __LINE__,i,j,rank,cbuffer[i][j]);
+                nerrs++;
+            }
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    if (bufsize>0) free(cbuffer[0]);
+    for (i=0; i<nreqs; i++) free(buffer[i]);
+    free(starts[0][0]);
+    free(counts[0][0]);
+    free(starts[0]);
+    free(counts[0]);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/nonblocking/interleaved.c b/test/nonblocking/interleaved.c
new file mode 100644
index 0000000..23cc18d
--- /dev/null
+++ b/test/nonblocking/interleaved.c
@@ -0,0 +1,195 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: interleaved.c 2133 2015-09-26 19:16:01Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This program tests nonblocking APIs for handling interleaved file types.
+ * It makes 3 calls to ncmpi_iput_vara_int(), where the first 2 interleaved and
+ * the third one does not.
+ * It first defines a netCDF variable of size 10 x 20.
+ * First  write: a subarray of size 3 x 5 at the start offsets of 6 x 8
+ * Second write: a subarray of size 2 x 5 at the start offsets of 6 x 13
+ * Third  write: a subarray of size 1 x 5 at the start offsets of 8 x 13
+ *
+ * % mpiexec -n 1 ./interleaved
+ * % ncmpidump testfile.nc
+ * netcdf testfile {
+ * // file format: CDF-5 (big variables)
+ * dimensions:
+ * 	Y = 10 ;
+ * 	X = 20 ;
+ * variables:
+ * 	int var(Y, X) ;
+ * data:
+ *
+ *  var =
+ *   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ *   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ *   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ *   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ *   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ *   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ *   -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -1, -1,
+ *   -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -1, -1,
+ *   -1, -1, -1, -1, -1, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1,
+ *   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ;
+ * }
+ *
+
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 10
+#define NX 20
+
+#define ERR if (err!=NC_NOERR) {printf("Error at line %d: %s\n", __LINE__,ncmpi_strerror(err)); exit(-1);}
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int i, j, rank, nprocs, err, nerrs=0, expected;
+    int ncid, cmode, varid, dimid[2], req[3], st[3], *buf;
+    MPI_Offset start[2], count[2];
+    MPI_Info info;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* this program is intended to run on one process */
+    if (rank) goto fn_exit;
+
+    /* get command-line arguments */
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for writing interleaved fileviews ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    MPI_Info_create(&info);
+    MPI_Info_set(info, "romio_cb_write", "disable");
+    MPI_Info_set(info, "ind_wr_buffer_size", "8");
+    /* these 2 hints are required to cause a core dump if r1758 fix is not
+     * presented */
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_SELF, filename, cmode, info, &ncid);
+    ERR
+
+    MPI_Info_free(&info);
+
+    /* define dimensions Y and X */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]);
+    ERR
+
+    /* define a 2D variable of integer type */
+    err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimid, &varid);
+    ERR
+
+    /* do not forget to exit define mode */
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* now we are in data mode */
+    buf = (int*) malloc(NY*NX * sizeof(int));
+    for (i=0; i<NY*NX; i++) buf[i] = -1;
+
+    /* fill the entire array with -1s */
+    err = ncmpi_put_var_int_all(ncid, varid, buf); ERR
+
+    /* rearrange buffer contents, as buf is 2D */
+    for (i=0;  i<5;  i++) buf[i] = 10 + i;
+    for (i=5;  i<10; i++) buf[i] = 10 + i +  5;
+    for (i=10; i<15; i++) buf[i] = 10 + i + 10;
+    start[0] = 6; start[1] = 8;
+    count[0] = 3; count[1] = 5;
+    err = ncmpi_iput_vara_int(ncid, varid, start, count, buf, &req[0]);
+    ERR
+
+    for (i=15; i<20; i++) buf[i] = 10 + i - 10;
+    for (i=20; i<25; i++) buf[i] = 10 + i -  5;
+    start[0] = 6; start[1] = 13;
+    count[0] = 2; count[1] = 5;
+    err = ncmpi_iput_vara_int(ncid, varid, start, count, buf+15, &req[1]);
+    ERR
+
+    for (i=25; i<30; i++) buf[i] = 10 + i;
+    start[0] = 8; start[1] = 13;
+    count[0] = 1; count[1] = 5;
+    err = ncmpi_iput_vara_int(ncid, varid, start, count, buf+25, &req[2]);
+    ERR
+
+    err = ncmpi_wait_all(ncid, 3, req, st);
+    ERR
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    /* open the same file and read back for validate */
+    err = ncmpi_open(MPI_COMM_SELF, filename, NC_NOWRITE, MPI_INFO_NULL,
+                     &ncid); ERR
+
+    err = ncmpi_inq_varid(ncid, "var", &varid); ERR
+
+    /* initialize the contents of the array to a different value */
+    for (i=0; i<NY*NX; i++) buf[i] = -1;
+
+    /* read the entire array */
+    err = ncmpi_get_var_int_all(ncid, varid, buf); ERR
+
+    /* check if the contents of buf are expected */
+    expected = 10;
+    for (j=6; j<9; j++) {
+        for (i=8; i<18; i++) {
+            if (buf[j*NX+i] != expected) {
+                printf("%d: Unexpected read buf[%d]=%d, should be %d\n",
+                       rank, i, buf[j*NX+i], expected);
+                nerrs++;
+            }
+            expected++;
+        }
+    }
+
+    err = ncmpi_close(ncid); ERR
+
+    free(buf);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR && malloc_size > 0)
+        printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n", malloc_size);
+
+fn_exit:
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/nonblocking/mcoll_perf.c b/test/nonblocking/mcoll_perf.c
new file mode 100644
index 0000000..fe50e0f
--- /dev/null
+++ b/test/nonblocking/mcoll_perf.c
@@ -0,0 +1,685 @@
+/* -*- Mode: C; c-basic-offset:4 ; -*- */
+/*  
+ *  (C) 2001 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ *
+ *  $Id: mcoll_perf.c 2150 2015-10-10 05:52:57Z wkliao $
+ */
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pnetcdf.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <testutils.h>
+
+/* The file name is taken as a command-line argument. */
+
+static int verbose;
+static int nerrs;
+
+/* Measures the I/O bandwidth for writing/reading a 3D
+   block-distributed array to a file corresponding to the global array
+   in row-major (C) order.
+   Note that the file access pattern is noncontiguous.
+  
+   Array size 128^3. For other array sizes, change array_of_gsizes below.*/
+#define HANDLE_ERROR                                      \
+    if (status != NC_NOERR) {                             \
+        printf("Error: func=%s line=%d err=%s\n",         \
+               __func__,__LINE__,ncmpi_strerror(status)); \
+        nerrs++;                                        \
+    }
+
+#define HANDLE_DIFF(str) {                                       \
+    int doStop, isDiff = (str[0] == '\0') ? 0 : 1;               \
+    MPI_Allreduce(&isDiff, &doStop, 1, MPI_INT, MPI_MAX, comm);  \
+    if (doStop) {                                                \
+        printf("P%d: diff at line %d (%s)\n",rank,__LINE__,str); \
+        MPI_Finalize();                                          \
+        exit(1);                                                 \
+    }                                                            \
+}
+
+#define CHECK_GLOBAL_ATT_DIFF(type, func, nctype) {                          \
+    int   pos, len = attlen1 * sizeof(type);                                 \
+    type *b1 = (type *)malloc(len);                                          \
+    type *b2 = (type *)malloc(len);                                          \
+    status = func(ncid1, NC_GLOBAL, name1, b1);                              \
+    HANDLE_ERROR                                                             \
+    status = func(ncid2, NC_GLOBAL, name2, b2);                              \
+    HANDLE_ERROR                                                             \
+    if ((pos = memcmp(b1, b2, len)) != 0) {                                  \
+        printf("P%d: diff at line %d (attribute[%d] %s: %s buf1 != buf2 at position %d)\n", \
+               rank,__LINE__,i,name1,#nctype,pos);                           \
+        nerrs++;                                                           \
+    }                                                                        \
+    free(b1);                                                                \
+    free(b2);                                                                \
+    break;                                                                   \
+}
+
+#define CHECK_VAR_ATT_DIFF(type, func, nctype) {                             \
+    int   pos, len = attlen1 * sizeof(type);                                 \
+    type *b1 = (type *)malloc(len);                                          \
+    type *b2 = (type *)malloc(len);                                          \
+    status = func(ncid1, i, name1, b1);                                      \
+    HANDLE_ERROR                                                             \
+    status = func(ncid2, i, name2, b2);                                      \
+    HANDLE_ERROR                                                             \
+    if ((pos = memcmp(b1, b2, len)) != 0) {                                  \
+        printf("P%d: diff at line %d (variable[%d] %s: attribute[%d] %s: %s buf1 != buf2 at position %d)\n", \
+               rank,__LINE__,i,name,j,name1,#nctype,pos);                    \
+        nerrs++;                                                           \
+    }                                                                        \
+    free(b1);                                                                \
+    free(b2);                                                                \
+    break;                                                                   \
+}
+
+
+#define CHECK_VAR_DIFF(type, func, nctype) {                                 \
+    int   pos, len = varsize * sizeof(type);                                 \
+    type *b1 = (type *)malloc(len);                                          \
+    type *b2 = (type *)malloc(len);                                          \
+    status = func(ncid1, i, start, shape, b1);                               \
+    HANDLE_ERROR                                                             \
+    status = func(ncid2, i, start, shape, b2);                               \
+    HANDLE_ERROR                                                             \
+    if ((pos = memcmp(b1, b2, len)) != 0) {                                  \
+        printf("P%d: diff at line %d variable[%d] %s: %s buf1 != buf2 at position %d)\n", \
+               rank,__LINE__,i,name,#nctype,pos);                            \
+        nerrs++;                                                           \
+    }                                                                        \
+    free(b1);                                                                \
+    free(b2);                                                                \
+    break;                                                                   \
+}
+
+
+static
+int ncmpi_diff(char *filename1, char *filename2) {
+    int i, j, status, rank, nprocs;
+    int ncid1, ndims1, nvars1, natts1, unlimdimid1, dimids1[NC_MAX_DIMS];
+    int ncid2, ndims2, nvars2, natts2, unlimdimid2, dimids2[NC_MAX_DIMS];
+    char str[512], name1[NC_MAX_NAME], name2[NC_MAX_NAME], name[NC_MAX_NAME];
+    MPI_Offset shape[NC_MAX_VAR_DIMS], varsize, start[NC_MAX_VAR_DIMS];
+    MPI_Offset attlen1, dimlen1, attlen2, dimlen2;
+    nc_type type1, type2;
+    MPI_Comm comm=MPI_COMM_WORLD;
+
+    MPI_Comm_size(comm, &nprocs);
+    MPI_Comm_rank(comm, &rank);
+
+    str[0] = '\0';
+    status = ncmpi_open(comm, filename1, NC_NOWRITE, MPI_INFO_NULL, &ncid1);
+    HANDLE_ERROR
+    status = ncmpi_open(comm, filename2, NC_NOWRITE, MPI_INFO_NULL, &ncid2);
+    HANDLE_ERROR
+
+    /**
+     * Inquire the dataset definitions of input dataset AND
+     * Add dataset definitions for output dataset.
+     */
+    status = ncmpi_inq(ncid1, &ndims1, &nvars1, &natts1, &unlimdimid1);
+    HANDLE_ERROR
+    status = ncmpi_inq(ncid2, &ndims2, &nvars2, &natts2, &unlimdimid2);
+    HANDLE_ERROR
+    if (ndims1 != ndims2)
+        sprintf(str,"ndims1(%d) != ndims2(%d)",ndims1, ndims2);
+    HANDLE_DIFF(str)
+    if (nvars1 != nvars2)
+        sprintf(str,"nvars1(%d) != nvars2(%d)",nvars1, nvars2);
+    HANDLE_DIFF(str)
+    if (natts1 != natts2)
+        sprintf(str,"natts1(%d) != natts2(%d)",natts1, natts2);
+    HANDLE_DIFF(str)
+
+    /* Inquire global attributes, assume CHAR attributes. */
+    for (i=0; i<natts1; i++) {
+        status = ncmpi_inq_attname(ncid1, NC_GLOBAL, i, name1);
+        HANDLE_ERROR
+        status = ncmpi_inq_attname(ncid1, NC_GLOBAL, i, name2);
+        HANDLE_ERROR
+        if (strcmp(name1, name2) != 0)
+            sprintf(str,"attribute[%d] name1(%s) != name2(%s)",i,name1,name2);
+        HANDLE_DIFF(str)
+
+        status = ncmpi_inq_att(ncid1, NC_GLOBAL, name1, &type1, &attlen1);
+        HANDLE_ERROR
+        status = ncmpi_inq_att(ncid2, NC_GLOBAL, name2, &type2, &attlen2);
+        HANDLE_ERROR
+        if (type1 != type2)
+            sprintf(str,"attribute[%d] %s: type1(%d) != type2(%d)",i,name1,type1,type2);
+        HANDLE_DIFF(str)
+        if (attlen1 != attlen2)
+            sprintf(str,"attribute[%d] %s: attlen1(%lld) != attlen2(%lld)",i,name1, attlen1, attlen2);
+        HANDLE_DIFF(str)
+        switch (type1) {
+            case NC_CHAR:   CHECK_GLOBAL_ATT_DIFF(char,   ncmpi_get_att_text,   NC_CHAR)
+            case NC_SHORT:  CHECK_GLOBAL_ATT_DIFF(short,  ncmpi_get_att_short,  NC_SHORT)
+            case NC_INT:    CHECK_GLOBAL_ATT_DIFF(int,    ncmpi_get_att_int,    NC_INT)
+            case NC_FLOAT:  CHECK_GLOBAL_ATT_DIFF(float,  ncmpi_get_att_float,  NC_FLOAT)
+            case NC_DOUBLE: CHECK_GLOBAL_ATT_DIFF(double, ncmpi_get_att_double, NC_DOUBLE)
+            default: ; /* TODO: handle unexpected types */
+        }
+    }
+
+    /* Inquire dimension */
+    for (i=0; i<ndims1; i++) {
+        status = ncmpi_inq_dim(ncid1, i, name1, &dimlen1);
+        HANDLE_ERROR
+        status = ncmpi_inq_dim(ncid2, i, name2, &dimlen2);
+        HANDLE_ERROR
+        if (dimlen1 != dimlen2)
+            sprintf(str,"dimension[%d] %s: dimlen1(%lld) != dimlen2(%lld)",i,name1,dimlen1,dimlen2);
+        HANDLE_DIFF(str)
+    }
+
+    /* Inquire variables */
+    for (i=0; i<nvars1; i++) {
+        status = ncmpi_inq_var(ncid1, i, name1, &type1, &ndims1, dimids1, &natts1);
+        HANDLE_ERROR
+        status = ncmpi_inq_var(ncid2, i, name2, &type2, &ndims2, dimids2, &natts2);
+        HANDLE_ERROR
+        if (strcmp(name1, name2) != 0)
+            sprintf(str,"variable[%d]: name1(%s) != name2(%s)",i,name1,name2);
+        HANDLE_DIFF(str)
+        if (type1 != type2)
+            sprintf(str,"variable[%d] %s: type1(%d) != type2(%d)",i,name1,type1,type2);
+        HANDLE_DIFF(str)
+        if (ndims1 != ndims2)
+            sprintf(str,"variable[%d] %s: ndims1(%d) != ndims2(%d)",i,name1,ndims1,ndims2);
+        HANDLE_DIFF(str)
+        for (j=0; j<ndims1; j++) {
+            if (dimids1[j] != dimids2[j])
+                sprintf(str,"variable[%d] %s: dimids1[%d]=%d != dimids2[%d]=%d",i,name1,j,dimids1[j],j,dimids2[j]);
+            HANDLE_DIFF(str)
+        }
+        if (natts1 != natts2)
+            sprintf(str,"variable[%d] %s: natts1(%d) != natts2(%d)",i,name1,natts1,natts2);
+        HANDLE_DIFF(str)
+
+        strcpy(name,name1);
+
+        /* var attributes, assume CHAR attributes */
+        for (j=0; j<natts1; j++) {
+            status = ncmpi_inq_attname(ncid1, i, j, name1);
+            HANDLE_ERROR
+            status = ncmpi_inq_attname(ncid2, i, j, name2);
+            HANDLE_ERROR
+            if (strcmp(name1, name2) != 0)
+                sprintf(str,"variable[%d] %s: attr name[%d] (%s) != (%s)",i,name,j,name1,name2);
+            HANDLE_DIFF(str)
+
+            status = ncmpi_inq_att(ncid1, i, name1, &type1, &attlen1);
+            HANDLE_ERROR
+            status = ncmpi_inq_att(ncid2, i, name2, &type2, &attlen2);
+            HANDLE_ERROR
+            if (type1 != type2)
+                sprintf(str,"variable[%d] %s: attr type[%d] (%d) != (%d)",i,name,j,type1,type2);
+            HANDLE_DIFF(str)
+            if (attlen1 != attlen2)
+                sprintf(str,"variable[%d] %s: attr attlen[%d] (%lld) != (%lld)",i,name,j, attlen1, attlen2);
+            HANDLE_DIFF(str)
+
+            switch (type1) {
+                case NC_CHAR:   CHECK_VAR_ATT_DIFF(char,   ncmpi_get_att_text,   NC_CHAR)
+                case NC_SHORT:  CHECK_VAR_ATT_DIFF(short,  ncmpi_get_att_short,  NC_SHORT)
+                case NC_INT:    CHECK_VAR_ATT_DIFF(int,    ncmpi_get_att_int,    NC_INT)
+                case NC_FLOAT:  CHECK_VAR_ATT_DIFF(float,  ncmpi_get_att_float,  NC_FLOAT)
+                case NC_DOUBLE: CHECK_VAR_ATT_DIFF(double, ncmpi_get_att_double, NC_DOUBLE)
+                default: ; /* TODO: handle unexpected types */
+            }
+        }
+    }
+
+    /**
+     * Read data of variables from input dataset 
+     * (ONLY DEAL WITH: NC_INT, NC_FLOAT, NC_DOUBLE for now)
+     * Write the data out to the corresponding variables in the output dataset
+     *
+     *  Data Partition (Assume 4 processors):
+     *   square: 2-D, (Block, *), 25*100 from 100*100
+     *   cube:   3-D, (Block, *, *), 25*100*100 from 100*100*100
+     *   xytime: 3-D, (Block, *, *), 25*100*100 from 100*100*100
+     *   time:   1-D, Block-wise, 25 from 100
+     *
+     *  Data Mode API: collective
+     */
+
+    for (i=0; i<NC_MAX_VAR_DIMS; i++)
+        start[i] = 0;
+
+    for (i=0; i<nvars1; i++) {
+        varsize = 1;
+        status = ncmpi_inq_var(ncid1, i, name1, &type1, &ndims1, dimids1, &natts1);
+        HANDLE_ERROR
+        strcpy(name,name1);
+        for (j=0; j<ndims1; j++) {
+            status = ncmpi_inq_dim(ncid1, dimids1[j], name2, shape + j);
+            HANDLE_ERROR
+            /* name2 will be discarded */
+            if (j == 0) {
+                shape[j] /= nprocs;
+                start[j] = shape[j] * rank;
+            }
+            varsize *= shape[j];
+        }
+        switch (type1) {
+            case NC_CHAR:   CHECK_VAR_DIFF(char,   ncmpi_get_vara_text_all,   NC_CHAR)
+            case NC_SHORT:  CHECK_VAR_DIFF(short,  ncmpi_get_vara_short_all,  NC_SHORT)
+            case NC_INT:    CHECK_VAR_DIFF(int,    ncmpi_get_vara_int_all,    NC_INT)
+            case NC_FLOAT:  CHECK_VAR_DIFF(float,  ncmpi_get_vara_float_all,  NC_FLOAT)
+            case NC_DOUBLE: CHECK_VAR_DIFF(double, ncmpi_get_vara_double_all, NC_DOUBLE)
+            default: ; /* TODO: handle unexpected types */
+        }
+    }
+
+    status = ncmpi_close(ncid1);
+    HANDLE_ERROR
+    status = ncmpi_close(ncid2);
+    HANDLE_ERROR
+
+    return NC_NOERR;
+}
+
+
+int main(int argc, char **argv)
+{
+    int i, j, array_of_gsizes[3];
+    int nprocs, **buf, rank;
+    MPI_Offset bufcount;
+    int array_of_psizes[3];
+    int status;
+    MPI_Offset array_of_starts[3], stride[3];
+    char basename[256], filename[256];
+    char filename1[256], filename2[256], filename3[256];
+    char dimname[20], varname[20];
+    int ncid, dimids0[3], dimids1[3], rank_dim[3], *varid;
+    MPI_Info info;
+    MPI_Offset **starts, **counts;
+    MPI_Offset *bufcounts;
+    int ndims = 3;
+    int nvars = 10;
+    int k;
+    MPI_Datatype *datatype_list;
+    int length;
+    int *reqs;
+    int *sts;
+    int *buf_var;
+/*
+    int buf_var[32] ={1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2,
+                      3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4};
+*/
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    nerrs = 0;
+    verbose = 0;
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [file base name]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(basename, "testfile.nc");
+    if (argc == 2) strcpy(basename, argv[1]);
+    MPI_Bcast(basename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for mput/iput APIs ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    length = 2;
+    array_of_gsizes[0] = array_of_gsizes[1] = array_of_gsizes[2] = length;
+
+    nvars = 4;
+
+    buf = (int **)malloc(nvars*sizeof(int*));
+    if (buf == NULL){
+        printf("buf malloc error\n");
+        return 0;
+    }
+    bufcounts = (MPI_Offset *)malloc(nvars*sizeof(MPI_Offset));
+    if (bufcounts == NULL){
+        printf("bufcounts malloc error\n");
+        return 0;
+    }
+    starts = (MPI_Offset **)malloc(nvars*sizeof(MPI_Offset *));
+    if (starts== NULL){
+        printf("starts malloc error\n");
+        return 0;
+    }
+    counts = (MPI_Offset **)malloc(nvars*sizeof(MPI_Offset *));
+    if (counts == NULL){
+        printf("counts malloc error\n");
+        return 0;
+    }
+    datatype_list = (MPI_Datatype*)malloc(nvars*sizeof(MPI_Datatype));
+    if (datatype_list == NULL){
+        printf("counts malloc error\n");
+        return 0;
+    }
+    
+    reqs = (int *)malloc(nvars*sizeof(int));
+    sts = (int *)malloc(nvars*sizeof(int));
+    
+    for (i=0; i<nvars; i++) {
+        starts[i] = (MPI_Offset *)malloc(ndims*sizeof(MPI_Offset));
+        if (starts[i] == NULL){
+            printf("starts[%d] malloc error\n", i);
+            return 0;
+        }
+        counts[i] = (MPI_Offset *)malloc(ndims*sizeof(MPI_Offset));
+        if (counts[i] == NULL){
+            printf("counts[%d] malloc error\n", i);
+            return 0;
+        }
+    }
+  
+    bufcount = 1;
+    for (i=0; i<ndims; i++) {
+        array_of_psizes[i] = 0;
+        bufcount *= length;
+    }
+    MPI_Dims_create(nprocs, ndims, array_of_psizes);
+
+    /* subarray in each process is len x len x len */
+    for (i=0; i<ndims; i++)
+        array_of_gsizes[i] = length * array_of_psizes[i];
+
+    /* mynd's process rank in each dimension (in MPI_ORDER_C) */
+    rank_dim[2] =  rank %  array_of_psizes[2];
+    rank_dim[1] = (rank /  array_of_psizes[2]) % array_of_psizes[1];
+    rank_dim[0] =  rank / (array_of_psizes[2]  * array_of_psizes[1]);
+
+    /* starting coordinates of the subarray in each dimension */
+    for (i=0; i<ndims; i++)
+        array_of_starts[i] = length * rank_dim[i];
+
+    for (i=0; i<nvars; i++) {
+        for (j=0; j<ndims; j++) {
+           starts[i][j] = array_of_starts[j];
+           counts[i][j]  = length;
+        }
+        bufcounts[i] = bufcount;
+        datatype_list[i] = MPI_INT;
+    }
+
+    buf[0] = (int *) malloc(bufcount * nvars * sizeof(int));
+    if (buf[0] == NULL) {
+        printf("buf[i]malloc error\n");
+        return 0;
+    }
+    for (i=1; i<nvars; i++) buf[i] = buf[i-1] + bufcount;
+
+    for (i=0; i<nvars; i++) {
+        for (j=0; j<bufcount; j++)
+            buf[i][j]=rank+1;
+    }
+    buf_var = (int *) malloc(bufcount*nprocs*sizeof(int));
+    for (i=0; i<bufcount*nprocs; i++)
+        buf_var[i] = rank + 1;  
+
+    int nvars2 = (nvars > nprocs) ? nvars : nprocs;
+    varid = (int *)malloc(nvars2*sizeof(int));
+    if (varid == NULL){
+        printf("varid malloc error\n");
+        return 0;
+    }
+    MPI_Info_create(&info);
+/*
+    MPI_Info_set(info, "romio_pvfs2_posix_write", "enable");
+    MPI_Info_set(info, "group_cyclic_fd", "enable");
+    MPI_Info_set(info, "cb_buffer_size", "1024");
+    MPI_Info_set(info, "cb_buffer_size", "16777216");
+    MPI_Info_set(info, "romio_no_indep_rw", "true");
+    MPI_Info_set(info, "romio_cb_write", "true");
+ */
+    for (k=0; k<=9; k++){
+        sprintf(filename, "%s.%d.%d.%d.nc", basename, length, nvars, k);
+        if (k==0)
+            strcpy(filename1, filename);
+        else if (k==7)
+            strcpy(filename2, filename);
+        else 
+            strcpy(filename3, filename);
+
+        status = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER|NC_64BIT_OFFSET,
+                              info, &ncid);
+        HANDLE_ERROR
+        /* define dimensions */
+        for (i=0; i<ndims; i++){
+            sprintf(dimname, "dim0_%d", i);
+            status = ncmpi_def_dim(ncid, dimname, array_of_gsizes[i], &dimids0[i]);
+            HANDLE_ERROR
+        }
+        sprintf(dimname, "dim1_%d", 0);
+        status = ncmpi_def_dim(ncid, dimname, NC_UNLIMITED, &dimids1[0]);
+        HANDLE_ERROR
+        for (i=1; i<ndims; i++){
+            sprintf(dimname, "dim1_%d", i);
+            status = ncmpi_def_dim(ncid, dimname, array_of_gsizes[i], &dimids1[i]);
+            HANDLE_ERROR
+        } 
+
+        /* define variables */
+        if (k<7){
+            for (i=0; i<2; i++){
+                sprintf(varname, "var0_%d", i);
+                status = ncmpi_def_var(ncid, varname, NC_INT, ndims, dimids0, &varid[i]);
+                HANDLE_ERROR
+            }
+            for (i=2; i<nvars; i++){
+                sprintf(varname, "var1_%d", i);
+                status = ncmpi_def_var(ncid, varname, NC_INT, ndims, dimids1, &varid[i]);
+                HANDLE_ERROR
+            }
+        } else {
+            for (i=0; i<nprocs; i++){
+                sprintf(varname, "var0_%d", i);
+                status = ncmpi_def_var(ncid, varname, NC_INT, ndims, dimids0, &varid[i]);
+                HANDLE_ERROR
+            }
+        }
+
+        status = ncmpi_enddef(ncid);
+        HANDLE_ERROR
+
+        if (k == 0) {
+            if (rank == 0 && verbose)
+                printf("*** Testing to write 2 non-record variables and 2 record variables by using ncmpi_put_vara_all() ...");
+            for (i=0; i<nvars; i++){
+                status = ncmpi_put_vara_all(ncid, varid[i], starts[i], counts[i], buf[i], bufcounts[i], MPI_INT);
+                HANDLE_ERROR
+            }
+        }
+
+        if (k == 1) {
+            if (rank == 0 && verbose)
+                printf("*** Testing to write 2 non-record variables and 2 record variables by using ncmpi_put_vara() ...");
+            status = ncmpi_begin_indep_data(ncid);
+            HANDLE_ERROR
+            for (i=0; i<nvars; i++){
+                status = ncmpi_put_vara(ncid, varid[i], starts[i], counts[i], buf[i], bufcounts[i], MPI_INT);
+                HANDLE_ERROR
+            }
+            status = ncmpi_end_indep_data(ncid);
+            HANDLE_ERROR
+        } 
+
+        if (k == 2) {
+            if (rank == 0 && verbose)
+                printf("*** Testing to write 2 non-record variables and 2 record variables by using ncmpi_mput_vara_all() ...");
+            status = ncmpi_mput_vara_all(ncid, nvars, varid, starts, counts, (void**)buf, bufcounts, datatype_list);
+            HANDLE_ERROR
+        }
+
+        if (k == 3) {
+            if (rank == 0 && verbose)
+                printf("*** Testing to write 2 non-record variables and 2 record variables by using ncmpi_iput_vara() and ncmpi_wait() ...");
+            status = ncmpi_begin_indep_data(ncid);
+            HANDLE_ERROR
+            for (i=0; i<nvars; i++){
+                status = ncmpi_iput_vara(ncid, varid[i], starts[i], counts[i], buf[i], bufcounts[i], MPI_INT, &reqs[i]);
+                HANDLE_ERROR
+                status = ncmpi_wait(ncid, 1, &reqs[i], &sts[i]);
+                HANDLE_ERROR
+            }
+            status = ncmpi_end_indep_data(ncid);
+            HANDLE_ERROR
+        }
+
+        if (k == 4) {
+            if (rank == 0 && verbose)
+                printf("*** Testing to write 2 non-record variables and 2 record variables by using ncmpi_iput_vara() and ncmpi_wait_all() ...");
+            for (i=0; i<nvars; i++){
+                status = ncmpi_iput_vara(ncid, varid[i], starts[i], counts[i], buf[i], bufcounts[i], MPI_INT, &reqs[i]);
+                HANDLE_ERROR
+            }
+            status = ncmpi_wait_all(ncid, nvars, reqs, sts);
+            HANDLE_ERROR
+        } 
+
+        if (k == 5) {
+            if (rank == 0 && verbose)
+                printf("*** Testing to write 2 non-record variables and 2 record variables by using ncmpi_iput_vars() and ncmpi_wait() ...");
+            stride[0] = 1;
+            stride[1] = 1;
+            stride[2] = 1;
+            status = ncmpi_begin_indep_data(ncid);
+            HANDLE_ERROR
+            for (i=0; i<nvars; i++){
+                status = ncmpi_iput_vars(ncid, varid[i], starts[i], counts[i], stride, buf[i], bufcounts[i], MPI_INT, &reqs[i]);
+                HANDLE_ERROR
+                status = ncmpi_wait(ncid, 1, &reqs[i], &sts[i]);
+                HANDLE_ERROR
+            }
+            status = ncmpi_end_indep_data(ncid);
+            HANDLE_ERROR
+        } 
+
+        if (k == 6) {
+            if (rank == 0 && verbose)
+                printf("*** Testing to write 2 non-record variables and 2 record variables by using ncmpi_iput_vars() and ncmpi_wait_all() ...");
+            stride[0] = 1;
+            stride[1] = 1;
+            stride[2] = 1;
+            for (i=0; i<nvars; i++){
+                status = ncmpi_iput_vars(ncid, varid[i], starts[i], counts[i], stride, buf[i], bufcounts[i], MPI_INT, &reqs[i]);
+                HANDLE_ERROR
+            }
+            status = ncmpi_wait_all(ncid, nvars, reqs, sts);
+            HANDLE_ERROR
+        } 
+        if (k == 7) {
+            if (rank == 0 && verbose)
+                printf("*** Testing to write %d non-record variable(s) by using ncmpi_put_var() ...", nprocs);
+            status = ncmpi_begin_indep_data(ncid);
+            HANDLE_ERROR
+            status = ncmpi_put_var(ncid, varid[rank], buf_var, bufcount*nprocs, MPI_INT);
+            HANDLE_ERROR
+            status = ncmpi_end_indep_data(ncid);
+            HANDLE_ERROR
+        }
+        if (k == 8) {
+            if (rank == 0 && verbose)
+                printf("*** Testing to write %d non-record variable(s) by using ncmpi_iput_var() and ncmpi_wait() ...", nprocs);
+            i = 0;
+            status = ncmpi_iput_var(ncid, varid[rank], buf_var, bufcount*nprocs, MPI_INT, &reqs[i]);
+            HANDLE_ERROR
+            status = ncmpi_begin_indep_data(ncid);
+            HANDLE_ERROR
+            status = ncmpi_wait(ncid, 1, &reqs[i], &sts[i]);
+            HANDLE_ERROR
+            status = ncmpi_end_indep_data(ncid);
+            HANDLE_ERROR
+        }
+        if (k == 9) {
+            if (rank == 0 && verbose)
+                printf("*** Testing to write %d non-record variable(s) by using ncmpi_iput_var() and ncmpi_wait_all() ...", nprocs);
+            status = ncmpi_iput_var(ncid, varid[rank], buf_var, bufcount*nprocs, MPI_INT, &reqs[0]);
+            HANDLE_ERROR
+            status = ncmpi_wait_all(ncid, 1, &reqs[0], &sts[0]);
+            HANDLE_ERROR
+        }
+
+        status = ncmpi_close(ncid);
+        HANDLE_ERROR
+
+        if (status == NC_NOERR){
+            if ((k>0)&&(k<7)){
+            status = ncmpi_diff(filename1, filename3);
+            if (rank == 0 && status == NC_NOERR && verbose)
+                printf("\t OK\n");                                       
+            } else if (k>7){
+/*
+printf("filename2=%s filename3=%s\n",filename2, filename3);
+                status = ncmpi_diff(filename2, filename3);
+                if (rank == 0 && status == NC_NOERR && verbose)
+                    printf("\t OK\n");                                       
+*/
+            } else {
+             if (rank == 0 && verbose)
+                 printf("\t OK\n");                                       
+            }
+        }
+    }
+
+/*
+    int nkeys; 
+    MPI_Info_get_nkeys(info, &nkeys);
+    printf("MPI File Info: nkeys = %d\n",nkeys);
+    for (i=0; i<nkeys; i++) {
+        char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
+        int  valuelen, flag;
+
+        MPI_Info_get_nthkey(info, i, key);
+        MPI_Info_get_valuelen(info, key, &valuelen, &flag);
+        MPI_Info_get(info, key, valuelen+1, value, &flag);
+        printf("MPI File Info: [%2d] key = %21s, flag = %d, valuelen = %d value = %s\n",
+               i,key,flag,valuelen,value);
+    }
+*/
+
+    MPI_Info_free(&info);
+    
+    for (i=0; i<nvars; i++){
+        free(starts[i]);
+        free(counts[i]);
+    }
+    free(buf[0]);
+    free(buf);
+    free(buf_var);
+    free(bufcounts);
+    free(datatype_list);
+    free(reqs);
+    free(sts);
+    free(varid);
+    free(starts);
+    free(counts);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    int err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/test/nonblocking/mcoll_testf.f90 b/test/nonblocking/mcoll_testf.f90
new file mode 100644
index 0000000..4bde342
--- /dev/null
+++ b/test/nonblocking/mcoll_testf.f90
@@ -0,0 +1,461 @@
+
+!=============================================================================
+!
+! Note that this code was adapted from fanc/pntf_test.F, which was written by:
+! John Tannahill, LLNL
+!
+! This a multi-variable write test on Fortran.
+!
+! This code writes the array, tt(k)(j)(i), into the file 'testfile.nc'. It
+! then reads the array from the file, and compares it with the original
+! values.
+! 
+! i=longitude, j=latitude, k=level
+!
+! $Id: mcoll_testf.f90 2131 2015-09-25 22:33:12Z wkliao $
+!
+!=============================================================================
+
+      program Mcoll_Testf
+
+      use mpi
+      use pnetcdf
+      implicit none
+
+!     -----------------------
+!     Parameter declarations.
+!     -----------------------
+
+      integer NREADS, NWRITES 
+      parameter (NREADS = 5, NWRITES = 5 )
+      ! number of read samples
+      ! number of write samples
+      INTEGER(KIND=MPI_OFFSET_KIND) TOTSIZ_3D(3) ! global sizes of 3D field
+
+!     ----------------------
+!     Variable declarations.
+!     ----------------------
+
+      logical reorder
+      logical isperiodic(3)
+      integer comm_cart                   ! Cartesian communicator
+      integer err, ierr, get_args
+      INTEGER(KIND=MPI_OFFSET_KIND) istart, jstart, kstart      ! offsets of 3D field
+      INTEGER(KIND=MPI_OFFSET_KIND) locsiz
+      integer mype                        ! rank in comm_cart
+      integer totpes                      ! total number of PEs
+              
+      INTEGER(KIND=MPI_OFFSET_KIND) locsiz_3d(3)  ! local sizes of 3D fields
+      integer pe_coords(3)                ! Cartesian PE coords
+      integer numpes(3)                   ! number of PEs along axes;
+                                          !   determined by MPI where a
+                                          !   zero is specified
+      integer rank, Write_File
+      character(len=256) :: filename, cmd, msg
+
+      real*4  filsiz
+      real*4  rdt_l(2)
+      real*4  wrt_g(2)
+      real*4  wrt_l(2)
+              
+      real*4  wrates_g(2)
+      real*4  wrates_l(2)
+
+      data reorder / .false. /
+      data isperiodic / .false., .false., .false. /
+      data numpes / 1, 1, 0 /
+!      data TOTSIZ_3D / 256, 256, 256 /
+      data TOTSIZ_3D / 8, 8, 8 /
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+      call MPI_Init (ierr)
+      call MPI_Comm_Size(MPI_COMM_WORLD, totpes, ierr)
+      call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
+
+      if (rank .EQ. 0) then
+          filename = 'testfile.nc'
+          err = get_args(cmd, filename)
+      endif
+      call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+      if (err .EQ. 0) goto 999
+
+      call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+      call MPI_Dims_Create (totpes, 3, numpes, ierr)
+
+      call MPI_Cart_Create(MPI_COMM_WORLD, 3, numpes, isperiodic, &
+                           reorder, comm_cart, ierr)
+
+      call MPI_Comm_Rank (comm_cart, mype, ierr)
+
+      call MPI_Cart_Coords (comm_cart, mype, 3, pe_coords, ierr)
+
+      rdt_l(1) = 1.0e38
+      rdt_l(2) = 1.0e38
+      wrt_l(1) = 1.0e38
+      wrt_l(2) = 1.0e38
+!      rdt_l(:) = Huge (rdt_l)   ! initialize for timing
+!      wrt_l(:) = Huge (wrt_l)
+
+!     ----------------------------------------
+!     Determine local size for tt (locsiz_3d).
+!     ----------------------------------------
+
+!     ===============
+      call Find_Locnx(TOTSIZ_3D(1), pe_coords(1), numpes(1), &
+                      locsiz_3d(1), istart)
+      call Find_Locnx(TOTSIZ_3D(2), pe_coords(2), numpes(2), &
+                      locsiz_3d(2), jstart)
+      call Find_Locnx(TOTSIZ_3D(3), pe_coords(3), numpes(3), &
+                      locsiz_3d(3), kstart)
+!     ===============
+
+!     -------------------------------
+!     Compute file size in 1d6 bytes.
+!     -------------------------------
+
+      filsiz = real((TOTSIZ_3D(1) * TOTSIZ_3D(2) * TOTSIZ_3D(3)) * &
+               1.0d-6 * 4.0d0)
+
+!     -------------------------------------
+!     Print data decomposition information.
+!     -------------------------------------
+
+!      if (mype == 0) Write (6,900)
+
+      call MPI_Barrier (comm_cart, ierr)
+
+!      Write (6, 902)
+!     &  mype, pe_coords(1), pe_coords(2), pe_coords(3),
+!     &  TOTSIZ_3D(1), TOTSIZ_3D(2), TOTSIZ_3D(3),
+!     &  locsiz_3d(1), locsiz_3d(2), locsiz_3d(3),
+!     &  kstart, jstart, istart
+
+! 900  format ("mype  pe_coords    totsiz_3d         locsiz_3d       ",&
+!              "kstart,jstart,istart")
+! 902  format (i3,3x,i2,1x,i2,1x,i2,2x,i4,1x,i4,1x,i4,4x,i4,1x,i4,1x, &
+!              i4,3x,i6,1x,i6,1x,i6)
+
+!     -------------------------
+!     Write and then read back.
+!     -------------------------
+
+      locsiz = locsiz_3d(1) * locsiz_3d(2) * locsiz_3d(3)
+
+!     ===============
+      ierr = Write_File(filename, NWRITES, comm_cart, &
+                      istart, jstart, kstart, locsiz, locsiz_3d,  &
+                      TOTSIZ_3D, wrt_l)
+      if (ierr .NE. NF90_NOERR) then
+          write(6,*) trim(nf90mpi_strerror(ierr))
+          goto 999
+      endif
+!!!   Write (6,*) wrt_l(1), wrt_l(2)
+
+!     ----------------------------
+!     Compute and print I/O rates.
+!     ----------------------------
+
+      wrates_l(1) = filsiz / wrt_l(2)               ! write rate
+      wrates_l(2) = filsiz / (wrt_l(1) + wrt_l(2))  ! effective write rate
+
+      call MPI_Allreduce(wrates_l, wrates_g, 2, MPI_REAL, MPI_MIN, &
+                         comm_cart, ierr)
+      call MPI_Allreduce(wrt_l,    wrt_g,    2, MPI_REAL, MPI_MAX, &
+                         comm_cart, ierr)
+
+!      if (mype == 0) then
+!        Write (6,905) filsiz
+!        Write (6,910) wrates_g(1), wrates_g(2)
+!      end if 
+
+! 905  format ("File size: ", e10.3, " MB")
+! 910  format ("    Write: ", f9.3, " MB/s  (eff., ", f9.3, " MB/s)")
+! 915  format ("    Read : ", f9.3, " MB/s  (eff., ", f9.3, " MB/s)")
+! 920  format ("Total number PEs: ", i4)
+! 922  format (e11.3, e11.3, f9.3, e11.3, e11.3, f9.3)
+
+      call MPI_Comm_Free (comm_cart, ierr)
+
+      msg = '*** TESTING F90 '//trim(cmd)//' for nf90mpi_iput_var API'
+      if (rank .EQ. 0) call pass_fail(0, msg)
+
+ 999  call MPI_Finalize(ierr)
+
+      end program Mcoll_Testf
+
+!     ------------
+
+
+      integer function Write_File(filename, nwrites, comm_cart, &
+                            istart, jstart, kstart, locsiz,  &
+                            locsiz_3d, totsiz_3d, wrt_l)
+
+      use mpi
+      use pnetcdf
+      implicit none
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      character (len=*) filename
+      integer nwrites
+      integer comm_cart
+      INTEGER(KIND=MPI_OFFSET_KIND) istart, jstart, kstart
+      INTEGER(KIND=MPI_OFFSET_KIND) locsiz
+      INTEGER(KIND=MPI_OFFSET_KIND) locsiz_3d(3)
+      INTEGER(KIND=MPI_OFFSET_KIND) totsiz_3d(3)
+      real*4  wrt_l(2)
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      integer ierr, info
+      integer lon_id, lat_id, lev_id
+      integer ncid
+      integer nw
+      integer tt1_id
+      integer req(nwrites)
+      integer stat(nwrites)
+      INTEGER(KIND=MPI_OFFSET_KIND) start_3d(3)
+      INTEGER(KIND=MPI_OFFSET_KIND) count_3d(3)
+      integer dim_id(3)
+      double precision  t1, t2, t3
+      integer max_loc_size
+      parameter( max_loc_size = 20000000 )
+      ! real*4  tt1(max_loc_size)   ! Need tt(locsiz)
+      real*4, dimension(locsiz_3d(1), locsiz_3d(2), locsiz_3d(3)) :: tt1
+
+      if (locsiz .gt. MAX_LOC_SIZE) then
+         print *, 'locsiz = ', locsiz, ' larger than MAX_LOC_SIZE'
+         stop
+      endif
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+!      start_3d(1:3) = (/ kstart, jstart, istart /)
+!      count_3d(:)   = locsiz_3d(:)
+      start_3d(1) = istart
+      start_3d(2) = jstart
+      start_3d(3) = kstart
+      count_3d(1) = locsiz_3d(1)
+      count_3d(2) = locsiz_3d(2)
+      count_3d(3) = locsiz_3d(3)
+
+!       ==============
+        call Get_Field(istart, jstart, kstart, locsiz_3d, &
+                       totsiz_3d, tt1)
+
+        call MPI_Barrier (comm_cart, ierr)
+        t1 = MPI_Wtime ( )
+
+!       =================
+        call MPI_Info_create(info, ierr)
+        ! call MPI_Info_set(info, "romio_pvfs2_posix_write","enable",ierr)
+
+        Write_File = nf90mpi_create(comm_cart, filename, NF90_CLOBBER, &
+                                    info, ncid)
+        if (Write_File .NE. NF90_NOERR) return
+
+        call MPI_Info_free(info, ierr)
+
+!       ==================
+        Write_File = nf90mpi_def_dim(ncid, "level",     totsiz_3d(1)*nwrites, &
+                             lon_id)
+        if (Write_File .NE. NF90_NOERR) return
+        Write_File = nf90mpi_def_dim(ncid, "latitude",  totsiz_3d(2), lat_id)
+        if (Write_File .NE. NF90_NOERR) return
+        Write_File = nf90mpi_def_dim(ncid, "longitude", totsiz_3d(3), lev_id)
+        if (Write_File .NE. NF90_NOERR) return
+!       ==================
+
+        dim_id(1) = lon_id
+        dim_id(2) = lat_id
+        dim_id(3) = lev_id
+
+!       ==================
+        Write_File = nf90mpi_def_var(ncid, "tt1", NF90_REAL, dim_id, tt1_id)
+        if (Write_File .NE. NF90_NOERR) return
+
+!       =================
+        Write_File = nf90mpi_enddef (ncid)
+        if (Write_File .NE. NF90_NOERR) return
+!       =================
+
+        t2 = MPI_Wtime ( )
+
+      do nw = 1, nwrites
+         Write_File = nf90mpi_iput_var(ncid, tt1_id, tt1, req(nw), &
+                                 start_3d, count_3d)
+        if (Write_File .NE. NF90_NOERR) return
+
+         start_3d(1) = start_3d(1) + count_3d(1)
+      end do
+
+      Write_File = nf90mpi_wait_all(ncid, nwrites, req, stat)
+      if (Write_File .NE. NF90_NOERR) return
+
+!       ================
+      Write_File = nf90mpi_close (ncid)
+      if (Write_File .NE. NF90_NOERR) return
+!       ================
+
+! 900  format ("mynod:", i1, " reqid : ", i1)
+
+      call MPI_Barrier (comm_cart, ierr)
+      t3 = MPI_Wtime ( )
+
+      if (t2 - t1 < wrt_l(1)) wrt_l(1) = real(t2 - t1)
+      if (t3 - t2 < wrt_l(2)) wrt_l(2) = real(t3 - t2)
+
+      end
+
+!     ------------
+
+      subroutine Find_Locnx(nx, mype, totpes, locnx, ibegin)
+
+      use mpi
+      implicit none
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      INTEGER(KIND=MPI_OFFSET_KIND) nx
+      integer mype
+      integer totpes
+      INTEGER(KIND=MPI_OFFSET_KIND) locnx
+      INTEGER(KIND=MPI_OFFSET_KIND) ibegin
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      INTEGER(KIND=MPI_OFFSET_KIND) iremain
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+      locnx = nx / totpes
+
+      iremain = nx - (totpes * locnx)
+
+      if (mype < iremain) locnx = locnx + 1
+
+      ibegin = mype * (nx / totpes) + iremain + 1
+
+      if (mype < iremain) ibegin = ibegin + (mype - iremain)
+
+      end
+
+!     ------------
+
+      subroutine Get_Field(istart, jstart, kstart, locsiz_3d, &
+                           totsiz_3d, tt)
+
+      use mpi
+      implicit none
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      INTEGER(KIND=MPI_OFFSET_KIND) istart, jstart, kstart
+      INTEGER(KIND=MPI_OFFSET_KIND) locsiz_3d(3)
+      INTEGER(KIND=MPI_OFFSET_KIND) totsiz_3d(3)
+      real*4, dimension(locsiz_3d(1),locsiz_3d(2),locsiz_3d(3)) ::tt
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      integer ii, jj, kk
+      integer ind
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+      ind = 1
+
+      do kk = 1, int(locsiz_3d(3))
+        do jj = 1, int(locsiz_3d(2))
+          do ii = 1, int(locsiz_3d(1))
+
+             tt(ii,jj,kk) = real( &
+               (istart-1 +(ii - 1) + 1 + totsiz_3d(3)*(jstart-1 +  &
+                       (jj - 1) + totsiz_3d(2)*(kstart-1 +  &
+                       (kk-1)))) * 1.0d-3)
+             ind = ind + 1
+
+          end do
+        end do
+      end do
+
+      end
+
+!     ------------
+
+      subroutine Compare_Vec(comm_cart, locsiz, tt, buf)
+
+      use mpi
+      implicit none
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      integer comm_cart
+      INTEGER(KIND=MPI_OFFSET_KIND) locsiz
+      real*4  tt (locsiz)
+      real*4  buf(locsiz)
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      integer ierr
+      integer ii
+      real*4  delmax(1), delmin(1), delta
+      real*4  diff
+      real*4  wr(5)
+      real*4  ws(5)
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+      ws(1) = 0.0d0      ! diff
+      ws(2) = 0.0d0      ! sumsq
+      ws(3) = real(locsiz)     ! locsiz
+      ws(4) = 0.0d0      ! delmax
+      ws(5) = 1.0d38     ! Huge (ws)  ! delmin
+
+      do ii = 1, int(locsiz)
+        delta = (tt(ii) - buf(ii)) * (tt(ii) - buf(ii))
+        ws(1) = ws(1) + delta
+        ws(2) = ws(2) + tt(ii) * tt(ii)
+        if (delta > ws(4)) ws(4) = delta
+        if (delta < ws(5)) ws(5) = delta
+      end do
+
+      call MPI_Allreduce(ws,    wr,     3, MPI_REAL, MPI_SUM, &
+                         comm_cart, ierr)
+      call MPI_Allreduce(ws(4), delmax, 1, MPI_REAL, MPI_MAX, &
+                         comm_cart, ierr)
+      call MPI_Allreduce(ws(5), delmin(1), 1, MPI_REAL, MPI_MIN, &
+                         comm_cart, ierr)
+
+      diff      = Sqrt (wr(1) / wr(2))         ! normalized error
+      delmax(1) = Sqrt (wr(3) * delmax(1)/wr(2))  ! normalized max difference
+      delmin(1) = Sqrt (wr(3) * delmin(1)/wr(2))  ! normalized min difference
+
+      end
+
diff --git a/test/nonblocking/mcoll_testf77.f b/test/nonblocking/mcoll_testf77.f
new file mode 100644
index 0000000..c4cbe35
--- /dev/null
+++ b/test/nonblocking/mcoll_testf77.f
@@ -0,0 +1,521 @@
+!
+!   Copyright (C) 2012, Northwestern University and Argonne National Lab
+!   See COPYRIGHT notice in top-level directory.
+!
+!   Note that this code was adapted from fanc/pntf_test.F, which was written by:
+!   John Tannahill, LLNL
+!
+! This a multi-variable write test on Fortran.
+!
+! This code writes the array, tt(k)(j)(i), into the file 'testfile.nc'. It
+! then reads the array from the file, and compares it with the original
+! values.
+! 
+! i=longitude, j=latitude, k=level
+!
+! $Id: mcoll_testf77.f 2224 2015-12-16 06:10:36Z wkliao $
+!
+!=============================================================================
+
+       INTEGER FUNCTION XTRIM(STRING)
+           CHARACTER*(*) STRING
+           INTEGER I, N
+           N = LEN(STRING)
+           DO I = N, 1, -1
+              IF (STRING(I:I) .NE. ' ') GOTO 10
+           ENDDO
+ 10        XTRIM = I
+       END ! FUNCTION XTRIM
+
+      program Mcoll_Testf
+
+      implicit none
+      include "mpif.h"
+      include "pnetcdf.inc"
+
+!     -----------------------
+!     Parameter declarations.
+!     -----------------------
+
+      integer XTRIM
+      integer NWRITES 
+      parameter (NWRITES = 5 )
+      ! number of read samples
+      ! number of write samples
+
+      integer*8 TOTSIZ_3D(3) ! global sizes of 3D field
+
+
+!     ----------------------
+!     Variable declarations.
+!     ----------------------
+
+      logical reorder
+              
+      logical isperiodic(3)
+              
+      integer comm_cart                   ! Cartesian communicator
+      integer err, ierr, get_args
+      integer*8 istart, jstart, kstart      ! offsets of 3D field
+      integer*8 locsiz
+      integer mype                        ! rank in comm_cart
+      integer totpes                      ! total number of PEs
+              
+      integer*8 locsiz_3d(3)                ! local sizes of 3D fields
+      integer pe_coords(3)                ! Cartesian PE coords
+              
+      integer numpes(3)                   ! number of PEs along axes;
+                                          !   determined by MPI where a
+                                          !   zero is specified
+
+      integer rank, Write_File
+      character*256 filename, cmd, msg
+
+      real*4  filsiz
+              
+      real*4  rdt_l(2)
+      real*4  wrt_g(2)
+      real*4  wrt_l(2)
+              
+      real*4  wrates_g(2)
+      real*4  wrates_l(2)
+
+
+      data reorder / .false. /
+      data isperiodic / .false., .false., .false. /
+      data numpes / 1, 1, 0 /
+!      data TOTSIZ_3D / 256, 256, 256 /
+      data TOTSIZ_3D / 8, 8, 8 /
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+      call MPI_Init (ierr)
+      call MPI_Comm_Size(MPI_COMM_WORLD, totpes, ierr)
+      call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
+
+      if (rank .EQ. 0) then
+          filename = "testfile.nc"
+          err = get_args(cmd, filename)
+      endif
+      call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+      if (err .EQ. 0) goto 999
+
+      call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD,
+     +               ierr)
+
+      call MPI_Dims_Create (totpes, 3, numpes, ierr)
+
+      call MPI_Cart_Create(MPI_COMM_WORLD, 3, numpes, isperiodic,
+     +                     reorder, comm_cart, ierr)
+
+      call MPI_Comm_Rank (comm_cart, mype, ierr)
+
+      call MPI_Cart_Coords (comm_cart, mype, 3, pe_coords, ierr)
+
+
+      rdt_l(1) = 1.0e38
+      rdt_l(2) = 1.0e38
+      wrt_l(1) = 1.0e38
+      wrt_l(2) = 1.0e38
+!      rdt_l(:) = Huge (rdt_l)   ! initialize for timing
+!      wrt_l(:) = Huge (wrt_l)
+
+!     ----------------------------------------
+!     Determine local size for tt (locsiz_3d).
+!     ----------------------------------------
+
+!     ===============
+      call Find_Locnx(TOTSIZ_3D(1), pe_coords(1), numpes(1),
+     +                locsiz_3d(1), istart)
+      call Find_Locnx(TOTSIZ_3D(2), pe_coords(2), numpes(2),
+     +                locsiz_3d(2), jstart)
+      call Find_Locnx(TOTSIZ_3D(3), pe_coords(3), numpes(3),
+     +                locsiz_3d(3), kstart)
+!     ===============
+
+!     -------------------------------
+!     Compute file size in 1d6 bytes.
+!     -------------------------------
+
+      filsiz = real((TOTSIZ_3D(1) * TOTSIZ_3D(2) * TOTSIZ_3D(3)) *
+     +         1.0d-6 * 4.0d0)
+
+!     -------------------------------------
+!     Print data decomposition information.
+!     -------------------------------------
+
+!      if (mype == 0) Write (6,900)
+
+      call MPI_Barrier (comm_cart, ierr)
+
+!      Write (6, 902)
+!     &  mype, pe_coords(1), pe_coords(2), pe_coords(3),
+!     &  TOTSIZ_3D(1), TOTSIZ_3D(2), TOTSIZ_3D(3),
+!     &  locsiz_3d(1), locsiz_3d(2), locsiz_3d(3),
+!     &  kstart, jstart, istart
+
+! 900  format ("mype  pe_coords    totsiz_3d         locsiz_3d       ",
+!     +        "kstart,jstart,istart")
+! 902  format (i3,3x,i2,1x,i2,1x,i2,2x,i4,1x,i4,1x,i4,4x,i4,1x,i4,1x,
+!     +        i4,3x,i6,1x,i6,1x,i6)
+
+
+!     -------------------------
+!     Write and then read back.
+!     -------------------------
+
+      locsiz = locsiz_3d(1) * locsiz_3d(2) * locsiz_3d(3)
+
+!     ===============
+      ierr = Write_File(filename, NWRITES, comm_cart,
+     +                istart, jstart, kstart, locsiz, locsiz_3d,
+     +                TOTSIZ_3D, wrt_l)
+      if (ierr .NE. NF_NOERR) then
+          write(6,*) nfmpi_strerror(ierr)
+          goto 999
+      endif
+!!!   Write (6,*) wrt_l(1), wrt_l(2)
+
+!     ----------------------------
+!     Compute and print I/O rates.
+!     ----------------------------
+
+      wrates_l(1) = filsiz / wrt_l(2)               ! write rate
+      wrates_l(2) = filsiz / (wrt_l(1) + wrt_l(2))  ! effective write rate
+
+      call MPI_Allreduce(wrates_l, wrates_g, 2, MPI_REAL, MPI_MIN,
+     +                   comm_cart, ierr)
+      call MPI_Allreduce(wrt_l,    wrt_g,    2, MPI_REAL, MPI_MAX,
+     +                   comm_cart, ierr)
+
+!      if (mype == 0) then
+!        Write (6,905) filsiz
+!        Write (6,910) wrates_g(1), wrates_g(2)
+!      end if 
+
+! 905  format ("File size: ", e10.3, " MB")
+! 910  format ("    Write: ", f9.3, " MB/s  (eff., ", f9.3, " MB/s)")
+! 915  format ("    Read : ", f9.3, " MB/s  (eff., ", f9.3, " MB/s)")
+! 920  format ("Total number PEs: ", i4)
+! 922  format (e11.3, e11.3, f9.3, e11.3, e11.3, f9.3)
+
+
+      call MPI_Comm_Free (comm_cart, ierr)
+
+      msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//' for iput API'
+      if (rank .EQ. 0) call pass_fail(0, msg)
+
+ 999  call MPI_Finalize  (ierr)
+
+      end ! program Mcoll_Testf
+
+
+!     ------------
+
+
+      integer function Write_File(filename, nwrites, comm_cart,
+     +                      istart, jstart, kstart, locsiz,
+     +                      locsiz_3d, totsiz_3d, wrt_l)
+
+      implicit none
+      include "mpif.h"
+      include "pnetcdf.inc"
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      character*(*) filename
+      integer nwrites
+      integer comm_cart
+      integer*8 istart, jstart, kstart
+      integer*8 locsiz
+      integer*8 locsiz_3d(3)
+      integer*8 totsiz_3d(3)
+      real*4  wrt_l(2)
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      integer ierr, info
+      integer lon_id, lat_id, lev_id
+      integer ncid
+      integer nw
+      integer tt1_id
+      integer req1
+      integer req(nwrites)
+      integer stat(nwrites)
+        
+      integer*8 count_3d(3)
+      integer*8 start_3d(3)
+              
+      integer dim_id(3)
+              
+      double precision  t1, t2, t3
+           
+      integer max_loc_size
+      parameter( max_loc_size = 20000000 )
+      real*4  tt1(max_loc_size)   ! Need tt(locsiz)
+
+
+      if (locsiz .gt. MAX_LOC_SIZE) then
+         print *, 'locsiz = ', locsiz, ' larger than MAX_LOC_SIZE'
+         stop
+      endif
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+!      start_3d(1:3) = (/ kstart, jstart, istart /)
+!      count_3d(:)   = locsiz_3d(:)
+      start_3d(1) = istart
+      start_3d(2) = jstart
+      start_3d(3) = kstart
+      count_3d(1) = locsiz_3d(1)
+      count_3d(2) = locsiz_3d(2)
+      count_3d(3) = locsiz_3d(3)
+
+!       ==============
+        call Get_Field(istart, jstart, kstart, locsiz, locsiz_3d,
+     +                 totsiz_3d, tt1)
+
+        call MPI_Barrier (comm_cart, ierr)
+        t1 = MPI_Wtime ( )
+
+!       =================
+       call MPI_Info_create(info, ierr)
+       ! call MPI_Info_set(info, "romio_pvfs2_posix_write", "enable",ierr)
+
+        Write_File = nfmpi_create(comm_cart, filename, NF_CLOBBER,
+     +                            info, ncid)
+        if (Write_File .NE. NF_NOERR) return
+
+       call MPI_Info_free(info, ierr)
+
+!       ==================
+        Write_File = nfmpi_def_dim(ncid, "level",
+     +               totsiz_3d(1)*nwrites, lon_id)
+        if (Write_File .NE. NF_NOERR) return
+        Write_File = nfmpi_def_dim(ncid, "latitude",  totsiz_3d(2),
+     +                             lat_id)
+        if (Write_File .NE. NF_NOERR) return
+        Write_File = nfmpi_def_dim(ncid, "longitude", totsiz_3d(3),
+     +                             lev_id)
+        if (Write_File .NE. NF_NOERR) return
+!       ==================
+
+        dim_id(1) = lon_id
+        dim_id(2) = lat_id
+        dim_id(3) = lev_id
+
+!       ==================
+        Write_File = nfmpi_def_var(ncid, "tt1", NF_REAL, 3, dim_id,
+     +                             tt1_id)
+        if (Write_File .NE. NF_NOERR) return
+
+!       =================
+        Write_File = nfmpi_enddef (ncid)
+        if (Write_File .NE. NF_NOERR) return
+!       =================
+
+        t2 = MPI_Wtime ( )
+
+      do nw = 1, nwrites
+
+         Write_File = nfmpi_iput_vara_real(ncid, tt1_id, start_3d,
+     +                               count_3d, tt1, req1)
+        if (Write_File .NE. NF_NOERR) return
+         req(nw)=req1
+
+         start_3d(1) = start_3d(1) + count_3d(1)
+      end do
+
+      Write_File = nfmpi_wait_all(ncid, nwrites, req, stat)
+      if (Write_File .NE. NF_NOERR) return
+
+!       ================
+      Write_File = nfmpi_close (ncid)
+      if (Write_File .NE. NF_NOERR) return
+!       ================
+
+! 900  format ("mynod:", i1, " reqid : ", i1)
+
+
+      call MPI_Barrier (comm_cart, ierr)
+      t3 = MPI_Wtime ( )
+
+
+      if (t2 - t1 .LT. wrt_l(1)) wrt_l(1) = real(t2 - t1)
+      if (t3 - t2 .LT. wrt_l(2)) wrt_l(2) = real(t3 - t2)
+
+      Return
+
+      end
+
+
+!     ------------
+
+      subroutine Find_Locnx(nx, mype, totpes, locnx, ibegin)
+
+      implicit none
+      include "mpif.h"
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      integer*8 nx
+      integer mype
+      integer totpes
+      integer*8 locnx
+      integer*8 ibegin
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      integer*8 iremain
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+      locnx = nx / totpes
+
+      iremain = nx - (totpes * locnx)
+
+      if (mype .LT. iremain) locnx = locnx + 1
+
+      ibegin = mype * (nx / totpes) + iremain + 1
+
+      if (mype .LT. iremain) ibegin = ibegin + (mype - iremain)
+
+      Return
+
+      end
+
+
+!     ------------
+
+
+      subroutine Get_Field(istart, jstart, kstart, locsiz, locsiz_3d,
+     +                     totsiz_3d, tt)
+
+      implicit none
+      include "mpif.h"
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      integer*8 istart, jstart, kstart
+      integer*8 locsiz
+      integer*8 locsiz_3d(3)
+      integer*8 totsiz_3d(3)
+      real*4  tt(locsiz)
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      integer ii, jj, kk
+      integer ind
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+      ind = 1
+
+
+      do kk = 1, int(locsiz_3d(3))
+        do jj = 1, int(locsiz_3d(2))
+          do ii = 1, int(locsiz_3d(1))
+
+             tt(ind) = real(
+     +         (istart-1 +(ii - 1) + 1 + totsiz_3d(3)*(jstart-1 +
+     +                 (jj - 1) + totsiz_3d(2)*(kstart-1 +
+     +                 (kk-1)))) * 1.0d-3)
+             ind = ind + 1
+
+          end do
+        end do
+      end do
+
+
+      Return
+
+      end
+
+
+!     ------------
+
+
+      subroutine Compare_Vec(comm_cart, locsiz, tt, buf)
+
+      implicit none
+      include "mpif.h"
+
+!     ----------------------
+!     Argument declarations.
+!     ----------------------
+
+      integer comm_cart
+      integer*8 locsiz
+      real*4  tt (locsiz)
+      real*4  buf(locsiz)
+
+
+!     ----------------------------
+!     Local variable declarations.
+!     ----------------------------
+
+      integer ierr
+      integer ii
+              
+      real*4  delmax(1), delmin(1), delta
+      real*4  diff
+              
+      real*4  wr(5)
+      real*4  ws(5)
+
+
+!     ----------------
+!     Begin execution.
+!     ----------------
+
+      ws(1) = 0.0d0      ! diff
+      ws(2) = 0.0d0      ! sumsq
+      ws(3) = real(locsiz)     ! locsiz
+      ws(4) = 0.0d0      ! delmax
+      ws(5) = 1.0d38     ! Huge (ws)  ! delmin
+
+
+      do ii = 1, int(locsiz)
+        delta = (tt(ii) - buf(ii)) * (tt(ii) - buf(ii))
+        ws(1) = ws(1) + delta
+        ws(2) = ws(2) + tt(ii) * tt(ii)
+        if (delta .GT. ws(4)) ws(4) = delta
+        if (delta .LT. ws(5)) ws(5) = delta
+      end do
+
+
+      call MPI_Allreduce(ws,    wr,     3, MPI_REAL, MPI_SUM,
+     +                   comm_cart, ierr)
+      call MPI_Allreduce(ws(4), delmax, 1, MPI_REAL, MPI_MAX,
+     +                   comm_cart, ierr)
+      call MPI_Allreduce(ws(5), delmin, 1, MPI_REAL, MPI_MIN,
+     +                   comm_cart, ierr)
+
+      diff      = Sqrt (wr(1) / wr(2))         ! normalized error
+      delmax(1) = Sqrt (wr(3) * delmax(1)/wr(2))  ! normalized max difference
+      delmin(1) = Sqrt (wr(3) * delmin(1)/wr(2))  ! normalized min difference
+
+
+      Return
+
+      end
+
diff --git a/test/nonblocking/req_all.c b/test/nonblocking/req_all.c
new file mode 100644
index 0000000..6407792
--- /dev/null
+++ b/test/nonblocking/req_all.c
@@ -0,0 +1,157 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id$ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example shows how to use NC_REQ_ALL in nonblocking I/O operations.
+ * The program writes 2 arrays by calling the nonblocking APIs with NULLs for
+ * argument request ID. When calling ncmpi_wait_all(), NC_REQ_ALL is used to
+ * commit all the pending requests without checking the individual statuses of
+ * the requests.
+ *
+ *    To compile:
+ *        mpicc -O2 req_all.c -o req_all -lpnetcdf
+ *
+ * Example commands for MPI run and outputs from running ncmpidump on the
+ * NC file produced by this example program:
+ *
+ *    % mpiexec -n 4 ./req_all /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    dimensions:
+ *            Y = 8 ;
+ *            X = 8 ;
+ *    variables:
+ *            int var_int(Y, X) ;
+ *            float var_flt(Y, X) ;
+ *    data:
+ *    
+ *     var_int =
+ *      0, 0, 1, 1, 2, 2, 3, 3,
+ *      0, 0, 1, 1, 2, 2, 3, 3,
+ *      0, 0, 1, 1, 2, 2, 3, 3,
+ *      0, 0, 1, 1, 2, 2, 3, 3,
+ *      0, 0, 1, 1, 2, 2, 3, 3,
+ *      0, 0, 1, 1, 2, 2, 3, 3,
+ *      0, 0, 1, 1, 2, 2, 3, 3,
+ *      0, 0, 1, 1, 2, 2, 3, 3 ;
+ *    
+ *     var_flt =
+ *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
+ *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
+ *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
+ *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
+ *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
+ *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
+ *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1,
+ *      0.1, 0.1, 1.1, 1.1, 2.1, 2.1, 3.1, 3.1 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 8
+#define NX 2
+
+#define ERR {if(err!=NC_NOERR) {printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); nerrs++;}}
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int i, j, rank, nprocs, nerrs=0, err;
+    int ncid, cmode, varid[2], dimid[2], buf_int[NY][NX];
+    float buf_flt[NY][NX];
+    MPI_Offset  global_ny, global_nx;
+    MPI_Offset start[2], count[2];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for NC_REQ_ALL ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+
+    /* the global array is NY * (NX * nprocs) */
+    global_ny = NY;
+    global_nx = NX * nprocs;
+
+    for (i=0; i<NY; i++)
+        for (j=0; j<NX; j++) {
+             buf_int[i][j] = rank;
+             buf_flt[i][j] = 0.1 + rank;
+        }
+
+    /* define dimensions x and y */
+    err = ncmpi_def_dim(ncid, "Y", global_ny, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", global_nx, &dimid[1]); ERR
+
+    /* define a 2D variable of integer type */
+    err = ncmpi_def_var(ncid, "var_int", NC_INT, 2, dimid, &varid[0]); ERR
+
+    /* define a 2D variable of float type */
+    err = ncmpi_def_var(ncid, "var_flt", NC_FLOAT, 2, dimid, &varid[1]); ERR
+
+    /* do not forget to exit define mode */
+    err = ncmpi_enddef(ncid); ERR
+
+    /* now we are in data mode */
+    start[0] = 0;
+    start[1] = NX * rank;
+    count[0] = NY;
+    count[1] = NX;
+
+    err = ncmpi_iput_vara_int(ncid, varid[0], start, count, &buf_int[0][0], NULL); ERR
+    err = ncmpi_iput_vara_float(ncid, varid[1], start, count, &buf_flt[0][0], NULL); ERR
+
+    err = ncmpi_wait_all(ncid, NC_REQ_ALL, NULL, NULL); ERR
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    /* check if there is any PnetCDF internal malloc residue */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/nonblocking/test_bput.c b/test/nonblocking/test_bput.c
new file mode 100644
index 0000000..2660132
--- /dev/null
+++ b/test/nonblocking/test_bput.c
@@ -0,0 +1,145 @@
+/*
+ *  Copyright (C) 2012, Northwestern University
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: test_bput.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define FILE_NAME "testfile.nc"
+
+#define ERR if (err!=NC_NOERR) {printf("Error at line %d: err=%d %s\n", __LINE__, err, ncmpi_strerror(err)); nerrs++;}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv) {
+    int i, j, ncid, dimid[2], varid, err, nerrs=0, rank, nprocs, verbose;
+    int req[2], status[2];
+    float  var[4][6];
+    char *filename="testfile.nc";
+    MPI_Offset bufsize,  start[2], count[2], stride[2], imap[2];
+    MPI_Info info;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    verbose = 0;
+    if (nprocs > 1 && rank == 0 && verbose)
+        printf("Warning: %s is designed to run on 1 process\n", argv[0]);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for bput API ", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    MPI_Info_create(&info);
+    /* MPI_Info_set(info, "romio_pvfs2_posix_write","enable"); */
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER | NC_64BIT_DATA, info, &ncid); ERR
+    MPI_Info_free(&info);
+
+    /* define a variable of a 6 x 4 integer array in the nc file */
+    err = ncmpi_def_dim(ncid, "Y", 6, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 4, &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT64, 2, dimid, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* set the contents of the write buffer var, a 4 x 6 float array
+          50, 51, 52, 53, 54, 55,
+          56, 57, 58, 59, 60, 61,
+          62, 63, 64, 65, 66, 67,
+          68, 69, 70, 71, 72, 73
+     */
+    for (j=0; j<4; j++) for (i=0; i<6; i++) var[j][i] = j*6+i + 50;
+
+    /* bufsize must be max of data type converted before and after */
+    bufsize = 4*6*sizeof(long long);
+    err = ncmpi_buffer_attach(ncid, bufsize); ERR
+
+    /* write var to the NC variable in the matrix transposed way */
+    count[0]  = 6; count[1]  = 2;
+    stride[0] = 1; stride[1] = 1;
+    imap[0]   = 1; imap[1]   = 6;   /* would be {4, 1} if not transposing */
+
+    if (rank > 0) /* non-root processes just participate the call */
+        count[0] = count[1] = 0;
+
+    /* write the first two columns of the NC variable in the matrix transposed way */
+    start[0]  = 0; start[1]  = 0;
+    err = ncmpi_bput_varm_float(ncid, varid, start, count, stride, imap, &var[0][0], &req[0]); ERR
+
+    /* write the second two columns of the NC variable in the matrix transposed way */
+    start[0]  = 0; start[1]  = 2;
+    err = ncmpi_bput_varm_float(ncid, varid, start, count, stride, imap, &var[2][0], &req[1]); ERR
+
+    err = ncmpi_wait_all(ncid, 2, req, status); ERR
+
+    /* check each bput status */
+    for (i=0; i<2; i++)
+        if (status[i] != NC_NOERR) {
+            printf("Error at line %d: err=%d %s\n", __LINE__, status[i], ncmpi_strerror(err));
+            nerrs++;
+        }
+
+    err = ncmpi_buffer_detach(ncid); ERR
+
+    /* the output from command "ncmpidump -v var test.nc" should be:
+           var =
+            50, 56, 62, 68,
+            51, 57, 63, 69,
+            52, 58, 64, 70,
+            53, 59, 65, 71,
+            54, 60, 66, 72,
+            55, 61, 67, 73 ;
+     */
+
+    /* check if the contents of write buffer have been altered (should not be) */
+    for (j=0; j<4; j++) {
+        for (i=0; i<6; i++) {
+            if (var[j][i] != j*6+i + 50) {
+#ifdef PRINT_ERR_ON_SCREEN
+                /* this error is a pntecdf internal error, if occurs */
+                printf("Error: bput_varm write buffer has been altered at j=%d i=%d\n",j,i);
+#endif
+                nerrs++;
+                break;
+            }
+        }
+    }
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+
+    return nerrs;
+}
+
diff --git a/test/nonblocking/test_bputf.f90 b/test/nonblocking/test_bputf.f90
new file mode 100644
index 0000000..93f6b84
--- /dev/null
+++ b/test/nonblocking/test_bputf.f90
@@ -0,0 +1,175 @@
+!
+!   Copyright (C) 2012, Northwestern University
+!   See COPYRIGHT notice in top-level directory.
+!
+!   $Id: test_bputf.f90 2131 2015-09-25 22:33:12Z wkliao $
+
+      program main
+
+      use mpi
+      use pnetcdf
+      implicit none
+
+      logical verbose
+      integer i, j, ncid, varid, err, ierr, rank, nprocs, info
+      integer no_err, cmode, get_args
+      integer dimid(2), req(2), status(2)
+      integer(kind=MPI_OFFSET_KIND) start(2)
+      integer(kind=MPI_OFFSET_KIND) count(2)
+      integer(kind=MPI_OFFSET_KIND) stride(2)
+      integer(kind=MPI_OFFSET_KIND) imap(2)
+      integer(kind=MPI_OFFSET_KIND) bufsize
+      real  var(6,4)
+      character(len=256) :: filename, cmd, msg
+
+      call MPI_INIT(ierr)
+      call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
+      call MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, ierr)
+
+      if (rank .EQ. 0) then
+          filename = "testfile.nc"
+          err = get_args(cmd, filename)
+      endif
+      call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+      if (err .EQ. 0) goto 999
+
+      call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+      verbose = .FALSE.
+      if (nprocs > 1 .AND. rank .EQ. 0 .AND. verbose) then
+          print*,'Warning: ',trim(cmd), &
+                 ' is designed to run on 1 process'
+      endif
+
+      call MPI_Info_create(info, ierr)
+      ! call MPI_Info_set(info, "romio_pvfs2_posix_write","enable",ierr)
+
+      cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+      err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode,  &
+                           info, ncid)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_create ', &
+                                   nf90mpi_strerror(err)
+
+      call MPI_Info_free(info, ierr)
+
+      ! define a variable of a 4 x 6 integer array in the nc file
+      err = nf90mpi_def_dim(ncid, 'X', 4_MPI_OFFSET_KIND, dimid(1))
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_def_dim ', &
+                                   nf90mpi_strerror(err)
+
+      err = nf90mpi_def_dim(ncid, 'Y', 6_MPI_OFFSET_KIND, dimid(2))
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_def_dim ', &
+                                   nf90mpi_strerror(err)
+
+      err = nf90mpi_def_var(ncid, 'var', NF90_INT64, dimid, varid)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_def_var ', &
+                                   nf90mpi_strerror(err)
+
+      err = nf90mpi_enddef(ncid)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_enddef ', &
+                                   nf90mpi_strerror(err)
+
+      ! set the contents of write buffer var, a 6 x 4 real array
+      !     50, 56, 62, 68,
+      !     51, 57, 63, 69,
+      !     52, 58, 64, 70,
+      !     53, 59, 65, 71,
+      !     54, 60, 66, 72,
+      !     55, 61, 67, 73
+      do j = 1, 4
+         do i = 1, 6
+            var(i,j) = (j-1)*6+(i-1) + 50
+         enddo
+      enddo
+
+      ! bufsize must be max of data type converted before and after
+      bufsize = 4*6*8
+      err = nf90mpi_buffer_attach(ncid, bufsize)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_buffer_attach ', &
+                                   nf90mpi_strerror(err)
+
+      ! write var to the NC variable in the matrix transposed way
+      count(1)  = 2
+      count(2)  = 6
+      stride(1) = 1
+      stride(2) = 1
+      imap(1)   = 6
+      imap(2)   = 1   ! imap would be {1, 4} if not transposing
+
+      if (rank .GT. 0) then
+         count(1)  = 0
+         count(2)  = 0
+      endif
+
+      ! write the first two columns of the NC variable in the matrix transposed way
+      start(1)  = 1
+      start(2)  = 1
+      err = nf90mpi_bput_var(ncid, varid, var(1:,1:), req(1), start, count, &
+                             stride, imap)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_bput_var', &
+                                   nf90mpi_strerror(err)
+
+      ! write the second two columns of the NC variable in the matrix transposed way
+      start(1)  = 3
+      start(2)  = 1
+      err = nf90mpi_bput_var(ncid, varid, var(1:,3:), req(2), start, count, &
+                             stride, imap)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_bput_var', &
+                                   nf90mpi_strerror(err)
+
+      err = nf90mpi_wait_all(ncid, 2, req, status)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_wait_all ', &
+                                   nf90mpi_strerror(err)
+
+      ! check each bput status
+      do i = 1, 2
+          if (status(i) .ne. NF90_NOERR) then
+              print*,'Error at bput status ', nf90mpi_strerror(status(i))
+          endif
+      enddo
+
+      err = nf90mpi_buffer_detach(ncid)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_buffer_detach ', &
+                                   nf90mpi_strerror(err)
+
+      ! the output from command "ncmpidump -v var test.nc" should be:
+      !      var =
+      !       50, 56, 62, 68,
+      !       51, 57, 63, 69,
+      !       52, 58, 64, 70,
+      !       53, 59, 65, 71,
+      !       54, 60, 66, 72,
+      !       55, 61, 67, 73 ;
+      ! note that the display of ncmpidump is in C array dimensional order
+
+      ! check if the contents of write buffer have been altered (should not be)
+      no_err = 0
+      if (rank .EQ. 0) then
+         do j = 1, 4
+            do i = 1, 6
+               if (var(i,j) .NE. (j-1)*6+(i-1) + 50) then
+! #ifdef PRINT_ERR_ON_SCREEN
+!                  ! this error is a pntecdf internal error, if occurs */
+!                  print*, &
+!                  'Error: nf90mpi_bput_var write buffer has been altered at j=', &
+!                  j,' i=',i,' var=',var(i,j)
+! #endif
+                   no_err = no_err + 1
+                endif
+            enddo
+         enddo
+      endif
+
+      err = nf90mpi_close(ncid)
+      if (err < NF90_NOERR) print*,'Error at nf90mpi_close ', &
+                                   nf90mpi_strerror(err)
+
+      if (rank .EQ. 0) then
+          msg = '*** TESTING F90 '//trim(cmd)//' for bput_var'
+          call pass_fail(no_err, msg)
+      endif
+
+ 999  CALL MPI_Finalize(ierr)
+
+      end program
+
diff --git a/test/nonblocking/test_bputf77.f b/test/nonblocking/test_bputf77.f
new file mode 100644
index 0000000..42c0f20
--- /dev/null
+++ b/test/nonblocking/test_bputf77.f
@@ -0,0 +1,190 @@
+!
+!   Copyright (C) 2012, Northwestern University and Argonne National Lab
+!   See COPYRIGHT notice in top-level directory.
+!
+!   $Id: test_bputf77.f 2224 2015-12-16 06:10:36Z wkliao $
+!
+
+       INTEGER FUNCTION XTRIM(STRING)
+           CHARACTER*(*) STRING
+           INTEGER I, N
+           N = LEN(STRING)
+           DO I = N, 1, -1
+              IF (STRING(I:I) .NE. ' ') GOTO 10
+           ENDDO
+ 10        XTRIM = I
+       END ! FUNCTION XTRIM
+
+      program main
+
+      implicit none
+      include "mpif.h"
+      include "pnetcdf.inc"
+
+      logical verbose
+      integer i, j, ncid, varid, err, ierr, rank, nprocs, info
+      integer no_err, cmode, get_args, XTRIM
+      integer dimid(2), req(2), status(2)
+      integer*8 start(2)
+      integer*8 count(2)
+      integer*8 stride(2)
+      integer*8 imap(2)
+      integer*8 bufsize, dim_size
+      real  var(6,4)
+      character*256 filename, cmd, msg
+
+      call MPI_INIT(ierr)
+      call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
+      call MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, ierr)
+
+      if (rank .EQ. 0) then
+          filename = "testfile.nc"
+          err = get_args(cmd, filename)
+      endif
+      call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+      if (err .EQ. 0) goto 999
+
+      call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD,
+     +               ierr)
+
+      verbose = .FALSE.
+      if (nprocs .GT. 1 .AND. rank .EQ. 0 .AND. verbose) then
+          print*,'Warning: ',cmd(1:XTRIM(cmd)),
+     +           ' is designed to run on 1 process'
+      endif
+
+      call MPI_Info_create(info, ierr)
+      ! call MPI_Info_set(info, "romio_pvfs2_posix_write","enable",ierr)
+
+      cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+      err = nfmpi_create(MPI_COMM_WORLD, 'testfile.nc', cmode,
+     +                   info, ncid)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_create ',
+     +                           nfmpi_strerror(err)
+
+      call MPI_Info_free(info, ierr)
+
+      ! define a variable of a 4 x 6 integer array in the nc file
+      dim_size = 4
+      err = nfmpi_def_dim(ncid, 'X', dim_size, dimid(1))
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_def_dim ',
+     +                           nfmpi_strerror(err)
+
+      dim_size = 6
+      err = nfmpi_def_dim(ncid, 'Y', dim_size, dimid(2))
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_def_dim ',
+     +                           nfmpi_strerror(err)
+
+      err = nfmpi_def_var(ncid, 'var', NF_INT64, 2, dimid, varid)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_def_var ',
+     +                           nfmpi_strerror(err)
+
+      err = nfmpi_enddef(ncid)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_enddef ',
+     +                           nfmpi_strerror(err)
+
+      ! set the contents of write buffer var, a 6 x 4 real array
+      !     50, 56, 62, 68,
+      !     51, 57, 63, 69,
+      !     52, 58, 64, 70,
+      !     53, 59, 65, 71,
+      !     54, 60, 66, 72,
+      !     55, 61, 67, 73
+      do j = 1, 4
+         do i = 1, 6
+            var(i,j) = (j-1)*6+(i-1) + 50
+         enddo
+      enddo
+
+      ! bufsize must be max of data type converted before and after
+      bufsize = 4*6*8
+      err = nfmpi_buffer_attach(ncid, bufsize)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_buffer_attach ',
+     +                           nfmpi_strerror(err)
+
+      ! write var to the NC variable in the matrix transposed way
+      count(1)  = 2
+      count(2)  = 6
+      stride(1) = 1
+      stride(2) = 1
+      imap(1)   = 6
+      imap(2)   = 1   ! imap would be {1, 4} if not transposing
+
+      if (rank .GT. 0) then
+         count(1)  = 0
+         count(2)  = 0
+      endif
+
+      ! write the first two columns of the NC variable in the matrix transposed way
+      start(1)  = 1
+      start(2)  = 1
+      err = nfmpi_bput_varm_real(ncid, varid, start, count, stride,
+     +                           imap, var(1,1), req(1))
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_bput_varm_real ',
+     +                           nfmpi_strerror(err)
+
+      ! write the second two columns of the NC variable in the matrix transposed way
+      start(1)  = 3
+      start(2)  = 1
+      err = nfmpi_bput_varm_real(ncid, varid, start, count, stride,
+     +                           imap, var(1,3), req(2))
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_bput_varm_real ',
+     +                           nfmpi_strerror(err)
+
+      err = nfmpi_wait_all(ncid, 2, req, status)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_wait_all ',
+     +                           nfmpi_strerror(err)
+
+      ! check each bput status
+      do i = 1, 2
+          if (status(i) .ne. NF_NOERR) then
+              print*,'Error at bput status ', nfmpi_strerror(status(i))
+          endif
+      enddo
+
+      err = nfmpi_buffer_detach(ncid)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_buffer_detach ',
+     +                           nfmpi_strerror(err)
+
+      ! the output from command "ncmpidump -v var test.nc" should be:
+      !      var =
+      !       50, 56, 62, 68,
+      !       51, 57, 63, 69,
+      !       52, 58, 64, 70,
+      !       53, 59, 65, 71,
+      !       54, 60, 66, 72,
+      !       55, 61, 67, 73 ;
+      ! note that the display of ncmpidump is in C array dimensional order
+
+      ! check if the contents of write buffer have been altered (should not be)
+      no_err = 0
+      if (rank .EQ. 0) then
+         do j = 1, 4
+            do i = 1, 6
+               if (var(i,j) .NE. (j-1)*6+(i-1) + 50) then
+! #ifdef PRINT_ERR_ON_SCREEN
+!                  ! this error is a pntecdf internal error, if occurs */
+!                  print*, &
+!                  'Error: bput_varm write buffer has been altered at j=', &
+!                  j,' i=',i,' var=',var(i,j)
+! #endif
+                   no_err = no_err + 1
+                endif
+            enddo
+         enddo
+      endif
+
+      err = nfmpi_close(ncid)
+      if (err .NE. NF_NOERR) print*,'Error at nfmpi_close ',
+     +                           nfmpi_strerror(err)
+
+      if (rank .EQ. 0) then
+         msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//
+     +         ' for bput_varm_real API'
+         call pass_fail(no_err, msg)
+      endif
+
+ 999  CALL MPI_Finalize(ierr)
+
+      end ! program
+
diff --git a/test/nonblocking/wait_after_indep.c b/test/nonblocking/wait_after_indep.c
new file mode 100644
index 0000000..206739d
--- /dev/null
+++ b/test/nonblocking/wait_after_indep.c
@@ -0,0 +1,98 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: wait_after_indep.c 2133 2015-09-26 19:16:01Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This example tests if ncmpi_end_indep_data() works properly when nonblocking
+ * APIs are called in the independent data mode, but the wait call is made later
+ * in collective data mode.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+#define ERR \
+    if (err != NC_NOERR) { \
+        printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); \
+        nerrs++; \
+    }
+
+int main(int argc, char** argv)
+{
+    int i, j, rank, nprocs, err, nerrs=0;
+    int ncid, varid, dimid[2], req, st;
+    MPI_Offset start[2], count[2], stride[2];
+    unsigned char buffer[NY][NX];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for ncmpi_end_indep_data ", argv[0]);
+        printf("%-66s ------ ",cmd_str);
+    }
+
+    err = ncmpi_create(MPI_COMM_WORLD, "testfile.nc", NC_CLOBBER|NC_64BIT_DATA,
+                       MPI_INFO_NULL, &ncid);
+    ERR
+
+    err = ncmpi_def_dim(ncid, "Y", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX*nprocs,    &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var", NC_UBYTE, NDIMS, dimid, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    for (i=0; i<NY; i++) for (j=0; j<NX; j++) buffer[i][j] = rank;
+
+     start[0] = 0;     start[1] = NX*rank;
+     count[0] = NY/2;  count[1] = NX/2;
+    stride[0] = 2;    stride[1] = 2;
+    err = ncmpi_buffer_attach(ncid, NY*NX); ERR
+
+    err = ncmpi_begin_indep_data(ncid); ERR
+    err = ncmpi_bput_vars_uchar(ncid, varid, start, count, stride,
+                                &buffer[0][0], &req);
+    ERR
+    err = ncmpi_end_indep_data(ncid); ERR
+
+    /* calling wait API after exiting independent data mode on purpose */
+    err = ncmpi_wait_all(ncid, 1, &req, &st); ERR
+
+    err = ncmpi_buffer_detach(ncid); ERR
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/subfile/Makefile.in b/test/subfile/Makefile.in
new file mode 100644
index 0000000..e235239
--- /dev/null
+++ b/test/subfile/Makefile.in
@@ -0,0 +1,79 @@
+#
+# Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2251 2015-12-20 21:13:42Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I../../src/lib -I$(srcdir)/../common
+FPPFLAGS += -I../../src/libf @FC_MODINC at ../../src/libf90
+F90FLAGS += @FC_MODOUT at .
+LDFLAGS  := $(LDFLAGS) -L../common
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
+ifeq (@PNC_DEBUG@, yes)
+CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
+endif
+
+C_SRCS   = test_subfile.c
+
+CXX_SRCS = 
+
+F77_SRCS = 
+
+PROGS    = $(C_SRCS:.c=)
+OBJS     = $(C_SRCS:.c=.o)
+ifeq (@has_mpicxx@, yes)
+PROGS   += $(CXX_SRCS:.cpp=)
+OBJS    += $(CXX_SRCS:.cpp=.o)
+endif
+
+ifeq (@has_fortran@, yes)
+PROGS   += $(F77_SRCS:.f=)
+OBJS    += $(F77_SRCS:.f=.o)
+endif
+
+GARBAGE      = $(PROGS) *.nc
+PACKING_LIST = $(C_SRCS) $(F77_SRCS) $(CXX_SRCS) Makefile.in depend README
+
+all: $(PROGS)
+
+$(C_SRCS:.c=.o) $(CXX_SRCS:.cpp=.o): $(srcdir)/../common/testutils.h
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+test_subfile: test_subfile.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+testing check verbose_testing:
+
+TEST_MPIRUN_2 = $(subst NP,2,$(TEST_MPIRUN))
+TEST_MPIRUN_4 = $(subst NP,4,$(TEST_MPIRUN))
+
+ptest2: $(PROGS)
+	@for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_2) ./$$i -f $(TEST_OUTDIR)/testfile.nc -s 2 \
+	; ) ; done
+
+ptest4: $(PROGS)
+	@for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_4) ./$$i -f $(TEST_OUTDIR)/testfile.nc -s 2 \
+	; ) ; done
+
+ptest: ptest4
+ptests: ptest2 ptest4
+ptest6 ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+include $(srcdir)/depend
+
+$(LIBRARY): ;
+
diff --git a/test/subfile/README b/test/subfile/README
new file mode 100644
index 0000000..73f8aad
--- /dev/null
+++ b/test/subfile/README
@@ -0,0 +1,15 @@
+#
+# Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: README 1468 2013-10-26 16:53:18Z wkliao $
+#
+
+In order to use the subfiling module, pnetcdf must be configured with "--enable-subfiling" option.
+
+This is a test run to create two subfiles. Note that the number of MPI processes must be equal or larger than the number of subfiles.
+
+$ mpiexec -n 2 ./test_subfile -f test_subfile.nc -s 2
+
+This will create 1 master file (the original file, i.e., test_subfile.nc) and two subfiles, test_subfile.nc.subfile_0.nc and test_subfile.nc.subfile_1.nc.
+Since the file is intended to subfiled, the original file does not have any data; all data is stored in two subfiles.
diff --git a/test/subfile/depend b/test/subfile/depend
new file mode 100644
index 0000000..f0c4e46
--- /dev/null
+++ b/test/subfile/depend
@@ -0,0 +1,2 @@
+test_subfile.o: test_subfile.c
+
diff --git a/test/subfile/test_subfile.c b/test/subfile/test_subfile.c
new file mode 100644
index 0000000..ab8e611
--- /dev/null
+++ b/test/subfile/test_subfile.c
@@ -0,0 +1,417 @@
+/*
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ */
+/* $Id: test_subfile.c 2205 2015-11-28 20:41:50Z wkliao $ */
+#include <mpi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define MAXLINE 128
+
+/* The file name is taken as a command-line argument. */
+
+/* Measures the I/O bandwidth for writing/reading a 3D
+   block-distributed array to a file corresponding to the global array
+   in row-major (C) order.
+   Note that the file access pattern is noncontiguous.
+
+   Array size 128^3. For other array sizes, change array_of_gsizes below.*/
+#define TEST_HANDLE_ERR(status)                         \
+        if ((status) != NC_NOERR) {                     \
+            printf("Error at line %d (%s)\n", __LINE__, \
+                   ncmpi_strerror((status)) );          \
+            nerrs++;                                     \
+        }                                               \
+
+int main(int argc, char **argv)
+{
+    int opt, verbose=0;
+    extern char *optarg;
+    extern int optind;
+    int i, j, array_of_gsizes[3];
+    int nprocs, len, **buf, rank;
+    MPI_Offset bufcount;
+    int array_of_psizes[3];
+    int status;
+    MPI_Offset array_of_starts[3];
+    char *basename = NULL, *basename1 = NULL, filename[256];
+    char dimname[20], varname[20];
+    int ncid, dimids0[3], rank_dim[3], *varid=NULL;
+    MPI_Info info=MPI_INFO_NULL, info_used=MPI_INFO_NULL;
+    MPI_Offset **starts_list, **count_list;
+    MPI_Offset *bufcount_list;
+    int ndims=3, nvars=1, ngatts, unlimdimid;
+    MPI_Datatype *datatype_list;
+    int length = 128; /* 8MB per proc */
+    double stim, write_tim, new_write_tim, write_bw;
+    double read_tim, new_read_tim, read_bw;
+    double open_tim, new_open_tim;
+    double close_tim, new_close_tim;
+    int num_sf = 2;
+    int par_dim_id = 0; /* default is 0 */
+    int do_read = 0;
+    int nerrs=0;
+
+    MPI_Init(&argc,&argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* process 0 takes the file name as a command-line argument and
+       broadcasts it to other processes */
+    if (!rank) {
+	while ((opt = getopt(argc, argv, "f:s:rp:n:l:")) != EOF) {
+	    switch (opt) {
+	    case 'f': basename = optarg;
+		break;
+	    case 's': num_sf = atoi(optarg);
+		break;
+	    case 'r': do_read = 1;
+		break;
+            case 'p': par_dim_id = atoi(optarg);
+                break;
+            case 'n': nvars = atoi(optarg);
+                break;
+            case 'l': length = atoi(optarg);
+                break;
+	    default:
+		break;
+	    }
+	}
+	if (basename == NULL) {
+	    fprintf(stderr, "\n*#  Usage: test_subfile -f pathname -s num_sf -p par_dim_id \n\n");
+	    MPI_Abort(MPI_COMM_WORLD, 1);
+	}
+
+	basename1 = (char *) malloc (MAXLINE);
+	sprintf(basename1, "%s", basename);
+	len = strlen(basename1);
+	MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD);
+	MPI_Bcast(basename, len+1, MPI_CHAR, 0, MPI_COMM_WORLD);
+        MPI_Bcast(&num_sf, 1, MPI_INT, 0, MPI_COMM_WORLD);
+        MPI_Bcast(&par_dim_id, 1, MPI_INT, 0, MPI_COMM_WORLD);
+        MPI_Bcast(&nvars, 1, MPI_INT, 0, MPI_COMM_WORLD);
+        MPI_Bcast(&do_read, 1, MPI_INT, 0, MPI_COMM_WORLD);
+        MPI_Bcast(&length, 1, MPI_INT, 0, MPI_COMM_WORLD);
+    }
+    else {
+	basename1 = (char *) malloc (MAXLINE);
+	MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD);
+	MPI_Bcast(basename1, len+1, MPI_CHAR, 0, MPI_COMM_WORLD);
+        MPI_Bcast(&num_sf, 1, MPI_INT, 0, MPI_COMM_WORLD);
+        MPI_Bcast(&par_dim_id, 1, MPI_INT, 0, MPI_COMM_WORLD);
+        MPI_Bcast(&nvars, 1, MPI_INT, 0, MPI_COMM_WORLD);
+        MPI_Bcast(&do_read, 1, MPI_INT, 0, MPI_COMM_WORLD);
+        MPI_Bcast(&length, 1, MPI_INT, 0, MPI_COMM_WORLD);
+    }
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for subfiling", argv[0]);
+        printf("%-66s ------ ", cmd_str);
+    }
+
+    array_of_gsizes[0] = array_of_gsizes[1] = array_of_gsizes[2] = length;
+
+    buf = (int **)malloc(nvars*sizeof(int*));
+    if (buf == NULL){
+        printf("buf malloc error\n");
+        return 0;
+    }
+    bufcount_list = (MPI_Offset *)malloc(nvars*sizeof(MPI_Offset));
+    if (bufcount_list == NULL){
+        printf("bufcount_list malloc error\n");
+        return 0;
+    }
+    starts_list = (MPI_Offset **)malloc(nvars*sizeof(MPI_Offset *));
+    if (starts_list== NULL){
+        printf("starts_list malloc error\n");
+        return 0;
+    }
+    count_list = (MPI_Offset **)malloc(nvars*sizeof(MPI_Offset *));
+    if (count_list == NULL){
+        printf("count_list malloc error\n");
+        return 0;
+    }
+    datatype_list = (MPI_Datatype*)malloc(nvars*sizeof(MPI_Datatype));
+    if (datatype_list == NULL){
+        printf("count_list malloc error\n");
+        return 0;
+    }
+
+    for (i=0; i<nvars; i++) {
+	starts_list[i] = (MPI_Offset *)malloc(ndims*sizeof(MPI_Offset));
+	if (starts_list[i] == NULL){
+	    printf("starts_list[%d] malloc error\n", i);
+	    return 0;
+	}
+	count_list[i] = (MPI_Offset *)malloc(ndims*sizeof(MPI_Offset));
+	if (count_list[i] == NULL){
+	    printf("count_list[%d] malloc error\n", i);
+	    return 0;
+	}
+    }
+
+    bufcount = 1;
+    for (i=0; i<ndims; i++) {
+        array_of_psizes[i] = 0;
+        bufcount *= length;
+    }
+    MPI_Dims_create(nprocs, ndims, array_of_psizes);
+    if (verbose)
+        for(i=0; i<ndims&&rank==0; i++)
+	    printf("array_of_psizes[%d]=%d\n", i, array_of_psizes[i]);
+
+    /* subarray in each process is len x len x len */
+    for (i=0; i<ndims; i++)
+        array_of_gsizes[i] = length * array_of_psizes[i];
+
+    /* mynd's process rank in each dimension (in MPI_ORDER_C) */
+    rank_dim[2] =  rank %  array_of_psizes[2];
+    rank_dim[1] = (rank /  array_of_psizes[2]) % array_of_psizes[1];
+    rank_dim[0] =  rank / (array_of_psizes[2]  * array_of_psizes[1]);
+
+    /* starting coordinates of the subarray in each dimension */
+    for (i=0; i<ndims; i++)
+        array_of_starts[i] = length * rank_dim[i];
+
+    for (i=0; i<nvars; i++) {
+	for (j=0; j<ndims; j++) {
+	    starts_list[i][j] = array_of_starts[j];
+	    count_list[i][j]  = length;
+	}
+        bufcount_list[i] = bufcount;
+        datatype_list[i] = MPI_INT;
+    }
+
+    for (i=0; i<nvars; i++) {
+	buf[i] = (int *) malloc(bufcount * sizeof(int));
+	if (buf[i] == NULL){
+	    printf("buf[i]malloc error\n");
+	    return 0;
+	}
+
+	for (j=0; j<bufcount; j++)
+	    buf[i][j]=rank+1;
+    }
+
+    MPI_Info_create(&info);
+    /* set all non-record variable to be subfiled */
+    char tmp[10];
+    sprintf(tmp, "%d", num_sf);
+    MPI_Info_set(info, "nc_num_subfiles", tmp);
+
+    sprintf(filename, "%s.%d.%d.%d.nc", basename1, length, 1, 0);
+
+    if (do_read == 1) goto read;
+
+    stim = MPI_Wtime();
+    status = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER|NC_64BIT_DATA,
+                          info, &ncid);
+    TEST_HANDLE_ERR(status)
+
+    open_tim = MPI_Wtime() - stim;
+
+    MPI_Allreduce(&open_tim, &new_open_tim, 1, MPI_DOUBLE, MPI_MAX,
+                  MPI_COMM_WORLD);
+    if (verbose && rank == 0)
+        printf("create time = %f sec\n", new_open_tim);
+
+    /* define dimensions */
+    for (i=0; i<ndims; i++){
+        sprintf(dimname, "dim0_%d", i);
+        status = ncmpi_def_dim(ncid, dimname, array_of_gsizes[i], &dimids0[i]);
+        TEST_HANDLE_ERR(status)
+    }
+
+    /* define variables */
+    varid = (int *)malloc(nvars*sizeof(int));
+    for (i=0; i<nvars; i++) {
+	sprintf(varname, "var0_%d", i);
+	status = ncmpi_def_var(ncid, varname, NC_INT, ndims, dimids0, &varid[i]);
+	TEST_HANDLE_ERR(status)
+    }
+
+    if (par_dim_id != 0) {
+        for (i=0; i<nvars; i++) {
+            status = ncmpi_put_att_int(ncid, varid[i], "par_dim_id",
+                                       NC_INT, 1, &dimids0[par_dim_id]);
+	    TEST_HANDLE_ERR(status)
+        }
+    }
+
+    /* set all non-record variable to be subfiled */
+    /*
+    MPI_Info_set(info, "nc_num_subfiles", "2");
+    status = ncmpi_set_var_info(ncid, varid, info);
+    TEST_HANDLE_ERR(status);
+    */
+
+    status = ncmpi_enddef(ncid);
+    TEST_HANDLE_ERR(status)
+
+    /* test ncmpi_inq_var() */
+    for (i=0; i<nvars; i++) {
+        char name[128];
+        nc_type typep;
+        int ndimsp, dimids[3], nattsp;
+
+        status = ncmpi_inq_var(ncid, varid[i], name, &typep, &ndimsp, dimids,
+                               &nattsp);
+        TEST_HANDLE_ERR(status)
+
+	sprintf(varname, "var0_%d", i);
+        if (strcmp(name, varname)) {
+            printf("Error: unexpected var[%d] name %s, should be %s\n",i,name,varname);
+            nerrs++;
+            continue;
+        }
+        if (typep != NC_INT) {
+            printf("Error: unexpected var[%d] type %d, should be %d\n",i,typep,NC_INT);
+            nerrs++;
+            continue;
+        }
+        if (ndimsp != ndims) {
+            printf("Error: unexpected var[%d] ndims %d, should be %d\n",i,ndimsp,ndims);
+            nerrs++;
+            continue;
+        }
+        for (j=0; j<ndims; j++) {
+            if (dimids[j] != dimids0[j]) {
+                printf("Error: unexpected var[%d] dimids[%d] %d, should be %d\n",i,j,dimids0[j],dimids[j]);
+                nerrs++;
+                continue;
+            }
+        }
+        /*
+        printf("var[%d] %s has %d attributes\n",i,name,nattsp);
+        */
+    }
+
+#if 0
+    if (rank == 0)
+        printf("*** Testing to write 1 non-record variable by using ncmpi_put_vara_all() ...");
+#endif
+    stim = MPI_Wtime();
+    for (i=0; i<nvars; i++) {
+        status = ncmpi_put_vara_all(ncid, varid[i],
+                                    starts_list[i], count_list[i],
+                                    buf[i],
+                                    bufcount_list[i], MPI_INT);
+        TEST_HANDLE_ERR(status)
+    }
+    write_tim = MPI_Wtime() - stim;
+
+    MPI_Allreduce(&write_tim, &new_write_tim, 1, MPI_DOUBLE, MPI_MAX,
+                  MPI_COMM_WORLD);
+
+    if (verbose && rank == 0) {
+        write_bw = ((double)array_of_gsizes[0]*(double)array_of_gsizes[1]*(double)array_of_gsizes[2]*(double)sizeof(int)*(double)nvars)/(new_write_tim*1024.0*1024.0);
+        printf("Global array size %d x %d x %d integers\n", array_of_gsizes[0], array_of_gsizes[1], array_of_gsizes[2]);
+        printf("Collective write time = %f sec, Collective write bandwidth = %f Mbytes/sec\n", new_write_tim, write_bw);
+    }
+
+    status = ncmpi_inq_file_info(ncid, &info_used);
+    TEST_HANDLE_ERR(status)
+
+    stim = MPI_Wtime();
+    status = ncmpi_close(ncid);
+    TEST_HANDLE_ERR(status)
+    close_tim = MPI_Wtime() - stim;
+
+    MPI_Allreduce(&close_tim, &new_close_tim, 1, MPI_DOUBLE, MPI_MAX,
+                  MPI_COMM_WORLD);
+
+    if (verbose && rank == 0) {
+        fprintf(stderr, "close time = %f sec\n", new_close_tim);
+    }
+
+    goto end;
+
+read:
+    status = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid);
+    TEST_HANDLE_ERR(status)
+
+    stim = MPI_Wtime();
+
+    /**
+     * Inquire the dataset definitions of input dataset AND
+     * Add dataset definitions for output dataset.
+     */
+
+    status = ncmpi_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid);
+    TEST_HANDLE_ERR(status)
+
+    for (i=0; i<nvars; i++) {
+        status = ncmpi_get_vara_all(ncid, i,
+                                    starts_list[i], count_list[i],
+                                    buf[i], bufcount_list[i], MPI_INT);
+        TEST_HANDLE_ERR(status)
+    }
+    read_tim = MPI_Wtime() - stim;
+
+    MPI_Allreduce(&read_tim, &new_read_tim, 1, MPI_DOUBLE, MPI_MAX,
+                  MPI_COMM_WORLD);
+
+    if (verbose && rank == 0) {
+        read_bw = ((double)array_of_gsizes[0]*(double)array_of_gsizes[1]*(double)array_of_gsizes[2]*sizeof(int)*(double)nvars)/(new_read_tim*1024.0*1024.0);
+        printf("Collective read time = %f sec, Collective read bandwidth = %f Mbytes/sec\n", new_read_tim, read_bw);
+    }
+
+    status = ncmpi_inq_file_info(ncid, &info_used);
+    TEST_HANDLE_ERR(status)
+
+    status = ncmpi_close(ncid);
+    TEST_HANDLE_ERR(status)
+
+end:
+    if (info      != MPI_INFO_NULL) MPI_Info_free(&info);
+    if (info_used != MPI_INFO_NULL) MPI_Info_free(&info_used);
+
+    for (i=0; i<nvars; i++){
+        free(buf[i]);
+        free(starts_list[i]);
+        free(count_list[i]);
+    }
+    free(buf);
+    free(bufcount_list);
+    free(datatype_list);
+    if (!do_read) free(varid);
+    free(starts_list);
+    free(count_list);
+    free(basename1);
+
+    MPI_Offset malloc_size, sum_size;
+    int err, nfiles, ncids[10];
+
+    /* check if there are files still left opened */
+    err = ncmpi_inq_files_opened(&nfiles, ncids);
+    TEST_HANDLE_ERR(err)
+    if (nfiles > 0) printf("nfiles %d still opened\n",nfiles);
+
+    /* check for any PnetCDF internal malloc residues */
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+
+    return 0;
+}
diff --git a/test/testcases/Makefile.in b/test/testcases/Makefile.in
new file mode 100644
index 0000000..0bcbe88
--- /dev/null
+++ b/test/testcases/Makefile.in
@@ -0,0 +1,251 @@
+#
+# Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+# See COPYRIGHT notice in top-level directory.
+#
+# $Id: Makefile.in 2288 2016-01-02 08:14:49Z wkliao $
+#
+# @configure_input@
+
+srcdir = @srcdir@
+VPATH  = @srcdir@
+
+include ../../macros.make
+
+INCLUDES  = -I../../src/lib -I$(srcdir)/../common
+FPPFLAGS += -I../../src/libf @FC_MODINC at ../../src/libf90
+ifeq (@SIZEOF_MPI_AINT_IS_4@, yes)
+FPPFLAGS += -DSIZEOF_MPI_AINT_IS_4
+endif
+LDFLAGS  := $(LDFLAGS) -L../common
+LIBS     := $(LIBRARY) -ltestutils $(LIBS) @LCOV_LIB@
+ifeq (@PNC_DEBUG@, yes)
+CPPFLAGS := $(CPPFLAGS) -DPNC_DEBUG
+endif
+
+NCMPIGEN  = ../../src/utils/ncmpigen/ncmpigen
+NCMPIDIFF = ../../src/utils/ncmpidiff/ncmpidiff
+
+C_SRCS   = ncmpi_vars_null_stride.c \
+           vectors.c \
+           collective_error.c \
+           test_varm.c \
+           alignment_test.c \
+           flexible.c \
+           flexible2.c \
+           flexible_varm.c \
+           nonblocking.c \
+           noclobber.c \
+           record.c \
+           inq_num_vars.c \
+           varn_int.c \
+           modes.c \
+           one_record.c \
+           inq_recsize.c \
+           test_vard.c \
+           varn_contig.c \
+           ivarn.c \
+           check_striping.c \
+           add_var.c \
+           buftype_free.c \
+           last_large_var.c \
+           check_type.c \
+           test_erange.c \
+           redef1.c
+
+F77_SRCS = varn_intf.f \
+           attrf.f \
+           buftype_freef.f \
+           put_parameter.f
+
+F77F_SRCS = test_vardf.F
+
+F90_SRCS = inq_num_varsf.f90 \
+           inq_recsizef.f90 \
+           test_vardf90.f90 \
+           varn_real.f90
+
+PROGS    = $(C_SRCS:.c=)
+OBJS     = $(C_SRCS:.c=.o)
+
+ifeq (@has_fortran@, yes)
+PROGS   += $(F77_SRCS:.f=)   $(F77F_SRCS:.F=)   $(F90_SRCS:.f90=)
+OBJS    += $(F77_SRCS:.f=.o) $(F77F_SRCS:.F=.o) $(F90_SRCS:.f90=.o)
+ifeq (@large_file_test@, yes)
+PROGS   += bigrecords
+OBJS    += bigrecords.o
+endif
+endif
+
+GARBAGE      = $(PROGS) *.nc
+PACKING_LIST = $(C_SRCS) $(F77_SRCS) $(F77F_SRCS) $(F90_SRCS) \
+               bigrecords.f \
+               Makefile.in depend \
+               geopotential.ncdump \
+               redef-good.ncdump \
+               interop1.sh \
+               redef1.sh
+
+all: $(PROGS)
+
+$(C_SRCS:.c=.o): $(srcdir)/../common/testutils.h
+
+$(PROGS): ../common/libtestutils.a
+
+../common/libtestutils.a:
+	set -e; cd ../common && $(MAKE) $(MFLAGS) all
+
+ncmpi_vars_null_stride: ncmpi_vars_null_stride.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+vectors: vectors.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+bigrecords: bigrecords.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+redef1: redef1.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+collective_error: collective_error.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+test_varm: test_varm.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+alignment_test: alignment_test.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+flexible: flexible.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+flexible2: flexible2.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+flexible_varm: flexible_varm.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+nonblocking: nonblocking.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+noclobber: noclobber.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+record: record.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+inq_num_vars: inq_num_vars.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+varn_int: varn_int.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+varn_contig: varn_contig.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+modes: modes.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+one_record: one_record.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+inq_recsize: inq_recsize.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+test_vard: test_vard.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+profile: profile.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+ivarn: ivarn.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+check_striping: check_striping.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+add_var: add_var.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+buftype_free: buftype_free.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+last_large_var: last_large_var.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+check_type: check_type.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+test_erange: test_erange.o $(LIBRARY)
+	$(LINK.c) $< $(LDFLAGS) $(LIBS)
+
+inq_num_varsf: inq_num_varsf.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+inq_recsizef: inq_recsizef.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+test_vardf: test_vardf.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+varn_intf: varn_intf.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+attrf: attrf.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+buftype_freef: buftype_freef.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+put_parameter: put_parameter.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+test_vardf90: test_vardf90.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+varn_real: varn_real.o $(LIBRARY)
+	$(LINK.F90) $< $(LDFLAGS) $(LIBS)
+
+testing check verbose_testing : $(PROGS)
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc $(TEST_OUTDIR)/redef1.nc
+	for i in $(PROGS); do ( \
+	$(TEST_SEQRUN) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+	$(TEST_SEQRUN) ./redef1 $(TEST_OUTDIR)/testfile.nc
+	$(TEST_SEQRUN) $(NCMPIGEN) -v 2 -o $(TEST_OUTDIR)/redef1.nc $(srcdir)/redef-good.ncdump
+	$(TEST_SEQRUN) $(NCMPIDIFF) $(TEST_OUTDIR)/testfile.nc $(TEST_OUTDIR)/redef1.nc
+
+# Some of these tests are designed to run on one process,
+# Run them on 4 processes to see if they can handle well
+# Some of these tests are designed to run on 4 processes,
+# Run them on 2, 4, and 6 processes to see if they can handle well
+TEST_MPIRUN_2  = $(subst NP,2,$(TEST_MPIRUN))
+TEST_MPIRUN_4  = $(subst NP,4,$(TEST_MPIRUN))
+TEST_MPIRUN_6  = $(subst NP,6,$(TEST_MPIRUN))
+
+ptest4: $(PROGS)
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc $(TEST_OUTDIR)/redef1.nc
+	for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_4) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest2: $(PROGS)
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc $(TEST_OUTDIR)/redef1.nc
+	for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_2) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest6: $(PROGS)
+	$(RM) -f $(TEST_OUTDIR)/testfile.nc $(TEST_OUTDIR)/redef1.nc
+	for i in $(PROGS); do ( \
+	$(TEST_MPIRUN_6) ./$$i $(TEST_OUTDIR)/testfile.nc \
+	; ) ; done
+
+ptest: ptest4
+ptests: ptest2 ptest4 ptest6
+ptest8 ptest10:
+
+include $(srcdir)/../../rules.make
+include $(srcdir)/depend
+
+$(LIBRARY): ;
+
diff --git a/test/testcases/add_var.c b/test/testcases/add_var.c
new file mode 100644
index 0000000..725f29d
--- /dev/null
+++ b/test/testcases/add_var.c
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: add_var.c 2169 2015-11-10 22:44:11Z wkliao $
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program adds two new variables to an existing netCDF file.
+ * It is used to test if PnetCDF can correctly calculate the file offsets
+ * for the two new variables, in particular for files that align the
+ * fix-size variables to a boundary larger than 4 bytes, for instance
+ * a file created by PnetCDF with defaut alignment of 512 bytes.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicc -g -o add_var add_var.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 1 add_var testfile.nc
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}}
+
+int main(int argc, char** argv) {
+    char filename[256], var_name[NC_MAX_NAME];
+    int i, nvars, rank, nprocs, err, nerrs=0;
+    int ncid, varid, dimid[2];
+    MPI_Offset prev_off, off;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for checking offsets of new variables ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, MPI_INFO_NULL, &ncid); ERR
+
+    /* define dimensions */
+    err = ncmpi_def_dim(ncid, "dim_1", 5, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "dim_2", 4, &dimid[1]); ERR
+
+    /* define a bunch of variables */
+    for (i=0; i<10; i++) {
+        sprintf(var_name, "var_%d", i);
+        err = ncmpi_def_var(ncid, var_name, NC_INT, 2, dimid, &varid); ERR
+    }
+    err = ncmpi_enddef(ncid); ERR
+
+    /* re-enter define mode */
+    err = ncmpi_redef(ncid); ERR
+
+    /* add 2 new dimensions */
+    err = ncmpi_def_dim(ncid, "new_dim_1", 5, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "new_dim_2", 4, &dimid[1]); ERR
+
+    /* add 2 new dimensions */
+    err = ncmpi_def_var(ncid, "new_var1", NC_INT,   2, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "new_var2", NC_FLOAT, 2, dimid, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    err = ncmpi_inq_nvars(ncid, &nvars); ERR
+    err = ncmpi_inq_varoffset(ncid, 0, &prev_off); ERR
+    for (i=1; i<nvars; i++) {
+        err = ncmpi_inq_varoffset(ncid, i, &off); ERR
+        if (off < prev_off + 5*4*4) { /* each variable is of size 5*4*4 bytes */
+            err = ncmpi_inq_varname(ncid, i, var_name); ERR
+            printf("Error in %s line %d: variable %s offset is set incorrectly\n",
+                   __FILE__,__LINE__,var_name);
+            nerrs++;
+        }
+        prev_off = off;
+    }
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/alignment_test.c b/test/testcases/alignment_test.c
new file mode 100644
index 0000000..862ce02
--- /dev/null
+++ b/test/testcases/alignment_test.c
@@ -0,0 +1,295 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: alignment_test.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program tests if the file header size and variable offsets are properly
+ * set when using a different set of alignment hints to open an existing file
+ * and entering the redef mode to add more dimensions, attributes, and
+ * variables, causing the expansion of the header.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicc -g -o alignment_test alignment_test.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 4 alignment_test testfile.nc
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NVARS 8
+#define NX 5
+
+#define ERR {if(err!=NC_NOERR){nerrs++;printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}}
+
+int main(int argc, char** argv) {
+    char *filename="redef1.nc";
+    int i, j, rank, nprocs, err, verbose=0, nerrs=0;
+    int ncid, cmode, varid[NVARS], dimid[2], *buf;
+    char str[32];
+    MPI_Offset start[2], count[2];
+    MPI_Offset new_var_off[NVARS*2], old_var_off[NVARS*2];
+    MPI_Offset header_size[2], header_extent[2];
+    MPI_Info info=MPI_INFO_NULL;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for alignment ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, info, &ncid); ERR
+
+    /* define dimension */
+    err = ncmpi_def_dim(ncid, "Y", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX*nprocs, &dimid[1]); ERR
+
+#define TEST_FIXED_VAR
+#define TEST_RECORD_VAR
+    /* Odd numbers are fixed variables, even numbers are record variables */
+    for (i=0; i<NVARS; i++) {
+#ifdef TEST_FIXED_VAR
+        if (i%2) {
+            sprintf(str,"fixed_var_%d",i);
+            err = ncmpi_def_var(ncid, str, NC_INT, 1, dimid+1, &varid[i]); ERR
+        }
+#endif
+#ifdef TEST_RECORD_VAR
+        if (i%2 == 0) {
+            sprintf(str,"record_var_%d",i);
+            err = ncmpi_def_var(ncid, str, NC_INT, 2, dimid, &varid[i]); ERR
+        }
+#endif
+    }
+    err = ncmpi_enddef(ncid); ERR
+
+    /* write all variables */
+    buf = (int*) malloc(NX * sizeof(int));
+    for (i=0; i<NVARS; i++) {
+        for (j=0; j<NX; j++) buf[j] = rank*1000 + i*10 + j;
+#ifdef TEST_FIXED_VAR
+        if (i%2) {
+            start[0] = NX*rank;
+            count[0] = NX;
+            err = ncmpi_put_vara_int_all(ncid, varid[i], start, count, buf); ERR
+        }
+#endif
+#ifdef TEST_RECORD_VAR
+        if (i%2 == 0) {
+            start[0] = 0; start[1] = NX*rank;
+            count[0] = 1; count[1] = NX;
+            err = ncmpi_put_vara_int_all(ncid, varid[i], start, count, buf); ERR
+            for (j=0; j<NX; j++) buf[j] = rank*1000 + 100 + i*10 + j;
+            start[0] = 1; /* write 2nd record */
+            err = ncmpi_put_vara_int_all(ncid, varid[i], start, count, buf); ERR
+        }
+#endif
+    }
+    err = ncmpi_close(ncid); ERR
+
+    /* Now, reopen the file and grow the header and read data back */
+
+    /* mimic netCDF that does not do alignments */
+    MPI_Info_create(&info);
+    MPI_Info_set(info, "nc_header_align_size", "1"); /* size in bytes */
+    MPI_Info_set(info, "nc_var_align_size",    "197"); /* size in bytes */
+
+    /* open the file for adding more metadata */
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, info, &ncid); ERR
+
+    /* get header size and extent, and offsets of all variables */
+    err = ncmpi_inq_header_size(ncid, &header_size[0]); ERR
+    err = ncmpi_inq_header_extent(ncid, &header_extent[0]); ERR
+    for (i=0; i<NVARS; i++) {
+#ifdef TEST_FIXED_VAR
+        if (i%2)
+            err = ncmpi_inq_varoffset(ncid, varid[i], &old_var_off[i]);
+#endif
+#ifdef TEST_RECORD_VAR
+        if (i%2==0)
+            err = ncmpi_inq_varoffset(ncid, varid[i], &old_var_off[i]);
+#endif
+        ERR
+    }
+
+    /* enter redef mode */
+    err = ncmpi_redef(ncid); ERR
+
+    /* add attributes to make header grow */
+    for (i=0; i<NVARS; i++) {
+        sprintf(str, "annotation_for_var_%d",i);
+#ifdef TEST_FIXED_VAR
+        if (i%2)
+            err = ncmpi_put_att_text(ncid, varid[i], "text_attr", strlen(str), str);
+#endif
+#ifdef TEST_RECORD_VAR
+        if (i%2==0)
+            err = ncmpi_put_att_text(ncid, varid[i], "text_attr", strlen(str), str);
+#endif
+        ERR
+    }
+
+    /* add new dimensions */
+    int new_dimid[3];
+    err = ncmpi_def_dim(ncid, "new_dim_a", 5,         &new_dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "new_dim_b", 4,         &new_dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "new_dim_c", NX*nprocs, &new_dimid[2]); ERR
+
+    /* add new variables */
+    int new_varid[NVARS];
+    for (i=0; i<NVARS; i++) {
+#ifdef TEST_FIXED_VAR
+        if (i%2 == 0) {
+            sprintf(str,"fixed_var_%d",i+NVARS);
+            err = ncmpi_def_var(ncid, str, NC_INT, 1, new_dimid+2, &new_varid[i]); ERR
+        }
+#endif
+#ifdef TEST_RECORD_VAR
+        if (i%2 == 1) {
+            sprintf(str,"record_var_%d",i+NVARS);
+            err = ncmpi_def_var(ncid, str, NC_INT, 2, dimid, &new_varid[i]); ERR
+        }
+#endif
+    }
+    err = ncmpi_enddef(ncid); ERR
+
+    /* get the new header size and extent, also all variables' starting
+       file offsets */
+    err = ncmpi_inq_header_size(ncid, &header_size[1]); ERR
+    err = ncmpi_inq_header_extent(ncid, &header_extent[1]); ERR
+    if (rank == 0 && verbose) {
+        printf("NX = %d (integer type)\n",NX);
+        printf("old header_size  =%lld new header_size  =%lld\n",header_size[0],header_size[1]);
+        printf("old header_extent=%lld new header_extent=%lld\n",header_extent[0],header_extent[1]);
+
+#ifdef TEST_FIXED_VAR
+        for (i=1; i<NVARS; i+=2) {
+            err = ncmpi_inq_varoffset(ncid, varid[i], &new_var_off[i]); ERR
+            printf("old fixed  var[%2d] old offset=%4lld new offset=%4lld\n",i,old_var_off[i],new_var_off[i]);
+        }
+        for (i=NVARS; i<2*NVARS; i++) {
+            if (i%2 == 0) {
+                err = ncmpi_inq_varoffset(ncid, new_varid[i-NVARS], &new_var_off[i]); ERR
+                printf("new fixed  var[%2d]                 new offset=%4lld\n",i,new_var_off[i]);
+            }
+        }
+#endif
+#ifdef TEST_RECORD_VAR
+        for (i=0; i<NVARS; i+=2) {
+            err = ncmpi_inq_varoffset(ncid, varid[i], &new_var_off[i]); ERR
+            printf("old record var[%2d] old offset=%4lld new offset=%4lld\n",i,old_var_off[i],new_var_off[i]);
+        }
+        for (i=NVARS; i<2*NVARS; i++) {
+            if (i%2) {
+                err = ncmpi_inq_varoffset(ncid, new_varid[i-NVARS], &new_var_off[i]); ERR
+                printf("new record var[%2d]                 new offset=%4lld\n",i,new_var_off[i]);
+            }
+        }
+#endif
+    }
+
+    /* write to the new variables */
+    for (i=0; i<NVARS; i++) {
+        for (j=0; j<NX; j++) buf[j] = -1 * (i*10 + j);
+#ifdef TEST_FIXED_VAR
+        if (i%2 == 0) {
+            start[0] = NX*rank;
+            count[0] = NX;
+            err = ncmpi_put_vara_int_all(ncid, new_varid[i], start, count, buf); ERR
+        }
+#endif
+#ifdef TEST_RECORD_VAR
+        if (i%2 == 1) {
+            start[0] = 0; start[1] = NX*rank;
+            count[0] = 1; count[1] = NX;
+            err = ncmpi_put_vara_int_all(ncid, new_varid[i], start, count, buf); ERR
+            for (j=0; j<NX; j++) buf[j] = -1 * (100 + i*10 + j);
+            start[0] = 1; /* write 2nd record */
+            err = ncmpi_put_vara_int_all(ncid, new_varid[i], start, count, buf); ERR
+        }
+#endif
+    }
+
+    /* read old variables and check their contents */
+    for (i=0; i<NVARS; i++) {
+#ifdef TEST_FIXED_VAR
+        if (i%2) {
+            start[0] = NX*rank;
+            count[0] = NX;
+            err = ncmpi_get_vara_int_all(ncid, varid[i], start, count, buf); ERR
+            for (j=0; j<NX; j++)
+                if (buf[j] != rank*1000 + i*10 + j) {
+                    printf("read error i=%d buf[j=%d]=%d != %d\n",i,j,buf[j],rank*1000+i*10+j);
+                    nerrs++;
+                }
+        }
+#endif
+#ifdef TEST_RECORD_VAR
+        if (i%2 == 0) {
+            start[0] = 0; start[1] = NX*rank;
+            count[0] = 1; count[1] = NX;
+            err = ncmpi_get_vara_int_all(ncid, varid[i], start, count, buf); ERR
+            for (j=0; j<NX; j++)
+                if (buf[j] != rank*1000+i*10+j) {
+                    printf("read error i=%d buf[j=%d]=%d != %d\n",i,j,buf[j],rank*1000+i*10+j);
+                    nerrs++;
+                }
+            start[0] = 1;
+            err = ncmpi_get_vara_int_all(ncid, varid[i], start, count, buf); ERR
+            for (j=0; j<NX; j++)
+                if (buf[j] != rank*1000 + 100 + i*10 + j) {
+                    printf("read error i=%d buf[j=%d]=%d != %d\n",i,j,buf[j],rank*1000+100+i*10+j);
+                    nerrs++;
+                }
+        }
+#endif
+    }
+    err = ncmpi_close(ncid); ERR
+    MPI_Info_free(&info);
+    free(buf);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/attrf.f b/test/testcases/attrf.f
new file mode 100644
index 0000000..cf3eddf
--- /dev/null
+++ b/test/testcases/attrf.f
@@ -0,0 +1,156 @@
+!
+!   Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: attrf.f 2263 2015-12-22 15:42:05Z wkliao $
+
+! This program tests if NF_ERANGE is properly returned with a coredump
+! when an out-of-range value is used to write to a global attribute.
+! When using NAG Fortran compiler, "Arithmetic exception" and coredump
+! happens.
+!
+!    % mpif77 -O2 -o attrf attrf.f -lpnetcdf
+!    % mpiexec -n 1 ./attrf /pvfs2/wkliao/testfile.nc
+!
+
+       INTEGER FUNCTION XTRIM(STRING)
+           CHARACTER*(*) STRING
+           INTEGER I, N
+           N = LEN(STRING)
+           DO I = N, 1, -1
+              IF (STRING(I:I) .NE. ' ') GOTO 10
+           ENDDO
+ 10        XTRIM = I
+       END ! FUNCTION XTRIM
+
+      subroutine check(err, message, nerrs)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err, nerrs, XTRIM
+          character*(*) message
+          character*128 msg
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message(1:XTRIM(message)), nfmpi_strerror(err)
+              msg = '*** TESTING F77 attrf.f for attribute overflow '
+              call pass_fail(1, msg)
+              nerrs = nerrs + 1
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          real                    buf_flt
+          double precision        buf_dbl
+          integer                 buf_int, XTRIM
+          integer*2 buf_int2
+          integer*8 buf_int8, one
+
+          character*256 filename, cmd, msg
+          integer ncid, err, ierr, nerrs, nprocs, rank, get_args
+          integer*8 malloc_size, sum_size
+
+          call MPI_Init(ierr)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, ierr)
+
+          one = 1
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              filename = "testfile.nc"
+              err = get_args(cmd, filename)
+          endif
+          call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+          if (err .EQ. 0) goto 999
+
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, ierr)
+
+          nerrs = 0
+
+          err = nfmpi_create(MPI_COMM_WORLD, filename, NF_CLOBBER,
+     +                       MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ', nerrs)
+
+          ! use a number > X_INT_MAX (which is 2147483647)
+          buf_flt  =  2147483648.0
+          buf_dbl  =  2147483648.0
+          buf_int8 =  1073741824
+          buf_int8 =  buf_int8 * 2
+
+          err = nfmpi_put_att_real(ncid, NF_GLOBAL, "attr1", NF_INT,
+     +                             one, buf_flt)
+          if (err .NE. NF_ERANGE) then
+              print*, "Error: expect NF_ERANGE but got ", err
+              if (err .NE. NF_NOERR) print*, nfmpi_strerror(err)
+              nerrs = nerrs + 1
+              ! Note: even with an error, the attribute is still being created
+          endif
+
+          err = nfmpi_put_att_double(ncid, NF_GLOBAL, "attr2", NF_INT,
+     +                               one, buf_dbl)
+          if (err .NE. NF_ERANGE) then
+              print*, "Error: expect NF_ERANGE but got ", err
+              if (err .NE. NF_NOERR) print*, nfmpi_strerror(err)
+              nerrs = nerrs + 1
+              ! Note: even with an error, the attribute is still being created
+          endif
+
+          err = nfmpi_put_att_int8(ncid, NF_GLOBAL, "attr3", NF_INT,
+     +                             one, buf_int8)
+          if (err .NE. NF_ERANGE) then
+              print*, "Error: expect NF_ERANGE but got ", err
+              if (err .NE. NF_NOERR) print*, nfmpi_strerror(err)
+              nerrs = nerrs + 1
+              ! Note: even with an error, the attribute is still being created
+          endif
+
+          buf_int = 2147483647
+          err = nfmpi_put_att_int(ncid, NF_GLOBAL, "attr4", NF_INT,
+     +                            one, buf_int)
+          call check(err, 'In nfmpi_put_att_int: ', nerrs)
+
+          ! because of the NF_ERANGE error, the attributes may become
+          ! inconsistent among processes, So NC_EMULTIDEFINE_ATTR_VAL
+          ! or NF_EMULTIDEFINE may be returned from nfmpi_enddef.
+          ! While in safe mode, the warning message of inconsistent metadata
+          ! may appear on the screen. This is expected.
+          err = nfmpi_enddef(ncid)
+          if (err .NE. NF_NOERR .AND. err .NE. NF_EMULTIDEFINE .AND.
+     +        err .NE. NF_EMULTIDEFINE_ATTR_VAL)
+     +        call check(err, 'In nfmpi_enddef: ', nerrs)
+
+          err = nfmpi_get_att_int2(ncid, NF_GLOBAL, "attr4", buf_int2)
+          if (err .NE. NF_ERANGE) then
+              print*, "Error: expect NF_ERANGE but got ", err
+              if (err .NE. NF_NOERR) print*, nfmpi_strerror(err)
+              nerrs = nerrs + 1
+          endif
+
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ', nerrs)
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, ierr)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+          msg ='*** TESTING F77 '//cmd(1:XTRIM(cmd))//
+     +         ' for attribute overflow '
+          if (rank .eq. 0) call pass_fail(nerrs, msg)
+
+ 999      call MPI_Finalize(ierr)
+
+      end ! program main
diff --git a/test/testcases/bigrecords.f b/test/testcases/bigrecords.f
new file mode 100644
index 0000000..eed43f9
--- /dev/null
+++ b/test/testcases/bigrecords.f
@@ -0,0 +1,338 @@
+!
+!  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+!  $Id: bigrecords.f 2224 2015-12-16 06:10:36Z wkliao $
+
+!
+! this test case came from Annette Koonts at PNNL
+!
+! test creates a dataset with several (large) record variables, but also a
+! smaller 'time' record variable.
+!
+! on 64 bit systems or on BlueGene (where MPI_AINT is 32 bits), this test will
+! read the smaller time variable OK, but on systems with a 32 bit MPI_AINT, the
+! time variable will be garbled.
+
+       INTEGER FUNCTION XTRIM(STRING)
+           CHARACTER*(*) STRING
+           INTEGER I, N
+           N = LEN(STRING)
+           DO I = N, 1, -1
+              IF (STRING(I:I) .NE. ' ') GOTO 10
+           ENDDO
+ 10        XTRIM = I
+       END ! FUNCTION XTRIM
+
+      program main
+      implicit none
+      include "mpif.h"
+      include "pnetcdf.inc"
+
+
+! error status return
+      integer  iret
+! netCDF id
+      integer  ncid
+! dimension ids
+      integer  time_dim
+      integer  cells_dim
+      integer  interfaces_dim
+      integer  XTRIM
+
+! dimension lengths
+      integer*8  cells_len
+      integer  interfaces_len
+
+      parameter (cells_len = 41943042)
+      parameter (interfaces_len = 26)
+
+! variable ids
+      integer  time_id
+      integer  interfaces_id
+      integer  pressure_id
+
+      integer (kind=MPI_OFFSET_KIND) :: longlen
+
+      integer (kind=MPI_OFFSET_KIND) :: start1d(1)
+      integer (kind=MPI_OFFSET_KIND) :: count1d(1)
+
+! rank (number of dimensions) for each variable
+      integer  time_rank
+      integer  interfaces_rank
+      integer  pressure_rank
+
+      parameter (time_rank = 1)
+      parameter (interfaces_rank = 1)
+      parameter (pressure_rank = 3)
+
+! variable shapes
+      integer  time_dims(time_rank)
+      integer  interfaces_dims(interfaces_rank)
+      integer  pressure_dims(pressure_rank)
+
+! data variables
+      real  interfaces(interfaces_len)
+
+      integer  myid, err, ierr, n, get_args
+      integer  numprocs
+
+      integer*8 i8_size
+
+      integer*8 time_start(1), time_count(1)
+
+      double precision  time(4)
+!      data time /0., 20., 40., 60./
+
+      data interfaces /2685.8359, 671.81, 495.91, 425.10001, 393.42999, 
+     + 377.5, 367.59, 360.06, 353.85999, 348.66, 342.5, 336, 328.5, 320,
+     + 310, 300, 290, 280, 270, 260, 250, 240, 230, 220, 210, 199.10001/
+
+      character*256 filename, cmd, msg
+
+! attribute vectors
+! enter define mode
+!      iret = nf_create('pressure_19010101_000000.nc', OR(NF_CLOBBER,NF_64BIT_OFFSET), ncid)
+
+      call MPI_INIT(ierr)
+      call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr)
+      call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr)
+
+      if (myid .EQ. 0) then
+          filename = "testfile.nc"
+          err = get_args(cmd, filename)
+      endif
+      call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+      if (err .EQ. 0) goto 999
+
+      call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD,
+     +               ierr)
+
+      iret = nfmpi_create( MPI_COMM_WORLD, filename,
+     +                       IOR(NF_CLOBBER,NF_64BIT_DATA), 
+     +                       MPI_INFO_NULL, ncid)
+
+        call check_err("nfmpi_create(): ", iret)
+  
+! define dimensions
+
+        iret = nfmpi_def_dim(ncid, 'time', NFMPI_UNLIMITED, time_dim)
+        call check_err("nfmpi_def_dim(): time ", iret)
+
+        i8_size = 41943042
+
+        iret = nfmpi_def_dim(ncid, 'cells', i8_size, cells_dim)
+        call check_err("nfmpi_def_dim(): cells ", iret)
+
+        i8_size = 26
+        iret = nfmpi_def_dim(ncid, 'interfaces', 
+     +                       i8_size, interfaces_dim)
+        call check_err("nfmpi_def_dim(): interfaces ", iret)
+! define variables
+        time_dims(1) = time_dim
+
+        iret = nfmpi_def_var(ncid, 'time', NF_DOUBLE, 
+     +                       time_rank, time_dims, 
+     +                       time_id)
+        call check_err("nfmpi_def_var(): time ", iret)
+        interfaces_dims(1) = interfaces_dim
+
+        iret = nfmpi_def_var(ncid, 'interfaces', NF_REAL, 
+     +                       interfaces_rank, 
+     +                       interfaces_dims, interfaces_id)
+        call check_err("nfmpi_def_var(): interfaces ", iret)
+
+        pressure_dims(3) = time_dim
+        pressure_dims(2) = cells_dim
+        pressure_dims(1) = interfaces_dim
+        iret = nfmpi_def_var(ncid, 
+     +                     'pressure', 
+     +                     NF_REAL, 
+     +                     pressure_rank, 
+     +                     pressure_dims, 
+     +                     pressure_id)
+
+        call check_err("nfmpi_def_var(): pressure ", iret)
+! assign attributes
+
+        longlen = 4
+        iret = nfmpi_put_att_text(ncid, time_id, 'long_name', 
+     +                            longlen, 'Time')
+        call check_err("nfmpi_put_att_text(): long_name ", iret)
+        longlen = 21
+        iret = nfmpi_put_att_text(ncid, time_id, 'units', 
+     +                            longlen, 
+     +                           'days since 1901-01-01')
+        call check_err("nfmpi_put_att_text(): units ", iret)
+
+        longlen = 41
+        iret = nfmpi_put_att_text(ncid, interfaces_id, 'long_name', 
+     +                            longlen,
+     +                     'Vertical interfaces, in terms of pressure')
+        call check_err("nfmpi_put_att_text(): long_name ", iret)
+
+        longlen = 2
+        iret = nfmpi_put_att_text(ncid, interfaces_id, 'units', 
+     +                            longlen, 'Pa')
+        call check_err("nfmpi_put_att_text(): units ", iret)
+
+        longlen = 8
+        iret = nfmpi_put_att_text(ncid, pressure_id, 'long_name', 
+     +                            longlen, 
+     1                       'Pressure')
+        call check_err("nfmpi_put_att_text(): ", iret)
+
+        longlen = 2
+        iret = nfmpi_put_att_text(ncid, pressure_id, 'units', 
+     +                            longlen, 'Pa')
+        call check_err("nfmpi_put_att_text(): units ", iret)
+
+! leave define mode
+        iret = nfmpi_enddef(ncid)
+        call check_err("nfmpi_enddef(): ", iret)
+
+        start1d(1) = 1
+        count1d(1) = 26
+        if (myid .GT. 0) count1d = 0
+
+! store interfaces
+        iret = nfmpi_put_vara_real_all(ncid, interfaces_id,
+     +                                 start1d, count1d, interfaces)
+        call check_err("nfmpi_put_vara_real_all(): ", iret)
+
+        time(1) = 0.0
+        time(2) = 20.0
+        time(3) = 40.0
+        time(4) = 60.0
+      
+! this test is tricky because it writes out the time variable one at a time.
+! This element-at-a-time workload does not actually exercise the tricky 32 bit
+! MPI_AINT problem, so the issue only shows up at read time.
+
+        do n = 1, 4
+          time_start(1) = n
+          if(myid .eq. 0) then
+            time_count(1) = 1
+          else
+            time_count(1) = 0
+          endif
+
+          iret = nfmpi_put_vara_double_all(ncid, time_id, 
+     +                                     time_start, time_count,
+     +                                     time(n))
+          call check_err("nfmpi_put_vara_double_all(): ", iret)
+        enddo
+
+        iret = nfmpi_close(ncid)
+
+        call MPI_Barrier (MPI_COMM_WORLD, iret)
+
+! todo: insert code to re-open dataset, read time variable all at onece
+! 
+      iret = nfmpi_open ( MPI_COMM_SELF,
+     +                   filename,
+     +                   IOR(NF_CLOBBER,NF_64BIT_DATA),
+     +                   MPI_INFO_NULL,
+     +                   ncid)
+      call check_err("nfmpi_open(): ", iret)
+
+      iret = nfmpi_inq_varid(ncid, 'time', time_id);
+      call check_err("nfmpi_inq_varid(): time ", iret)
+
+      ! deliberately want all processes to end up with the full time array
+      time_start(1) = 1
+      time_count(1) = 4
+      iret = nfmpi_get_vara_double_all(ncid, time_id,
+     +                               time_start, time_count, time);
+      call check_err("nfmpi_get_vara_double_all(): ", iret)
+
+      iret = nfmpi_close(ncid)
+      call check_err("nfmpi_close(): ", iret)
+
+!     write(6,*) "Time array: ", time
+!      if ( (time(1) .eq. 0) .and. (time(2) .eq. 20.0)
+!     &             .and. (time(3) .eq. 40.0) .and. (time(4) .eq. 60))
+!           write(6,*) " No Errors"
+!      else
+!           write(6,*) "Error: time array was ", time
+!      endif
+
+      msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//' for NF_64BIT_DATA'
+      if (myid .eq. 0) call pass_fail(0, msg)
+
+ 999  call MPI_FINALIZE(ierr)
+      end ! program main
+       
+      subroutine writerecs(ncid,time_id)
+
+      implicit none
+      include "mpif.h"
+      include "pnetcdf.inc"
+       
+! netCDF id
+      integer  ncid
+! variable ids
+      integer  time_id
+
+! error status return
+      integer  iret
+      integer  n
+       
+! netCDF dimension sizes for dimensions used with record variables
+      integer  cells_len
+      parameter (cells_len = 41943042)
+      integer  interfaces_len
+      parameter (interfaces_len = 26)
+       
+! rank (number of dimensions) for each variable
+      integer  time_rank
+      integer  pressure_rank
+      parameter (time_rank = 1)
+      parameter (pressure_rank = 3)
+! starts and counts for array sections of record variables
+      integer*8 time_start(1), time_count(1)
+
+! data variables
+       
+      integer  time_nr
+      parameter (time_nr = 4)
+       
+      integer  pressure_nr
+      parameter (pressure_nr = 1)
+!      real  pressure(interfaces_len, cells_len, pressure_nr)
+       
+      double precision  time(time_nr)
+      data time /0., 20., 40., 60./
+      
+
+!      pressure = NF_FILL_FLOAT
+
+! store time
+
+      do n = 1, 4
+        time_start(1) = n
+        time_count(1) = 1
+        iret = nfmpi_put_vara_double_all(ncid, time_id, 
+     +                                   time_start, time_count,
+     +                                   time)
+
+        call check_err("nfmpi_put_vara_double_all(): ", iret)
+      enddo
+       
+      end ! subroutine writerecs
+       
+      subroutine check_err(msg, iret)
+
+      include "pnetcdf.inc"
+
+      character*(*) msg
+      integer iret
+
+      if (iret .ne. NF_NOERR) then
+          print *, msg, nfmpi_strerror(iret)
+          msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//
+     +          ' for NF_64BIT_DATA'
+          call pass_fail(1, msg)
+          stop
+      endif
+      end ! subroutine check_err
diff --git a/test/testcases/buftype_free.c b/test/testcases/buftype_free.c
new file mode 100644
index 0000000..aa0234f
--- /dev/null
+++ b/test/testcases/buftype_free.c
@@ -0,0 +1,126 @@
+/*
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: buftype_free.c 2165 2015-11-05 07:18:49Z wkliao $
+ */
+
+/*
+ * This example tests if PnetCDF duplicates the MPI derived data type supplied
+ * by the user, when calling the flexible APIs. It tests a PnetCDF bug
+ * prior to version 1.6.1.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 4
+#define NX 4
+#define ERR if (err!=NC_NOERR) {printf("Error at line %d: %s\n", __LINE__,ncmpi_strerror(err)); exit(-1);}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv) {
+
+    char filename[256];
+    int  i, j, err, ncid, varid[4], dimids[2], req[4], st[4], nerrs=0;
+    int  rank, nprocs, buf[4][(NY+4)*(NX+4)];
+    int  gsize[2], subsize[2], a_start[2], ghost;
+    MPI_Offset start[2], count[2];
+    MPI_Datatype buftype[4];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for free buftype in flexible API ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, MPI_INFO_NULL, &ncid); ERR
+
+    /* define a 2D array */
+    err = ncmpi_def_dim(ncid, "Y", NY*nprocs, &dimids[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX,        &dimids[1]); ERR
+    err = ncmpi_def_var(ncid, "var0", NC_INT, 2, dimids, &varid[0]); ERR
+    err = ncmpi_def_var(ncid, "var1", NC_INT, 2, dimids, &varid[1]); ERR
+    err = ncmpi_def_var(ncid, "var2", NC_INT, 2, dimids, &varid[2]); ERR
+    err = ncmpi_def_var(ncid, "var3", NC_INT, 2, dimids, &varid[3]); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* initialize the contents of the array */
+    for (i=0; i<4; i++) for (j=0; j<(NY+4)*(NX+4); j++) buf[i][j] = rank;
+
+    start[0] = NY*rank; start[1] = 0;
+    count[0] = NY;      count[1] = NX;
+
+    err = ncmpi_put_vara_int_all(ncid, varid[0], start, count, buf[0]); ERR
+    err = ncmpi_put_vara_int_all(ncid, varid[1], start, count, buf[1]); ERR
+    err = ncmpi_put_vara_int_all(ncid, varid[2], start, count, buf[2]); ERR
+    err = ncmpi_put_vara_int_all(ncid, varid[3], start, count, buf[3]); ERR
+
+
+    /* define an MPI datatype using MPI_Type_create_subarray() */
+    ghost      = 2;
+    gsize[1]   = NX + 2 * ghost;
+    gsize[0]   = NY + 2 * ghost;
+    subsize[1] = NX;
+    subsize[0] = NY;
+    a_start[1] = ghost;
+    a_start[0] = ghost;
+
+    for (i=0; i<4; i++) {
+        req[i] = NC_REQ_NULL;
+        st[i]  = NC_NOERR;
+        MPI_Type_create_subarray(2, gsize, subsize, a_start, MPI_ORDER_C, MPI_INT, &buftype[i]);
+        MPI_Type_commit(&buftype[i]);
+
+        err = ncmpi_iget_vara(ncid, varid[i], start, count, buf[i], 1, buftype[i], &req[i]); ERR
+        MPI_Type_free(&buftype[i]);
+    }
+
+    err = ncmpi_wait_all(ncid, 4, req, st); ERR
+    for (i=0; i<4; i++) {
+        if (st[i] != NC_NOERR) {
+            printf("Error: ncmpi_wait_all st[%d] %s\n",i, ncmpi_strerror(st[i]));
+            nerrs++;
+        }
+    }
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/buftype_freef.f b/test/testcases/buftype_freef.f
new file mode 100644
index 0000000..e3dfcf1
--- /dev/null
+++ b/test/testcases/buftype_freef.f
@@ -0,0 +1,169 @@
+!
+!   Copyright (C) 2015, Northwestern University
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: buftype_freef.f 2224 2015-12-16 06:10:36Z wkliao $
+
+! This example tests if PnetCDF duplicates the MPI derived data type supplied
+! by the user, when calling the flexible APIs. It tests a PnetCDF bug
+! prior to version 1.6.1.
+!
+! The compile and run commands:
+!
+!    % mpif77 -O2 -o buftype_freef buftype_freef.f -lpnetcdf
+!    % mpiexec -n 4 ./buftype_freef /pvfs2/wkliao/testfile.nc
+!
+
+       INTEGER FUNCTION XTRIM(STRING)
+           CHARACTER*(*) STRING
+           INTEGER I, N
+           N = LEN(STRING)
+           DO I = N, 1, -1
+              IF (STRING(I:I) .NE. ' ') GOTO 10
+           ENDDO
+ 10        XTRIM = I
+       END ! FUNCTION XTRIM
+
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err, XTRIM
+          character*(*) message
+          character*128 msg
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message(1:XTRIM(message)), nfmpi_strerror(err)
+              msg = '*** TESTING F77 buftype_freef.f for flexible API '
+              call pass_fail(1, msg)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          integer NREQS, XTRIM
+          integer*8 NX, NY
+          PARAMETER(NREQS=4, NX=4, NY=4)
+
+          character*256 filename, cmd, msg, varname, str
+          integer i, err, ierr, nprocs, rank, nerrs, get_args
+          integer ncid, ghost
+          integer var(64,4), varid(4), dimid(2), req(4), st(4)
+          integer buftype(4), gsize(2), subsize(2), a_start(2)
+          integer*8 start(2), count(2)
+          integer*8 one, malloc_size, sum_size
+
+          call MPI_Init(ierr)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, ierr)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              filename = "testfile.nc"
+              err = get_args(cmd, filename)
+          endif
+          call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+          if (err .EQ. 0) goto 999
+
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, ierr)
+
+          nerrs = 0
+
+          ! create file, truncate it if exists
+          err = nfmpi_create(MPI_COMM_WORLD, filename, NF_CLOBBER,
+     +                        MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define dimensions x and y
+          err = nfmpi_def_dim(ncid, "X", NX, dimid(1))
+          call check(err, 'In nfmpi_def_dim X: ')
+          err = nfmpi_def_dim(ncid, "Y", NY*nprocs, dimid(2))
+          call check(err, 'In nfmpi_def_dim Y: ')
+
+          ! define 2D variables of integer type
+          do i=1, NREQS
+             write(str,'(I1)') i
+             varname = 'var'//str(1:XTRIM(str))
+             err = nfmpi_def_var(ncid,varname,NF_INT,2,dimid,varid(i))
+             call check(err, 'In nfmpi_def_var '//
+     |                  varname(1:XTRIM(varname))//' : ')
+          enddo
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! Note that in Fortran, array indices start with 1
+          start(1) = 1
+          start(2) = NY * rank + 1
+          count(1) = NX
+          count(2) = NY
+
+          do i=1, NREQS
+             err = nfmpi_put_vara_int_all(ncid, varid(i), start, count,
+     +                                    var(1,i))
+             call check(err, 'In nfmpi_put_vara_int_all: ')
+          enddo
+
+          ! define an MPI datatype using MPI_Type_create_subarray()
+          one        = 1
+          ghost      = 2
+          gsize(1)   = INT(NX) + 2 * ghost
+          gsize(2)   = INT(NY) + 2 * ghost
+          subsize(1) = INT(NX)
+          subsize(2) = INT(NY)
+          a_start(1) = ghost - 1
+          a_start(2) = ghost - 1
+
+          do i = 1, NREQS
+              call MPI_Type_create_subarray(2, gsize, subsize, a_start,
+     +             MPI_ORDER_FORTRAN, MPI_INTEGER, buftype(i), err)
+              call MPI_Type_commit(buftype(i), err)
+
+              err = nfmpi_iget_vara(ncid, varid(i), start, count,
+     +                              var(1,i), one, buftype(i), req(i))
+              call check(err, 'In nfmpi_iget_vara ')
+              ! immediately free the data type
+              call MPI_Type_free(buftype(i), err)
+          enddo
+
+          ! wait for the nonblocking I/O to complete
+          err = nfmpi_wait_all(ncid, NREQS, req, st)
+          call check(err, 'In nfmpi_wait_all')
+
+          ! check the status of each nonblocking request
+          do i=1, NREQS
+             write(str,'(I2)') i
+             call check(st(i), 'In nfmpi_wait_all req '//
+     +                         str(1:XTRIM(str)))
+          enddo
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+          msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//
+     +          ' for flexible API '
+          if (rank .eq. 0) call pass_fail(nerrs, msg)
+
+ 999      call MPI_Finalize(ierr)
+      end ! program main
+
diff --git a/test/testcases/check_striping.c b/test/testcases/check_striping.c
new file mode 100644
index 0000000..06b5092
--- /dev/null
+++ b/test/testcases/check_striping.c
@@ -0,0 +1,99 @@
+/*
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: check_striping.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program tests whether the file striping size and count retrieved from
+ * MPI-IO hints are consistent among all MPI processes.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicc -g -o get_striping get_striping.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 4 get_striping testfile.nc
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define ERR {if(err!=NC_NOERR){nerrs++;printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}}
+
+int main(int argc, char** argv) {
+    char *filename="testfile.nc";
+    int rank, nprocs, err, nerrs=0, ncid, cmode;
+    int striping_size, striping_count, root_striping_size, root_striping_count;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for strining info ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    err = ncmpi_inq_striping(ncid, &striping_size, &striping_count); ERR
+
+    root_striping_size  = striping_size;
+    root_striping_count = striping_count;
+    MPI_Bcast(&root_striping_size,  1, MPI_INT, 0, MPI_COMM_WORLD);
+    MPI_Bcast(&root_striping_count, 1, MPI_INT, 0, MPI_COMM_WORLD);
+    if (root_striping_size != striping_size) {
+        printf("Error at PE %2d: inconsistent striping_size (root=%d local=%d)\n",
+               rank, root_striping_size, striping_size);
+        nerrs++;
+    }
+    if (root_striping_count != striping_count) {
+        printf("Error at PE %2d: inconsistent striping_count (root=%d local=%d)\n",
+               rank, root_striping_count, striping_count);
+        nerrs++;
+    }
+/*
+    if (nerrs == 0 && rank == 0)
+        printf("Success: striping_size=%d striping_count=%d\n",striping_size,striping_count);
+*/
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/check_type.c b/test/testcases/check_type.c
new file mode 100644
index 0000000..b519ce9
--- /dev/null
+++ b/test/testcases/check_type.c
@@ -0,0 +1,249 @@
+/*
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id$
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program tests conflicted in-memory data types against external data
+ * types and see if the correct error codes were returned.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicc -g -o check_type check_type.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 1 check_type testfile.nc
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+static char* err_code_name(int err);
+
+static char* etype_name(nc_type etype) {
+    switch (etype) {
+        case (0):  return "NC_NAT";
+        case (1):  return "NC_BYTE";
+        case (2):  return "NC_CHAR";
+        case (3):  return "NC_SHORT";
+        case (4):  return "NC_INT";
+        case (5):  return "NC_FLOAT";
+        case (6):  return "NC_DOUBLE";
+        case (7):  return "NC_UBYTE";
+        case (8):  return "NC_USHORT";
+        case (9):  return "NC_UINT";
+        case (10): return "NC_INT64";
+        case (11): return "NC_UINT64";
+        default:
+              return "Invalid nc_type";
+    }
+}
+
+#define ERR0 { \
+    if (err != NC_NOERR) { \
+        printf("Error at line %d err=%s\n",__LINE__,err_code_name(err)); \
+        nerrs++; \
+    } \
+}
+
+#define ERR(expect_err,itype,etype) { \
+    if (err != expect_err) { \
+        printf("Error at line %3d: itype=%9s etype=%-9s err=%s\n", \
+               __LINE__,itype,etype_name(etype),err_code_name(err)); \
+        nerrs++; \
+    }  \
+} 
+
+int main(int argc, char* argv[])
+{
+    char filename[256], *varname[12], buf[1024], attname[256];
+    int i, err, nerrs=0, rank, ncid, dimid, varid[12];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for checking for type conflict ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER|NC_64BIT_DATA, MPI_INFO_NULL, &ncid); ERR0
+    err = ncmpi_def_dim(ncid, "x", 2, &dimid); ERR0
+
+    varname[0]  = "var_nat";
+    varname[1]  = "var_byte";
+    varname[2]  = "var_char";
+    varname[3]  = "var_short";
+    varname[4]  = "var_int";
+    varname[5]  = "var_float";
+    varname[6]  = "var_double";
+    varname[7]  = "var_ubyte";
+    varname[8]  = "var_ushort";
+    varname[9]  = "var_uint";
+    varname[10] = "var_int64";
+    varname[11] = "var_uint64";
+    for (i=NC_BYTE; i<=NC_UINT64; i++) {
+        err = ncmpi_def_var(ncid, varname[i], i, 1, &dimid, &varid[i]); ERR0
+    }
+
+    for (i=0; i<1024; i++) buf[i]=i;
+    err = ncmpi_put_att_text(ncid, NC_GLOBAL, "att_text", 3, (char*)buf); ERR0
+    ERR(NC_NOERR, "text", NC_CHAR)
+
+    for (i=0; i<1024; i++) buf[i]=0;
+    for (i=NC_BYTE; i<=NC_UINT64; i++) {
+        int expect_err = NC_NOERR;
+
+        if (i == NC_CHAR) expect_err = NC_ECHAR;
+
+        sprintf(attname,"att_uchar_for_var_%s",varname[i]);
+        err = ncmpi_put_att_uchar    (ncid, NC_GLOBAL, attname, i, 3, (unsigned char*)      buf);
+        ERR(expect_err, "uchar", i)
+        sprintf(attname,"att_schar_for_var_%s",varname[i]);
+        err = ncmpi_put_att_schar    (ncid, NC_GLOBAL, attname, i, 3, (signed char*)        buf);
+        ERR(expect_err, "schar", i)
+        sprintf(attname,"att_short_for_var_%s",varname[i]);
+        err = ncmpi_put_att_short    (ncid, NC_GLOBAL, attname, i, 3, (short*)              buf);
+        ERR(expect_err, "short", i)
+        sprintf(attname,"att_int_for_var_%s",varname[i]);
+        err = ncmpi_put_att_int      (ncid, NC_GLOBAL, attname, i, 3, (int*)                buf);
+        ERR(expect_err, "int", i)
+        sprintf(attname,"att_float_for_var_%s",varname[i]);
+        err = ncmpi_put_att_float    (ncid, NC_GLOBAL, attname, i, 3, (float*)              buf);
+        ERR(expect_err, "float", i)
+        sprintf(attname,"att_double_for_var_%s",varname[i]);
+        err = ncmpi_put_att_double   (ncid, NC_GLOBAL, attname, i, 3, (double*)             buf);
+        ERR(expect_err, "double", i)
+        sprintf(attname,"att_ushort_for_var_%s",varname[i]);
+        err = ncmpi_put_att_ushort   (ncid, NC_GLOBAL, attname, i, 3, (unsigned short*)     buf);
+        ERR(expect_err, "ushort", i)
+        sprintf(attname,"att_uint_for_var_%s",varname[i]);
+        err = ncmpi_put_att_uint     (ncid, NC_GLOBAL, attname, i, 3, (unsigned int*)       buf);
+        ERR(expect_err, "uint", i)
+        sprintf(attname,"att_longlong_for_var_%s",varname[i]);
+        err = ncmpi_put_att_longlong (ncid, NC_GLOBAL, attname, i, 3, (long long*)          buf);
+        ERR(expect_err, "longlong", i)
+        sprintf(attname,"att_ulonglong_for_var_%s",varname[i]);
+        err = ncmpi_put_att_ulonglong(ncid, NC_GLOBAL, attname, i, 3, (unsigned long long*) buf);
+        ERR(expect_err, "ulonglong", i)
+    }
+
+    for (i=NC_BYTE; i<=NC_UINT64; i++) {
+        int expect_err = NC_NOERR;
+
+        if (i == NC_CHAR) continue;
+
+        sprintf(attname,"att_uchar_for_var_%s",varname[i]);
+        err = ncmpi_get_att_uchar    (ncid, NC_GLOBAL, attname, (unsigned char*)      buf);
+        ERR(expect_err, "uchar", i)
+        sprintf(attname,"att_schar_for_var_%s",varname[i]);
+        err = ncmpi_get_att_schar    (ncid, NC_GLOBAL, attname, (signed char*)        buf);
+        ERR(expect_err, "schar", i)
+        sprintf(attname,"att_short_for_var_%s",varname[i]);
+        err = ncmpi_get_att_short    (ncid, NC_GLOBAL, attname, (short*)              buf);
+        ERR(expect_err, "short", i)
+        sprintf(attname,"att_int_for_var_%s",varname[i]);
+        err = ncmpi_get_att_int      (ncid, NC_GLOBAL, attname, (int*)                buf);
+        ERR(expect_err, "int", i)
+        sprintf(attname,"att_float_for_var_%s",varname[i]);
+        err = ncmpi_get_att_float    (ncid, NC_GLOBAL, attname, (float*)              buf);
+        ERR(expect_err, "float", i)
+        sprintf(attname,"att_double_for_var_%s",varname[i]);
+        err = ncmpi_get_att_double   (ncid, NC_GLOBAL, attname, (double*)             buf);
+        ERR(expect_err, "double", i)
+        sprintf(attname,"att_ushort_for_var_%s",varname[i]);
+        err = ncmpi_get_att_ushort   (ncid, NC_GLOBAL, attname, (unsigned short*)     buf);
+        ERR(expect_err, "ushort", i)
+        sprintf(attname,"att_uint_for_var_%s",varname[i]);
+        err = ncmpi_get_att_uint     (ncid, NC_GLOBAL, attname, (unsigned int*)       buf);
+        ERR(expect_err, "uint", i)
+        sprintf(attname,"att_longlong_for_var_%s",varname[i]);
+        err = ncmpi_get_att_longlong (ncid, NC_GLOBAL, attname, (long long*)          buf);
+        ERR(expect_err, "longlong", i)
+        sprintf(attname,"att_ulonglong_for_var_%s",varname[i]);
+        err = ncmpi_get_att_ulonglong(ncid, NC_GLOBAL, attname, (unsigned long long*) buf);
+        ERR(expect_err, "ulonglong", i)
+    }
+
+    err = ncmpi_close(ncid); ERR0
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+
+    return 0;
+}
+
+static char* err_code_name(int err)
+{
+    static char unknown_str[32];
+    switch (err) {
+        case (NC_NOERR):			return "NC_NOERR";
+        case (NC_EBADID):			return "NC_EBADID";
+        case (NC_ENFILE):			return "NC_ENFILE";
+        case (NC_EEXIST):			return "NC_EEXIST";
+        case (NC_EINVAL):			return "NC_EINVAL";
+        case (NC_EPERM):			return "NC_EPERM";
+        case (NC_ENOTINDEFINE):			return "NC_ENOTINDEFINE";
+        case (NC_EINDEFINE):			return "NC_EINDEFINE";
+        case (NC_EINVALCOORDS):			return "NC_EINVALCOORDS";
+        case (NC_EMAXDIMS):			return "NC_EMAXDIMS";
+        case (NC_ENAMEINUSE):			return "NC_ENAMEINUSE";
+        case (NC_ENOTATT):			return "NC_ENOTATT";
+        case (NC_EMAXATTS):			return "NC_EMAXATTS";
+        case (NC_EBADTYPE):			return "NC_EBADTYPE";
+        case (NC_EBADDIM):			return "NC_EBADDIM";
+        case (NC_EUNLIMPOS):			return "NC_EUNLIMPOS";
+        case (NC_EMAXVARS):			return "NC_EMAXVARS";
+        case (NC_ENOTVAR):			return "NC_ENOTVAR";
+        case (NC_EGLOBAL):			return "NC_EGLOBAL";
+        case (NC_ENOTNC):			return "NC_ENOTNC";
+        case (NC_ESTS):				return "NC_ESTS";
+        case (NC_EMAXNAME):			return "NC_EMAXNAME";
+        case (NC_EUNLIMIT):			return "NC_EUNLIMIT";
+        case (NC_ENORECVARS):			return "NC_ENORECVARS";
+        case (NC_ECHAR):			return "NC_ECHAR";
+        case (NC_EEDGE):			return "NC_EEDGE";
+        case (NC_ESTRIDE):			return "NC_ESTRIDE";
+        case (NC_EBADNAME):			return "NC_EBADNAME";
+        case (NC_ERANGE):			return "NC_ERANGE";
+        case (NC_ENOMEM):			return "NC_ENOMEM";
+        case (NC_EVARSIZE):			return "NC_EVARSIZE";
+        case (NC_EDIMSIZE):			return "NC_EDIMSIZE";
+        case (NC_ETRUNC):			return "NC_ETRUNC";
+        default:
+              sprintf(unknown_str,"Unknown code %d",err);
+    }
+    return unknown_str;
+}
+
diff --git a/test/testcases/collective_error.c b/test/testcases/collective_error.c
new file mode 100644
index 0000000..571176d
--- /dev/null
+++ b/test/testcases/collective_error.c
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: collective_error.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+/* This test program checks if a collective API can be nicely aborted without
+ * causing the program to hang. It runs on 2 processes. One process deliberately
+ * produces an error (using an illegal start argument), while the other does not.
+ */
+
+#include <mpi.h>
+#include <pnetcdf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <testutils.h>
+
+#define ERR { if (err!=NC_NOERR){printf("PE %d: error at line %d (%s)\n",rank,__LINE__,ncmpi_strerror(err)); nerrs++;}}
+#define CHECK_ERROR(fn) { \
+   if (rank == 0 && err != NC_NOERR) \
+       printf("PE %d: %s error is %s\n",rank,fn,ncmpi_strerror(err)); \
+   if (rank == 1 && err != NC_EINVALCOORDS) \
+       printf("PE %d: %s error code should be NC_EINVALCOORDS but got %s",rank,fn,nc_err_code_name(err)); \
+}
+
+int main(int argc, char *argv[])
+{
+    char *filename="testfile.nc";
+    int rank, nproc, ncid, err, nerrs=0, varid, dimids[1];
+    int req, status, verbose;
+    MPI_Offset start[1], count[1];
+    double buf[2];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for collective abort ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    verbose = 0;
+    if (nproc != 2 && rank == 0 && verbose)
+        printf("Warning: %s is designed to run on 2 processes\n",argv[0]);
+
+    /* Create a 2 element vector of doubles */
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, MPI_INFO_NULL, &ncid);
+    ERR
+
+    err = ncmpi_def_dim(ncid, "dim", 2, &dimids[0]);
+    ERR
+
+    err = ncmpi_def_var(ncid, "var", NC_DOUBLE, 1, dimids, &varid);
+    ERR
+
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    if (rank == 0) {
+        start[0] = 0;
+        count[0] = 2;
+    } else if (rank == 1) {
+        start[0] = 2; /* illegal for a start > defined shape */
+        count[0] = 0;
+    }
+    else
+        count[0] = 0;
+
+    err = ncmpi_put_vara_all(ncid, varid, start, count,
+			     buf, count[0], MPI_DOUBLE);
+    CHECK_ERROR("ncmpi_put_vara_all")
+
+    err = ncmpi_put_vara_double_all(ncid, varid, start, count, buf);
+    CHECK_ERROR("ncmpi_put_vara_double_all")
+
+    err = ncmpi_iput_vara_double(ncid, varid, start, count, buf, &req);
+    CHECK_ERROR("ncmpi_iput_vara_double")
+
+    err = ncmpi_wait_all(ncid, 1, &req, &status);
+    ERR
+
+    err = ncmpi_get_vara_all(ncid, varid, start, count,
+			     buf, count[0], MPI_DOUBLE);
+    CHECK_ERROR("ncmpi_get_vara_all")
+
+    err = ncmpi_get_vara_double_all(ncid, varid, start, count, buf);
+    CHECK_ERROR("ncmpi_get_vara_double_all")
+
+    err = ncmpi_iget_vara_double(ncid, varid, start, count, buf, &req);
+    CHECK_ERROR("ncmpi_iget_vara_double")
+
+    err = ncmpi_wait_all(ncid, 1, &req, &status);
+    ERR
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return (nerrs == 0) ? 0 : 1;
+}
diff --git a/test/testcases/depend b/test/testcases/depend
new file mode 100644
index 0000000..3989a50
--- /dev/null
+++ b/test/testcases/depend
@@ -0,0 +1,37 @@
+alignment_test.o: alignment_test.c
+bigrecords.o: bigrecords.f
+collective_error.o: collective_error.c
+flexible.o: flexible.c
+flexible2.o: flexible2.c
+flexible_varm.o: flexible_varm.c
+inq_num_vars.o: inq_num_vars.c
+inq_num_varsf.o: inq_num_varsf.f90
+inq_recsize.o: inq_recsize.c
+inq_recsizef.o: inq_recsizef.f90
+ivarn.o: ivarn.c
+modes.o: modes.c
+ncmpi_vars_null_stride.o: ncmpi_vars_null_stride.c
+noclobber.o: noclobber.c
+nonblocking.o: nonblocking.c
+one_record.o: one_record.c
+profile.o: profile.c
+varn_int.o: varn_int.c
+varn_contig.o: varn_contig.c
+varn_intf.o: varn_intf.f
+varn_real.o: varn_real.f90
+record.o: record.c
+redef1.o: redef1.c
+test_vard.o: test_vard.c
+test_vardf.o: test_vardf.F
+test_vardf90.o: test_vardf90.f90
+test_varm.o: test_varm.c
+vectors.o: vectors.c
+check_striping.o: check_striping.c
+attrf.o: attrf.f
+add_var.o: add_var.c
+buftype_free.o: buftype_free.c
+buftype_freef.o: buftype_freef.f
+put_parameter.o: put_parameter.f
+last_large_var.o: last_large_var.c
+check_type.o: check_type.c
+test_erange.o: test_erange.c
diff --git a/test/testcases/flexible.c b/test/testcases/flexible.c
new file mode 100644
index 0000000..d4085ab
--- /dev/null
+++ b/test/testcases/flexible.c
@@ -0,0 +1,205 @@
+/*
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: flexible.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+/*
+ * This program tests the use of flexible API.
+ * The write buffer is a 2D array of size NY x NX
+ * The MPI data type for the buffer is defined by swapping the 1st and 2nd
+ * rows of the array. It uses MPI_Type_create_hindex(). After the write, this
+ * test reads back the array using regular and flexible get APIs (blocking and
+ * nonblokcing) and check the contents.
+ *
+ * The expected reults from the output file contents are:
+ * (when running on 1 MPI process)
+ *
+ *  % ncmpidump testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-1
+ *    dimensions:
+ * 	   Y = UNLIMITED ; // (2 currently)
+ * 	   X = 5 ;
+ *    variables:
+ * 	   int VAR(Y, X) ;
+ *    data:
+ * 
+ *    var =
+ *      1, 1, 1, 1, 1,
+ *      0, 0, 0, 0, 0 ;
+ *    }
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 2
+#define NX 5
+#define ERR if (err!=NC_NOERR) {printf("Error at line %d: %s\n", __LINE__,ncmpi_strerror(err)); nerrs++;}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv) {
+
+    char         filename[256];
+    int          i, j, err, ncid, varid, dimids[2], debug=0;
+    int          rank, nprocs, blocklengths[2], buf[NY][NX], *bufptr;
+    int         *ncbuf, req, st, nerrs=0;
+    int          array_of_sizes[2], array_of_subsizes[2], array_of_starts[2];
+    MPI_Offset   start[2], count[2];
+    MPI_Aint     a0, a1, disps[2];
+    MPI_Datatype buftype;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for flexible put and get ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, MPI_INFO_NULL,
+                       &ncid); ERR
+
+    /* define a 2D array */
+    err = ncmpi_def_dim(ncid, "Y", NC_UNLIMITED, &dimids[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX*nprocs,    &dimids[1]); ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimids, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* initialize the contents of the array */
+    for (j=0; j<NY; j++) for (i=0; i<NX; i++) buf[j][i] = j;
+
+    /* construct an MPI derived data type for swapping 1st row with 2nd row */
+    blocklengths[0] = blocklengths[1] = NX;
+    MPI_Get_address(buf[1], &a0);
+    MPI_Get_address(buf[0], &a1);
+    disps[0] = 0;
+    disps[1] = a1 - a0;
+    bufptr = buf[1];
+    err = MPI_Type_create_hindexed(2, blocklengths, disps, MPI_INT, &buftype);
+    if (err != MPI_SUCCESS) printf("MPI error MPI_Type_create_hindexed\n");
+    MPI_Type_commit(&buftype);
+
+    start[0] = 0; start[1] = NX*rank;
+    count[0] = 2; count[1] = NX;
+    if (debug) printf("put start=%lld %lld count=%lld %lld\n",start[0],start[1],count[0],count[1]);
+
+    /* call flexible API */
+    err = ncmpi_put_vara_all(ncid, varid, start, count, bufptr, 1, buftype); ERR
+    MPI_Type_free(&buftype);
+
+    /* check if the contents of buf are altered */
+    for (j=0; j<NY; j++)
+        for (i=0; i<NX; i++)
+            if (buf[j][i] != j)
+                printf("buf[%d][%d] != %d\n",j,i,buf[j][i]);
+ 
+    /* check if root process can write to file header in data mode */
+    err = ncmpi_rename_var(ncid, varid, "VAR"); ERR
+
+    err = ncmpi_close(ncid); ERR
+
+    /* open the same file and read back for validate */
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL,
+                     &ncid); ERR
+
+    err = ncmpi_inq_varid(ncid, "VAR", &varid); ERR
+
+    /* initialize the contents of the array to a different value */
+    for (j=0; j<NY; j++) for (i=0; i<NX; i++) buf[j][i] = -1;
+
+    /* read back variable */
+    start[0] = 0; start[1] = NX*rank;
+    count[0] = 2; count[1] = NX;
+    if (debug) printf("get start=%lld %lld count=%lld %lld\n",start[0],start[1],count[0],count[1]);
+
+    err = ncmpi_get_vara_int_all(ncid, varid, start, count, buf[0]); ERR
+
+    /* check if the contents of buf are expected */
+    for (j=0; j<2; j++) {
+        int val = (j == 0) ? 1 : 0;
+        for (i=0; i<NX; i++)
+            if (buf[j][i] != val) {
+                printf("Unexpected buf[%d][%d]=%d != %d\n",j,i,buf[j][i],val);
+                nerrs++;
+            }
+    }
+
+    /* create a buftype with ghost cells on each side */
+    ncbuf = (int *) malloc((count[0]+4)*(count[1]+4)*sizeof(int));
+    array_of_sizes[0] = count[0]+4;
+    array_of_sizes[1] = count[1]+4;
+    array_of_subsizes[0] = count[0];
+    array_of_subsizes[1] = count[1];
+    array_of_starts[0] = 2;
+    array_of_starts[1] = 2;
+    MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                             array_of_starts, MPI_ORDER_C,
+                             MPI_INT, &buftype);
+    MPI_Type_commit(&buftype);
+    err = ncmpi_get_vara_all(ncid, varid, start, count, ncbuf, 1, buftype); ERR
+
+    for (j=0; j<count[0]; j++) {
+        for (i=0; i<count[1]; i++)
+            if (buf[j][i] != ncbuf[(j+2)*(count[1]+4)+(i+2)]) {
+                printf("Error: expecting ncbuf[%d][%d]=%d but got %d\n",
+                       j,i,buf[j][i],ncbuf[(j+2)*(count[1]+4)+(i+2)]);
+                nerrs++;
+            }
+    }
+    for (i=0; i<(count[0]+4)*(count[1]+4); i++) ncbuf[i] = -1;
+
+    err = ncmpi_iget_vara(ncid, varid, start, count, ncbuf, 1, buftype, &req); ERR
+    err = ncmpi_wait_all(ncid, 1, &req, &st); ERR
+
+    for (j=0; j<count[0]; j++) {
+        for (i=0; i<count[1]; i++)
+            if (buf[j][i] != ncbuf[(j+2)*(count[1]+4)+(i+2)]) {
+                printf("Error: expecting ncbuf[%d][%d]=%d but got %d\n",
+                       j,i,buf[j][i],ncbuf[(j+2)*(count[1]+4)+(i+2)]);
+                nerrs++;
+            }
+    }
+
+    MPI_Type_free(&buftype);
+    free(ncbuf);
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/test/testcases/flexible2.c b/test/testcases/flexible2.c
new file mode 100644
index 0000000..8cf89e3
--- /dev/null
+++ b/test/testcases/flexible2.c
@@ -0,0 +1,279 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: flexible2.c 2133 2015-09-26 19:16:01Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program tests PnetCDF flexible APIs, ncmpi_put_vara_all(),
+ * ncmpi_iput_vara() to write two 2D array variables (one is of 4-byte
+ * integer byte and the other float type) in parallel. It then uses flexible
+ * get/iget APIs to read data back and check the contents. The program first
+ * defines 2 netCDF variables of sizes
+ *    var_zy: NZ*nprocs x NY
+ *    var_yx: NY x NX*nprocs
+ *
+ * The data partitioning patterns on the 2 variables are row-wise and
+ * column-wise, respectively. Each process writes a subarray of size
+ * NZ x NY and NY x NX to var_zy and var_yx, respectively.
+ * Both local buffers have a ghost cell of length 3 surrounded along each
+ * dimension.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicc -O2 -o flexible2 flexible2.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 4 ./flexible2 /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            Z = 20 ;
+ *            Y = 5 ;
+ *            X = 20 ;
+ *    variables:
+ *            int var_zy(Z, Y) ;
+ *            float var_yx(Y, X) ;
+ *    data:
+ *
+ *     var_zy =
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0,
+ *      1, 1, 1, 1, 1,
+ *      1, 1, 1, 1, 1,
+ *      1, 1, 1, 1, 1,
+ *      1, 1, 1, 1, 1,
+ *      1, 1, 1, 1, 1,
+ *      2, 2, 2, 2, 2,
+ *      2, 2, 2, 2, 2,
+ *      2, 2, 2, 2, 2,
+ *      2, 2, 2, 2, 2,
+ *      2, 2, 2, 2, 2,
+ *      3, 3, 3, 3, 3,
+ *      3, 3, 3, 3, 3,
+ *      3, 3, 3, 3, 3,
+ *      3, 3, 3, 3, 3,
+ *      3, 3, 3, 3, 3 ;
+ *
+ *     var_yx =
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ *      0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 ;
+ *    }
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NZ 5
+#define NY 5
+#define NX 5
+
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); nerrs++;}}
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int i, j, rank, nprocs, err, nerrs=0, req, status, ghost_len=3;
+    int ncid, cmode, varid0, varid1, dimid[3], *buf_zy;
+    int array_of_sizes[2], array_of_subsizes[2], array_of_starts[2];
+    double *buf_yx;
+    MPI_Offset start[2], count[2];
+    MPI_Datatype  subarray;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for flexible APIs ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* define 3 dimensions */
+    err = ncmpi_def_dim(ncid, "Z", NZ*nprocs, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "Y", NY,        &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX*nprocs, &dimid[2]); ERR
+
+    /* define a variable of size (NZ * nprocs) * NY */
+    err = ncmpi_def_var(ncid, "var_zy", NC_INT,   2, &dimid[0], &varid0); ERR
+    /* define a variable of size NY * (NX * nprocs) */
+    err = ncmpi_def_var(ncid, "var_yx", NC_FLOAT, 2, &dimid[1], &varid1); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* var_zy is partitioned along Z dimension */
+    array_of_sizes[0]    = NZ + 2*ghost_len;
+    array_of_sizes[1]    = NY + 2*ghost_len;
+    array_of_subsizes[0] = NZ;
+    array_of_subsizes[1] = NY;
+    array_of_starts[0]   = ghost_len;
+    array_of_starts[1]   = ghost_len;
+    MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                             array_of_starts, MPI_ORDER_C, MPI_INT, &subarray);
+    MPI_Type_commit(&subarray);
+
+    int buffer_len = (NZ+2*ghost_len) * (NY+2*ghost_len);
+    buf_zy = (int*) malloc(buffer_len * sizeof(int));
+    for (i=0; i<buffer_len; i++) buf_zy[i] = rank;
+
+    start[0] = NZ * rank; start[1] = 0;
+    count[0] = NZ;        count[1] = NY;
+    /* calling a blocking flexible API */
+    err = ncmpi_put_vara_all(ncid, varid0, start, count, buf_zy, 1, subarray);
+    ERR
+
+    /* check the contents of put buffer */
+    for (i=0; i<buffer_len; i++) {
+        if (buf_zy[i] != rank) {
+            printf("Error put buffer[%d] is altered\n",i);
+            nerrs++;
+        }
+    }
+
+    for (i=0; i<buffer_len; i++) buf_zy[i] = -1;
+    /* calling a blocking flexible API */
+    err = ncmpi_get_vara_all(ncid, varid0, start, count, buf_zy, 1, subarray);
+    ERR
+
+    /* check the contents of get buffer */
+    for (i=0; i<array_of_sizes[0]; i++) {
+        for (j=0; j<array_of_sizes[1]; j++) {
+            int index = i*array_of_sizes[1] + j;
+            if (i < ghost_len || ghost_len+array_of_subsizes[0] <= i ||
+                j < ghost_len || ghost_len+array_of_subsizes[1] <= j) {
+                if (buf_zy[index] != -1) {
+                    printf("Unexpected get buffer[%d][%d]=%d\n",
+                           i,j,buf_zy[index]);
+                    nerrs++;
+                }
+            }
+            else {
+                if (buf_zy[index] != rank) {
+                    printf("Unexpected get buffer[%d][%d]=%d\n",
+                           i,j,buf_zy[index]);
+                    nerrs++;
+                }
+            }
+        }
+    }
+    free(buf_zy);
+    MPI_Type_free(&subarray);
+
+    /* var_yx is partitioned along X dimension */
+    array_of_sizes[0]    = NY + 2*ghost_len;
+    array_of_sizes[1]    = NX + 2*ghost_len;
+    array_of_subsizes[0] = NY;
+    array_of_subsizes[1] = NX;
+    array_of_starts[0]   = ghost_len;
+    array_of_starts[1]   = ghost_len;
+    MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                             array_of_starts, MPI_ORDER_C, MPI_DOUBLE,
+                             &subarray);
+    MPI_Type_commit(&subarray);
+
+    buffer_len = (NY+2*ghost_len) * (NX+2*ghost_len);
+    buf_yx = (double*) malloc(buffer_len * sizeof(double));
+    for (i=0; i<buffer_len; i++) buf_yx[i] = rank;
+
+    start[0] = 0;  start[1] = NX * rank;
+    count[0] = NY; count[1] = NX;
+
+    /* calling a non-blocking flexible API */
+    err = ncmpi_iput_vara(ncid, varid1, start, count, buf_yx, 1, subarray,&req);
+    ERR
+    err = ncmpi_wait_all(ncid, 1, &req, &status); ERR
+    err = status; ERR
+
+    /* check the contents of put buffer */
+    for (i=0; i<buffer_len; i++) {
+        if (buf_yx[i] != rank) {
+            printf("Error iput buffer[%d]=%f is altered\n",i,buf_yx[i]);
+            nerrs++;
+        }
+    }
+
+    for (i=0; i<buffer_len; i++) buf_yx[i] = -1;
+
+    /* calling a non-blocking flexible API */
+    err = ncmpi_iget_vara(ncid, varid1, start, count, buf_yx, 1, subarray,&req);
+    ERR
+    err = ncmpi_wait_all(ncid, 1, &req, &status); ERR
+    err = status; ERR
+
+    /* check the contents of iget buffer */
+    for (i=0; i<array_of_sizes[0]; i++) {
+        for (j=0; j<array_of_sizes[1]; j++) {
+            int index = i*array_of_sizes[1] + j;
+            if (i < ghost_len || ghost_len+array_of_subsizes[0] <= i ||
+                j < ghost_len || ghost_len+array_of_subsizes[1] <= j) {
+                if (buf_yx[index] != -1) {
+                    printf("Unexpected get buffer[%d][%d]=%f\n",
+                           i,j,buf_yx[index]);
+                    nerrs++;
+                }
+            }
+            else {
+                if (buf_yx[index] != rank) {
+                    printf("Unexpected get buffer[%d][%d]=%f\n",
+                           i,j,buf_yx[index]);
+                    nerrs++;
+                }
+            }
+        }
+    }
+    free(buf_yx);
+    MPI_Type_free(&subarray);
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/flexible_varm.c b/test/testcases/flexible_varm.c
new file mode 100644
index 0000000..3df4ec1
--- /dev/null
+++ b/test/testcases/flexible_varm.c
@@ -0,0 +1,247 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: flexible_varm.c 2133 2015-09-26 19:16:01Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program tests PnetCDF flexible varm APIs, i.e. ncmpi_put_varm_all(),
+ * ncmpi_get_varm_all(), and their nonblocking versions, to write a 2D array
+ * double variable of size NY x NX*nproc in parallel.
+ *
+ * The data partitioning patterns on the variable is column-wise.
+ * The local buffer has ghost cells surrounded along both dimensions.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicc -O2 -o flexible_varm flexible_varm.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 4 ./flexible_varm /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *            Y = 6 ;
+ *            X = 16 ;
+ *    variables:
+ *            double var(Y, X) ;
+ *    data:
+ *            
+ *    var =
+ *      0,  6, 12, 18, 0,  6, 12, 18, 0,  6, 12, 18, 0,  6, 12, 18,
+ *      1,  7, 13, 19, 1,  7, 13, 19, 1,  7, 13, 19, 1,  7, 13, 19,
+ *      2,  8, 14, 20, 2,  8, 14, 20, 2,  8, 14, 20, 2,  8, 14, 20,
+ *      3,  9, 15, 21, 3,  9, 15, 21, 3,  9, 15, 21, 3,  9, 15, 21,
+ *      4, 10, 16, 22, 4, 10, 16, 22, 4, 10, 16, 22, 4, 10, 16, 22,
+ *      5, 11, 17, 23, 5, 11, 17, 23, 5, 11, 17, 23, 5, 11, 17, 23 ;
+ *    }
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <assert.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 6
+#define NX 4
+#define GHOST 2
+
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); nerrs++;}}
+
+#define INIT_PUT_BUF \
+    for (i=0; i<array_of_sizes[0]; i++) { \
+        for (j=0; j<array_of_sizes[1]; j++) { \
+            if (i < GHOST || GHOST+array_of_subsizes[0] <= i || \
+                j < GHOST || GHOST+array_of_subsizes[1] <= j) \
+                buf[i][j] = -1; \
+            else \
+                buf[i][j] = (i-GHOST)*array_of_subsizes[1]+(j-GHOST); \
+        } \
+    }
+
+#define CHECK_PUT_BUF \
+    for (i=0; i<array_of_sizes[0]; i++) { \
+        for (j=0; j<array_of_sizes[1]; j++) { \
+            if (i < GHOST || GHOST+array_of_subsizes[0] <= i || \
+                j < GHOST || GHOST+array_of_subsizes[1] <= j) { \
+                if (buf[i][j] != -1) { \
+                    printf("Error: put buffer altered buffer[%d][%d]=%d\n", \
+                           i,j,buf[i][j]); \
+                    nerrs++; \
+                } \
+            } \
+            else { \
+                if (buf[i][j] != (i-GHOST)*array_of_subsizes[1]+(j-GHOST)) { \
+                    printf("Error: put buffer altered buffer[%d][%d]=%d\n", \
+                           i,j,buf[i][j]); \
+                    nerrs++; \
+                } \
+            } \
+        } \
+    }
+
+#define INIT_GET_BUF \
+    for (i=0; i<array_of_sizes[0]; i++) \
+        for (j=0; j<array_of_sizes[1]; j++) \
+            buf[i][j] = -2;
+
+#define CHECK_GET_BUF \
+    for (i=0; i<array_of_sizes[0]; i++) { \
+        for (j=0; j<array_of_sizes[1]; j++) { \
+            if (i < GHOST || GHOST+array_of_subsizes[0] <= i || \
+                j < GHOST || GHOST+array_of_subsizes[1] <= j) { \
+                if (buf[i][j] != -2) { \
+                    printf("Unexpected get buffer[%d][%d]=%d\n", \
+                           i,j,buf[i][j]); \
+                    nerrs++; \
+                } \
+            } \
+            else { \
+                if (buf[i][j] != (i-GHOST)*array_of_subsizes[1]+(j-GHOST)) { \
+                    printf("Unexpected get buffer[%d][%d]=%d\n", \
+                           i,j,buf[i][j]); \
+                    nerrs++; \
+                } \
+            } \
+        } \
+    }
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int i, j, rank, nprocs, err, nerrs=0, req, status;
+    int ncid, cmode, varid, dimid[2];
+    int array_of_sizes[2], array_of_subsizes[2], array_of_starts[2];
+    int buf[NX+2*GHOST][NY+2*GHOST];
+    MPI_Offset start[2], count[2], stride[2], imap[2];
+    MPI_Datatype  subarray;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for flexible varm APIs ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* define 2 dimensions */
+    err = ncmpi_def_dim(ncid, "Y", NY,        &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX*nprocs, &dimid[1]); ERR
+
+    /* define a variable of size NY * (NX * nprocs) */
+    err = ncmpi_def_var(ncid, "var", NC_DOUBLE, 2, dimid, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+     start[0] = 0;  start[1] = NX * rank;
+     count[0] = NY; count[1] = NX;
+    stride[0] = 1; stride[1] = 1;
+      imap[0] = 1;   imap[1] = NY; /* would be {NX, 1} if not transposing */
+
+    /* var is partitioned along X dimension in a matrix transported way */
+    array_of_sizes[0]    = NX + 2*GHOST;
+    array_of_sizes[1]    = NY + 2*GHOST;
+    array_of_subsizes[0] = NX;
+    array_of_subsizes[1] = NY;
+    array_of_starts[0]   = GHOST;
+    array_of_starts[1]   = GHOST;
+    MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                             array_of_starts, MPI_ORDER_C, MPI_INT, &subarray);
+    MPI_Type_commit(&subarray);
+
+    /* calling a blocking put_varm flexible API -----------------------------*/
+    /* initiate put buffer contents */
+    INIT_PUT_BUF
+    err = ncmpi_put_varm_all(ncid, varid, start, count, stride, imap, buf,
+                             1, subarray);
+    ERR
+
+    /* check the contents of put buffer */
+    CHECK_PUT_BUF
+
+    /* calling a nonblocking put_varm flexible API --------------------------*/
+    /* initiate put buffer contents */
+    INIT_PUT_BUF
+    err = ncmpi_iput_varm(ncid, varid, start, count, stride, imap, buf,
+                          1, subarray, &req);
+    ERR
+    err = ncmpi_wait_all(ncid, 1, &req, &status); ERR
+    err = status; ERR
+
+    /* check the contents of put buffer */
+    CHECK_PUT_BUF
+
+    /* read back using a blocking get_varm flexible API ---------------------*/
+    /* initiate get buffer contents */
+    INIT_GET_BUF
+
+    /* calling a blocking flexible API */
+    err = ncmpi_get_varm_all(ncid, varid, start, count, stride, imap, buf,
+                             1, subarray);
+    ERR
+
+    /* check the contents of get buffer */
+    CHECK_GET_BUF
+
+    /* read back using a non-blocking flexible API --------------------------*/
+    /* initiate get buffer contents */
+    INIT_GET_BUF
+
+    /* calling a blocking flexible API */
+    err = ncmpi_iget_varm(ncid, varid, start, count, stride, imap, buf,
+                          1, subarray, &req);
+    ERR
+    err = ncmpi_wait_all(ncid, 1, &req, &status); ERR
+    err = status; ERR
+
+    /* check the contents of get buffer */
+    CHECK_GET_BUF
+
+    MPI_Type_free(&subarray);
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/geopotential.ncdump b/test/testcases/geopotential.ncdump
new file mode 100644
index 0000000..511bef7
--- /dev/null
+++ b/test/testcases/geopotential.ncdump
@@ -0,0 +1,48 @@
+netcdf r6_geopotential_19010101_100000 {
+dimensions:
+	time = UNLIMITED ; // (3 currently)
+	cells = 40962 ;
+	cellneighbors = 6 ;
+	interfaces = 26 ;
+	cellcorners = 6 ;
+variables:
+	double time(time) ;
+		time:long_name = "Time" ;
+		time:units = "days since 01-01-1901" ;
+		time:standard_name = "time" ;
+		time:calendar = "no leap year" ;
+	float grid_center_lat(cells) ;
+		grid_center_lat:long_name = "Latitude of cell center" ;
+		grid_center_lat:units = "radians" ;
+		grid_center_lat:standard_name = "latitude" ;
+		grid_center_lat:bounds = "grid_corner_lat" ;
+	float grid_center_lon(cells) ;
+		grid_center_lon:long_name = "Longitude of cell center" ;
+		grid_center_lon:units = "radians" ;
+		grid_center_lon:standard_name = "longitude" ;
+		grid_center_lon:bounds = "grid_corner_lon" ;
+	float area(cells) ;
+		area:long_name = "Cell area" ;
+		area:units = "square radians" ;
+	int cell_neighbors(cells, cellneighbors) ;
+		cell_neighbors:long_name = "List of neighbors to this cell" ;
+		cell_neighbors:units = "unitless" ;
+	float interfaces(interfaces) ;
+		interfaces:long_name = "Vertical interfaces, in terms of pressure" ;
+		interfaces:units = "Pa" ;
+		interfaces:positive = "down" ;
+		interfaces:axis = "Z" ;
+	float geopotential(time, cells, interfaces) ;
+		geopotential:long_name = "Geo Potential" ;
+		geopotential:units = "m**2/sec**2" ;
+		geopotential:coordinates = "grid_center_lat grid_center_lon" ;
+	float grid_corner_lat(cells, cellcorners) ;
+		grid_corner_lat:long_name = "Latitude of cell corner" ;
+		grid_corner_lat:units = "radians" ;
+	float grid_corner_lon(cells, cellcorners) ;
+		grid_corner_lon:long_name = "Longitude of cell corner" ;
+		grid_corner_lon:units = "radians" ;
+
+// global attributes:
+		:history = "Fri Jan 23 15:41:48 2009: ncks -v grid_corner_lat,grid_corner_lon wind_19010101_100000.nc -A geopotential_19010101_100000.nc" ;
+}
diff --git a/test/testcases/inq_num_vars.c b/test/testcases/inq_num_vars.c
new file mode 100644
index 0000000..302743c
--- /dev/null
+++ b/test/testcases/inq_num_vars.c
@@ -0,0 +1,135 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: inq_num_vars.c 2219 2015-12-11 22:30:03Z wkliao $
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program tests if one can get the number of record variables and fixed-
+ * sized variables correctly. It first defines some number of fixed-size and
+ * record variables and then calls the APIs
+ *     ncmpi_inq_num_rec_vars() and ncmpi_inq_num_fix_vars()
+ * to varify if the numbers are correct.
+ *
+ * The compile and run commands are given below. This program is to be run on
+ * one MPI process.
+ *
+ *    % mpicc -g -o inq_num_vars inq_num_vars.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 1 inq_num_vars testfile.nc
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+static
+void check_num_vars(int  ncid,
+                    int  expected_nvars,
+                    int  expected_num_rec_vars,
+                    int  expected_num_fix_vars,
+                    int *nerrs)
+{
+    int err, nvars, num_rec_vars, num_fix_vars;
+
+    err = ncmpi_inq_nvars(ncid, &nvars); ERR
+    err = ncmpi_inq_num_rec_vars(ncid, &num_rec_vars); ERR
+    err = ncmpi_inq_num_fix_vars(ncid, &num_fix_vars); ERR
+
+    if (nvars != expected_nvars) {
+        printf("Error: expecting %d number of variables defined, but got %d\n", expected_nvars, nvars);
+        (*nerrs)++;
+    }
+    if (num_rec_vars != expected_num_rec_vars) {
+        printf("Error: expecting %d number of record variables defined, but got %d\n", expected_num_rec_vars, num_rec_vars);
+        (*nerrs)++;
+    }
+    if (num_fix_vars != expected_num_fix_vars) {
+        printf("Error: expecting %d number of fixed-size variables defined, but got %d\n", expected_num_fix_vars, num_fix_vars);
+        (*nerrs)++;
+    }
+}
+
+int main(int argc, char** argv) {
+    char *filename="testfile.nc";
+    int nerrs, rank, nprocs, err;
+    int ncid, cmode, varid[7], dimid[3];
+    MPI_Info info=MPI_INFO_NULL;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        goto fn_exit;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for no. record/fixed variables", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    /* printf("PnetCDF version string: \"%s\"\n", ncmpi_inq_libvers()); */
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, info, &ncid); ERR
+
+    /* define dimension and variable */
+    err = ncmpi_def_dim(ncid, "REC_DIM", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "Y",       2,            &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "X",       10,           &dimid[2]); ERR
+
+    nerrs = 0;
+
+    err = ncmpi_def_var(ncid, "REC_VAR_1", NC_INT, 1, dimid, &varid[0]); ERR
+    err = ncmpi_def_var(ncid, "REC_VAR_2", NC_INT, 3, dimid, &varid[1]); ERR
+    err = ncmpi_def_var(ncid, "REC_VAR_3", NC_INT, 2, dimid, &varid[2]); ERR
+    err = ncmpi_def_var(ncid, "REC_VAR_4", NC_INT, 1, dimid, &varid[3]); ERR
+
+    check_num_vars(ncid, 4, 4, 0, &nerrs);
+
+    err = ncmpi_def_var(ncid, "FIX_VAR_1", NC_INT, 2, dimid+1, &varid[4]); ERR
+    err = ncmpi_def_var(ncid, "FIX_VAR_2", NC_INT, 1, dimid+1, &varid[5]); ERR
+    err = ncmpi_def_var(ncid, "FIX_VAR_3", NC_INT, 1, dimid+2, &varid[6]); ERR
+
+    check_num_vars(ncid, 7, 4, 3, &nerrs);
+
+    err = ncmpi_enddef(ncid); ERR
+
+    check_num_vars(ncid, 7, 4, 3, &nerrs);
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+fn_exit:
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/inq_num_varsf.f90 b/test/testcases/inq_num_varsf.f90
new file mode 100644
index 0000000..3f2fa4d
--- /dev/null
+++ b/test/testcases/inq_num_varsf.f90
@@ -0,0 +1,166 @@
+!
+!   Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: inq_num_varsf.f90 2205 2015-11-28 20:41:50Z wkliao $
+
+!
+! This program tests if one can get the number of record variables and
+! fixed-size variables correctly. It first defines some number of
+! fixed-size and record variables and then calls the APIs
+!     ncmpi_inq_num_rec_vars() and ncmpi_inq_num_fix_vars()
+! to varify if the numbers are correct.
+!
+! The compile and run commands are given below. This program is to be
+! run on one MPI process.
+!
+!    % mpif90 -g -o inq_num_varsf inq_num_varsf.f90 -lpnetcdf
+!
+!    % mpiexec -l -n 1 inq_num_varsf testfile.nc
+!
+!    % ncmpidump -h testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-2 (large file)
+!    dimensions:
+!            X = 10 ;
+!            Y = 2 ;
+!            REC_DIM = UNLIMITED ; // (0 currently)
+!    variables:
+!            int REC_VAR_1(REC_DIM) ;
+!            int REC_VAR_2(REC_DIM, Y, X) ;
+!            int REC_VAR_3(REC_DIM, Y) ;
+!            int REC_VAR_4(REC_DIM) ;
+!            int FIX_VAR_1(Y, X) ;
+!            int FIX_VAR_2(X) ;
+!            int FIX_VAR_3(X) ;
+!    }
+!
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+          character(len=128) msg
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              msg = '*** TESTING F90 inq_num_varsf.f90 for no. record/fixed variables'
+              call pass_fail(1, msg)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          character(LEN=256) filename, cmd, msg
+          integer err, ierr, nprocs, rank, cmode, ncid, get_args
+          integer varid(7), dimid(3), dimid_1D(1), dimid_2D(2)
+          integer nerrs, nvars, num_rec_vars, num_fix_vars
+          integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+
+          call MPI_Init(ierr)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, ierr)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              filename = "testfile.nc"
+              err = get_args(cmd, filename)
+          endif
+          call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+          if (err .EQ. 0) goto 999
+
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_OFFSET)
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! define dimensions
+          err = nf90mpi_def_dim(ncid, "X", 10_MPI_OFFSET_KIND, dimid(1))
+          call check(err, 'In nf90mpi_def_dim X: ')
+          err = nf90mpi_def_dim(ncid, "Y", 2_MPI_OFFSET_KIND,  dimid(2))
+          call check(err, 'In nf90mpi_def_dim Y: ')
+          err = nf90mpi_def_dim(ncid, "REC_DIM", NF90MPI_UNLIMITED, dimid(3))
+          call check(err, 'In nf90mpi_def_dim REC_DIM: ')
+
+          ! define some record variables
+          dimid_1D(1) = dimid(3)
+          dimid_2D(1) = dimid(2)
+          dimid_2D(2) = dimid(3)
+
+          err = nf90mpi_def_var(ncid, "REC_VAR_1", NF90_INT, dimid_1D, varid(1))
+          call check(err, 'In nf90mpi_def_var: REC_VAR_1')
+          err = nf90mpi_def_var(ncid, "REC_VAR_2", NF90_INT, dimid,    varid(2))
+          call check(err, 'In nf90mpi_def_var: REC_VAR_2')
+          err = nf90mpi_def_var(ncid, "REC_VAR_3", NF90_INT, dimid_2D, varid(3))
+          call check(err, 'In nf90mpi_def_var: REC_VAR_3')
+          err = nf90mpi_def_var(ncid, "REC_VAR_4", NF90_INT, dimid_1D, varid(4))
+          call check(err, 'In nf90mpi_def_var: REC_VAR_4')
+
+          ! define some fixed-size variables
+          dimid_1D(1) = dimid(1)
+          dimid_2D(1) = dimid(1)
+          dimid_2D(2) = dimid(2)
+
+          err = nf90mpi_def_var(ncid, "FIX_VAR_1", NF90_INT, dimid_2D, varid(5))
+          call check(err, 'In nf90mpi_def_var: FIX_VAR_1')
+          err = nf90mpi_def_var(ncid, "FIX_VAR_2", NF90_INT, dimid_1D, varid(6))
+          call check(err, 'In nf90mpi_def_var: FIX_VAR_2')
+          err = nf90mpi_def_var(ncid, "FIX_VAR_3", NF90_INT, dimid_1D, varid(7))
+          call check(err, 'In nf90mpi_def_var: FIX_VAR_3')
+
+          ! do not forget to exit define mode
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! inquire the numbers of variables (record and fixed-size
+          err = nf90mpi_inquire(ncid, nVariables=nvars)
+          call check(err, 'In nf90mpi_inquire: ')
+          err = nf90mpi_inq_num_rec_vars(ncid, num_rec_vars)
+          call check(err, 'In nf90mpi_inq_num_rec_vars: ')
+          err = nf90mpi_inq_num_fix_vars(ncid, num_fix_vars)
+          call check(err, 'In nf90mpi_inq_num_fix_vars: ')
+
+          ! check if the numbers of variables are expected
+          nerrs = 0
+          if (nvars .NE. 7) then
+              write(6,*) "Error: expecting 7 number of variables defined, but got ", nvars
+              nerrs = nerrs + 1
+          endif
+          if (num_rec_vars .NE. 4) then
+              write(6,*) "Error: expecting 4 number of recond variables defined, but got ", nvars
+              nerrs = nerrs + 1
+          endif
+          if (num_fix_vars .NE. 3) then
+              write(6,*) "Error: expecting 3 number of fixed-size variables defined, but got ", nvars
+              nerrs = nerrs + 1
+          endif
+
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err == NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, ierr)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+          msg = '*** TESTING F90 '//trim(cmd)//' for no. record/fixed variables'
+          if (rank .eq. 0) call pass_fail(nerrs, msg)
+
+ 999      call MPI_Finalize(ierr)
+      end program main
+
diff --git a/test/testcases/inq_recsize.c b/test/testcases/inq_recsize.c
new file mode 100644
index 0000000..cf3bea3
--- /dev/null
+++ b/test/testcases/inq_recsize.c
@@ -0,0 +1,115 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: inq_recsize.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program tests if one can get the size of record block correctly. The
+ * record block size is the sum of individual record of all record variables.
+ * It first defines some number of record and fixed-size variables and then
+ * calls the API ncmpi_inq_recsize() and varify if the numbers are correct.
+ *
+ * The compile and run commands are given below. This program is to be run on
+ * one MPI process.
+ *
+ *    % mpicc -g -o inq_recsize inq_recsize.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 1 inq_recsize testfile.nc
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+int main(int argc, char** argv) {
+    char *filename="testfile.nc";
+    int nerrs, rank, nprocs, err;
+    int ncid, cmode, varid[7], dimid[3];
+    MPI_Offset expected_recsize, recsize;
+    MPI_Info info=MPI_INFO_NULL;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        goto fn_exit;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for inquiring record size ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    /* printf("PnetCDF version string: \"%s\"\n", ncmpi_inq_libvers()); */
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, info, &ncid); ERR
+
+    /* define dimension and variable */
+    err = ncmpi_def_dim(ncid, "REC_DIM", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "Y",       2,            &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "X",       10,           &dimid[2]); ERR
+
+    nerrs = 0;
+    expected_recsize = 0;
+
+    /* define some record variables */
+    err = ncmpi_def_var(ncid, "REC_VAR_1", NC_INT, 1, dimid, &varid[0]); ERR
+    expected_recsize += sizeof(int);
+    err = ncmpi_def_var(ncid, "REC_VAR_2", NC_INT, 3, dimid, &varid[1]); ERR
+    expected_recsize += 2 * 10 * sizeof(int);
+    err = ncmpi_def_var(ncid, "REC_VAR_3", NC_INT, 2, dimid, &varid[2]); ERR
+    expected_recsize += 2 * sizeof(int);
+    err = ncmpi_def_var(ncid, "REC_VAR_4", NC_INT, 1, dimid, &varid[3]); ERR
+    expected_recsize += sizeof(int);
+
+    /* define some fixed-size variables */
+    err = ncmpi_def_var(ncid, "FIX_VAR_1", NC_INT, 2, dimid+1, &varid[4]); ERR
+    err = ncmpi_def_var(ncid, "FIX_VAR_2", NC_INT, 1, dimid+1, &varid[5]); ERR
+    err = ncmpi_def_var(ncid, "FIX_VAR_3", NC_INT, 1, dimid+2, &varid[6]); ERR
+
+    err = ncmpi_enddef(ncid); ERR
+
+    err = ncmpi_inq_recsize(ncid, &recsize); ERR
+    if (expected_recsize != recsize) {
+        printf("Error at line %d: expecting record size %lld but got %lld\n", __LINE__,expected_recsize, recsize);
+        nerrs++;
+    }
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+fn_exit:
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/inq_recsizef.f90 b/test/testcases/inq_recsizef.f90
new file mode 100644
index 0000000..f78a7fa
--- /dev/null
+++ b/test/testcases/inq_recsizef.f90
@@ -0,0 +1,142 @@
+!
+!   Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: inq_recsizef.f90 2205 2015-11-28 20:41:50Z wkliao $
+
+!
+! This program tests if one can get the size of record block correctly.
+! The record block size is the sum of individual record of all record
+! variables. It first defines some number of record and fixed-size
+! variables and then calls the API ncmpi_inq_recsize() and varify if
+! the numbers are ! correct.
+!
+! The compile and run commands are given below. This program is to be
+! run on one MPI process.
+!
+!    % mpif90 -g -o inq_recsizef inq_recsizef.f90 -lpnetcdf
+!
+!    % mpiexec -l -n 1 inq_recsizef testfile.nc
+!
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+          character(len=128) msg
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              msg = '*** TESTING F90 inq_recsizef.f90 for inquiring record size'
+              call pass_fail(1, msg)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          character(LEN=256) filename, cmd, msg
+          integer err, ierr, nprocs, rank, cmode, ncid, nerrs, get_args
+          integer varid(7), dimid(3), dimid_1D(1), dimid_2D(2)
+          integer(kind=MPI_OFFSET_KIND) expected_recsize, recsize
+          integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+
+          call MPI_Init(ierr)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, ierr)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              filename = "testfile.nc"
+              err = get_args(cmd, filename)
+          endif
+          call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+          if (err .EQ. 0) goto 999
+          
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_OFFSET)
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! define dimensions
+          err = nf90mpi_def_dim(ncid, "X", 10_MPI_OFFSET_KIND, dimid(1))
+          call check(err, 'In nf90mpi_def_dim X: ')
+          err = nf90mpi_def_dim(ncid, "Y", 2_MPI_OFFSET_KIND,  dimid(2))
+          call check(err, 'In nf90mpi_def_dim Y: ')
+          err = nf90mpi_def_dim(ncid, "REC_DIM", NF90MPI_UNLIMITED, dimid(3))
+          call check(err, 'In nf90mpi_def_dim REC_DIM: ')
+
+          ! define some record variables
+          dimid_1D(1) = dimid(3)
+          dimid_2D(1) = dimid(2)
+          dimid_2D(2) = dimid(3)
+
+          expected_recsize = 0;
+
+          err = nf90mpi_def_var(ncid, "REC_VAR_1", NF90_INT, dimid_1D, varid(1))
+          call check(err, 'In nf90mpi_def_var: REC_VAR_1')
+          expected_recsize = expected_recsize + 4
+          err = nf90mpi_def_var(ncid, "REC_VAR_2", NF90_INT, dimid,    varid(2))
+          call check(err, 'In nf90mpi_def_var: REC_VAR_2')
+          expected_recsize = expected_recsize + 10 * 2 * 4
+          err = nf90mpi_def_var(ncid, "REC_VAR_3", NF90_INT, dimid_2D, varid(3))
+          call check(err, 'In nf90mpi_def_var: REC_VAR_3')
+          expected_recsize = expected_recsize + 2 * 4
+          err = nf90mpi_def_var(ncid, "REC_VAR_4", NF90_INT, dimid_1D, varid(4))
+          call check(err, 'In nf90mpi_def_var: REC_VAR_4')
+          expected_recsize = expected_recsize + 4
+
+          ! define some fixed-size variables
+          dimid_1D(1) = dimid(1)
+          dimid_2D(1) = dimid(1)
+          dimid_2D(2) = dimid(2)
+
+          err = nf90mpi_def_var(ncid, "FIX_VAR_1", NF90_INT, dimid_2D, varid(5))
+          call check(err, 'In nf90mpi_def_var: FIX_VAR_1')
+          err = nf90mpi_def_var(ncid, "FIX_VAR_2", NF90_INT, dimid_1D, varid(6))
+          call check(err, 'In nf90mpi_def_var: FIX_VAR_2')
+          err = nf90mpi_def_var(ncid, "FIX_VAR_3", NF90_INT, dimid_1D, varid(7))
+          call check(err, 'In nf90mpi_def_var: FIX_VAR_3')
+
+          ! do not forget to exit define mode
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! inquire the numbers of variables (record and fixed-size
+          err = nf90mpi_inq_recsize(ncid, recsize)
+          call check(err, 'In nf90mpi_inquire: ')
+
+          nerrs = 0
+          if (expected_recsize .NE. recsize) then
+              write(6,*) "Error: expecting resize ", expected_recsize,", but got ", recsize
+              nerrs = nerrs + 1
+          endif
+
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err == NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, ierr)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+          msg = '*** TESTING F90 '//trim(cmd)//' for inquiring record size'
+          if (rank .eq. 0) call pass_fail(nerrs, msg)
+
+ 999      call MPI_Finalize(ierr)
+      end program main
+
diff --git a/test/testcases/interop1.sh b/test/testcases/interop1.sh
new file mode 100755
index 0000000..77225fc
--- /dev/null
+++ b/test/testcases/interop1.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# a test to ensure we can work with files created by serial netcdf.  does
+# require both ncgen and ncdump to be in your path.
+
+# Step 0: see if we have the utilities in our path:
+
+which ncgen >/dev/null 
+
+if [ $? -ne 0 ] ; then
+	echo "could not find 'ncgen' (from serial netcdf) in path. exiting"
+	exit 1
+fi
+
+which ncmpidump >/dev/null
+
+if [ $? -ne 0 ] ; then
+	echo "could not find 'ncmpidump' (from parallel-netcdf) in path. exiting"
+	exit 1
+fi
+
+OUTPUT=geo-${RANDOM}-${RANDOM}.nc
+rm -f $OUTPUT
+
+# Step 1: create the file:
+ncgen -b -v 2 -o $OUTPUT geopotential.ncdump
+
+# step 2: ensure we can at least parse the header
+ncmpidump -h $OUTPUT >/dev/null
+
+if [ $? -ne 0 ] ; then
+	echo "error parsing generated netcdf file!"
+	exit 1
+else
+	echo " No Errors"
+	rm $OUTPUT
+	exit 0
+fi
diff --git a/test/testcases/ivarn.c b/test/testcases/ivarn.c
new file mode 100644
index 0000000..87ae2f7
--- /dev/null
+++ b/test/testcases/ivarn.c
@@ -0,0 +1,447 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: ivarn.c 2219 2015-12-11 22:30:03Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example tests using calls to ncmpi_iput_varn_int(),
+ * ncmpi_iput_varn_float(), ncmpi_iput_varn_double() to write a sequence of
+ * requests with arbitrary array indices and lengths. Note that the request IDs
+ * in the argument array_of_requests[] of ncmpi_wait_all() are in an arbitray
+ * order (instead in an increasing order).
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o ivarn ivarn.c -lpnetcdf
+ *    % mpiexec -n 4 ./ivarn /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             netcdf testfile {
+ *    dimensions:
+ *            dim000001 = 16 ;
+ *            time = UNLIMITED ; // (1 currently)
+ *    variables:
+ *            int vari0001(time, dim000001) ;
+ *            float varr0001(time, dim000001) ;
+ *            double vard0001(time, dim000001) ;
+ *            int vari0002(time, dim000001) ;
+ *            float varr0002(time, dim000001) ;
+ *            double vard0002(time, dim000001) ;
+ *    data:
+ *    
+ *     vari0001 =
+ *      1, _, 3, 4, 5, 6, 7, _, 9, 10, 11, 12, 13, 14, _, 16 ;
+ *    
+ *     varr0001 =
+ *      1.1, _, 3.1, 4.1, 5.1, 6.1, 7.1, _, 9.1, 10.1, 11.1, 12.1, 13.1, 14.1, _, 16.1 ;
+ *    
+ *     vard0001 =
+ *      1.3, _, 3.3, 4.3, 5.3, 6.3, 7.3, _, 9.3, 10.3, 11.3, 12.3, 13.3, 14.3, _, 16.3 ;
+ *    
+ *     vari0002 =
+ *      1, _, 3, 4, 5, 6, 7, _, 9, 10, 11, 12, 13, 14, _, 16 ;
+ *    
+ *     varr0002 =
+ *      1.2, _, 3.2, 4.2, 5.2, 6.2, 7.2, _, 9.2, 10.2, 11.2, 12.2, 13.2, 14.2, _, 16.2 ;
+ *    
+ *     vard0002 =
+ *      1.4, _, 3.4, 4.4, 5.4, 6.4, 7.4, _, 9.4, 10.4, 11.4, 12.4, 13.4, 14.4, _, 16.4 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define LEN 16
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+static
+int check_int_buf(int *buffer)
+{
+    int i, nprocs;
+    int expected[LEN];
+
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    for (i=0; i<LEN; i++) expected[i] = i+1;
+    expected[1] = expected[7] = expected[14] = NC_FILL_INT;
+
+    /* check if the contents of buf are expected */
+    for (i=0; i<LEN; i++) {
+        if (nprocs == 1) { if (i == 4) break; }
+        else if (nprocs == 2) {
+            if (3 < i && i < 7) continue;
+            if (i == 12) break;
+        }
+        else if (nprocs == 3) { if (i == 12) break; }
+
+        if (buffer[i] != expected[i]) {
+            printf("Expected read buf[%d]=%d, but got %d\n",
+                   i,expected[i],buffer[i]);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static
+int check_flt_buf(float *buffer, float extra)
+{
+    int i, nprocs;
+    float expected[LEN];
+
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    for (i=0; i<LEN; i++) expected[i] = extra+i+1;
+    expected[1] = expected[7] = expected[14] = NC_FILL_FLOAT;
+
+    /* check if the contents of buf are expected */
+    for (i=0; i<LEN; i++) {
+        if (nprocs == 1) { if (i == 4) break; }
+        else if (nprocs == 2) {
+            if (3 < i && i < 7) continue;
+            if (i == 12) break;
+        }
+        else if (nprocs == 3) { if (i == 12) break; }
+
+        if (buffer[i] != expected[i]) {
+            printf("Expected read buf[%d]=%.1f, but got %.1f\n",
+                   i,expected[i],buffer[i]);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static
+int check_dbl_buf(double *buffer, double extra)
+{
+    int i, nprocs;
+    double expected[LEN];
+
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    for (i=0; i<LEN; i++) expected[i] = extra+i+1;
+    expected[1] = expected[7] = expected[14] = NC_FILL_DOUBLE;
+
+    /* check if the contents of buf are expected */
+    for (i=0; i<LEN; i++) {
+        if (nprocs == 1) { if (i == 4) break; }
+        else if (nprocs == 2) {
+            if (3 < i && i < 7) continue;
+            if (i == 12) break;
+        }
+        else if (nprocs == 3) { if (i == 12) break; }
+
+        if (buffer[i] != expected[i]) {
+            printf("Expected read buf[%d]=%.1f, but got %.1f\n",
+                   i,expected[i],buffer[i]);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int i, rank, nprocs, err, verbose=0, nerrs=0;
+    int ncid, cmode, dimid[2];
+    int vari0001, vari0002, varr0001, varr0002, vard0001, vard0002;
+    MPI_Offset **starts, **counts;
+    int req[LEN], st[LEN], num_reqs=0;
+    int ibuf1[LEN], ibuf2[LEN];
+    float rbuf1[LEN], rbuf2[LEN];
+    double dbuf1[LEN], dbuf2[LEN];
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for ncmpi_iput_varn_<type>() ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    if (verbose && nprocs != 4 && rank == 0)
+        printf("Warning: %s is intended to run on 4 processes\n",argv[0]);
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+
+    err = ncmpi_def_dim(ncid, "dim000001", LEN, &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_var(ncid, "vari0001", NC_INT, 2, dimid, &vari0001); ERR
+    err = ncmpi_def_var(ncid, "varr0001", NC_FLOAT, 2, dimid, &varr0001); ERR
+    err = ncmpi_def_var(ncid, "vard0001", NC_DOUBLE, 2, dimid, &vard0001); ERR
+    err = ncmpi_def_var(ncid, "vari0002", NC_INT, 2, dimid, &vari0002); ERR
+    err = ncmpi_def_var(ncid, "varr0002", NC_FLOAT, 2, dimid, &varr0002); ERR
+    err = ncmpi_def_var(ncid, "vard0002", NC_DOUBLE, 2, dimid, &vard0002); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    starts    = (MPI_Offset**) malloc(2 *    sizeof(MPI_Offset*));
+    counts    = (MPI_Offset**) malloc(2 *    sizeof(MPI_Offset*));
+    starts[0] = (MPI_Offset*)  calloc(2 * 2, sizeof(MPI_Offset));
+    counts[0] = (MPI_Offset*)  calloc(2 * 2, sizeof(MPI_Offset));
+    for (i=1; i<2; i++) {
+        starts[i] = starts[i-1] + 2;
+        counts[i] = counts[i-1] + 2;
+    }
+
+    /* assign arbitrary starts and counts */
+    if (rank == 0) {
+        /* vari0001 and vari0002 */
+        starts[0][0] = 0; starts[0][1] = 1; counts[0][0] = 1; counts[0][1] = 1;
+        ibuf1[0] = NC_FILL_INT;
+        err = ncmpi_iput_varn_int(ncid, vari0001, 1, starts, counts, ibuf1, &req[1]); ERR
+        ibuf2[0] = NC_FILL_INT;
+        err = ncmpi_iput_varn_int(ncid, vari0002, 1, starts, counts, ibuf2, &req[7]); ERR
+
+        starts[0][0] = 0; starts[0][1] = 0; counts[0][0] = 1; counts[0][1] = 1;
+        starts[1][0] = 0; starts[1][1] = 2; counts[1][0] = 1; counts[1][1] = 2;
+        ibuf1[1] = 1; ibuf1[2] = 3; ibuf1[3] = 4;
+        err = ncmpi_iput_varn_int(ncid, vari0001, 2, starts, counts, ibuf1+1, &req[0]); ERR
+        ibuf2[1] = 1; ibuf2[2] = 3; ibuf2[3] = 4;
+        err = ncmpi_iput_varn_int(ncid, vari0002, 2, starts, counts, ibuf2+1, &req[6]); ERR
+
+        /* varr0001 and varr0002 */
+        starts[0][0] = 0; starts[0][1] = 1; counts[0][0] = 1; counts[0][1] = 1;
+        rbuf1[0] = NC_FILL_FLOAT;
+        err = ncmpi_iput_varn_float(ncid, varr0001, 1, starts, counts, rbuf1, &req[3]); ERR
+        rbuf2[0] = NC_FILL_FLOAT;
+        err = ncmpi_iput_varn_float(ncid, varr0002, 1, starts, counts, rbuf2, &req[9]); ERR
+
+        starts[0][0] = 0; starts[0][1] = 0; counts[0][0] = 1; counts[0][1] = 1;
+        starts[1][0] = 0; starts[1][1] = 2; counts[1][0] = 1; counts[1][1] = 2;
+        rbuf1[1] = 1.1; rbuf1[2] = 3.1; rbuf1[3] = 4.1;
+        err = ncmpi_iput_varn_float(ncid, varr0001, 2, starts, counts, rbuf1+1, &req[2]); ERR
+        rbuf2[1] = 1.2; rbuf2[2] = 3.2; rbuf2[3] = 4.2;
+        err = ncmpi_iput_varn_float(ncid, varr0002, 2, starts, counts, rbuf2+1, &req[8]); ERR
+
+        /* vard0001 and vard0002 */
+        starts[0][0] = 0; starts[0][1] = 1; counts[0][0] = 1; counts[0][1] = 1;
+        dbuf1[0] = NC_FILL_DOUBLE;
+        err = ncmpi_iput_varn_double(ncid, vard0001, 1, starts, counts, dbuf1, &req[5]); ERR
+        dbuf2[0] = NC_FILL_DOUBLE;
+        err = ncmpi_iput_varn_double(ncid, vard0002, 1, starts, counts, dbuf2, &req[11]); ERR
+
+        starts[0][0] = 0; starts[0][1] = 0; counts[0][0] = 1; counts[0][1] = 1;
+        starts[1][0] = 0; starts[1][1] = 2; counts[1][0] = 1; counts[1][1] = 2;
+        dbuf1[1] = 1.3; dbuf1[2] = 3.3; dbuf1[3] = 4.3;
+        err = ncmpi_iput_varn_double(ncid, vard0001, 2, starts, counts, dbuf1+1, &req[4]); ERR
+        dbuf2[1] = 1.4; dbuf2[2] = 3.4; dbuf2[3] = 4.4;
+        err = ncmpi_iput_varn_double(ncid, vard0002, 2, starts, counts, dbuf2+1, &req[10]); ERR
+
+        num_reqs = 12;
+        /* rank 0 is writing the followings: ("x" means skip, "-" means fill value)
+                  1  -  3  4  x  x  x  x  x  x  x  x  x  x  x  x 
+         */
+    } else if (rank ==1) {
+        /* vari0001 and vari0002 */
+        starts[0][0] = 0; starts[0][1] = 7; counts[0][0] = 1; counts[0][1] = 1;
+        ibuf1[0] = NC_FILL_INT;
+        err = ncmpi_iput_varn_int(ncid, vari0001, 1, starts, counts, ibuf1, &req[1]); ERR
+        ibuf2[0] = NC_FILL_INT;
+        err = ncmpi_iput_varn_int(ncid, vari0002, 1, starts, counts, ibuf2, &req[7]); ERR
+
+        starts[0][0] = 0; starts[0][1] = 8; counts[0][0] = 1; counts[0][1] = 4;
+        ibuf1[1] = 9; ibuf1[2] = 10; ibuf1[3] = 11; ibuf1[4] = 12;
+        err = ncmpi_iput_varn_int(ncid, vari0001, 1, starts, counts, ibuf1+1, &req[0]); ERR
+        ibuf2[1] = 9; ibuf2[2] = 10; ibuf2[3] = 11; ibuf2[4] = 12;
+        err = ncmpi_iput_varn_int(ncid, vari0002, 1, starts, counts, ibuf2+1, &req[6]); ERR
+
+        /* varr0001 and varr0002 */
+        starts[0][0] = 0; starts[0][1] = 7; counts[0][0] = 1; counts[0][1] = 1;
+        rbuf1[0] = NC_FILL_FLOAT;
+        err = ncmpi_iput_varn_float(ncid, varr0001, 1, starts, counts, rbuf1, &req[3]); ERR
+        rbuf2[0] = NC_FILL_FLOAT;
+        err = ncmpi_iput_varn_float(ncid, varr0002, 1, starts, counts, rbuf2, &req[9]); ERR
+
+        starts[0][0] = 0; starts[0][1] = 8; counts[0][0] = 1; counts[0][1] = 4;
+        rbuf1[1] = 9.1; rbuf1[2] = 10.1; rbuf1[3] = 11.1; rbuf1[4] = 12.1;
+        err = ncmpi_iput_varn_float(ncid, varr0001, 1, starts, counts, rbuf1+1, &req[2]); ERR
+        rbuf2[1] = 9.2; rbuf2[2] = 10.2; rbuf2[3] = 11.2; rbuf2[4] = 12.2;
+        err = ncmpi_iput_varn_float(ncid, varr0002, 1, starts, counts, rbuf2+1, &req[8]); ERR
+
+        /* vard0001 and vard0002 */
+        starts[0][0] = 0; starts[0][1] = 7; counts[0][0] = 1; counts[0][1] = 1;
+        dbuf1[0] = NC_FILL_DOUBLE;
+        err = ncmpi_iput_varn_double(ncid, vard0001, 1, starts, counts, dbuf1, &req[5]); ERR
+        dbuf2[0] = NC_FILL_DOUBLE;
+        err = ncmpi_iput_varn_double(ncid, vard0002, 1, starts, counts, dbuf2, &req[11]); ERR
+
+        starts[0][0] = 0; starts[0][1] = 8; counts[0][0] = 1; counts[0][1] = 4;
+        dbuf1[1] = 9.3; dbuf1[2] = 10.3; dbuf1[3] = 11.3; dbuf1[4] = 12.3;
+        err = ncmpi_iput_varn_double(ncid, vard0001, 1, starts, counts, dbuf1+1, &req[4]); ERR
+        dbuf2[1] = 9.4; dbuf2[2] = 10.4; dbuf2[3] = 11.4; dbuf2[4] = 12.4;
+        err = ncmpi_iput_varn_double(ncid, vard0002, 1, starts, counts, dbuf2+1, &req[10]); ERR
+
+        num_reqs = 12;
+        /* rank 1 is writing the followings: ("x" means skip, "-" means fill value)
+                  vari0001:
+                  x  x  x  x  x  x  x  x  -  9  10 11 12 x  x  x  x 
+         */
+    } else if (rank ==2) {
+        /* vari0001 and vari0002 */
+        starts[0][0] = 0; starts[0][1] = 4; counts[0][0] = 1; counts[0][1] = 3;
+        ibuf1[0] = 5; ibuf1[1] = 6; ibuf1[2] = 7;
+        err = ncmpi_iput_varn_int(ncid, vari0001, 1, starts, counts, ibuf1, &req[0]); ERR
+        ibuf2[0] = 5; ibuf2[1] = 6; ibuf2[2] = 7;
+        err = ncmpi_iput_varn_int(ncid, vari0002, 1, starts, counts, ibuf2, &req[1]); ERR
+
+        /* varr0001 and varr0002 */
+        rbuf1[0] = 5.1; rbuf1[1] = 6.1; rbuf1[2] = 7.1;
+        err = ncmpi_iput_varn_float(ncid, varr0001, 1, starts, counts, rbuf1, &req[2]); ERR
+        rbuf2[0] = 5.2; rbuf2[1] = 6.2; rbuf2[2] = 7.2;
+        err = ncmpi_iput_varn_float(ncid, varr0002, 1, starts, counts, rbuf2, &req[3]); ERR
+
+        /* vard0001 and vard0002 */
+        dbuf1[0] = 5.3; dbuf1[1] = 6.3; dbuf1[2] = 7.3;
+        err = ncmpi_iput_varn_double(ncid, vard0001, 1, starts, counts, dbuf1, &req[4]); ERR
+        dbuf2[0] = 5.4; dbuf2[1] = 6.4; dbuf2[2] = 7.4;
+        err = ncmpi_iput_varn_double(ncid, vard0002, 1, starts, counts, dbuf2, &req[5]); ERR
+
+        num_reqs = 6;
+        /* rank 2 is writing the followings: ("x" means skip, "-" means fill value)
+                  vari0001:
+                  x  x  x  x  x  5  6  7  x  x  x  x  x  x  x  x  x 
+         */
+    } else if (rank ==3) {
+        /* vari0001 and vari0002 */
+        starts[0][0] = 0; starts[0][1] = 14; counts[0][0] = 1; counts[0][1] = 1;
+        ibuf1[0] = NC_FILL_INT;
+        err = ncmpi_iput_varn_int(ncid, vari0001, 1, starts, counts, ibuf1, &req[0]); ERR
+        ibuf2[0] = NC_FILL_INT;
+        err = ncmpi_iput_varn_int(ncid, vari0002, 1, starts, counts, ibuf2, &req[1]); ERR
+
+        starts[0][0] = 0; starts[0][1] = 12; counts[0][0] = 1; counts[0][1] = 2;
+        starts[1][0] = 0; starts[1][1] = 15; counts[1][0] = 1; counts[1][1] = 1;
+        ibuf1[1] = 13; ibuf1[2] = 14; ibuf1[3] = 16;
+        err = ncmpi_iput_varn_int(ncid, vari0001, 2, starts, counts, ibuf1+1, &req[2]); ERR
+        ibuf2[1] = 13; ibuf2[2] = 14; ibuf2[3] = 16;
+        err = ncmpi_iput_varn_int(ncid, vari0002, 2, starts, counts, ibuf2+1, &req[3]); ERR
+
+        /* varr0001 and varr0002 */
+        starts[0][0] = 0; starts[0][1] = 14; counts[0][0] = 1; counts[0][1] = 1;
+        rbuf1[0] = NC_FILL_FLOAT;
+        err = ncmpi_iput_varn_float(ncid, varr0001, 1, starts, counts, rbuf1, &req[4]); ERR
+        rbuf2[0] = NC_FILL_FLOAT;
+        err = ncmpi_iput_varn_float(ncid, varr0002, 1, starts, counts, rbuf2, &req[5]); ERR
+
+        starts[0][0] = 0; starts[0][1] = 12; counts[0][0] = 1; counts[0][1] = 2;
+        starts[1][0] = 0; starts[1][1] = 15; counts[1][0] = 1; counts[1][1] = 1;
+        rbuf1[1] = 13.1; rbuf1[2] = 14.1; rbuf1[3] = 16.1;
+        err = ncmpi_iput_varn_float(ncid, varr0001, 2, starts, counts, rbuf1+1, &req[6]); ERR
+        rbuf2[1] = 13.2; rbuf2[2] = 14.2; rbuf2[3] = 16.2;
+        err = ncmpi_iput_varn_float(ncid, varr0002, 2, starts, counts, rbuf2+1, &req[7]); ERR
+
+        /* vard0001 and vard0002 */
+        starts[0][0] = 0; starts[0][1] = 14; counts[0][0] = 1; counts[0][1] = 1;
+        dbuf1[0] = NC_FILL_DOUBLE;
+        err = ncmpi_iput_varn_double(ncid, vard0001, 1, starts, counts, dbuf1, &req[8]); ERR
+        dbuf2[0] = NC_FILL_DOUBLE;
+        err = ncmpi_iput_varn_double(ncid, vard0002, 1, starts, counts, dbuf2, &req[9]); ERR
+
+        starts[0][0] = 0; starts[0][1] = 12; counts[0][0] = 1; counts[0][1] = 2;
+        starts[1][0] = 0; starts[1][1] = 15; counts[1][0] = 1; counts[1][1] = 1;
+        dbuf1[1] = 13.3; dbuf1[2] = 14.3; dbuf1[3] = 16.3;
+        err = ncmpi_iput_varn_double(ncid, vard0001, 2, starts, counts, dbuf1+1, &req[10]); ERR
+        dbuf2[1] = 13.4; dbuf2[2] = 14.4; dbuf2[3] = 16.4;
+        err = ncmpi_iput_varn_double(ncid, vard0002, 2, starts, counts, dbuf2+1, &req[11]); ERR
+
+        num_reqs = 12;
+        /* rank 3 is writing the followings: ("x" means skip, "-" means fill value)
+                  vari0001:
+                  x  x  x  x  x  x  x  x  x  x  x  x 13 14  - 16
+         */
+    }
+
+    err = ncmpi_wait_all(ncid, num_reqs, req, st); ERR
+    for (i=0; i<num_reqs; i++) {
+        err = st[i]; ERR
+    }
+
+    err = ncmpi_close(ncid); ERR
+
+    free(starts[0]);
+    free(counts[0]);
+    free(starts);
+    free(counts);
+
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR
+
+    err = ncmpi_inq_varid(ncid, "vari0001", &vari0001); ERR
+    err = ncmpi_inq_varid(ncid, "varr0001", &varr0001); ERR
+    err = ncmpi_inq_varid(ncid, "vard0001", &vard0001); ERR
+    err = ncmpi_inq_varid(ncid, "vari0002", &vari0002); ERR
+    err = ncmpi_inq_varid(ncid, "varr0002", &varr0002); ERR
+    err = ncmpi_inq_varid(ncid, "vard0002", &vard0002); ERR
+
+    for (i=0; i<LEN; i++) ibuf1[i] = -1;
+    err = ncmpi_get_var_int_all(ncid, vari0001, ibuf1); ERR
+    nerrs += check_int_buf(ibuf1);
+
+    for (i=0; i<LEN; i++) ibuf2[i] = -1;
+    err = ncmpi_get_var_int_all(ncid, vari0002, ibuf2); ERR
+    nerrs += check_int_buf(ibuf2);
+
+    for (i=0; i<LEN; i++) rbuf1[i] = -1;
+    err = ncmpi_get_var_float_all(ncid, varr0001, rbuf1); ERR
+    nerrs += check_flt_buf(rbuf1, 0.1);
+
+    for (i=0; i<LEN; i++) rbuf2[i] = -1;
+    err = ncmpi_get_var_float_all(ncid, varr0002, rbuf2); ERR
+    nerrs += check_flt_buf(rbuf2, 0.2);
+
+    for (i=0; i<LEN; i++) dbuf1[i] = -1;
+    err = ncmpi_get_var_double_all(ncid, vard0001, dbuf1); ERR
+    nerrs += check_dbl_buf(dbuf1, 0.3);
+
+    for (i=0; i<LEN; i++) dbuf2[i] = -1;
+    err = ncmpi_get_var_double_all(ncid, vard0002, dbuf2); ERR
+    nerrs += check_dbl_buf(dbuf2, 0.4);
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/last_large_var.c b/test/testcases/last_large_var.c
new file mode 100644
index 0000000..80d0a7b
--- /dev/null
+++ b/test/testcases/last_large_var.c
@@ -0,0 +1,260 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: last_large_var.c 2291 2016-01-03 05:14:45Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This program tests the special case when there is no record variable, the
+ * last fixed-size variable can be larger than 2GiB if its starting file offset
+ * is less than 2GiB. See NetCDF Classic Format Limitations (The NetCDF Users
+ * Guide).  Quoted here:
+ * "If you don't use the unlimited dimension, only one variable can exceed 2
+ * GiB in size, but it can be as large as the underlying file system permits.
+ * It must be the last variable in the dataset, and the offset to the beginning
+ * of this variable must be less than about 2 GiB."
+ * http://www.unidata.ucar.edu/software/netcdf/old_docs/docs_3_6_3/netcdf-c/nc_005fcreate.html
+ *
+ *    To compile:
+ *        mpicc -O2 last_large_var.c -o last_large_var -lpnetcdf
+ *
+ * Example commands for MPI run and outputs from running ncmpidump on the
+ * NC file produced by this example program:
+ *
+ *    % mpiexec -n 4 ./last_large_var /pvfs2/wkliao/testfile.nc
+ *
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-1
+ *    netcdf testfile {
+ *    dimensions:
+ *    	    Y = 4 ;
+ *    	    X = 5 ;
+ *    	    YY = 66661 ;
+ *    	    XX = 66661 ;
+ *    variables:
+ *    	    int var(Y, X) ;
+ *    	    float var_last(YY, XX) ;
+ *    }
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err)); nerrs++;}}
+
+static
+int check_last_var(char *filename)
+{
+    int err, nerrs=0, ncid, cmode, varid, dimid[4];
+
+    /* create a new file ---------------------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    err = ncmpi_def_dim(ncid, "Y", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 5, &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "YY", 66661, &dimid[2]); ERR
+    err = ncmpi_def_dim(ncid, "XX", 66661, &dimid[3]); ERR
+
+    /* define only fixed-size variables */
+    err = ncmpi_def_var(ncid, "var", NC_INT, 1, dimid+1, &varid); ERR
+    err = ncmpi_def_var(ncid, "var_last", NC_FLOAT, 2, dimid+2, &varid); ERR
+
+    err = ncmpi_enddef(ncid); ERR
+    err = ncmpi_close(ncid); ERR
+
+    return nerrs;
+}
+
+static
+int check_rec_var(char *filename)
+{
+    int err, nerrs=0, ncid, cmode, varid, dimid[4];
+
+    /* create a new file ---------------------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    err = ncmpi_def_dim(ncid, "Y", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 5, &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "YY", 66661, &dimid[2]); ERR
+    err = ncmpi_def_dim(ncid, "XX", 66661, &dimid[3]); ERR
+
+    /* define a record variable */
+    err = ncmpi_def_var(ncid, "var", NC_INT, 1, dimid, &varid); ERR
+    err = ncmpi_def_var(ncid, "var_last", NC_FLOAT, 2, dimid+2, &varid); ERR
+
+    err = ncmpi_enddef(ncid);
+    if (err != NC_EVARSIZE) {
+        printf("\nError at line=%d: expecting error code NC_EVARSIZE but got %s\n",__LINE__,nc_err_code_name(err));
+        nerrs++;
+    }
+    err = ncmpi_close(ncid);
+    if (err != NC_EVARSIZE) {
+        printf("\nError at line=%d: expecting error code NC_EVARSIZE but got %s\n",__LINE__,nc_err_code_name(err));
+        nerrs++;
+    }
+
+    return nerrs;
+}
+
+static
+int check_not_last_var(char *filename)
+{
+    int err, nerrs=0, ncid, cmode, varid, dimid[4];
+
+    /* create a new file ---------------------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    err = ncmpi_def_dim(ncid, "Y", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 5, &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "YY", 66661, &dimid[2]); ERR
+    err = ncmpi_def_dim(ncid, "XX", 66661, &dimid[3]); ERR
+
+    /* the large variable is not the last */
+    err = ncmpi_def_var(ncid, "var_last", NC_FLOAT, 2, dimid+2, &varid); ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT, 1, dimid+1, &varid); ERR
+
+    err = ncmpi_enddef(ncid);
+    if (err != NC_EVARSIZE) {
+        printf("\nError at line=%d: expecting error code NC_EVARSIZE but got %s\n",__LINE__,nc_err_code_name(err));
+        nerrs++;
+    }
+
+    err = ncmpi_close(ncid);
+    if (err != NC_EVARSIZE) {
+        printf("\nError at line=%d: expecting error code NC_EVARSIZE but got %s\n",__LINE__,nc_err_code_name(err));
+        nerrs++;
+    }
+    return nerrs;
+}
+
+static
+int check_add_var(char *filename)
+{
+    int err, nerrs=0, ncid, cmode, varid, dimid[4];
+
+    /* create a new file ---------------------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    err = ncmpi_def_dim(ncid, "Y", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 5, &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "YY", 66661, &dimid[2]); ERR
+    err = ncmpi_def_dim(ncid, "XX", 66661, &dimid[3]); ERR
+
+    err = ncmpi_def_var(ncid, "var", NC_INT, 1, dimid+1, &varid); ERR
+    err = ncmpi_def_var(ncid, "var_last", NC_FLOAT, 2, dimid+2, &varid); ERR
+
+    err = ncmpi_enddef(ncid); ERR
+
+    /* add a new fixed-size variable */
+    err = ncmpi_redef(ncid); ERR
+    err = ncmpi_def_var(ncid, "var_new", NC_INT, 2, dimid, &varid); ERR
+
+    err = ncmpi_enddef(ncid);
+    if (err != NC_EVARSIZE) {
+        printf("\nError at line=%d: expecting error code NC_EVARSIZE but got %s\n",__LINE__,nc_err_code_name(err));
+        nerrs++;
+    }
+
+    err = ncmpi_close(ncid);
+    if (err != NC_EVARSIZE) {
+        printf("\nError at line=%d: expecting error code NC_EVARSIZE but got %s\n",__LINE__,nc_err_code_name(err));
+        nerrs++;
+    }
+    return nerrs;
+}
+
+static
+int check_var_offset(char *filename)
+{
+    int err, nerrs=0, ncid, cmode, varid, dimid[4];
+
+    /* create a new file ---------------------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    err = ncmpi_def_dim(ncid, "Y", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 5, &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "YY", 66661, &dimid[2]); ERR
+    err = ncmpi_def_dim(ncid, "XX", 66661, &dimid[3]); ERR
+
+    err = ncmpi_def_var(ncid, "var", NC_INT, 1, dimid+1, &varid); ERR
+    err = ncmpi_def_var(ncid, "var_last", NC_FLOAT, 2, dimid+2, &varid); ERR
+
+    /* make the file header size larger than 2 GiB */
+    err = ncmpi__enddef(ncid, 2147483648LL, 1, 1, 1);
+    if (err != NC_EVARSIZE) {
+        printf("\nError at line=%d: expecting error code NC_EVARSIZE but got %s\n",__LINE__,nc_err_code_name(err));
+        nerrs++;
+    }
+
+    err = ncmpi_close(ncid); ERR
+    return nerrs;
+}
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int  rank, nprocs, err, nerrs=0;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for last large var in CDF-1/2", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    nerrs += check_last_var(filename);
+    nerrs += check_rec_var(filename);
+    nerrs += check_not_last_var(filename);
+    nerrs += check_add_var(filename);
+    nerrs += check_var_offset(filename);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/modes.c b/test/testcases/modes.c
new file mode 100644
index 0000000..8e9ec21
--- /dev/null
+++ b/test/testcases/modes.c
@@ -0,0 +1,156 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: modes.c 2219 2015-12-11 22:30:03Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This program tests if the correct error codes are returns given various
+ * create/open modes.
+ *
+ * NC_EINVAL_CMODE should be returned when creating a file using
+ * comde with both NC_64BIT_OFFSET & NC_64BIT_DATA flags set.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy() */
+#include <unistd.h> /* unlink(), access() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define ERR {if(err!=NC_NOERR)printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}
+
+#define EXPECT_ERR(err_no) \
+    if (err != err_no) { \
+        nerrs++; \
+        printf("Error at line %d: expect error code %s but got %s\n", \
+               __LINE__,nc_err_code_name(err_no),nc_err_code_name(err)); \
+    }
+
+static
+int check_modes(char *filename)
+{
+    int rank, err, nerrs=0, file_exist;
+    int ncid, cmode;
+
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    /* delete the file and ignore error */
+    unlink(filename);
+    MPI_Barrier(MPI_COMM_WORLD);
+
+    /* create a new file and test various cmodes ----------------------------*/
+    cmode = NC_CLOBBER;
+
+    /* It is illegal to use both NC_64BIT_OFFSET and NC_64BIT_DATA together */
+    cmode |= NC_64BIT_OFFSET | NC_64BIT_DATA;
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    EXPECT_ERR(NC_EINVAL_CMODE)
+
+    /* The file should not be created */
+    file_exist = 0;
+    if (rank == 0 && access(filename, F_OK) == 0) file_exist = 1;
+    MPI_Bcast(&file_exist, 1, MPI_INT, 0, MPI_COMM_WORLD);
+    if (file_exist) {
+        printf("Error at line %d: file (%s) should not be created\n", __LINE__, filename);
+        nerrs++;
+    }
+
+    /* delete the file and ignore error */
+    unlink(filename);
+    MPI_Barrier(MPI_COMM_WORLD);
+
+    /* Collectively opening a non-existing file for read, expect error code
+     * NC_ENOENT on all processes */
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid);
+    EXPECT_ERR(NC_ENOENT)
+
+    file_exist = 0;
+    if (rank == 0 && access(filename, F_OK) == 0) file_exist = 1;
+    MPI_Bcast(&file_exist, 1, MPI_INT, 0, MPI_COMM_WORLD);
+    if (file_exist) {
+        printf("Error at line %d: file (%s) should not be created\n", __LINE__, filename);
+        nerrs++;
+    }
+
+    /* delete the file and ignore error */
+    unlink(filename);
+    MPI_Barrier(MPI_COMM_WORLD);
+
+    /* Collectively opening a non-existing file for write, expect error code
+     * NC_ENOENT on all processes */
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, MPI_INFO_NULL, &ncid);
+    EXPECT_ERR(NC_ENOENT)
+
+    file_exist = 0;
+    if (rank == 0 && access(filename, F_OK) == 0) file_exist = 1;
+    MPI_Bcast(&file_exist, 1, MPI_INT, 0, MPI_COMM_WORLD);
+    if (file_exist) {
+        printf("Error at line %d: file (%s) should not be created\n", __LINE__, filename);
+        nerrs++;
+    }
+
+    /* delete the file and ignore error */
+    unlink(filename);
+
+    return nerrs;
+}
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int rank, err, nerrs=0;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for file create/open modes ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    /* test under safe mode enabled */
+    setenv("PNETCDF_SAFE_MODE", "1", 1);
+    nerrs += check_modes(filename);
+
+    /* test under safe mode disabled */
+    setenv("PNETCDF_SAFE_MODE", "0", 1);
+    nerrs += check_modes(filename);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/ncmpi_vars_null_stride.c b/test/testcases/ncmpi_vars_null_stride.c
new file mode 100644
index 0000000..de69c0c
--- /dev/null
+++ b/test/testcases/ncmpi_vars_null_stride.c
@@ -0,0 +1,88 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: ncmpi_vars_null_stride.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define HANDLE_ERROR(err) { \
+    nerrs++; \
+    fprintf(stderr, "Error at line %d: %s\n", __LINE__, ncmpi_strerror(err)); \
+    goto fn_exit; \
+}
+
+#define NDIMS 1
+int main(int argc, char **argv)
+{
+    int err, nerrs=0, ncfile, dimid, varid, ndims=NDIMS;
+    int i, nprocs, rank;
+    MPI_Offset start[NDIMS] = {0};
+    MPI_Offset count[NDIMS] = {0};
+    int buf[512];
+    char *filename="testfile.nc";
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for NULL stride ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, 0, MPI_INFO_NULL, &ncfile);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    err = ncmpi_def_dim(ncfile, "d1", nprocs, &dimid);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    err = ncmpi_def_var(ncfile, "v1", NC_INT, ndims, &dimid, &varid);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    err = ncmpi_enddef(ncfile);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    start[0] = rank;
+    count[0] = 1;
+    for (i=0; i<512; i++) buf[i] = rank;
+    err = ncmpi_put_vars_int_all(ncfile, varid, start, count, NULL, buf);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    err = ncmpi_close(ncfile);
+    if (err != NC_NOERR) HANDLE_ERROR(err)
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+fn_exit:
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/test/testcases/noclobber.c b/test/testcases/noclobber.c
new file mode 100644
index 0000000..f7e9a82
--- /dev/null
+++ b/test/testcases/noclobber.c
@@ -0,0 +1,76 @@
+/*
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: noclobber.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+/*
+ * This program tests if PnetCDF can return the right error code NC_EEXIST
+ * when create mode NC_NOCLOBBER is used and the file exists.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define ERR if (err!=NC_NOERR) {printf("Error at line %d: %s\n", __LINE__,ncmpi_strerror(err)); exit(-1);}
+
+int main(int argc, char **argv) {
+    char filename[256];
+    int  err, nerrs=0, ncid, cmode, rank, nprocs;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for NC_NOCLOBBER and NC_EEXIST ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    /* create a file if it does not exist */
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+    err = ncmpi_close(ncid); ERR
+
+    /* now the file exists, test if PnetCDF can return correct error code */
+    cmode = NC_NOCLOBBER;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    if (err != NC_EEXIST) /* err == NC_EOFILE */
+        nerrs++;
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/test/testcases/nonblocking.c b/test/testcases/nonblocking.c
new file mode 100644
index 0000000..b840f28
--- /dev/null
+++ b/test/testcases/nonblocking.c
@@ -0,0 +1,163 @@
+/*
+ *  Copyright (C) 2013, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: nonblocking.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+/*
+ * This program tests the use of nonblocking API.
+ * The write buffer is a 2D array of size NY x NX
+ * It writes the 2nd row of the memory buffer to the 1st row of the variable
+ * array in file. Then it writes the 1st row of the memory buffer to the
+ * 2nd row of the variable array in file.
+ *
+ * The expected reults from the output file contents are:
+ * (when running on 1 MPI process)
+ *
+ *  % ncmpidump testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-1
+ *    dimensions:
+ *         Y = UNLIMITED ; // (2 currently)
+ *         X = 5 ;
+ *    variables:
+ *         int VAR(Y, X) ;
+ *    data:
+ * 
+ *    var =
+ *      1, 1, 1, 1, 1,
+ *      0, 0, 0, 0, 0 ;
+ *    }
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 4
+#define NX 5
+#define ERR if (err!=NC_NOERR) {printf("Error at line %d: %s\n", __LINE__,ncmpi_strerror(err)); exit(-1);}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv) {
+
+    char       filename[256];
+    int        i, j, err, ncid, varid, dimids[2], req[2], st[2], nerrs=0;
+    int        rank, nprocs, buf[NY+1][NX];
+    MPI_Offset start[2], count[2];
+    MPI_Info   info;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for using ncmpi_iput_vara_int() ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    MPI_Info_create(&info);
+    /* When using PVFS2, unexpected buffer value error message might occur.
+     * This is due to  a possible bug in ADIOI_PVFS2_OldWriteStrided() when
+     * filetype is contiguous and buftype is non-contiguous.
+     * Fix: Add ROMIO hint to force ADIO driever to use POSIX I/O */
+    /* MPI_Info_set(info, "romio_pvfs2_posix_write", "enable"); */
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, info, &ncid); ERR
+    MPI_Info_free(&info);
+
+    /* define a 2D array */
+    err = ncmpi_def_dim(ncid, "Y", NC_UNLIMITED, &dimids[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", NX,    &dimids[1]); ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimids, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* initialize the contents of the array */
+    for (j=0; j<NY+1; j++) for (i=0; i<NX; i++) buf[j][i] = j;
+
+    start[0] = 2*rank; start[1] = 0;
+    count[0] = 1;      count[1] = NX;
+
+    /* call nonblocking API */
+    err = ncmpi_iput_vara_int(ncid, varid, start, count, buf[1], &req[0]); ERR
+
+    start[0] += 1;
+    err = ncmpi_iput_vara_int(ncid, varid, start, count, buf[0], &req[1]); ERR
+
+    st[0] = st[1] = NC_NOERR;
+    err = ncmpi_wait_all(ncid, 2, req, st); ERR
+    err = st[0]; ERR
+    err = st[1]; ERR
+
+    /* check if the contents of buf are altered */
+    for (j=0; j<NY; j++)
+        for (i=0; i<NX; i++)
+            if (buf[j][i] != j)
+                printf("Error: buf[%d][%d]=%d != %d\n",j,i,buf[j][i],j);
+ 
+    /* check if root process can write to file header in data mode */
+    err = ncmpi_rename_var(ncid, varid, "VAR"); ERR
+
+    err = ncmpi_close(ncid); ERR
+
+    /* open the same file and read back for validate */
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL,
+                     &ncid); ERR
+
+    err = ncmpi_inq_varid(ncid, "VAR", &varid); ERR
+
+    /* initialize the contents of the array to a different value */
+    for (j=0; j<NY; j++) for (i=0; i<NX; i++) buf[j][i] = -1;
+
+    /* read back variable */
+    start[0] = 2*rank; start[1] = 0;
+    count[0] = 2;      count[1] = NX;
+    err = ncmpi_get_vara_int_all(ncid, varid, start, count, buf[0]); ERR
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if the contents of buf are expected */
+    for (j=0; j<2; j++) {
+        int val = (j == 0) ? 1 : 0;
+        for (i=0; i<NX; i++)
+            if (buf[j][i] != val) {
+                printf("Unexpected read buf[%d][%d]=%d, should be %d\n",
+                       j,i,buf[j][i],val);
+                nerrs++;
+            }
+    }
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/test/testcases/one_record.c b/test/testcases/one_record.c
new file mode 100644
index 0000000..23d93e4
--- /dev/null
+++ b/test/testcases/one_record.c
@@ -0,0 +1,118 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: one_record.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+/*
+ * This program tests the special case of ONLY one record variable is defined
+ * and the record size is not aligned with the 4-byte boundary. As defined in
+ * CDF-1 and CDF-2 format specifications:
+ *    "A special case: Where there is exactly one record variable, we drop the
+ *    requirement that each record be four-byte aligned, so in this case there
+ *    is no record padding."
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define ERRCODE 2
+#define ERR if (err != NC_NOERR) {printf("Error at line %d: err=%d %s\n", __LINE__, err, ncmpi_strerror(err));}
+
+#define STR_LEN 19
+#define NUM_VALS 2
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    int i, err, nerrs=0, rank, nprocs, cmode;
+    int ncid, dimids[2], varid;
+    char data[NUM_VALS][STR_LEN + 1], data_in[NUM_VALS*STR_LEN];
+    MPI_Offset start[2];
+    MPI_Offset count[2];
+    char *filename="testfile.nc";
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for only one record variable ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    strcpy(data[0], "2005-04-11_12:00:00"); /* 19 bytes not a multiply of 4 */
+    strcpy(data[1], "2005-04-11_13:00:00");
+
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    cmode = NC_CLOBBER;
+    err  = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid); ERR
+
+    err = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, dimids); ERR
+    err = ncmpi_def_dim(ncid, "text_dim", STR_LEN, &dimids[1]); ERR
+
+    /* create ONLY one record variable of type NC_CHAR and make sure each
+     * record is of size not aligned with 4-byte boundary.
+     */
+    err = ncmpi_def_var(ncid, "text_var", NC_CHAR, 2, dimids, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* Write some records of var data. */
+    count[0] = 1;
+    count[1] = STR_LEN;
+    start[0] = 0;
+    start[1] = 0;
+    for (i=0; i<NUM_VALS; i++) {
+        err = ncmpi_put_vara_text_all(ncid, varid, start, count, data[start[0]]);
+        ERR
+        start[0]++;
+    }
+
+    /* read the entire data back */
+    err = ncmpi_get_var_text_all(ncid, varid, data_in); ERR
+
+    /* check the contents */
+    for (i=0; i<NUM_VALS; i++)
+      if (strncmp(data[i], data_in+i*STR_LEN, STR_LEN)) {
+          printf("Error: expecting %s but got %s\n", data[i],data_in+i*STR_LEN);
+          nerrs++;
+      }
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+
+    return nerrs;
+}
+
diff --git a/test/testcases/put_parameter.f b/test/testcases/put_parameter.f
new file mode 100644
index 0000000..902e024
--- /dev/null
+++ b/test/testcases/put_parameter.f
@@ -0,0 +1,166 @@
+!
+!   Copyright (C) 2015, Northwestern University and Argonne National
+!   Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: put_parameter.f 2224 2015-12-16 06:10:36Z wkliao $
+
+! This example tests PnetCDF's avoiding in-place Endianness byte swap when
+! the user's write buffer is immutable, i.e. defined as PARAMETER.
+!
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file.
+!
+!    % mpif77 -O2 -o put_parameter put_parameter.f -lpnetcdf
+!    % mpiexec -n 4 ./put_parameter /pvfs2/wkliao/testfile.nc
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-2 (large file)
+!    dimensions:
+!            X = 4 ;
+!            Y = 4 ;
+!    variables:
+!            int var1(Y, X) ;
+!            int var2(Y, X) ;
+!    data:
+!    
+!     var1 =
+!      1, 2, 3, 4,
+!      1, 2, 3, 4,
+!      1, 2, 3, 4,
+!      1, 2, 3, 4 ;
+!    
+!     var2 =
+!      5, 6, 7, 8,
+!      5, 6, 7, 8,
+!      5, 6, 7, 8,
+!      5, 6, 7, 8 ;
+!    }
+!
+!    Note the above dump is in C order
+!
+
+       INTEGER FUNCTION XTRIM(STRING)
+           CHARACTER*(*) STRING
+           INTEGER I, N
+           N = LEN(STRING)
+           DO I = N, 1, -1
+              IF (STRING(I:I) .NE. ' ') GOTO 10
+           ENDDO
+ 10        XTRIM = I
+       END ! FUNCTION XTRIM
+
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err, XTRIM
+          character*(*) message
+          character*128 msg
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message(1:XTRIM(message)), nfmpi_strerror(err)
+              msg = '*** TESTING F77 put_parameter.f for immutable put '
+              call pass_fail(1, msg)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          integer NX, buffer(4)
+          PARAMETER(NX=4)
+          data buffer /5,6,7,8/
+
+          character*256 filename, cmd, msg
+          integer err, ierr, nprocs, rank, nerrs, get_args, XTRIM
+          integer cmode, ncid, varid(2), dimid(2)
+          integer*8 len_ll, start(2), count(2)
+          integer*8 malloc_size, sum_size
+
+          call MPI_Init(ierr)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, ierr)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              filename = "testfile.nc"
+              err = get_args(cmd, filename)
+          endif
+          call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+          if (err .EQ. 0) goto 999
+
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, ierr)
+
+          nerrs = 0
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_OFFSET)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                        MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define dimensions x and y
+          len_ll = NX
+          err = nfmpi_def_dim(ncid, "X", len_ll, dimid(1))
+          call check(err, 'In nfmpi_def_dim X: ')
+
+          len_ll = nprocs
+          err = nfmpi_def_dim(ncid, "Y", len_ll, dimid(2))
+          call check(err, 'In nfmpi_def_dim Y: ')
+
+          ! define a 1D variable of integer type
+          err = nfmpi_def_var(ncid, "var1", NF_INT, 2, dimid, varid(1))
+          call check(err, 'In nfmpi_def_var: ')
+
+          err = nfmpi_def_var(ncid, "var2", NF_INT, 2, dimid, varid(2))
+          call check(err, 'In nfmpi_def_var: ')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! now we are in data mode
+
+          start(1) = 1
+          start(2) = rank + 1
+          count(1) = NX
+          count(2) = 1
+!
+! pgf77 does not like using (/1,2,3,4/) as a function argument
+!          err = nfmpi_put_vara_int_all(ncid, varid(1), start, count,
+!     +                                 (/1,2,3,4/))
+!          call check(err, 'In nfmpi_put_var_int_all: ')
+!
+          err = nfmpi_put_vara_int_all(ncid, varid(2), start, count,
+     +                                 buffer)
+          call check(err, 'In nfmpi_put_var_int_all: ')
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+          msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//
+     +          ' for using immutable write buf '
+          if (rank .eq. 0) call pass_fail(nerrs, msg)
+
+ 999      call MPI_Finalize(ierr)
+      end ! program main
+
diff --git a/test/testcases/record.c b/test/testcases/record.c
new file mode 100644
index 0000000..2f3bfdf
--- /dev/null
+++ b/test/testcases/record.c
@@ -0,0 +1,299 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: record.c 2219 2015-12-11 22:30:03Z wkliao $
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program tests if the number of records is updated correctly. It first
+ * writes to the 2nd record of a variable, followed by writing to the 1st
+ * record. After the 2nd write, a call to ncmpi_inq_dimlen() or ncmpi_inq_dim()
+ * should report seeing 2 records. Then, it does a similar test under
+ * independent data mode. The same test will repeat for 3 cases:
+ * 1) there is only one 1D record variable
+ * 2) there is only one 3D record variable
+ * 3) there are one 1D record variable and one 3D record variable
+ *
+ * The compile and run commands are given below. This program is to be run on
+ * one MPI process.
+ *
+ *    % mpicc -g -o record record.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 1 record record.nc
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define ERR {if(err!=NC_NOERR) {nerrs++; printf("Error at line=%d: %s\n", __LINE__, ncmpi_strerror(err));}}
+
+static
+int test_only_record_var_1D(char *filename)
+{
+    int ncid, cmode, varid, dimid, buf[20], err, nerrs=0;
+    MPI_Offset start, count, length;
+    MPI_Info info=MPI_INFO_NULL;
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_SELF, filename, cmode, info, &ncid); ERR
+
+    /* define dimension and variable */
+    err = ncmpi_def_dim(ncid, "REC_DIM", NC_UNLIMITED, &dimid); ERR
+    err = ncmpi_def_var(ncid, "REC_VAR_1D", NC_INT, 1, &dimid, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* write the 2nd record first */
+    buf[0] = 91;
+    start = 1; count = 1;
+    err = ncmpi_put_vara_int_all(ncid, varid, &start, &count, buf); ERR
+
+    /* write the 1st record now */
+    buf[0] = 90;
+    start = 0; count = 1;
+    err = ncmpi_put_vara_int_all(ncid, varid, &start, &count, buf); ERR
+
+    err = ncmpi_inq_dimlen(ncid, dimid, &length); ERR
+    if (length != 2) {
+        printf("Error: expecting 2 records, but got %lld record(s)\n",length);
+        nerrs++;
+    }
+
+    if (nerrs == 0) { /* test independent data mode */
+        err = ncmpi_begin_indep_data(ncid); ERR
+        /* write the 4th record */
+        buf[0] = 93;
+        start = 3; count = 1;
+        err = ncmpi_put_vara_int(ncid, varid, &start, &count, buf); ERR
+
+        /* write the 3rd record */
+        buf[0] = 92; buf[1] = 93;
+        start = 2; count = 2;
+        err = ncmpi_put_vara_int(ncid, varid, &start, &count, buf); ERR
+
+        err = ncmpi_inq_dimlen(ncid, dimid, &length); ERR
+        if (length != 4) {
+            printf("Error: expecting 4 records, but got %lld record(s)\n",
+                   length);
+            nerrs++;
+        }
+        err = ncmpi_end_indep_data(ncid); ERR
+    }
+    err = ncmpi_close(ncid); ERR
+    return nerrs;
+}
+
+static
+int test_only_record_var_3D(char *filename)
+{
+    int i, ncid, cmode, varid, dimid[3], buf[20], err, nerrs=0;
+    MPI_Offset start[3], count[3], length;
+    MPI_Info info=MPI_INFO_NULL;
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_SELF, filename, cmode, info, &ncid); ERR
+
+    /* define dimension and variable */
+    err = ncmpi_def_dim(ncid, "REC_DIM", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "FIX_DIM_Y", 2,          &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "FIX_DIM_X", 10,         &dimid[2]); ERR
+    err = ncmpi_def_var(ncid, "REC_VAR_3D", NC_INT, 3, dimid, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    start[1] = 0; start[2] = 0; count[0] = 1; count[1] = 2; count[2] = 5;
+
+    /* write the 2nd record first */
+    for (i=0; i<20; i++) buf[i] = 91;
+    start[0] = 1;
+    err = ncmpi_put_vara_int_all(ncid, varid, start, count, buf); ERR
+
+    /* write the 1st record now */
+    for (i=0; i<20; i++) buf[i] = 90;
+    start[0] = 0;
+    err = ncmpi_put_vara_int_all(ncid, varid, start, count, buf); ERR
+
+    err = ncmpi_inq_dimlen(ncid, dimid[0], &length); ERR
+    if (length != 2) {
+        printf("Error: expecting 2 records, but got %lld record(s)\n",length);
+        nerrs++;
+    }
+
+    if (nerrs == 0) { /* test independent data mode */
+        err = ncmpi_begin_indep_data(ncid); ERR
+        /* write the 4th record */
+        for (i=0; i<20; i++) buf[i] = 93;
+        start[0] = 3;
+        err = ncmpi_put_vara_int(ncid, varid, start, count, buf); ERR
+
+        /* write the 3rd record */
+        for (i=0; i<20; i++) buf[i] = 92;
+        start[0] = 2;
+        err = ncmpi_put_vara_int(ncid, varid, start, count, buf); ERR
+
+        err = ncmpi_inq_dimlen(ncid, dimid[0], &length); ERR
+        if (length != 4) {
+            printf("Error: expecting 4 records, but got %lld record(s)\n",
+                   length);
+            nerrs++;
+        }
+        err = ncmpi_end_indep_data(ncid); ERR
+    }
+    err = ncmpi_close(ncid); ERR
+    return nerrs;
+}
+
+static
+int test_two_record_var(char *filename)
+{
+    int i, ncid, cmode, varid[2], dimid[3], buf[20], err, nerrs=0;
+    MPI_Offset start[3], count[3], length;
+    MPI_Info info=MPI_INFO_NULL;
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER;
+    err = ncmpi_create(MPI_COMM_SELF, filename, cmode, info, &ncid); ERR
+
+    /* define dimension and variable */
+    err = ncmpi_def_dim(ncid, "REC_DIM", NC_UNLIMITED, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "FIX_DIM_Y", 2,          &dimid[1]); ERR
+    err = ncmpi_def_dim(ncid, "FIX_DIM_X", 10,         &dimid[2]); ERR
+    err = ncmpi_def_var(ncid, "REC_VAR_1D", NC_INT, 1, dimid, &varid[0]); ERR
+    err = ncmpi_def_var(ncid, "REC_VAR_3D", NC_INT, 3, dimid, &varid[1]); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* REC_VAR_1D: write the 2nd record first */
+    buf[0] = 91;
+    start[0] = 1; count[0] = 1;
+    err = ncmpi_put_vara_int_all(ncid, varid[0], start, count, buf); ERR
+
+    /* write the 1st record now */
+    buf[0] = 90;
+    start[0] = 0; count[0] = 1;
+    err = ncmpi_put_vara_int_all(ncid, varid[0], start, count, buf); ERR
+
+    err = ncmpi_inq_dimlen(ncid, dimid[0], &length); ERR
+    if (length != 2) {
+        printf("Error: expecting 2 records, but got %lld record(s)\n",length);
+        nerrs++;
+    }
+
+    if (nerrs == 0) { /* test independent data mode */
+        err = ncmpi_begin_indep_data(ncid); ERR
+        /* write the 4th record */
+        buf[0] = 93;
+        start[0] = 3; count[0] = 1;
+        err = ncmpi_put_vara_int(ncid, varid[0], start, count, buf); ERR
+
+        /* write the 3rd and 4th records */
+        buf[0] = 92; buf[1] = 93;
+        start[0] = 2; count[0] = 2;
+        err = ncmpi_put_vara_int(ncid, varid[0], start, count, buf); ERR
+
+        err = ncmpi_inq_dimlen(ncid, dimid[0], &length); ERR
+        if (length != 4) {
+            printf("Error: expecting 4 records, but got %lld record(s)\n",
+                   length);
+            nerrs++;
+        }
+        err = ncmpi_end_indep_data(ncid); ERR
+    }
+
+    /* REC_VAR_3D: write the 2nd record first */
+    start[1] = 0; start[2] = 0; count[0] = 1; count[1] = 2; count[2] = 5;
+
+    for (i=0; i<20; i++) buf[i] = 91;
+    start[0] = 1;
+    err = ncmpi_put_vara_int_all(ncid, varid[1], start, count, buf); ERR
+
+    /* write the 1st record now */
+    for (i=0; i<20; i++) buf[i] = 90;
+    start[0] = 0;
+    err = ncmpi_put_vara_int_all(ncid, varid[1], start, count, buf); ERR
+
+    err = ncmpi_inq_dimlen(ncid, dimid[0], &length); ERR
+    if (length != 4) {
+        printf("Error: expecting 4 records, but got %lld record(s)\n",length);
+        nerrs++;
+    }
+
+    if (nerrs == 0) { /* test independent data mode */
+        err = ncmpi_begin_indep_data(ncid); ERR
+        /* write the 4th record */
+        for (i=0; i<20; i++) buf[i] = 93;
+        start[0] = 3;
+        err = ncmpi_put_vara_int(ncid, varid[1], start, count, buf); ERR
+
+        /* write the 3rd record */
+        for (i=0; i<20; i++) buf[i] = 92;
+        start[0] = 2;
+        err = ncmpi_put_vara_int(ncid, varid[1], start, count, buf); ERR
+
+        err = ncmpi_inq_dimlen(ncid, dimid[0], &length); ERR
+        if (length != 4) {
+            printf("Error: expecting 4 records, but got %lld record(s)\n",
+                   length);
+            nerrs++;
+        }
+        err = ncmpi_end_indep_data(ncid); ERR
+    }
+    err = ncmpi_close(ncid); ERR
+    return nerrs;
+}
+
+int main(int argc, char** argv) {
+    char *filename="testfile.nc";
+    int nerrs=0, rank, nprocs, err;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        goto fn_exit;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for write records in reversed order", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    if (rank >= 1) goto fn_exit; /* this test is for running 1 process */
+
+    /* test only one 1D record variable */
+    nerrs += test_only_record_var_1D(filename);
+
+    /* test only one 3D record variable */
+    nerrs += test_only_record_var_3D(filename);
+
+    /* test two record variables */
+    nerrs += test_two_record_var(filename);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR && malloc_size > 0) /* this test is for running 1 process */
+        printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+               malloc_size);
+
+fn_exit:
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/redef-good.ncdump b/test/testcases/redef-good.ncdump
new file mode 100644
index 0000000..10f1a56
--- /dev/null
+++ b/test/testcases/redef-good.ncdump
@@ -0,0 +1,63 @@
+netcdf test {
+// file format: CDF-2 (large file)
+dimensions:
+	dim0 = 10 ;
+	dim1 = 3 ;
+	dim5 = 5 ;
+	dim9 = 9 ;
+	dim2 = 10 ;
+variables:
+	int xyz(dim0, dim1) ;
+	int connect(dim0, dim5) ;
+	int connect_exterior(dim0, dim9) ;
+	double xyz_r(dim0, dim2) ;
+data:
+
+ xyz =
+  0, 1, 2,
+  3, 4, 5,
+  6, 7, 8,
+  9, 10, 11,
+  12, 13, 14,
+  15, 16, 17,
+  18, 19, 20,
+  21, 22, 23,
+  24, 25, 26,
+  27, 28, 29 ;
+
+ connect =
+  0, 1, 2, 3, 4,
+  5, 6, 7, 8, 9,
+  10, 11, 12, 13, 14,
+  15, 16, 17, 18, 19,
+  20, 21, 22, 23, 24,
+  25, 26, 27, 28, 29,
+  30, 31, 32, 33, 34,
+  35, 36, 37, 38, 39,
+  40, 41, 42, 43, 44,
+  45, 46, 47, 48, 49;
+
+ connect_exterior =
+  0, 1,  2,  3,  4,  5,  6,  7, 8,
+  9,  10, 11, 12, 13, 14, 15, 16, 17,
+  18, 19, 20, 21, 22, 23, 24, 25, 26, 
+  27, 28, 29, 30, 31, 32, 33, 34, 35, 
+  36, 37, 38, 39, 40, 41, 42, 43, 44, 
+  45, 46, 47, 48, 49, 50, 51, 52, 53, 
+  54, 55, 56, 57, 58, 59, 60, 61, 62, 
+  63, 64, 65, 66, 67, 68, 69, 70, 71, 
+  72, 73, 74, 75, 76, 77, 78, 79, 80, 
+  81, 82, 83, 84, 85, 86, 87, 88, 89 ;
+
+ xyz_r =
+  0, 1, 4, 9, 16, 25, 36, 49, 64, 81,
+  100, 121, 144, 169, 196, 225, 256, 289, 324, 361,
+  400, 441, 484, 529, 576, 625, 676, 729, 784, 841,
+  900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521,
+  1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401,
+  2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481,
+  3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761,
+  4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241,
+  6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921,
+  8100, 8281, 8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801 ;
+}
diff --git a/test/testcases/redef1.c b/test/testcases/redef1.c
new file mode 100644
index 0000000..2658c50
--- /dev/null
+++ b/test/testcases/redef1.c
@@ -0,0 +1,197 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: redef1.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program tests redefine mode.
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicc -g -o redef1 redef1.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 4 redef1 testfile.nc
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define PNCDF_Error(err, msg) \
+    if (err != NC_NOERR) { \
+        printf("Error: %s (%s)\n", msg, ncmpi_strerror(err)); \
+        nerrs++; \
+        goto fn_exit; \
+    }  
+
+int main(int argc, char** argv)
+{
+    char filename[256]="redef1.nc";
+    int i, j, k, commsize, rank, ncid, verbose=0, err, nerrs=0;
+    int dim0id, dim1id, dim5id, dim9id, dim2id, dimsid[2], dims2id[2];
+    int varid, var3id, var4id, var2id;
+    int *data;
+    double *dbl_data;
+    MPI_Offset len0=10, len1=3, len5=5, len9=9, len2=10;
+    MPI_Offset start[2], count[2];
+    MPI_Comm comm = MPI_COMM_WORLD;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(comm, &commsize);
+    MPI_Comm_rank(comm, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    if (argc == 2) strcpy(filename, argv[1]);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for entering re-define mode ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    if (commsize > 1 && rank == 0 && verbose)
+        printf("Warning: %s is designed to run on 1 process\n",argv[0]);
+  
+    err = ncmpi_create(comm, filename, NC_CLOBBER|NC_64BIT_OFFSET,
+                          MPI_INFO_NULL, &ncid);
+    PNCDF_Error(err, "create")
+  
+    err = ncmpi_def_dim(ncid, "dim0", len0, &dim0id);
+    PNCDF_Error(err, "def_dim0")
+
+    err = ncmpi_def_dim(ncid, "dim1", len1, &dim1id);
+    PNCDF_Error(err, "def_dim1")
+
+    err = ncmpi_def_dim(ncid, "dim5", len5, &dim5id);
+    PNCDF_Error(err, "def_dim5")
+
+    err = ncmpi_def_dim(ncid, "dim9", len9, &dim9id);
+    PNCDF_Error(err, "def_dim9")
+  
+    dimsid[0] = dim0id;
+    dimsid[1] = dim1id;
+    err = ncmpi_def_var(ncid, "xyz", NC_INT, 2, dimsid, &varid);
+    PNCDF_Error(err, "def_var")
+ 
+    dimsid[0] = dim0id;
+    dimsid[1] = dim5id;
+    err = ncmpi_def_var(ncid, "connect", NC_INT, 2, dimsid, &var3id);
+    PNCDF_Error(err, "def_var3")
+
+    dimsid[0] = dim0id;
+    dimsid[1] = dim9id;
+    err = ncmpi_def_var(ncid, "connect_exterior", NC_INT, 2, dimsid, &var4id);
+    PNCDF_Error(err, "def_var4")
+
+    err = ncmpi_enddef(ncid);
+    PNCDF_Error(err, "enddef")
+
+    /* put data */
+    start[0] = 0;
+    start[1] = 0;
+    count[0] = len0;
+    count[1] = len1;
+
+    data = (int*) malloc(len0*len1 * sizeof(int));
+    k=0;
+    for (i=0; i<len0; i++)
+        for (j=0; j<len1; j++)
+            data[i*len1+j] = k++;
+    if (rank > 0) count[0] = count[1] = 0;
+    err = ncmpi_put_vara_int_all(ncid, varid, start, count, &data[0]);
+    PNCDF_Error(err, "put1")
+    free(data);
+    
+    count[0] = len0;
+    count[1] = len5;
+    data = (int*) malloc(len0*len5 * sizeof(int));
+    k=0;
+    for (i=0; i<len0; i++)
+        for (j=0; j<len5; j++)
+            data[i*len5+j] = k++;
+    if (rank > 0) count[0] = count[1] = 0;
+    err = ncmpi_put_vara_int_all(ncid, var3id, start, count, &data[0]);
+    PNCDF_Error(err, "put3")
+    free(data);
+
+    count[0] = len0;
+    count[1] = len9;
+    data = (int*) malloc(len0*len9 * sizeof(int));
+    k=0;
+    for (i=0; i<len0; i++)
+        for (j=0; j<len9; j++)
+            data[i*len9+j] = k++;
+    if (rank > 0) count[0] = count[1] = 0;
+    err = ncmpi_put_vara_int_all(ncid, var4id, start, count, &data[0]);
+    PNCDF_Error(err, "put4")
+    free(data);
+
+    err = ncmpi_close(ncid);
+    PNCDF_Error(err, "close")
+
+    err = ncmpi_open(comm, filename, NC_WRITE, MPI_INFO_NULL, &ncid);
+
+    err = ncmpi_redef(ncid);
+    PNCDF_Error(err, "redef")
+
+    err = ncmpi_def_dim(ncid, "dim2", len2, &dim2id);
+    PNCDF_Error(err, "def_dim")
+  
+    dims2id[0] = dim0id;
+    dims2id[1] = dim2id;
+    err = ncmpi_def_var(ncid, "xyz_r", NC_DOUBLE, 2, dims2id, &var2id);
+    PNCDF_Error(err, "def_var")
+
+    err = ncmpi_enddef(ncid);
+    PNCDF_Error(err, "enddef")
+
+    start[0] = 0;
+    start[1] = 0;
+    count[0] = len0;
+    count[1] = len2;
+    k=0;
+    dbl_data = (double*) malloc(len0*len2 * sizeof(double));
+    for (i=0; i<len0; i++)
+        for (j=0; j<len2; j++) {
+            dbl_data[i*len2+j] = (k*k);
+            k++;
+        }
+    if (rank > 0) count[0] = count[1] = 0;
+    err = ncmpi_put_vara_double_all(ncid, var2id, start, count, &dbl_data[0]);
+    PNCDF_Error(err, "put2")
+    free(dbl_data);
+
+    err = ncmpi_close(ncid);
+    PNCDF_Error(err, "close")
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+fn_exit:
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/test/testcases/redef1.sh b/test/testcases/redef1.sh
new file mode 100755
index 0000000..b3b0360
--- /dev/null
+++ b/test/testcases/redef1.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# quick test of re-entering define mode: the file created by ncmpigen and the
+# file created by test program should be bit-for-bit identical, else there is
+# an error
+
+if [ $# -ne 2 ] ; then
+	echo "usage: $0 <executable> <reference>"
+	echo "example: $0 redef1 redef-good.ncdump"
+	exit -1
+fi
+
+REFERENCE=redef1-a-${RANDOM}-${RANDOM}-${RANDOM}.nc
+
+# dataset via ncmpigen:
+../../src/utils/ncmpigen/ncmpigen -v 2 -o $REFERENCE $2
+
+# dataset via test
+$1
+
+# now compare
+
+diff $REFERENCE redef1.nc
diff --git a/test/testcases/test_erange.c b/test/testcases/test_erange.c
new file mode 100644
index 0000000..d22199b
--- /dev/null
+++ b/test/testcases/test_erange.c
@@ -0,0 +1,100 @@
+/*
+ *  Copyright (C) 2015, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id$
+ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * This program tests NC_ERANGE error code for the following 2 case.
+ * 1. get a value of 255 from a NC_UBYTE variable in a netCDF to a memory
+ *    buffer of signed char 
+ * 2. put a value of -1 of signed char from a in-memory buffer to a NC_UBYTE
+ *    variable in a netCDF file
+ *
+ * The compile and run commands are given below.
+ *
+ *    % mpicc -g -o test_erange test_erange.c -lpnetcdf
+ *
+ *    % mpiexec -l -n 1 test_erange testfile.nc
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define ERR if (err!=NC_NOERR) {printf("Error at line %d: %s\n",__LINE__,ncmpi_strerror(err));nerrs++;}
+#define EXPECT_ERR if (err != NC_ERANGE) {printf("Error at line %d: expecting NC_ERANGE, but got %d\n",__LINE__,err);nerrs++;}
+
+int main(int argc, char* argv[])
+{
+    char filename[256];
+    int err, nerrs=0, ncid, uc_vid, sc_vid, dimid, rank;
+    unsigned char uc;
+    signed char sc;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for checking for NC_ERANGE ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER|NC_64BIT_DATA, MPI_INFO_NULL, &ncid); ERR
+
+    uc = 255; /* a value should cause NC_ERANGE at ncmpi_get_att_schar() */
+    err = ncmpi_put_att_uchar(ncid, NC_GLOBAL, "att1", NC_UBYTE, 1, &uc); ERR
+    err = ncmpi_get_att_schar(ncid, NC_GLOBAL, "att1", &sc); EXPECT_ERR
+
+    sc = -1; /* a value should cause NC_ERANGE */
+    err = ncmpi_put_att_schar(ncid, NC_GLOBAL, "att2", NC_UBYTE, 1, &sc); EXPECT_ERR
+
+    err = ncmpi_def_dim(ncid, "x", 2, &dimid); ERR
+    err = ncmpi_def_var(ncid, "var_ubyte", NC_UBYTE, 1, &dimid, &uc_vid); ERR
+    err = ncmpi_def_var(ncid, "var_byte",  NC_BYTE,  1, &dimid, &sc_vid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    uc = 255; /* a value should cause NC_ERANGE at ncmpi_get_var_schar() */
+    err = ncmpi_put_var_uchar_all(ncid, uc_vid, &uc); ERR
+    err = ncmpi_get_var_schar_all(ncid, uc_vid, &sc); EXPECT_ERR
+
+    sc = -1; /* a value should cause NC_ERANGE */
+    err = ncmpi_put_var_schar_all(ncid, uc_vid, &sc); EXPECT_ERR
+
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+
+    return 0;
+}
diff --git a/test/testcases/test_vard.c b/test/testcases/test_vard.c
new file mode 100644
index 0000000..9250d6b
--- /dev/null
+++ b/test/testcases/test_vard.c
@@ -0,0 +1,322 @@
+/*
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: test_vard.c 2219 2015-12-11 22:30:03Z wkliao $
+ */
+
+/*
+ * This program tests the vard API.
+ * The write buffer is a 2D array of size NY x NX
+ * The MPI data type for the buffer is defined by swapping the 1st and 2nd
+ * rows of the array using a butype constructed by MPI_Type_create_hindex().
+ * It also writes a fixed-size variable using a buftype constructed by
+ * MPI_Type_create_subarray(). Both record and foxed-size variables are read
+ * back using various filetypes and buftypes and check the contents.
+ *
+ * The expected reults from the output file contents are:
+ * (when running on 1 MPI process)
+ *
+ *  % ncmpidump testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-1
+ *    dimensions:
+ *           REC_DIM = UNLIMITED ; // (2 currently)
+ *           X = 5 ;
+ *           FIX_DIM = 2 ;
+ *    variables:
+ *           int rec_var(REC_DIM, X) ;
+ *           int dummy_rec(REC_DIM, X) ;
+ *           int fix_var(FIX_DIM, X) ;
+ *    data:
+ * 
+ *    rec_var =
+ *      10, 11, 12, 13, 14,
+ *      0, 1, 2, 3, 4 ;
+ * 
+ *    dummy_rec =
+ *      0, 0, 0, 0, 0,
+ *      0, 0, 0, 0, 0 ;
+ *
+ *    fix_var =
+ *      10, 11, 12, 13, 14,
+ *      0, 1, 2, 3, 4 ;
+ * }
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 2
+#define NX 5
+#define ERR if (err!=NC_NOERR) {printf("Error at line %d: %s\n", __LINE__,ncmpi_strerror(err)); nerrs++;}
+
+#define CHECK_VALUE_PERMUTED { \
+    for (j=0; j<count[0]; j++) { \
+        int val = (j == 0) ? 1 : 0; \
+        val = rank * 100 + val * 10; \
+        for (i=0; i<count[1]; i++) \
+            if (buf[j][i] != val+i) { \
+                printf("line %d: expecting buf[%d][%d]=%d but got %d\n",__LINE__,j,i,val+i,buf[j][i]); \
+                nerrs++; \
+            } \
+    } \
+} \
+
+#define CHECK_VALUE { \
+    for (j=0; j<count[0]; j++) { \
+        for (i=0; i<count[1]; i++) \
+            if (buf[j][i] != rank*100+j*10+i) { \
+                printf("line %d: expecting buf[%d][%d]=%d but got %d\n",__LINE__,j,i,rank*100+j*10+i,buf[j][i]); \
+                nerrs++; \
+            } \
+    } \
+}
+
+static
+int get_var_and_verify(int ncid,
+                       int varid,
+                       MPI_Offset *start,
+                       MPI_Offset *count,
+                       int **buf,
+                       MPI_Datatype buftype,
+                       MPI_Datatype ghost_buftype,
+                       MPI_Datatype filetype)
+{
+    int i, j, rank, err, *ncbuf, nerrs=0;
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    ncbuf = (int *) malloc((count[0]+4)*(count[1]+4)*sizeof(int));
+
+    /* clear the contents of the read buffer */
+    for (j=0; j<count[0]; j++) for (i=0; i<count[1]; i++) buf[j][i] = -1;
+
+    /* read back using regular vara API */
+    err = ncmpi_get_vara_int_all(ncid, varid, start, count, buf[0]); ERR
+
+    /* check if the contents of buf are expected */
+    CHECK_VALUE_PERMUTED
+
+    /* clear the contents of the read buffer */
+    for (j=0; j<count[0]; j++) for (i=0; i<count[1]; i++) buf[j][i] = -1;
+
+    /* read back using flexible vara API */
+    err = ncmpi_get_vara_all(ncid, varid, start, count, buf[1], 1, buftype); ERR
+
+    /* check if the contents of buf are expected */
+    CHECK_VALUE
+
+    /* clear the contents of the read buffer */
+    for (j=0; j<count[0]; j++) for (i=0; i<count[1]; i++) buf[j][i] = -1;
+
+    /* read back using vard API and permuted buftype */
+    err = ncmpi_get_vard_all(ncid, varid, filetype, buf[1], 1, buftype); ERR
+
+    /* check if the contents of buf are expected */
+    CHECK_VALUE
+
+    /* clear the contents of the read buffer */
+    for (j=0; j<count[0]; j++) for (i=0; i<count[1]; i++) buf[j][i] = -1;
+
+    /* read back using vard API and no buftype */
+    err = ncmpi_get_vard_all(ncid, varid, filetype, buf[0], 0, MPI_DATATYPE_NULL); ERR
+
+    /* check if the contents of buf are expected */
+    CHECK_VALUE_PERMUTED
+
+    /* clear the contents of the read buffer */
+    for (i=0; i<(count[0]+4)*(count[1]+4); i++) ncbuf[i] = -1;
+
+    /* read back using ghost buftype */
+    err = ncmpi_get_vard_all(ncid, varid, filetype, ncbuf, 1, ghost_buftype); ERR
+
+    for (j=0; j<count[0]; j++) {
+        for (i=0; i<count[1]; i++)
+            if (buf[j][i] != ncbuf[(j+2)*(count[1]+4)+(i+2)]) {
+                printf("Error at line %d: expecting ncbuf[%d][%d]=%d but got %d\n",
+                       __LINE__,j,i,buf[j][i],ncbuf[(j+2)*(count[1]+4)+(i+2)]);
+                nerrs++;
+            }
+    }
+    free(ncbuf);
+    return nerrs;
+}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv) {
+
+    char         filename[256];
+    int          i, j, err, ncid, varid0, varid1, varid2, dimids[2], nerrs=0;
+    int          rank, nprocs, debug=0, blocklengths[2], **buf, *bufptr;
+    int          array_of_sizes[2], array_of_subsizes[2], array_of_starts[2];
+    MPI_Offset   start[2], count[2];
+    MPI_Aint     a0, a1, disps[2];
+    MPI_Datatype buftype, ghost_buftype, rec_filetype, fix_filetype;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for flexible put and get ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    buf = (int**)malloc(NY * sizeof(int*));
+    buf[0] = (int*)malloc(NY * NX * sizeof(int));
+    for (i=1; i<NY; i++) buf[i] = buf[i-1] + NX;
+
+    /* construct various MPI derived data types */
+
+    /* construct an MPI derived data type for swapping 1st row with 2nd row */
+    blocklengths[0] = blocklengths[1] = NX;
+    MPI_Get_address(buf[1], &a0);
+    MPI_Get_address(buf[0], &a1);
+    disps[0] = 0;
+    disps[1] = a1 - a0;
+    bufptr = buf[1];
+    err = MPI_Type_create_hindexed(2, blocklengths, disps, MPI_INT, &buftype);
+    if (err != MPI_SUCCESS) printf("MPI error MPI_Type_create_hindexed\n");
+    MPI_Type_commit(&buftype);
+
+    start[0] = 0; start[1] = NX*rank;
+    count[0] = 2; count[1] = NX;
+    if (debug) printf("put start=%lld %lld count=%lld %lld\n",start[0],start[1],count[0],count[1]);
+
+    /* create a file type for the fixed-size variable */
+    array_of_sizes[0] = 2;
+    array_of_sizes[1] = NX*nprocs;
+    array_of_subsizes[0] = count[0];
+    array_of_subsizes[1] = count[1];
+    array_of_starts[0] = start[0];
+    array_of_starts[1] = start[1];
+    MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                             array_of_starts, MPI_ORDER_C,
+                             MPI_INT, &fix_filetype);
+    MPI_Type_commit(&fix_filetype);
+
+    /* create a buftype with ghost cells on each side */
+    array_of_sizes[0] = count[0]+4;
+    array_of_sizes[1] = count[1]+4;
+    array_of_subsizes[0] = count[0];
+    array_of_subsizes[1] = count[1];
+    array_of_starts[0] = 2;
+    array_of_starts[1] = 2;
+    MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes,
+                             array_of_starts, MPI_ORDER_C,
+                             MPI_INT, &ghost_buftype);
+    MPI_Type_commit(&ghost_buftype);
+
+    /* create a new file for write */
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, MPI_INFO_NULL,
+                       &ncid); ERR
+
+    /* define a 2D array */
+    err = ncmpi_def_dim(ncid, "REC_DIM", NC_UNLIMITED, &dimids[0]); ERR
+    err = ncmpi_def_dim(ncid, "X",       NX*nprocs,    &dimids[1]); ERR
+    err = ncmpi_def_var(ncid, "rec_var", NC_INT, 2, dimids, &varid0); ERR
+    err = ncmpi_def_var(ncid, "dummy_rec", NC_INT, 2, dimids, &varid2); ERR
+    err = ncmpi_def_dim(ncid, "FIX_DIM", 2, &dimids[0]); ERR
+    err = ncmpi_def_var(ncid, "fix_var", NC_INT, 2, dimids, &varid1); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* create a file type for the record variable */
+    int *array_of_blocklengths=(int*) malloc(count[0]*sizeof(int));
+    MPI_Aint *array_of_displacements=(MPI_Aint*) malloc(count[0]*sizeof(MPI_Aint));
+    MPI_Offset recsize;
+    err = ncmpi_inq_recsize(ncid, &recsize);
+    for (i=0; i<count[0]; i++) {
+        array_of_blocklengths[i] = count[1];
+        array_of_displacements[i] = start[1]*sizeof(int) + recsize * i;
+    }
+    MPI_Type_create_hindexed(2, array_of_blocklengths, array_of_displacements,
+                             MPI_INT, &rec_filetype);
+    MPI_Type_commit(&rec_filetype);
+    free(array_of_blocklengths);
+    free(array_of_displacements);
+
+    /* initialize the contents of the array */
+    for (j=0; j<NY; j++) for (i=0; i<NX; i++) buf[j][i] = rank*100 + j*10 + i;
+
+    /* write the record variable */
+    err = ncmpi_put_vard_all(ncid, varid0, rec_filetype, bufptr, 1, buftype); ERR
+
+    /* check if the contents of buf are altered */
+    CHECK_VALUE
+
+    /* check if root process can write to file header in data mode */
+    err = ncmpi_rename_var(ncid, varid0, "rec_VAR"); ERR
+
+    /* write the fixed-size variable */
+    err = ncmpi_put_vard_all(ncid, varid1, fix_filetype, bufptr, 1, buftype); ERR
+
+    /* check if the contents of buf are altered */
+    CHECK_VALUE
+ 
+    /* check if root process can write to file header in data mode */
+    err = ncmpi_rename_var(ncid, varid0, "rec_var"); ERR
+
+    /* test the same routines in independent data mode */
+    err = ncmpi_begin_indep_data(ncid); ERR
+    err = ncmpi_put_vard(ncid, varid0, rec_filetype, bufptr, 1, buftype); ERR
+    CHECK_VALUE
+    err = ncmpi_rename_var(ncid, varid0, "rec_VAR"); ERR
+    err = ncmpi_put_vard(ncid, varid1, fix_filetype, bufptr, 1, buftype); ERR
+    CHECK_VALUE
+    err = ncmpi_rename_var(ncid, varid0, "rec_var"); ERR
+    err = ncmpi_end_indep_data(ncid); ERR
+
+    err = ncmpi_close(ncid); ERR
+
+    /* open the same file and read back for validate */
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL,
+                     &ncid); ERR
+
+    err = ncmpi_inq_varid(ncid, "rec_var", &varid0); ERR
+    err = ncmpi_inq_varid(ncid, "fix_var", &varid1); ERR
+
+    nerrs += get_var_and_verify(ncid, varid0, start, count, buf, buftype, ghost_buftype, rec_filetype);
+    nerrs += get_var_and_verify(ncid, varid1, start, count, buf, buftype, ghost_buftype, fix_filetype);
+
+    err = ncmpi_close(ncid); ERR
+
+    MPI_Type_free(&rec_filetype);
+    MPI_Type_free(&fix_filetype);
+    MPI_Type_free(&buftype);
+    MPI_Type_free(&ghost_buftype);
+    free(buf[0]); free(buf);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
diff --git a/test/testcases/test_vardf.F b/test/testcases/test_vardf.F
new file mode 100644
index 0000000..a25cecf
--- /dev/null
+++ b/test/testcases/test_vardf.F
@@ -0,0 +1,392 @@
+!
+!   Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_vardf.F 2236 2015-12-18 03:49:41Z wkliao $
+
+!
+! This program tests the vard API.
+! The write buffer is a 2D array of size NX x NY
+! The MPI data type for the buffer is defined by swapping the 1st and 2nd
+! rows of the array using a butype constructed by MPI_Type_create_hindex().
+! It also writes a fixed-size variable using a buftype constructed by
+! MPI_Type_create_subarray(). Both record and foxed-size variables are read
+! back using various filetypes and buftypes and check the contents.
+!
+! The expected reults from the output file contents are:
+! (when running on 1 MPI process)
+!
+!  % ncmpidump testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-1
+!    dimensions:
+!           REC_DIM = UNLIMITED ; // (2 currently)
+!           X = 5 ;
+!           FIX_DIM = 2 ;
+!    variables:
+!           int rec_var(REC_DIM, X) ;
+!           int dummy_rec(REC_DIM, X) ;
+!           int fix_var(FIX_DIM, X) ;
+!    data:
+! 
+!    rec_var =
+!      10, 11, 12, 13, 14,
+!      0, 1, 2, 3, 4 ;
+! 
+!    dummy_rec =
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0 ;
+!
+!    fix_var =
+!      10, 11, 12, 13, 14,
+!      0, 1, 2, 3, 4 ;
+! }
+!
+       INTEGER FUNCTION XTRIM(STRING)
+           CHARACTER*(*) STRING
+           INTEGER I, N
+           N = LEN(STRING)
+           DO I = N, 1, -1
+              IF (STRING(I:I) .NE. ' ') GOTO 10
+           ENDDO
+ 10        XTRIM = I
+       END ! FUNCTION XTRIM
+
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err, XTRIM
+          character*(*) message
+          character*128 msg
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message(1:XTRIM(message)), nfmpi_strerror(err)
+              msg = '*** TESTING F77 test_vardf.f for vard API '
+              call pass_fail(1, msg)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      subroutine check_value(rank, nx, ny, buf, nerrs)
+          implicit none
+          include "mpif.h"
+          integer NX, NY
+          integer rank, buf(nx, ny), nerrs
+          integer i, j
+ 543      format(A,I2,A,I2,A,I3,A,I3)
+          do j=1, ny
+             do i=1, nx
+                if (buf(i,j) .NE. rank*100+j*10+i) then
+                    print 543,'expecting buf(',i,',',j,')=',
+     +              rank*100+j*10+i,' but got ',buf(i,j)
+                    nerrs = nerrs + 1
+                endif
+             enddo
+          enddo
+      end ! subroutine check_value
+
+      subroutine check_value_permuted(rank, nx, ny, buf, nerrs)
+          implicit none
+          include "mpif.h"
+          integer NX, NY
+          integer rank, buf(nx, ny), nerrs, val
+          integer i, j
+ 543      format(A,I2,A,I2,A,I3,A,I3)
+          do j=1, ny
+             val = 1
+             if (j .EQ. 1) val = 2
+             val = rank * 100 + val * 10
+             do i=1, nx
+                if (buf(i,j) .NE. val+i) then
+                    print 543,'expecting buf(',i,',',j,')=',
+     +              val+i,' but got ',buf(i,j)
+                    nerrs = nerrs + 1
+                endif
+             enddo
+          enddo
+      end ! subroutine check_value_permuted
+
+      subroutine clear_buf(nx, ny, buf)
+          implicit none
+          include "mpif.h"
+          integer NX, NY
+          integer buf(nx, ny)
+          integer i, j
+          do j=1, NY
+             do i=1, NX
+                buf(i,j) = -1
+             enddo
+          enddo
+      end ! subroutine clear_buf
+
+      subroutine get_var_and_verify(ncid,varid,NX,NY,start,count,buf,
+     +                       buftype, ghost_buftype, filetype, nerrs)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer NX, NY
+          integer*8 start(2), count(2), one, zero
+          integer i, j, rank, err, ncid, varid, nerrs, buf(NX, NY)
+          integer buftype, ghost_buftype, filetype
+          integer ncbuf(NX+4, NY+4)
+
+          one = 1
+          zero = 0
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          ! clear the contents of the read buffer
+          call clear_buf(NX, NY, buf)
+
+          ! read back using regular vara API
+          err = nfmpi_get_vara_int_all(ncid, varid, start, count, buf)
+          call check(err, 'In nfmpi_get_vara_int_all: ')
+
+          ! check if the contents of buf are expected
+          call check_value_permuted(rank, NX, NY, buf, nerrs)
+          call clear_buf(NX, NY, buf)
+
+          ! read back using flexible vara API
+          err = nfmpi_get_vara_all(ncid, varid, start, count, buf(1,2),
+     +                             one, buftype)
+          call check(err, 'In nfmpi_get_vara_all: ')
+
+          ! check if the contents of buf are expected
+          call check_value(rank, NX, NY, buf, nerrs)
+          call clear_buf(NX, NY, buf)
+
+          ! read back using vard API and permuted buftype
+          err = nfmpi_get_vard_all(ncid, varid, filetype, buf(1,2),
+     +                             one, buftype)
+          call check(err, 'In nfmpi_get_vard_all: ')
+
+          ! check if the contents of buf are expected
+          call check_value(rank, NX, NY, buf, nerrs)
+          call clear_buf(NX, NY, buf)
+
+          ! read back using vard API and no buftype
+          err = nfmpi_get_vard_all(ncid, varid, filetype, buf,
+     +                             zero, MPI_DATATYPE_NULL)
+          call check(err, 'In nfmpi_get_vard_all: ')
+
+          ! check if the contents of buf are expected
+          call check_value_permuted(rank, NX, NY, buf, nerrs)
+
+          ! read back using ghost buftype
+          err = nfmpi_get_vard_all(ncid, varid, filetype, ncbuf,
+     +                             one, ghost_buftype)
+          call check(err, 'In nfmpi_get_vard_all: ')
+
+ 543      format(A,I2,A,I2,A,I3,A,I3)
+          do j=1, NY
+             do i=1, NX
+                if (buf(i,j) .NE. ncbuf(i+2, j+2)) then
+                    print 543,'expecting buf(',i,',',j,')=',
+     +              buf(i,j),' but got ',ncbuf(i+2,j+2)
+                    nerrs = nerrs + 1
+                endif
+             enddo
+          enddo
+      end ! subroutine get_var_and_verify
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          character*256 filename, cmd, msg
+          integer err, ierr, nprocs, rank, i, j, get_args
+          integer cmode, ncid, varid0, varid1, varid2, dimid(2), nerrs
+          integer NX, NY, XTRIM
+          PARAMETER(NX=5, NY=2)
+          integer buf(NX, NY)
+          integer buftype, ghost_buftype, rec_filetype, fix_filetype
+          integer array_of_sizes(2), array_of_subsizes(2)
+          integer array_of_starts(2), blocklengths(2)
+          integer*8 start(2), count(2), len, one, two
+          integer*8 malloc_size, sum_size, recsize
+#ifdef SIZEOF_MPI_AINT_IS_4
+          integer a0, a1, disps(2)
+#else
+          integer*8 a0, a1, disps(2)
+#endif
+
+          call MPI_Init(ierr)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, ierr)
+
+          one = 1
+          two = 2
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              filename = "testfile.nc"
+              err = get_args(cmd, filename)
+          endif
+          call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+          if (err .EQ. 0) goto 999
+
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, ierr)
+
+          nerrs = 0
+
+          start(1) = NX * rank
+          start(2) = 0
+          count(1) = NX
+          count(2) = 2
+
+          ! construct various MPI derived data types
+          blocklengths(1) = NX
+          blocklengths(2) = NX
+          call MPI_Get_address(buf(1,2), a0, ierr)
+          call MPI_Get_address(buf(1,1), a1, ierr)
+          disps(1) = 0
+          disps(2) = a1 - a0
+          call MPI_Type_create_hindexed(2, blocklengths, disps,
+     +                  MPI_INTEGER, buftype, ierr)
+          call MPI_Type_commit(buftype, ierr)
+
+          ! create a file type for the fixed-size variable
+          array_of_sizes(1) = NX*nprocs
+          array_of_sizes(2) = 2
+          array_of_subsizes(1) = INT(count(1))
+          array_of_subsizes(2) = INT(count(2))
+          array_of_starts(1) = INT(start(1))
+          array_of_starts(2) = INT(start(2))
+          call MPI_Type_create_subarray(2, array_of_sizes,
+     +         array_of_subsizes, array_of_starts, MPI_ORDER_FORTRAN,
+     +         MPI_INTEGER, fix_filetype, ierr)
+          call MPI_Type_commit(fix_filetype, ierr)
+
+          ! create a buftype with ghost cells on each side */
+          array_of_sizes(1) = INT(count(1))+4
+          array_of_sizes(2) = INT(count(2))+4
+          array_of_subsizes(1) = INT(count(1))
+          array_of_subsizes(2) = INT(count(2))
+          array_of_starts(1) = 2
+          array_of_starts(2) = 2
+          call MPI_Type_create_subarray(2, array_of_sizes,
+     +         array_of_subsizes, array_of_starts, MPI_ORDER_FORTRAN,
+     +         MPI_INTEGER, ghost_buftype, ierr)
+          call MPI_Type_commit(ghost_buftype, ierr)
+
+          ! initialized buffer contents
+          do j=1, INT(count(2))
+             do i=1, INT(count(1))
+                 buf(i, j) = rank*100 + j*10 + i
+             enddo
+          enddo
+
+          ! create file, truncate it if exists
+          cmode = NF_CLOBBER
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                       MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define 2 dimensions
+          err = nfmpi_def_dim(ncid, "REC_DIM", NFMPI_UNLIMITED,dimid(2))
+          call check(err, 'In nfmpi_def_dim REC_DIM: ')
+          len = NX * nprocs
+          err = nfmpi_def_dim(ncid, "X", len, dimid(1))
+          call check(err, 'In nfmpi_def_dim X: ')
+
+          ! define 2D record variables of integer type
+          err = nfmpi_def_var(ncid, "rec_var", NF_INT, 2, dimid, varid0)
+          call check(err, 'In nfmpi_def_var: rec_var ')
+          err = nfmpi_def_var(ncid, "dummy_rec", NF_INT, 2,dimid,varid2)
+          call check(err, 'In nfmpi_def_var: dummy_rec ')
+
+          ! define 2D fixed-size variable of integer type
+          err = nfmpi_def_dim(ncid, "FIX_DIM", two, dimid(2))
+          call check(err, 'In nfmpi_def_dim RECV_DIM: ')
+          err = nfmpi_def_var(ncid, "fix_var", NF_INT, 2, dimid, varid1)
+          call check(err, 'In nfmpi_def_var: fix_var ')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! create a file type for the record variable */
+          err = nfmpi_inq_recsize(ncid, recsize)
+          call check(err, 'In nfmpi_inq_recsize: ')
+          blocklengths(1) = INT(count(1))
+          blocklengths(2) = INT(count(1))
+          disps(1) = start(1)*4
+          disps(2) = recsize + start(1)*4
+          call MPI_Type_create_hindexed(2, blocklengths, disps,
+     +                                  MPI_INTEGER, rec_filetype, ierr)
+          call MPI_Type_commit(rec_filetype, ierr)
+
+          ! write the record variable */
+          err = nfmpi_put_vard_all(ncid, varid0, rec_filetype, buf(1,2),
+     +                             one, buftype)
+          call check(err, 'In nfmpi_put_vard_all: ')
+          ! check if the contents of buf are altered
+          call check_value(rank, NX, NY, buf, nerrs)
+
+          ! check if root process can write to file header in data mode
+          err = nfmpi_rename_var(ncid, varid0, 'rec_VAR')
+          call check(err, 'In nfmpi_rename_var: ')
+
+          ! write the fixed-size variable
+          err = nfmpi_put_vard_all(ncid, varid1, fix_filetype, buf(1,2),
+     +                             one, buftype)
+          call check(err, 'In nfmpi_put_vard_all: ')
+          ! check if the contents of buf are altered
+          call check_value(rank, NX, NY, buf, nerrs)
+
+          ! check if root process can write to file header in data mode
+          err = nfmpi_rename_var(ncid, varid0, 'rec_var')
+          call check(err, 'In nfmpi_rename_var: ')
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! open the same file and read back for validate */
+          err = nfmpi_open(MPI_COMM_WORLD, filename, NF_NOWRITE,
+     +                     MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_open: ')
+
+          err = nfmpi_inq_varid(ncid, "rec_var", varid0)
+          call check(err, 'In nfmpi_inq_varid rec_var: ')
+          err = nfmpi_inq_varid(ncid, "fix_var", varid1)
+          call check(err, 'In nfmpi_inq_varid fix_var: ')
+
+          ! PnetCDF start() argument starts with 1
+          start(1) = start(1) + 1
+          start(2) = start(2) + 1
+          call get_var_and_verify(ncid, varid0, NX,NY,start, count, buf,
+     +                 buftype, ghost_buftype, rec_filetype, nerrs)
+
+          call get_var_and_verify(ncid, varid1, NX,NY,start, count, buf,
+     +                 buftype, ghost_buftype, fix_filetype, nerrs)
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          call MPI_Type_free(rec_filetype, ierr)
+          call MPI_Type_free(fix_filetype, ierr)
+          call MPI_Type_free(buftype, ierr)
+          call MPI_Type_free(ghost_buftype, ierr)
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, ierr)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+          msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//' for vard API '
+          if (rank .eq. 0) call pass_fail(nerrs, msg)
+
+ 999      call MPI_Finalize(ierr)
+      end ! program main
+
diff --git a/test/testcases/test_vardf90.f90 b/test/testcases/test_vardf90.f90
new file mode 100644
index 0000000..2fe2ffc
--- /dev/null
+++ b/test/testcases/test_vardf90.f90
@@ -0,0 +1,372 @@
+!
+!   Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: test_vardf90.f90 2205 2015-11-28 20:41:50Z wkliao $
+
+!
+! This program tests the vard API.
+! The write buffer is a 2D array of size NX x NY
+! The MPI data type for the buffer is defined by swapping the 1st and 2nd
+! rows of the array using a butype constructed by MPI_Type_create_hindex().
+! It also writes a fixed-size variable using a buftype constructed by
+! MPI_Type_create_subarray(). Both record and foxed-size variables are read
+! back using various filetypes and buftypes and check the contents.
+!
+! The expected reults from the output file contents are:
+! (when running on 1 MPI process)
+!
+!  % ncmpidump testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-1
+!    dimensions:
+!           REC_DIM = UNLIMITED ; // (2 currently)
+!           X = 5 ;
+!           FIX_DIM = 2 ;
+!    variables:
+!           int rec_var(REC_DIM, X) ;
+!           int dummy_rec(REC_DIM, X) ;
+!           int fix_var(FIX_DIM, X) ;
+!    data:
+! 
+!    rec_var =
+!      10, 11, 12, 13, 14,
+!      0, 1, 2, 3, 4 ;
+! 
+!    dummy_rec =
+!      0, 0, 0, 0, 0,
+!      0, 0, 0, 0, 0 ;
+!
+!    fix_var =
+!      10, 11, 12, 13, 14,
+!      0, 1, 2, 3, 4 ;
+! }
+!
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+          character(len=128) msg
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) trim(message), trim(nf90mpi_strerror(err))
+              msg = '*** TESTING F90 test_vardf90.f90 for vard API '
+              call pass_fail(1, msg)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      subroutine check_value(rank, nx, ny, buf, nerrs)
+          use mpi
+          implicit none
+          integer NX, NY
+          integer rank, buf(nx, ny), nerrs
+          integer i, j
+ 543      format(A,I2,A,I2,A,I3,A,I3)
+          do j=1, ny
+             do i=1, nx
+                if (buf(i,j) .NE. rank*100+j*10+i) then
+                    print 543,'expecting buf(',i,',',j,')=', &
+                    rank*100+j*10+i,' but got ',buf(i,j)
+                    nerrs = nerrs + 1
+                endif
+             enddo
+          enddo
+      end subroutine check_value
+
+      subroutine check_value_permuted(rank, nx, ny, buf, nerrs)
+          use mpi
+          implicit none
+          integer NX, NY
+          integer rank, buf(nx, ny), nerrs, val
+          integer i, j
+ 543      format(A,I2,A,I2,A,I3,A,I3)
+          do j=1, ny
+             val = 1
+             if (j .EQ. 1) val = 2
+             val = rank * 100 + val * 10
+             do i=1, nx
+                if (buf(i,j) .NE. val+i) then
+                    print 543,'expecting buf(',i,',',j,')=', &
+                    val+i,' but got ',buf(i,j)
+                    nerrs = nerrs + 1
+                endif
+             enddo
+          enddo
+      end subroutine check_value_permuted
+
+      subroutine clear_buf(nx, ny, buf)
+          use mpi
+          implicit none
+          integer NX, NY
+          integer buf(nx, ny)
+          integer i, j
+          do j=1, NY
+             do i=1, NX
+                buf(i,j) = -1
+             enddo
+          enddo
+      end subroutine clear_buf
+
+      subroutine get_var_and_verify(ncid,varid,NX,NY,start,count,buf, &
+                             buftype, ghost_buftype, filetype, nerrs)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer NX, NY
+          integer(kind=MPI_OFFSET_KIND) start(2), count(2)
+          integer i, j, rank, err, ncid, varid, nerrs, buf(NX, NY)
+          integer buftype, ghost_buftype, filetype
+          integer ncbuf(NX+4, NY+4)
+
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, err)
+          ! clear the contents of the read buffer
+          call clear_buf(NX, NY, buf)
+
+          ! read back using regular vara API
+          err = nf90mpi_get_var_all(ncid, varid, buf, start, count)
+          call check(err, 'In nf90mpi_get_var_all: ')
+
+          ! check if the contents of buf are expected
+          call check_value_permuted(rank, NX, NY, buf, nerrs)
+          call clear_buf(NX, NY, buf)
+
+          ! read back using flexible vara API
+          err = nf90mpi_get_var_all(ncid, varid, buf(:,2), start, count, &
+                                    BUFCOUNT=1_MPI_OFFSET_KIND, BUFTYPE=buftype)
+          call check(err, 'In nf90mpi_get_var_all: ')
+
+          ! check if the contents of buf are expected
+          call check_value(rank, NX, NY, buf, nerrs)
+          call clear_buf(NX, NY, buf)
+
+          ! read back using vard API and permuted buftype
+          err = nf90mpi_get_vard_all(ncid, varid, filetype, buf(:,2), &
+                                     1_MPI_OFFSET_KIND, buftype)
+          call check(err, 'In nf90mpi_get_vard_all: ')
+
+          ! check if the contents of buf are expected
+          call check_value(rank, NX, NY, buf, nerrs)
+          call clear_buf(NX, NY, buf)
+
+          ! read back using vard API and no buftype
+          err = nf90mpi_get_vard_all(ncid, varid, filetype, buf, 0_MPI_OFFSET_KIND, &
+                                     MPI_DATATYPE_NULL)
+          call check(err, 'In nf90mpi_get_vard_all: ')
+
+          ! check if the contents of buf are expected
+          call check_value_permuted(rank, NX, NY, buf, nerrs)
+
+          ! read back using ghost buftype
+          err = nf90mpi_get_vard_all(ncid, varid, filetype, ncbuf, 1_MPI_OFFSET_KIND,&
+                                     ghost_buftype)
+          call check(err, 'In nf90mpi_get_vard_all: ')
+
+ 543      format(A,I2,A,I2,A,I3,A,I3)
+          do j=1, NY
+             do i=1, NX
+                if (buf(i,j) .NE. ncbuf(i+2, j+2)) then
+                    print 543,'expecting buf(',i,',',j,')=', &
+                    buf(i,j),' but got ',ncbuf(i+2,j+2)
+                    nerrs = nerrs + 1
+                endif
+             enddo
+          enddo
+      end subroutine get_var_and_verify
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          character(LEN=256) filename, cmd, msg
+          integer err, ierr, nprocs, rank, i, j, get_args
+          integer cmode, ncid, varid0, varid1, varid2, dimid(2), nerrs
+          integer NX, NY
+          PARAMETER(NX=5, NY=2)
+          integer buf(NX, NY)
+          integer buftype, ghost_buftype, rec_filetype, fix_filetype
+          integer array_of_sizes(2), array_of_subsizes(2)
+          integer array_of_starts(2), blocklengths(2)
+          integer(kind=MPI_OFFSET_KIND) start(2), count(2)
+          integer(kind=MPI_OFFSET_KIND) len, malloc_size, sum_size, recsize
+          integer(kind=MPI_ADDRESS_KIND) a0, a1, disps(2)
+
+          call MPI_Init(ierr)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, ierr)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              filename = "testfile.nc"
+              err = get_args(cmd, filename)
+          endif
+          call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+          if (err .EQ. 0) goto 999
+          
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+          nerrs = 0
+
+          start(1) = NX * rank
+          start(2) = 0
+          count(1) = NX
+          count(2) = 2
+
+          ! construct various MPI derived data types
+          blocklengths(1) = NX;
+          blocklengths(2) = NX;
+          call MPI_Get_address(buf(1,2), a0, ierr)
+          call MPI_Get_address(buf(1,1), a1, ierr)
+          disps(1) = 0
+          disps(2) = a1 - a0
+          call MPI_Type_create_hindexed(2, blocklengths, disps, MPI_INTEGER, &
+                                        buftype, ierr)
+          call MPI_Type_commit(buftype, ierr)
+
+          ! create a file type for the fixed-size variable
+          array_of_sizes(1) = NX*nprocs
+          array_of_sizes(2) = 2
+          array_of_subsizes(1) = INT(count(1))
+          array_of_subsizes(2) = INT(count(2))
+          array_of_starts(1) = INT(start(1))
+          array_of_starts(2) = INT(start(2))
+          call MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes, &
+               array_of_starts, MPI_ORDER_FORTRAN, MPI_INTEGER, fix_filetype,&
+               ierr)
+          call MPI_Type_commit(fix_filetype, ierr)
+
+          ! create a buftype with ghost cells on each side */
+          array_of_sizes(1) = INT(count(1))+4
+          array_of_sizes(2) = INT(count(2))+4
+          array_of_subsizes(1) = INT(count(1))
+          array_of_subsizes(2) = INT(count(2))
+          array_of_starts(1) = 2
+          array_of_starts(2) = 2
+          call MPI_Type_create_subarray(2, array_of_sizes, array_of_subsizes, &
+               array_of_starts, MPI_ORDER_FORTRAN, MPI_INTEGER, ghost_buftype,&
+               ierr)
+          call MPI_Type_commit(ghost_buftype, ierr)
+
+          ! initialized buffer contents
+          do j=1, INT(count(2))
+             do i=1, INT(count(1))
+                 buf(i, j) = rank*100 + j*10 + i
+             enddo
+          enddo
+
+          ! create file, truncate it if exists
+          cmode = NF90_CLOBBER
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                               MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! define 2 dimensions
+          err = nf90mpi_def_dim(ncid, "RECV_DIM", NF90MPI_UNLIMITED, dimid(2))
+          call check(err, 'In nf90mpi_def_dim RECV_DIM: ')
+          len = NX * nprocs
+          err = nf90mpi_def_dim(ncid, "X", len, dimid(1))
+          call check(err, 'In nf90mpi_def_dim X: ')
+
+          ! define 2D record variables of integer type
+          err = nf90mpi_def_var(ncid, "rec_var", NF90_INT, dimid, varid0)
+          call check(err, 'In nf90mpi_def_var: rec_var ')
+          err = nf90mpi_def_var(ncid, "dummy_rec", NF90_INT, dimid, varid2)
+          call check(err, 'In nf90mpi_def_var: dummy_rec ')
+
+          ! define 2D fixed-size variable of integer type
+          err = nf90mpi_def_dim(ncid, "FIX_DIM", 2_MPI_OFFSET_KIND, dimid(2))
+          call check(err, 'In nf90mpi_def_dim RECV_DIM: ')
+          err = nf90mpi_def_var(ncid, "fix_var", NF90_INT, dimid, varid1)
+          call check(err, 'In nf90mpi_def_var: fix_var ')
+
+          ! do not forget to exit define mode
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! create a file type for the record variable */
+          err = nf90mpi_inq_recsize(ncid, recsize)
+          call check(err, 'In nf90mpi_inq_recsize: ')
+          blocklengths(1) = INT(count(1))
+          blocklengths(2) = INT(count(1))
+          disps(1) = start(1)*4
+          disps(2) = recsize + start(1)*4
+          call MPI_Type_create_hindexed(2, blocklengths, disps, &
+                                        MPI_INTEGER, rec_filetype, err)
+          call MPI_Type_commit(rec_filetype, err)
+
+          ! write the record variable */
+          err = nf90mpi_put_vard_all(ncid, varid0, rec_filetype, buf(:,2), &
+                                     1_MPI_OFFSET_KIND, buftype)
+          call check(err, 'In nf90mpi_put_vard_all: ')
+          ! check if the contents of buf are altered
+          call check_value(rank, NX, NY, buf, nerrs)
+
+          ! check if root process can write to file header in data mode
+          err = nf90mpi_rename_var(ncid, varid0, 'rec_VAR')
+          call check(err, 'In nf90mpi_rename_var: ')
+
+          ! write the fixed-size variable
+          err = nf90mpi_put_vard_all(ncid, varid1, fix_filetype, buf(:,2), &
+                                     1_MPI_OFFSET_KIND, buftype)
+          call check(err, 'In nf90mpi_put_vard_all: ')
+          ! check if the contents of buf are altered
+          call check_value(rank, NX, NY, buf, nerrs)
+
+          ! check if root process can write to file header in data mode
+          err = nf90mpi_rename_var(ncid, varid0, 'rec_var')
+          call check(err, 'In nf90mpi_rename_var: ')
+
+          ! close the file
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          ! open the same file and read back for validate */
+          err = nf90mpi_open(MPI_COMM_WORLD, filename, NF90_NOWRITE, &
+                             MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_open: ')
+
+          err = nf90mpi_inq_varid(ncid, "rec_var", varid0)
+          call check(err, 'In nf90mpi_inq_varid rec_var: ')
+          err = nf90mpi_inq_varid(ncid, "fix_var", varid1)
+          call check(err, 'In nf90mpi_inq_varid fix_var: ')
+
+          ! PnetCDF start() argument starts with 1
+          start = start + 1
+          call get_var_and_verify(ncid, varid0, NX,NY,start, count, buf, &
+                       buftype, ghost_buftype, rec_filetype, nerrs)
+
+          call get_var_and_verify(ncid, varid1, NX,NY,start, count, buf, &
+                       buftype, ghost_buftype, fix_filetype, nerrs)
+
+          ! close the file
+          err = nf90mpi_close(ncid)
+          call check(err, 'In nf90mpi_close: ')
+
+          call MPI_Type_free(rec_filetype, ierr)
+          call MPI_Type_free(fix_filetype, ierr)
+          call MPI_Type_free(buftype, ierr)
+          call MPI_Type_free(ghost_buftype, ierr)
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err == NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, ierr)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+          msg = '*** TESTING F90 '//trim(cmd)//' for vard API '
+          if (rank .eq. 0) call pass_fail(nerrs, msg)
+
+ 999      call MPI_Finalize(ierr)
+      end program main
+
diff --git a/test/testcases/test_varm.c b/test/testcases/test_varm.c
new file mode 100644
index 0000000..91fee12
--- /dev/null
+++ b/test/testcases/test_varm.c
@@ -0,0 +1,201 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: test_varm.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define PRINT_ERR_ON_SCREEN
+
+#define ERRCODE 2
+#define ERR {if (err!=NC_NOERR) {printf("Error at line %d: %s\n", __LINE__, ncmpi_strerror(err)); nerrs++;}}
+
+/*----< main() >------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+    int i, j, err, nerrs=0, rank, nprocs, verbose;
+    int ncid, dimid[2], varid, req, status;
+
+    MPI_Offset start[2], count[2], stride[2], imap[2];
+    int   var[6][4];
+    float rh[4][6];
+    signed char  varT[4][6];
+    char *filename="testfile.nc";
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for get/put varm ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    verbose = 0;
+    if (nprocs > 1 && rank == 0 && verbose)
+        printf("Warning: %s is designed to run on 1 process\n", argv[0]);
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER | NC_64BIT_DATA,
+                       MPI_INFO_NULL, &ncid); ERR
+
+    /* define a variable of a 6 x 4 integer array in the nc file */
+    err = ncmpi_def_dim(ncid, "Y", 6, &dimid[0]); ERR
+    err = ncmpi_def_dim(ncid, "X", 4, &dimid[1]); ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT, 2, dimid, &varid); ERR
+    err = ncmpi_enddef(ncid); ERR
+
+    /* create a 6 x 4 integer variable in the file with contents:
+           0,  1,  2,  3,
+           4,  5,  6,  7,
+           8,  9, 10, 11,
+          12, 13, 14, 15,
+          16, 17, 18, 19,
+          20, 21, 22, 23
+     */
+    for (j=0; j<6; j++) for (i=0; i<4; i++) var[j][i] = j*4+i;
+
+    start[0] = 0; start[1] = 0;
+    count[0] = 6; count[1] = 4;
+    if (rank > 0) count[0] = count[1] = 0;
+    err = ncmpi_put_vara_int_all(ncid, varid, start, count, &var[0][0]); ERR
+
+    if (nprocs > 1) MPI_Barrier(MPI_COMM_WORLD);
+
+    /* read the variable back in the matrix transposed way, rh is 4 x 6 */
+     count[0] = 6;  count[1] = 4;
+    stride[0] = 1; stride[1] = 1;
+      imap[0] = 1;   imap[1] = 6;   /* would be {4, 1} if not transposing */
+#define TEST_NON_BLOCKING_API
+#ifdef TEST_NON_BLOCKING_API
+    err = ncmpi_iget_varm_float(ncid, varid, start, count, stride, imap, &rh[0][0], &req); ERR
+
+    err = ncmpi_wait_all(ncid, 1, &req, &status); ERR
+
+    if (status != NC_NOERR) ERR
+#else
+    err = ncmpi_get_varm_float_all(ncid, varid, start, count, stride, imap, &rh[0][0]); ERR
+#endif
+
+    /* check the contents of read */
+    float k = 0.0;
+    for (i=0; i<6; i++) {
+        for (j=0; j<4; j++) {
+            if (rh[j][i] != k) {
+#ifdef PRINT_ERR_ON_SCREEN
+                printf("Error: expecting rh[%d][%d]=%f but got %f\n",j,i,k,rh[j][i]);
+#endif
+                nerrs++;
+                break;
+            }
+            k += 1.0;
+        }
+    }
+#ifdef PRINT_ON_SCREEN
+    /* print the contents of read */
+    for (j=0; j<4; j++) {
+        printf("[%2d]: ",j);
+        for (i=0; i<6; i++) {
+            printf("%5.1f",rh[j][i]);
+        }
+        printf("\n");
+    }
+#endif
+    /* the stdout should be:
+           [ 0]:   0.0  4.0  8.0 12.0 16.0 20.0
+           [ 1]:   1.0  5.0  9.0 13.0 17.0 21.0
+           [ 2]:   2.0  6.0 10.0 14.0 18.0 22.0
+           [ 3]:   3.0  7.0 11.0 15.0 19.0 23.0
+     */
+
+    /* testing get_varm(), first zero-out the variable in the file */
+    memset(&var[0][0], 0, 6*4*sizeof(int));
+    start[0] = 0; start[1] = 0;
+    count[0] = 6; count[1] = 4;
+    if (rank > 0) count[0] = count[1] = 0;
+    err = ncmpi_put_vara_int_all(ncid, varid, start, count, &var[0][0]); ERR
+
+    /* set the contents of the write buffer varT, a 4 x 6 char array
+          50, 51, 52, 53, 54, 55,
+          56, 57, 58, 59, 60, 61,
+          62, 63, 64, 65, 66, 67,
+          68, 69, 70, 71, 72, 73
+     */
+    for (j=0; j<4; j++) for (i=0; i<6; i++) varT[j][i] = j*6+i + 50;
+
+    /* write varT to the NC variable in the matrix transposed way */
+    start[0]  = 0; start[1]  = 0;
+    count[0]  = 6; count[1]  = 4;
+    stride[0] = 1; stride[1] = 1;
+    imap[0]   = 1; imap[1]   = 6;   /* would be {4, 1} if not transposing */
+    if (rank > 0) count[0] = count[1] = 0;
+#ifdef TEST_NON_BLOCKING_API
+    err = ncmpi_iput_varm_schar(ncid, varid, start, count, stride, imap, &varT[0][0], &req); ERR
+
+    err = ncmpi_wait_all(ncid, 1, &req, &status); ERR
+
+    if (status != NC_NOERR) ERR
+#else
+    err = ncmpi_put_varm_schar_all(ncid, varid, start, count, stride, imap, &varT[0][0]); ERR
+#endif
+
+    /* the output from command "ncmpidump -v var test.nc" should be:
+           var =
+            50, 56, 62, 68,
+            51, 57, 63, 69,
+            52, 58, 64, 70,
+            53, 59, 65, 71,
+            54, 60, 66, 72,
+            55, 61, 67, 73 ;
+     */
+
+    /* check if the contents of write buffer have been altered */
+    for (j=0; j<4; j++) {
+        for (i=0; i<6; i++) {
+            if (varT[j][i] != j*6+i + 50) {
+#ifdef PRINT_ERR_ON_SCREEN
+                /* this error is a pntecdf internal error, if occurs */
+                printf("Error: expecting varT[%d][%d]=%d but got %d\n",j,i,j*6+i + 50,varT[j][i]);
+#endif
+                nerrs++;
+                break;
+            }
+        }
+    }
+    err = ncmpi_close(ncid); ERR
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+
+    return (nerrs == 0) ? 0 : 1;
+}
+
diff --git a/test/testcases/varn_contig.c b/test/testcases/varn_contig.c
new file mode 100644
index 0000000..04b55e5
--- /dev/null
+++ b/test/testcases/varn_contig.c
@@ -0,0 +1,240 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: varn_contig.c 2219 2015-12-11 22:30:03Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example tests using a single call of ncmpi_put_varn_int_all() to
+ * write a sequence of requests with arbitrary array indices and lengths.
+ * Specifically, the fileview in each process is made a contiguous chunk.
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o varn_contig varn_contig.c -lpnetcdf
+ *    % mpiexec -n 4 ./varn_contig /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             Y = 4 ;
+ *             X = 10 ;
+ *    variables:
+ *             int var(Y, X) ;
+ *    data:
+ *
+ *     var =
+ *       200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
+ *       300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+ *       400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+ *       100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy(), memset() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+#define ERR {if(err!=NC_NOERR){printf("Error at %s line=%d: %s\n", __FILE__,__LINE__, ncmpi_strerror(err)); nerrs++;}}
+
+static
+int check_contents_for_fail(int *buffer)
+{
+    int i, nprocs;
+    int expected[NY*NX] = {200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
+                           300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+                           400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+                           100, 100, 100, 100, 100, 100, 100, 100, 100, 100};
+
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* check if the contents of buf are expected */
+    for (i=0; i<NY*NX; i++) {
+        if (expected[i] >= nprocs) continue;
+        if (buffer[i] != expected[i]) {
+            printf("Expected read buf[%d]=%d, but got %d\n",
+                   i,expected[i],buffer[i]);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int i, rank, nprocs, err, verbose=0, nerrs=0;
+    int ncid, cmode, varid[3], dimid[2], num_reqs, *buffer, *r_buffer;
+    MPI_Offset w_len, **starts, **counts;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for put_varn with contig fileview", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    if (verbose && nprocs != 4 && rank == 0)
+        printf("Warning: %s is intended to run on 4 processes\n",argv[0]);
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]);
+    ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT, NDIMS, dimid, &varid[0]);
+    ERR
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* pick arbitrary numbers of requests for 4 processes */
+    num_reqs = 0;
+    if (rank == 0)      num_reqs = 4;
+    else if (rank == 1) num_reqs = 5;
+    else if (rank == 2) num_reqs = 5;
+    else if (rank == 3) num_reqs = 5;
+
+    starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+    counts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+    starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+    counts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+    for (i=1; i<num_reqs; i++) {
+        starts[i] = starts[i-1] + NDIMS;
+        counts[i] = counts[i-1] + NDIMS;
+    }
+
+    /* assign arbitrary starts and counts */
+    const int y=0, x=1;
+    if (rank == 0) {
+        starts[0][y] = 3; starts[0][x] = 0; counts[0][y] = 1; counts[0][x] = 3;
+        starts[1][y] = 3; starts[1][x] = 4; counts[1][y] = 1; counts[1][x] = 3;
+        starts[2][y] = 3; starts[2][x] = 3; counts[2][y] = 1; counts[2][x] = 1;
+        starts[3][y] = 3; starts[3][x] = 7; counts[3][y] = 1; counts[3][x] = 3;
+        /*                  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,
+                            - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,
+                            - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,
+                           100, 100, 100, 100, 100, 100, 100, 100, 100, 100
+             req id:        0    0    0    2    1    1    1    3    3    3
+         */
+    } else if (rank ==1) {
+        starts[0][y] = 0; starts[0][x] = 3; counts[0][y] = 1; counts[0][x] = 2;
+        starts[1][y] = 0; starts[1][x] = 8; counts[1][y] = 1; counts[1][x] = 2;
+        starts[2][y] = 0; starts[2][x] = 5; counts[2][y] = 1; counts[2][x] = 2;
+        starts[3][y] = 0; starts[3][x] = 7; counts[3][y] = 1; counts[3][x] = 1;
+        starts[4][y] = 0; starts[4][x] = 0; counts[4][y] = 1; counts[4][x] = 3;
+        /*                 200, 200, 200, 200, 200, 200, 200, 200, 200, 200
+                            - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,
+                            - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,
+                            - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,
+             req id:        4    4    4    0    0    2    2    3    1    1
+         */
+    } else if (rank ==2) {
+        starts[0][y] = 1; starts[0][x] = 1; counts[0][y] = 1; counts[0][x] = 3;
+        starts[1][y] = 1; starts[1][x] = 0; counts[1][y] = 1; counts[1][x] = 1;
+        starts[2][y] = 1; starts[2][x] = 5; counts[2][y] = 1; counts[2][x] = 2;
+        starts[3][y] = 1; starts[3][x] = 7; counts[3][y] = 1; counts[3][x] = 3;
+        starts[4][y] = 1; starts[4][x] = 4; counts[4][y] = 1; counts[4][x] = 1;
+        /*                  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,
+                           300, 300, 300, 300, 300, 300, 300, 300, 300, 300
+                            - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,
+                            - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,
+             req id:        1    0    0    0    4    2    3    3    3    3
+         */
+    } else if (rank ==3) {
+        starts[0][y] = 2; starts[0][x] = 3; counts[0][y] = 1; counts[0][x] = 3;
+        starts[1][y] = 2; starts[1][x] = 6; counts[1][y] = 1; counts[1][x] = 2;
+        starts[2][y] = 2; starts[2][x] = 0; counts[2][y] = 1; counts[2][x] = 2;
+        starts[3][y] = 2; starts[3][x] = 8; counts[3][y] = 1; counts[3][x] = 2;
+        starts[4][y] = 2; starts[4][x] = 2; counts[4][y] = 1; counts[4][x] = 1;
+        /*                  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,
+                            - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,
+                           400, 400, 400, 400, 400, 400, 400, 400, 400, 400
+                            - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,  - ,
+             req id:        2    2    4    0    0    0    1    1    3    3
+         */
+    }
+
+    w_len = NX; /* total write length for this process */
+
+    /* allocate I/O buffer and initialize its contents */
+    r_buffer = (int*) malloc(NY*NX * sizeof(int));
+    buffer   = (int*) malloc(w_len * sizeof(int));
+    for (i=0; i<w_len; i++) buffer[i] = rank*100 + 100;
+
+    /* check error code: NC_ENULLSTART */
+    err = ncmpi_put_varn_int_all(ncid, varid[0], 1, NULL, NULL, NULL);
+    if (err != NC_ENULLSTART) {
+        printf("expecting error code NC_ENULLSTART but got %s\n",nc_err_code_name(err));
+        nerrs++;
+    }
+
+    /* write using varn API */
+    err = ncmpi_put_varn_int_all(ncid, varid[0], num_reqs, starts, counts, buffer);
+    ERR
+
+    if (nprocs > 4) MPI_Barrier(MPI_COMM_WORLD);
+
+    /* read back and check contents */
+    memset(r_buffer, 0, NY*NX*sizeof(int));
+    err = ncmpi_get_var_int_all(ncid, varid[0], r_buffer);
+    ERR
+    nerrs += check_contents_for_fail(r_buffer);
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    free(buffer);
+    free(r_buffer);
+    free(starts[0]);
+    free(counts[0]);
+    free(starts);
+    free(counts);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/varn_int.c b/test/testcases/varn_int.c
new file mode 100644
index 0000000..8394237
--- /dev/null
+++ b/test/testcases/varn_int.c
@@ -0,0 +1,320 @@
+/*********************************************************************
+ *
+ *  Copyright (C) 2014, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *********************************************************************/
+/* $Id: varn_int.c 2219 2015-12-11 22:30:03Z wkliao $ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * This example tests using a single call of ncmpi_put_varn_int_all() to
+ * write a sequence of requests with arbitrary array indices and lengths.
+ *
+ * The compile and run commands are given below, together with an ncmpidump of
+ * the output file.
+ *
+ *    % mpicc -O2 -o varn_int varn_int.c -lpnetcdf
+ *    % mpiexec -n 4 ./varn_int /pvfs2/wkliao/testfile.nc
+ *    % ncmpidump /pvfs2/wkliao/testfile.nc
+ *    netcdf testfile {
+ *    // file format: CDF-5 (big variables)
+ *    dimensions:
+ *             Y = 4 ;
+ *             X = 10 ;
+ *             REC_DIM = UNLIMITED ; // (4 currently)
+ *    variables:
+ *             int var(Y, X) ;
+ *             int rec_var(REC_DIM, X) ;
+ *    data:
+ *
+ *     var =
+ *       3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+ *       0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+ *       1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+ *       0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *
+ *     rec_var =
+ *       3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+ *       0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+ *       1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+ *       0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+ *    }
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strcpy(), memset() */
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define NY 4
+#define NX 10
+#define NDIMS 2
+
+#define ERR {if(err!=NC_NOERR){printf("Error at %s line=%d: %s\n", __FILE__,__LINE__, ncmpi_strerror(err)); nerrs++;}}
+
+static
+int check_contents_for_fail(int *buffer)
+{
+    int i, nprocs;
+    int expected[NY*NX] = {3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+                           0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+                           1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+                           0, 0, 0, 2, 1, 1, 1, 3, 3, 3};
+
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    /* check if the contents of buf are expected */
+    for (i=0; i<NY*NX; i++) {
+        if (expected[i] >= nprocs) continue;
+        if (buffer[i] != expected[i]) {
+            printf("Expected read buf[%d]=%d, but got %d\n",
+                   i,expected[i],buffer[i]);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static
+void permute(MPI_Offset a[NDIMS], MPI_Offset b[NDIMS])
+{
+    int i;
+    MPI_Offset tmp;
+    for (i=0; i<NDIMS; i++) {
+        tmp = a[i]; a[i] = b[i]; b[i] = tmp;
+    }
+}
+
+int main(int argc, char** argv)
+{
+    char filename[256];
+    int i, j, rank, nprocs, err, verbose=0, nerrs=0;
+    int ncid, cmode, varid[3], dimid[2], num_reqs, *buffer, *r_buffer;
+    MPI_Offset w_len, **starts, **counts;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    strcpy(filename, "testfile.nc");
+    if (argc == 2) strcpy(filename, argv[1]);
+    MPI_Bcast(filename, 256, MPI_CHAR, 0, MPI_COMM_WORLD);
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for ncmpi_put_varn_int_all() ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    if (verbose && nprocs != 4 && rank == 0)
+        printf("Warning: %s is intended to run on 4 processes\n",argv[0]);
+
+    /* create a new file for writing ----------------------------------------*/
+    cmode = NC_CLOBBER | NC_64BIT_DATA;
+    err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL, &ncid);
+    ERR
+
+    /* create a global array of size NY * NX */
+    err = ncmpi_def_dim(ncid, "Y", NY, &dimid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "X", NX, &dimid[1]);
+    ERR
+    err = ncmpi_def_var(ncid, "var", NC_INT, NDIMS, dimid, &varid[0]);
+    ERR
+    err = ncmpi_def_dim(ncid, "REC_DIM", NC_UNLIMITED, &dimid[0]);
+    ERR
+    err = ncmpi_def_var(ncid, "rec_var", NC_INT, NDIMS, dimid, &varid[1]);
+    ERR
+    err = ncmpi_enddef(ncid);
+    ERR
+
+    /* pick arbitrary numbers of requests for 4 processes */
+    num_reqs = 0;
+    if (rank == 0)      num_reqs = 4;
+    else if (rank == 1) num_reqs = 6;
+    else if (rank == 2) num_reqs = 5;
+    else if (rank == 3) num_reqs = 4;
+
+    starts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+    counts    = (MPI_Offset**) malloc(num_reqs *        sizeof(MPI_Offset*));
+    starts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+    counts[0] = (MPI_Offset*)  calloc(num_reqs * NDIMS, sizeof(MPI_Offset));
+    for (i=1; i<num_reqs; i++) {
+        starts[i] = starts[i-1] + NDIMS;
+        counts[i] = counts[i-1] + NDIMS;
+    }
+
+    /* assign arbitrary starts and counts */
+    const int y=0, x=1;
+    if (rank == 0) {
+        starts[0][y] = 0; starts[0][x] = 5; counts[0][y] = 1; counts[0][x] = 2;
+        starts[1][y] = 1; starts[1][x] = 0; counts[1][y] = 1; counts[1][x] = 1;
+        starts[2][y] = 2; starts[2][x] = 6; counts[2][y] = 1; counts[2][x] = 2;
+        starts[3][y] = 3; starts[3][x] = 0; counts[3][y] = 1; counts[3][x] = 3;
+        /* rank 0 is writing the followings: ("-" means skip)
+                  -  -  -  -  -  0  0  -  -  - 
+                  0  -  -  -  -  -  -  -  -  - 
+                  -  -  -  -  -  -  0  0  -  - 
+                  0  0  0  -  -  -  -  -  -  - 
+         */
+    } else if (rank ==1) {
+        starts[0][y] = 0; starts[0][x] = 3; counts[0][y] = 1; counts[0][x] = 2;
+        starts[1][y] = 0; starts[1][x] = 8; counts[1][y] = 1; counts[1][x] = 2;
+        starts[2][y] = 1; starts[2][x] = 5; counts[2][y] = 1; counts[2][x] = 2;
+        starts[3][y] = 2; starts[3][x] = 0; counts[3][y] = 1; counts[3][x] = 2;
+        starts[4][y] = 2; starts[4][x] = 8; counts[4][y] = 1; counts[4][x] = 2;
+        starts[5][y] = 3; starts[5][x] = 4; counts[5][y] = 1; counts[5][x] = 3;
+        /* rank 1 is writing the followings: ("-" means skip)
+                  -  -  -  1  1  -  -  -  1  1 
+                  -  -  -  -  -  1  1  -  -  - 
+                  1  1  -  -  -  -  -  -  1  1 
+                  -  -  -  -  1  1  1  -  -  - 
+         */
+    } else if (rank ==2) {
+        starts[0][y] = 0; starts[0][x] = 7; counts[0][y] = 1; counts[0][x] = 1;
+        starts[1][y] = 1; starts[1][x] = 1; counts[1][y] = 1; counts[1][x] = 3;
+        starts[2][y] = 1; starts[2][x] = 7; counts[2][y] = 1; counts[2][x] = 3;
+        starts[3][y] = 2; starts[3][x] = 2; counts[3][y] = 1; counts[3][x] = 1;
+        starts[4][y] = 3; starts[4][x] = 3; counts[4][y] = 1; counts[4][x] = 1;
+        /* rank 2 is writing the followings: ("-" means skip)
+                  -  -  -  -  -  -  -  2  -  - 
+                  -  2  2  2  -  -  -  2  2  2 
+                  -  -  2  -  -  -  -  -  -  - 
+                  -  -  -  2  -  -  -  -  -  - 
+         */
+    } else if (rank ==3) {
+        starts[0][y] = 0; starts[0][x] = 0; counts[0][y] = 1; counts[0][x] = 3;
+        starts[1][y] = 1; starts[1][x] = 4; counts[1][y] = 1; counts[1][x] = 1;
+        starts[2][y] = 2; starts[2][x] = 3; counts[2][y] = 1; counts[2][x] = 3;
+        starts[3][y] = 3; starts[3][x] = 7; counts[3][y] = 1; counts[3][x] = 3;
+        /* rank 3 is writing the followings: ("-" means skip)
+                  3  3  3  -  -  -  -  -  -  - 
+                  -  -  -  -  3  -  -  -  -  - 
+                  -  -  -  3  3  3  -  -  -  - 
+                  -  -  -  -  -  -  -  3  3  3 
+         */
+    }
+
+    w_len = 0; /* total write length for this process */
+    for (i=0; i<num_reqs; i++) {
+        MPI_Offset w_req_len=1;
+        for (j=0; j<NDIMS; j++)
+            w_req_len *= counts[i][j];
+        w_len += w_req_len;
+    }
+
+    /* allocate I/O buffer and initialize its contents */
+    r_buffer = (int*) malloc(NY*NX * sizeof(int));
+    buffer   = (int*) malloc(w_len * sizeof(int));
+    for (i=0; i<w_len; i++) buffer[i] = rank;
+
+    /* check error code: NC_ENULLSTART */
+    err = ncmpi_put_varn_int_all(ncid, varid[0], 1, NULL, NULL, NULL);
+    if (err != NC_ENULLSTART) {
+        printf("expecting error code NC_ENULLSTART but got %s\n",nc_err_code_name(err));
+        nerrs++;
+    }
+
+    /* write using varn API */
+    err = ncmpi_put_varn_int_all(ncid, varid[0], num_reqs, starts, counts, buffer);
+    ERR
+
+    if (nprocs > 4) MPI_Barrier(MPI_COMM_WORLD);
+
+    /* read back and check contents */
+    memset(r_buffer, 0, NY*NX*sizeof(int));
+    err = ncmpi_get_var_int_all(ncid, varid[0], r_buffer);
+    ERR
+    nerrs += check_contents_for_fail(r_buffer);
+
+    /* permute write order */
+    if (num_reqs > 0) {
+        permute(starts[1], starts[2]); permute(counts[1], counts[2]);
+        permute(starts[2], starts[3]); permute(counts[2], counts[3]);
+    }
+
+    /* write using varn API */
+    err = ncmpi_put_varn_int_all(ncid, varid[1], num_reqs, starts, counts, buffer);
+    ERR
+
+    /* read back using get_var API and check contents */
+    memset(r_buffer, 0, NY*NX*sizeof(int));
+    err = ncmpi_get_var_int_all(ncid, varid[1], r_buffer);
+    ERR
+    nerrs += check_contents_for_fail(r_buffer);
+
+    /* read back using get_varn API and check contents */
+    for (i=0; i<w_len; i++) buffer[i] = -1;
+    err = ncmpi_get_varn_int_all(ncid, varid[0], num_reqs, starts, counts, buffer);
+    ERR
+
+    for (i=0; i<w_len; i++) {
+        if (buffer[i] != rank) {
+            printf("Error at line %d: expecting buffer[%d]=%d but got %d\n",
+                   __LINE__,i,rank,buffer[i]);
+            nerrs++;
+        }
+    }
+
+    /* test flexible API, using a noncontiguous buftype */
+    MPI_Datatype buftype;
+    MPI_Type_vector(w_len, 1, 2, MPI_INT, &buftype);
+    MPI_Type_commit(&buftype);
+    free(buffer);
+    buffer = (int*) malloc(w_len * 2 * sizeof(int));
+    for (i=0; i<2*w_len; i++) buffer[i] = -1;
+    err = ncmpi_get_varn_all(ncid, varid[0], num_reqs, starts, counts, buffer, 1, buftype);
+    ERR
+    MPI_Type_free(&buftype);
+
+    for (i=0; i<w_len*2; i++) {
+        if (i%2 && buffer[i] != -1) {
+            printf("Error at line %d: expecting buffer[%d]=-1 but got %d\n",
+                   __LINE__,i,buffer[i]);
+            nerrs++;
+        }
+        if (i%2 == 0 && buffer[i] != rank) {
+            printf("Error at line %d: expecting buffer[%d]=%d but got %d\n",
+                   __LINE__,i,rank,buffer[i]);
+            nerrs++;
+        }
+    }
+
+    err = ncmpi_close(ncid);
+    ERR
+
+    free(buffer);
+    free(r_buffer);
+    free(starts[0]);
+    free(counts[0]);
+    free(starts);
+    free(counts);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+    return 0;
+}
+
diff --git a/test/testcases/varn_intf.f b/test/testcases/varn_intf.f
new file mode 100644
index 0000000..6b925e7
--- /dev/null
+++ b/test/testcases/varn_intf.f
@@ -0,0 +1,288 @@
+!
+!   Copyright (C) 2013, Northwestern University
+!   See COPYRIGHT notice in top-level directory.
+!
+! $Id: varn_intf.f 2224 2015-12-16 06:10:36Z wkliao $
+
+! This example shows how to use a single call of nfmpi_put_varn_int_all() to
+! write a sequence of requests with arbitrary array indices and lengths.
+! Using nfmpi_put_varn_int_all() can achieve the same effect of HDF5 writing
+! a sequence of selected file locations through the following 2 APIs.
+!
+!   H5Sselect_elements(fid, H5S_SELECT_SET, NUMP, (const hssize_t **)coord);
+!   H5Dwrite(dataset, H5T_NATIVE_INT, mid, fid, H5P_DEFAULT, val); 
+!
+! Note that in nfmpi_put_varn_int_all(), users can write more than one element
+! starting at each selected location.
+!
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file.
+!
+!    % mpif77 -O2 -o varn_int varn_intf.f -lpnetcdf
+!    % mpiexec -n 4 ./varn_intf /pvfs2/wkliao/testfile.nc
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!             X = 4 ;
+!             Y = 10 ;
+!    variables:
+!             int var(Y, X) ;
+!    data:
+!
+!     var =
+!      2, 2, 1, 1,
+!      2, 2, 0, 0,
+!      1, 1, 0, 0,
+!      1, 1, 3, 3,
+!      3, 3, 2, 2,
+!      0, 0, 1, 1,
+!      0, 0, 1, 1,
+!      2, 2, 0, 0,
+!      3, 3, 3, 3,
+!      3, 3, 3, 3 ;
+!    }
+!
+!    Note the above dump is in C order
+!
+
+       INTEGER FUNCTION XTRIM(STRING)
+           CHARACTER*(*) STRING
+           INTEGER I, N
+           N = LEN(STRING)
+           DO I = N, 1, -1
+              IF (STRING(I:I) .NE. ' ') GOTO 10
+           ENDDO
+ 10        XTRIM = I
+       END ! FUNCTION XTRIM
+
+      subroutine check(err, message)
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+          integer err, XTRIM
+          character*(*) message
+          character*128 msg
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF_NOERR) then
+              write(6,*) message(1:XTRIM(message)), nfmpi_strerror(err)
+              msg = '*** TESTING F77 varn_intf.f for varn API '
+              call pass_fail(1, msg)
+              call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end ! subroutine check
+
+      program main
+          implicit none
+          include "mpif.h"
+          include "pnetcdf.inc"
+
+          integer NDIMS, XTRIM
+          integer*8 NX, NY
+          PARAMETER(NDIMS=2, NX=4, NY=10)
+
+          character*256 filename, cmd, msg
+          integer i, j, err, ierr, nprocs, rank, nerrs, get_args
+          integer cmode, ncid, varid, dimid(NDIMS), num_reqs
+
+          integer*8 w_len, w_req_len
+          integer*8 starts(NDIMS, 13)
+          integer*8 counts(NDIMS, 13)
+          integer*8 malloc_size, sum_size
+          integer buffer(13)
+
+          call MPI_Init(ierr)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, ierr)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              filename = "testfile.nc"
+              err = get_args(cmd, filename)
+          endif
+          call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+          if (err .EQ. 0) goto 999
+
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0,
+     +                   MPI_COMM_WORLD, ierr)
+
+          nerrs = 0
+
+          if (.FALSE. .AND. nprocs .NE. 4 .AND. rank .EQ. 0)
+     +        print*,'Warning: ',cmd(1:XTRIM(cmd)),
+     +               ' is intended to run on 4 processes'
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF_CLOBBER, NF_64BIT_DATA)
+          err = nfmpi_create(MPI_COMM_WORLD, filename, cmode,
+     +                        MPI_INFO_NULL, ncid)
+          call check(err, 'In nfmpi_create: ')
+
+          ! define dimensions x and y
+          err = nfmpi_def_dim(ncid, "X", NX, dimid(1))
+          call check(err, 'In nfmpi_def_dim X: ')
+          err = nfmpi_def_dim(ncid, "Y", NY, dimid(2))
+          call check(err, 'In nfmpi_def_dim Y: ')
+
+          ! define a 2D variable of integer type
+          err = nfmpi_def_var(ncid, "var", NF_INT, NDIMS, dimid, varid)
+          call check(err, 'In nfmpi_def_var: ')
+
+          ! do not forget to exit define mode
+          err = nfmpi_enddef(ncid)
+          call check(err, 'In nfmpi_enddef: ')
+
+          ! now we are in data mode
+
+          ! pick arbitrary numbers of requests for 4 processes
+          num_reqs = 0
+          if (rank .EQ. 0) then
+              num_reqs = 3
+          elseif (rank .EQ. 1) then
+              num_reqs = 3
+          elseif (rank .EQ. 2) then
+              num_reqs = 3
+          elseif (rank .EQ. 3) then
+              num_reqs = 3
+          endif
+
+          ! assign arbitrary starts and counts
+          if (rank .EQ. 0) then
+              ! rank 0 is writing the followings: ("-" means skip)
+              !        -  -  -  -  -  0  0  -  -  - 
+              !        -  -  -  -  -  0  0  -  -  - 
+              !        -  0  0  -  -  -  -  0  -  - 
+              !        -  0  0  -  -  -  -  0  -  - 
+              ! Note this is in Fortran order
+              starts(1, 1) = 1
+              starts(2, 1) = 6
+              counts(1, 1) = 2
+              counts(2, 1) = 2
+              starts(1, 2) = 3
+              starts(2, 2) = 2
+              counts(1, 2) = 2
+              counts(2, 2) = 2
+              starts(1, 3) = 3
+              starts(2, 3) = 8
+              counts(1, 3) = 2
+              counts(2, 3) = 1
+          elseif (rank .EQ. 1) then
+              ! rank 1 is writing the followings: ("-" means skip)
+              !        -  -  1  1  -  -  -  -  -  - 
+              !        -  -  1  1  -  -  -  -  -  - 
+              !        1  -  -  -  -  1  1  -  -  - 
+              !        1  -  -  -  -  1  1  -  -  - 
+              ! Note this is in Fortran order
+              starts(1, 1) = 1
+              starts(2, 1) = 3
+              counts(1, 1) = 2
+              counts(2, 1) = 2
+              starts(1, 2) = 3
+              starts(2, 2) = 1
+              counts(1, 2) = 2
+              counts(2, 2) = 1
+              starts(1, 3) = 3
+              starts(2, 3) = 6
+              counts(1, 3) = 2
+              counts(2, 3) = 2
+          elseif (rank .EQ. 2) then
+              ! rank 2 is writing the followings: ("-" means skip)
+              !        2  2  -  -  -  -  -  2  -  - 
+              !        2  2  -  -  -  -  -  2  -  - 
+              !        -  -  -  -  2  -  -  -  -  - 
+              !        -  -  -  -  2  -  -  -  -  - 
+              ! Note this is in Fortran order
+              starts(1, 1) = 1
+              starts(2, 1) = 1
+              counts(1, 1) = 2
+              counts(2, 1) = 2
+              starts(1, 2) = 1
+              starts(2, 2) = 8
+              counts(1, 2) = 2
+              counts(2, 2) = 1
+              starts(1, 3) = 3
+              starts(2, 3) = 5
+              counts(1, 3) = 2
+              counts(2, 3) = 1
+          elseif (rank .EQ. 3) then
+              ! rank 3 is writing the followings: ("-" means skip)
+              !        -  -  -  -  3  -  -  -  3  3 
+              !        -  -  -  -  3  -  -  -  3  3 
+              !        -  -  -  3  -  -  -  -  3  3 
+              !        -  -  -  3  -  -  -  -  3  3 
+              ! Note this is in Fortran order
+              starts(1, 1) = 1
+              starts(2, 1) = 5
+              counts(1, 1) = 2
+              counts(2, 1) = 1
+              starts(1, 2) = 1
+              starts(2, 2) = 9
+              counts(1, 2) = 4
+              counts(2, 2) = 2
+              starts(1, 3) = 3
+              starts(2, 3) = 4
+              counts(1, 3) = 2
+              counts(2, 3) = 1
+          endif
+ 
+          ! w_len is total write length for this process
+          w_len = 0
+          do i=1, num_reqs
+             w_req_len = 1
+             do j=1, NDIMS
+                w_req_len = w_req_len * counts(j, i)
+             enddo
+             w_len = w_len + w_req_len
+          enddo
+
+          ! initialize buffer contents
+          do i=1, 13
+             buffer(i) = rank
+          enddo
+
+          err = nfmpi_put_varn_int_all(ncid, varid, num_reqs, starts,
+     +                                 counts, buffer)
+          call check(err, 'In nfmpi_put_varn_int_all: ')
+
+          if (nprocs .GT. 4) call MPI_Barrier(MPI_COMM_WORLD, err)
+
+          ! read back and check the contents
+          do i=1, 13
+             buffer(i) = -1
+          enddo
+          err = nfmpi_get_varn_int_all(ncid, varid, num_reqs, starts,
+     +                                 counts, buffer)
+          call check(err, 'In nfmpi_get_varn_int_all: ')
+
+ 997      format(A,I2,A,I2,A,I2)
+          do i=1, INT(w_len)
+             if (buffer(i) .NE. rank) then
+                 print 997, "Error: expecting buffer(",i,")=",rank,
+     +                      " but got", buffer(i)
+                 nerrs = nerrs + 1
+             endif
+          enddo
+
+          ! close the file
+          err = nfmpi_close(ncid)
+          call check(err, 'In nfmpi_close: ')
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nfmpi_inq_malloc_size(malloc_size)
+          if (err .EQ. NF_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET,
+     +                        MPI_SUM, 0, MPI_COMM_WORLD, err)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0)
+     +            print 998,
+     +            'heap memory allocated by PnetCDF internally has ',
+     +            sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+          msg = '*** TESTING F77 '//cmd(1:XTRIM(cmd))//' for varn API '
+          if (rank .eq. 0) call pass_fail(nerrs, msg)
+
+ 999      call MPI_Finalize(ierr)
+      end ! program main
+
diff --git a/test/testcases/varn_real.f90 b/test/testcases/varn_real.f90
new file mode 100644
index 0000000..1222b6f
--- /dev/null
+++ b/test/testcases/varn_real.f90
@@ -0,0 +1,299 @@
+!
+!  Copyright (C) 2012, Northwestern University and Argonne National Laboratory
+!  See COPYRIGHT notice in top-level directory.
+!
+! $Id: varn_real.f90 2205 2015-11-28 20:41:50Z wkliao $
+
+!
+! This example shows how to use a single call of nf90mpi_put_varn_all()
+! to write a sequence of one-element requests with arbitrary array indices.
+!
+! The compile and run commands are given below, together with an ncmpidump of
+! the output file.
+!
+!    % mpif90 -O2 -o varn_real varn_real.f90 -lpnetcdf
+!    % mpiexec -n 4 ./varn_real /pvfs2/wkliao/testfile.nc
+!    % ncmpidump /pvfs2/wkliao/testfile.nc
+!    netcdf testfile {
+!    // file format: CDF-5 (big variables)
+!    dimensions:
+!             Y = 4 ;
+!             X = 10 ;
+!    variables:
+!             float var(Y, X) ;
+!    data:
+!
+!     var =
+!       3, 3, 3, 1, 1, 0, 0, 2, 1, 1,
+!       0, 2, 2, 2, 3, 1, 1, 2, 2, 2,
+!       1, 1, 2, 3, 3, 3, 0, 0, 1, 1,
+!       0, 0, 0, 2, 1, 1, 1, 3, 3, 3 ;
+!    }
+!
+
+      subroutine check(err, message)
+          use mpi
+          use pnetcdf
+          implicit none
+          integer err
+          character(len=*) message
+          character(len=128) msg
+
+          ! It is a good idea to check returned value for possible error
+          if (err .NE. NF90_NOERR) then
+              write(6,*) message, trim(nf90mpi_strerror(err))
+              msg = '*** TESTING F90 varn_real.f90 for varn API '
+              call pass_fail(1, msg)
+              ! call MPI_Abort(MPI_COMM_WORLD, -1, err)
+          end if
+      end subroutine check
+
+      program main
+          use mpi
+          use pnetcdf
+          implicit none
+
+          integer NDIMS
+          PARAMETER(NDIMS=2)
+
+          character(LEN=256) filename, cmd, msg
+          integer rank, nprocs, err, ierr, num_reqs, get_args
+          integer ncid, cmode, varid, dimid(2), y, x, i, j, nerrs
+          integer, allocatable :: req_lens(:)
+          real, allocatable :: buffer(:), buffer2D(:,:)
+          real oneReal
+          integer(kind=MPI_OFFSET_KIND) NY, NX
+          integer(kind=MPI_OFFSET_KIND) w_len, w_req_len
+          integer(kind=MPI_OFFSET_KIND), allocatable :: starts(:,:)
+          integer(kind=MPI_OFFSET_KIND), allocatable :: counts(:,:)
+          integer(kind=MPI_OFFSET_KIND) malloc_size, sum_size
+
+          NY = 4
+          NX = 10
+
+          call MPI_Init(ierr)
+          call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
+          call MPI_Comm_size(MPI_COMM_WORLD, nprocs, ierr)
+
+          ! take filename from command-line argument if there is any
+          if (rank .EQ. 0) then
+              filename = "testfile.nc"
+              err = get_args(cmd, filename)
+          endif
+          call MPI_Bcast(err, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
+          if (err .EQ. 0) goto 999
+          
+          call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr)
+
+          nerrs = 0
+
+          if (.FALSE. .AND. nprocs .NE. 4 .AND. rank .EQ. 0) &
+              print*,'Warning: ',trim(cmd),' is intended to run on ', &
+                     '4 processes'
+
+          ! create file, truncate it if exists
+          cmode = IOR(NF90_CLOBBER, NF90_64BIT_DATA)
+          err = nf90mpi_create(MPI_COMM_WORLD, filename, cmode, &
+                             MPI_INFO_NULL, ncid)
+          call check(err, 'In nf90mpi_create: ')
+
+          ! create a global array of size NY * NX */
+          err = nf90mpi_def_dim(ncid, "Y", NY, dimid(2))
+          call check(err, 'In nf90mpi_def_dim Y: ')
+          err = nf90mpi_def_dim(ncid, "X", NX, dimid(1))
+          call check(err, 'In nf90mpi_def_dim X: ')
+          err = nf90mpi_def_var(ncid, "var", NF90_FLOAT, dimid, varid)
+          call check(err, 'In nf90mpi_def_var var: ')
+          err = nf90mpi_enddef(ncid)
+          call check(err, 'In nf90mpi_enddef: ')
+
+          ! pick arbitrary numbers of requests for 4 processes
+          num_reqs = 0
+          if (rank .EQ.  0) then
+              num_reqs = 8
+          elseif (rank .EQ. 1) then
+              num_reqs = 13
+          elseif (rank .EQ. 2) then
+              num_reqs = 9
+          elseif (rank .EQ. 3) then
+              num_reqs = 10
+          endif
+
+          ! Note that in Fortran, array indices start with 1
+          ALLOCATE(starts(NDIMS, num_reqs+1))
+          ALLOCATE(counts(NDIMS, num_reqs))
+
+          ! assign arbitrary starts
+          y=2
+          x=1
+          if (rank .EQ. 0) then
+              starts(y, 1) = 1; starts(x, 1) = 6
+              starts(y, 2) = 2; starts(x, 2) = 1
+              starts(y, 3) = 3; starts(x, 3) = 7
+              starts(y, 4) = 4; starts(x, 4) = 1
+              starts(y, 5) = 1; starts(x, 5) = 7
+              starts(y, 6) = 3; starts(x, 6) = 8
+              starts(y, 7) = 4; starts(x, 7) = 2
+              starts(y, 8) = 4; starts(x, 8) = 3
+              ! rank 0 is writing the following locations: ("-" means skip)
+              !   -  -  -  -  -  0  0  -  -  - 
+              !   0  -  -  -  -  -  -  -  -  - 
+              !   -  -  -  -  -  -  0  0  -  - 
+              !   0  0  0  -  -  -  -  -  -  - 
+          elseif (rank .EQ. 1) then
+              starts(y,  1) = 1; starts(x,  1) = 4
+              starts(y,  2) = 1; starts(x,  2) = 9
+              starts(y,  3) = 2; starts(x,  3) = 6
+              starts(y,  4) = 3; starts(x,  4) = 1
+              starts(y,  5) = 3; starts(x,  5) = 9
+              starts(y,  6) = 4; starts(x,  6) = 5
+              starts(y,  7) = 1; starts(x,  7) = 5
+              starts(y,  8) = 1; starts(x,  8) = 10
+              starts(y,  9) = 2; starts(x,  9) = 7
+              starts(y, 10) = 3; starts(x, 10) = 2
+              starts(y, 11) = 3; starts(x, 11) = 10
+              starts(y, 12) = 4; starts(x, 12) = 6
+              starts(y, 13) = 4; starts(x, 13) = 7
+              ! rank 1 is writing the following locations: ("-" means skip)
+              !   -  -  -  1  1  -  -  -  1  1 
+              !   -  -  -  -  -  1  1  -  -  - 
+              !   1  1  -  -  -  -  -  -  1  1 
+              !   -  -  -  -  1  1  1  -  -  - 
+          elseif (rank .EQ. 2) then
+              starts(y, 1) = 1; starts(x, 1) = 8
+              starts(y, 2) = 2; starts(x, 2) = 2
+              starts(y, 3) = 2; starts(x, 3) = 8
+              starts(y, 4) = 3; starts(x, 4) = 3
+              starts(y, 5) = 4; starts(x, 5) = 4
+              starts(y, 6) = 2; starts(x, 6) = 3
+              starts(y, 7) = 2; starts(x, 7) = 9
+              starts(y, 8) = 2; starts(x, 8) = 4
+              starts(y, 9) = 2; starts(x, 9) = 10
+              ! rank 2 is writing the following locations: ("-" means skip)
+              !   -  -  -  -  -  -  -  2  -  - 
+              !   -  2  2  2  -  -  -  2  2  2 
+              !   -  -  2  -  -  -  -  -  -  - 
+              !   -  -  -  2  -  -  -  -  -  - 
+          elseif (rank .EQ. 3) then
+              starts(y,  1) = 1; starts(x,  1) = 1
+              starts(y,  2) = 2; starts(x,  2) = 5
+              starts(y,  3) = 3; starts(x,  3) = 4
+              starts(y,  4) = 4; starts(x,  4) = 8
+              starts(y,  5) = 1; starts(x,  5) = 2
+              starts(y,  6) = 3; starts(x,  6) = 5
+              starts(y,  7) = 4; starts(x,  7) = 9
+              starts(y,  8) = 1; starts(x,  8) = 3
+              starts(y,  9) = 3; starts(x,  9) = 6
+              starts(y, 10) = 4; starts(x, 10) = 10
+              ! rank 3 is writing the following locations: ("-" means skip)
+              !   3  3  3  -  -  -  -  -  -  - 
+              !   -  -  -  -  3  -  -  -  -  - 
+              !   -  -  -  3  3  3  -  -  -  - 
+              !   -  -  -  -  -  -  -  3  3  3 
+          endif
+          counts = 1
+
+          ALLOCATE(req_lens(num_reqs))
+
+          ! allocate I/O buffer and initialize its contents
+          w_len = 0
+          do i=1, num_reqs
+             w_req_len = 1
+             do j=1, NDIMS
+                w_req_len = w_req_len * counts(j, i)
+             enddo
+             req_lens(i) = INT(w_req_len)
+             w_len = w_len + w_req_len
+          enddo
+          ALLOCATE(buffer(w_len))
+          ALLOCATE(buffer2D(3, w_len/3+1))
+          ! Note on 2D buffer, put_varn will fill in the first w_len
+          ! elements in buffer2D, no matter the shape of buffer2D is
+
+          buffer   = rank
+          buffer2D = rank
+
+          ! varn write a 2D buffer in memory to a 2D array in file
+          err = nf90mpi_put_varn_all(ncid, varid, buffer2D, num_reqs, &
+                                     starts, counts)
+          call check(err, 'In nf90mpi_put_varn_all: ')
+
+          ! varn write a 1D buffer in memory to a 2D array in file
+          err = nf90mpi_put_varn_all(ncid, varid, buffer, num_reqs, &
+                                     starts, counts)
+          call check(err, 'In nf90mpi_put_varn_all: ')
+
+          if (nprocs .GT. 4) call MPI_Barrier(MPI_COMM_WORLD, err)
+
+          ! read a scalar back and check the content
+          oneReal = -1.0  ! a scalar
+          if (rank .GE. 4) starts = 1_MPI_OFFSET_KIND
+          err = nf90mpi_get_varn_all(ncid, varid, oneReal, starts)
+          call check(err, ' 22 In nf90mpi_get_varn_all: ')
+
+ 995      format(A,I2,A,F4.1)
+          if (rank .LT. 4 .AND. oneReal .NE. rank) then
+              print 995, "Error: expecting OneReal=",rank, &
+                         " but got", oneReal
+              nerrs = nerrs + 1
+          endif
+
+          ! varn read a 2D array in file to a 2D buffer in memory
+          buffer2D = -1.0;
+          err = nf90mpi_get_varn_all(ncid, varid, buffer2D, num_reqs, &
+                                     starts, counts)
+          call check(err, 'In nf90mpi_get_varn_all: ')
+
+ 996      format(A,I2,A,I2,A,I2,A,F4.1)
+          do i=1, INT(w_len/3)
+             do j=1, 3
+                if (buffer2D(j,i) .NE. rank) then
+                    print 996, "Error: expecting buffer2D(",j,",",i,")=", &
+                               rank, " but got", buffer2D(j,i)
+                    nerrs = nerrs + 1
+                endif
+             enddo
+          enddo
+
+          ! varn read a 2D array in file to a 1D buffer in memory
+          buffer = -1.0;
+          err = nf90mpi_get_varn_all(ncid, varid, buffer, num_reqs, &
+                                     starts, counts)
+          call check(err, 'In nf90mpi_get_varn_all: ')
+
+ 997      format(A,I2,A,I2,A,F4.1)
+          do i=1, INT(w_len)
+             if (buffer(i) .NE. rank) then
+                 print 997, "Error: expecting buffer(",i,")=",rank, &
+                            " but got", buffer(i)
+                 nerrs = nerrs + 1
+             endif
+          enddo
+
+          err = nf90mpi_close(ncid);
+          call check(err, 'In nf90mpi_close: ')
+
+          DEALLOCATE(req_lens);
+          DEALLOCATE(buffer);
+          DEALLOCATE(buffer2D);
+          DEALLOCATE(starts);
+          DEALLOCATE(counts);
+
+          ! check if there is any PnetCDF internal malloc residue
+ 998      format(A,I13,A)
+          err = nf90mpi_inq_malloc_size(malloc_size)
+          if (err == NF90_NOERR) then
+              call MPI_Reduce(malloc_size, sum_size, 1, MPI_OFFSET, &
+                              MPI_SUM, 0, MPI_COMM_WORLD, ierr)
+              if (rank .EQ. 0 .AND. sum_size .GT. 0_MPI_OFFSET_KIND) print 998, &
+                  'heap memory allocated by PnetCDF internally has ',  &
+                  sum_size/1048576, ' MiB yet to be freed'
+          endif
+
+          msg = '*** TESTING F90 '//trim(cmd)//' for varn API '
+          if (rank .eq. 0) call pass_fail(nerrs, msg)
+
+ 999      call MPI_Finalize(ierr)
+
+      end program
+
diff --git a/test/testcases/vectors.c b/test/testcases/vectors.c
new file mode 100644
index 0000000..69b68e0
--- /dev/null
+++ b/test/testcases/vectors.c
@@ -0,0 +1,133 @@
+/*
+ *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
+ *  See COPYRIGHT notice in top-level directory.
+ *
+ *  $Id: vectors.c 2133 2015-09-26 19:16:01Z wkliao $
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <mpi.h>
+#include <pnetcdf.h>
+
+#include <testutils.h>
+
+#define HANDLE_ERR(err) { if (err!=NC_NOERR) {nerrs++; fprintf(stderr, "Error at line %d: %s\n",__LINE__,ncmpi_strerror(err));}}
+
+#define VECCOUNT 4
+#define BLOCKLEN  3
+#define STRIDE   5
+int main(int argc, char ** argv)
+{
+    int ncid, dimid, varid, rank, nprocs, verbose;
+    MPI_Datatype vtype, rtype, usertype;
+    MPI_Aint lb, extent;
+    int userbufsz, *userbuf, *cmpbuf, i, err, errs=0, nerrs=0;
+    int count = 25;
+    double pi = 3.14159;
+    MPI_Offset start, acount;
+    char *filename="testfile.nc";
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
+
+    if (argc > 2) {
+        if (!rank) printf("Usage: %s [filename]\n",argv[0]);
+        MPI_Finalize();
+        return 0;
+    }
+    if (argc == 2) filename = argv[1];
+
+    if (rank == 0) {
+        char cmd_str[256];
+        sprintf(cmd_str, "*** TESTING C   %s for put_vara/get_vara ", argv[0]);
+        printf("%-66s ------ ", cmd_str); fflush(stdout);
+    }
+
+    verbose = 0;
+    if (nprocs > 2 && rank == 0 && verbose)
+        printf("Warning: %s is designed to run on 1 process\n",argv[0]);
+
+    err = ncmpi_create(MPI_COMM_WORLD, filename, NC_CLOBBER, MPI_INFO_NULL, &ncid);
+    HANDLE_ERR(err)
+    err = ncmpi_def_dim(ncid, "50k", 1024*50, &dimid);
+    HANDLE_ERR(err)
+    err = ncmpi_def_var(ncid, "vector", NC_DOUBLE, 1, &dimid, &varid);
+    HANDLE_ERR(err)
+
+    err = ncmpi_enddef(ncid);
+    HANDLE_ERR(err)
+
+    MPI_Type_vector(VECCOUNT, BLOCKLEN, STRIDE, MPI_INT, &vtype);
+    MPI_Type_create_resized(vtype, 0, STRIDE*VECCOUNT*sizeof(int), &rtype);
+    MPI_Type_contiguous(count, rtype, &usertype);
+    MPI_Type_commit(&usertype);
+
+    MPI_Type_free(&vtype);
+    MPI_Type_free(&rtype);
+
+    MPI_Type_get_extent(usertype, &lb, &extent);
+    userbufsz = extent;
+    userbuf = (int*) malloc(userbufsz);
+    cmpbuf = (int*) calloc(userbufsz, 1);
+    for (i=0; i< userbufsz/sizeof(int); i++)
+        userbuf[i] = pi*i;
+
+    start = 10; acount = count*12;
+    err = ncmpi_begin_indep_data(ncid);
+    HANDLE_ERR(err)
+    if (rank == 0) {
+        err = ncmpi_put_vara(ncid, varid, &start, &acount, userbuf, 1, usertype);
+        HANDLE_ERR(err)
+    }
+
+    err = ncmpi_close(ncid);
+    HANDLE_ERR(err)
+
+    err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid);
+    HANDLE_ERR(err)
+    err = ncmpi_begin_indep_data(ncid);
+    HANDLE_ERR(err)
+    err = ncmpi_inq_varid(ncid, "vector", &varid);
+    HANDLE_ERR(err)
+    err = ncmpi_get_vara(ncid, varid, &start, &acount, cmpbuf, 1, usertype);
+    HANDLE_ERR(err)
+    err = ncmpi_close(ncid);
+    HANDLE_ERR(err)
+
+    for (i=0; errs < 10 &&  i < acount; i++) {
+        /* vector of 4,3,5, so skip 4th and 5th items of every block */
+        if (i%STRIDE >= BLOCKLEN) continue;
+        if (userbuf[i] != cmpbuf[i]) {
+            errs++;
+            fprintf(stderr, "%d: expected 0x%x got 0x%x\n", 
+                    i, userbuf[i], cmpbuf[i]);
+        }
+    }
+    nerrs += errs;
+    free(userbuf);
+    free(cmpbuf);
+    MPI_Type_free(&usertype);
+
+    /* check if PnetCDF freed all internal malloc */
+    MPI_Offset malloc_size, sum_size;
+    err = ncmpi_inq_malloc_size(&malloc_size);
+    if (err == NC_NOERR) {
+        MPI_Reduce(&malloc_size, &sum_size, 1, MPI_OFFSET, MPI_SUM, 0, MPI_COMM_WORLD);
+        if (rank == 0 && sum_size > 0)
+            printf("heap memory allocated by PnetCDF internally has %lld bytes yet to be freed\n",
+                   sum_size);
+    }
+
+    MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
+    if (rank == 0) {
+        if (nerrs) printf(FAIL_STR,nerrs);
+        else       printf(PASS_STR);
+    }
+
+    MPI_Finalize();
+
+    return 0;
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/pnetcdf.git



More information about the debian-science-commits mailing list